8014310: JAAS/Krb5LoginModule using des encytypes failure with NPE after JDK-8012679
authorweijun
Thu, 13 Jun 2013 09:59:29 +0800
changeset 18168 f47169155ea0
parent 18167 fb6a6363109c
child 18169 deb6268716ef
8014310: JAAS/Krb5LoginModule using des encytypes failure with NPE after JDK-8012679 Reviewed-by: valeriep
jdk/src/share/classes/sun/security/krb5/Config.java
jdk/src/share/classes/sun/security/krb5/EncryptionKey.java
jdk/src/share/classes/sun/security/krb5/KrbApReq.java
jdk/src/share/classes/sun/security/krb5/KrbTgsReq.java
jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java
jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java
jdk/test/sun/security/krb5/auto/BasicKrb5Test.java
jdk/test/sun/security/krb5/auto/OneKDC.java
jdk/test/sun/security/krb5/auto/OnlyDesLogin.java
--- a/jdk/src/share/classes/sun/security/krb5/Config.java	Wed Jun 12 14:07:14 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/Config.java	Thu Jun 13 09:59:29 2013 +0800
@@ -761,22 +761,23 @@
     }
 
     /**
-     * Returns the default encryption types.
-     *
+     * Returns all etypes specified in krb5.conf for the given configName,
+     * or all the builtin defaults. This result is always non-empty.
+     * If no etypes are found, an exception is thrown.
      */
-    public int[] defaultEtype(String enctypes) {
+    public int[] defaultEtype(String configName) throws KrbException {
         String default_enctypes;
-        default_enctypes = get("libdefaults", enctypes);
-        String delim = " ";
-        StringTokenizer st;
+        default_enctypes = get("libdefaults", configName);
         int[] etype;
         if (default_enctypes == null) {
             if (DEBUG) {
                 System.out.println("Using builtin default etypes for " +
-                    enctypes);
+                    configName);
             }
             etype = EType.getBuiltInDefaults();
         } else {
+            String delim = " ";
+            StringTokenizer st;
             for (int j = 0; j < default_enctypes.length(); j++) {
                 if (default_enctypes.substring(j, j + 1).equals(",")) {
                     // only two delimiters are allowed to use
@@ -791,17 +792,13 @@
             int type;
             for (int i = 0; i < len; i++) {
                 type = Config.getType(st.nextToken());
-                if ((type != -1) &&
-                    (EType.isSupported(type))) {
+                if (type != -1 && EType.isSupported(type)) {
                     ls.add(type);
                 }
             }
             if (ls.isEmpty()) {
-                if (DEBUG) {
-                    System.out.println(
-                        "no supported default etypes for " + enctypes);
-                }
-                return null;
+                throw new KrbException("no supported default etypes for "
+                        + configName);
             } else {
                 etype = new int[ls.size()];
                 for (int i = 0; i < etype.length; i++) {
@@ -811,7 +808,7 @@
         }
 
         if (DEBUG) {
-            System.out.print("default etypes for " + enctypes + ":");
+            System.out.print("default etypes for " + configName + ":");
             for (int i = 0; i < etype.length; i++) {
                 System.out.print(" " + etype[i]);
             }
--- a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java	Wed Jun 12 14:07:14 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java	Thu Jun 13 09:59:29 2013 +0800
@@ -98,36 +98,6 @@
     }
 
     /**
-     * Obtains the latest version of the secret key of
-     * the principal from a keytab.
-     *
-     * @param princ the principal whose secret key is desired
-     * @param keytab the path to the keytab file. A value of null
-     * will be accepted to indicate that the default path should be
-     * searched.
-     * @returns the secret key or null if none was found.
-     */
-    /*
-    // Replaced by acquireSecretKeys
-    public static EncryptionKey acquireSecretKey(PrincipalName princ,
-                                                 String keytab)
-        throws KrbException, IOException {
-
-        if (princ == null) {
-            throw new IllegalArgumentException(
-                "Cannot have null pricipal name to look in keytab.");
-        }
-
-        KeyTab ktab = KeyTab.getInstance(keytab);
-
-        if (ktab == null)
-            return null;
-
-        return ktab.readServiceKey(princ);
-    }
-    */
-
-    /**
      * Obtains all versions of the secret key of the principal from a
      * keytab.
      *
@@ -208,9 +178,6 @@
             String salt) throws KrbException {
 
         int[] etypes = EType.getDefaults("default_tkt_enctypes");
-        if (etypes == null) {
-            etypes = EType.getBuiltInDefaults();
-        }
 
         EncryptionKey[] encKeys = new EncryptionKey[etypes.length];
         for (int i = 0; i < etypes.length; i++) {
--- a/jdk/src/share/classes/sun/security/krb5/KrbApReq.java	Wed Jun 12 14:07:14 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApReq.java	Thu Jun 13 09:59:29 2013 +0800
@@ -490,10 +490,6 @@
      // Check that key is one of the permitted types
      private static void checkPermittedEType(int target) throws KrbException {
         int[] etypes = EType.getDefaults("permitted_enctypes");
-        if (etypes == null) {
-            throw new KrbException(
-                "No supported encryption types listed in permitted_enctypes");
-        }
         if (!EType.isSupported(target, etypes)) {
             throw new KrbException(EType.toString(target) +
                 " encryption type not in permitted_enctypes list");
--- a/jdk/src/share/classes/sun/security/krb5/KrbTgsReq.java	Wed Jun 12 14:07:14 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbTgsReq.java	Thu Jun 13 09:59:29 2013 +0800
@@ -291,8 +291,7 @@
                          Ticket[] additionalTickets,
                          EncryptionKey subKey,
                          PAData extraPA)
-        throws Asn1Exception, IOException, KdcErrException, KrbApErrException,
-               UnknownHostException, KrbCryptoException {
+        throws IOException, KrbException, UnknownHostException {
         KerberosTime req_till = null;
         if (till == null) {
             req_till = new KerberosTime(0);
@@ -314,10 +313,6 @@
         int[] req_eTypes = null;
         if (eTypes == null) {
             req_eTypes = EType.getDefaults("default_tgs_enctypes");
-            if (req_eTypes == null) {
-                throw new KrbCryptoException(
-            "No supported encryption types listed in default_tgs_enctypes");
-            }
         } else {
             req_eTypes = eTypes;
         }
--- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java	Wed Jun 12 14:07:14 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java	Thu Jun 13 09:59:29 2013 +0800
@@ -230,11 +230,14 @@
     /**
      * Retrieves the default etypes from the configuration file, or
      * if that's not available, return the built-in list of default etypes.
+     * This result is always non-empty. If no etypes are found,
+     * an exception is thrown.
      */
-    // used in KrbAsReq, KeyTab
-    public static int[] getDefaults(String configName) {
+    public static int[] getDefaults(String configName)
+            throws KrbException {
+        Config config = null;
         try {
-            return Config.getInstance().defaultEtype(configName);
+            config = Config.getInstance();
         } catch (KrbException exc) {
             if (DEBUG) {
                 System.out.println("Exception while getting " +
@@ -243,6 +246,7 @@
             }
             return getBuiltInDefaults();
         }
+        return config.defaultEtype(configName);
     }
 
     /**
@@ -254,12 +258,8 @@
      * we have keys.
      */
     public static int[] getDefaults(String configName, EncryptionKey[] keys)
-        throws KrbException {
+            throws KrbException {
         int[] answer = getDefaults(configName);
-        if (answer == null) {
-            throw new KrbException("No supported encryption types listed in "
-                + configName);
-        }
 
         List<Integer> list = new ArrayList<>(answer.length);
         for (int i = 0; i < answer.length; i++) {
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Wed Jun 12 14:07:14 2013 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Thu Jun 13 09:59:29 2013 +0800
@@ -279,8 +279,7 @@
 
     /**
      * Reads all keys for a service from the keytab file that have
-     * etypes that have been configured for use. If there are multiple
-     * keys with same etype, the one with the highest kvno is returned.
+     * etypes that have been configured for use.
      * @param service the PrincipalName of the requested service
      * @return an array containing all the service keys, never null
      */
@@ -313,35 +312,12 @@
         size = keys.size();
         EncryptionKey[] retVal = keys.toArray(new EncryptionKey[size]);
 
-        // Sort keys according to default_tkt_enctypes
-        if (DEBUG) {
-            System.out.println("Ordering keys wrt default_tkt_enctypes list");
-        }
-
-        final int[] etypes = EType.getDefaults("default_tkt_enctypes");
-
-        // Sort the keys, k1 is preferred than k2 if:
-        // 1. k1's etype appears earlier in etypes than k2's
-        // 2. If same, k1's KVNO is higher
+        // Sort the keys by kvno. Sometimes we must choose a single key (say,
+        // generate encrypted timestamp in AS-REQ). A key with a higher KVNO
+        // sounds like a newer one.
         Arrays.sort(retVal, new Comparator<EncryptionKey>() {
             @Override
             public int compare(EncryptionKey o1, EncryptionKey o2) {
-                if (etypes != null) {
-                    int o1EType = o1.getEType();
-                    int o2EType = o2.getEType();
-                    if (o1EType != o2EType) {
-                        for (int i=0; i<etypes.length; i++) {
-                            if (etypes[i] == o1EType) {
-                                return -1;
-                            } else if (etypes[i] == o2EType) {
-                                return 1;
-                            }
-                        }
-                        // Neither o1EType nor o2EType in default_tkt_enctypes,
-                        // therefore won't be used in AS-REQ. We do not care
-                        // about their order, use kvno is OK.
-                    }
-                }
                 return o2.getKeyVersionNumber().intValue()
                         - o1.getKeyVersionNumber().intValue();
             }
--- a/jdk/test/sun/security/krb5/auto/BasicKrb5Test.java	Wed Jun 12 14:07:14 2013 -0700
+++ b/jdk/test/sun/security/krb5/auto/BasicKrb5Test.java	Thu Jun 13 09:59:29 2013 +0800
@@ -59,6 +59,7 @@
 import org.ietf.jgss.GSSName;
 import sun.security.jgss.GSSUtil;
 import sun.security.krb5.Config;
+import sun.security.krb5.KrbException;
 import sun.security.krb5.internal.crypto.EType;
 
 /**
@@ -84,12 +85,10 @@
 
         // Creates and starts the KDC. This line must be put ahead of etype check
         // since the check needs a krb5.conf.
-        new OneKDC(etype).writeJAASConf();
-
-        System.out.println("Testing etype " + etype);
-        if (etype != null && !EType.isSupported(Config.getType(etype))) {
-            // aes256 is not enabled on all systems
-            System.out.println("Not supported.");
+        try {
+            new OneKDC(etype).writeJAASConf();
+        } catch (KrbException ke) {
+            System.out.println("Testing etype " + etype + "Not supported.");
             return;
         }
 
--- a/jdk/test/sun/security/krb5/auto/OneKDC.java	Wed Jun 12 14:07:14 2013 -0700
+++ b/jdk/test/sun/security/krb5/auto/OneKDC.java	Thu Jun 13 09:59:29 2013 +0800
@@ -67,10 +67,19 @@
         addPrincipalRandKey("krbtgt/" + REALM);
         addPrincipalRandKey(SERVER);
         addPrincipalRandKey(BACKEND);
+
+        String extraConfig = "";
+        if (etype != null) {
+            extraConfig += "default_tkt_enctypes=" + etype
+                    + "\ndefault_tgs_enctypes=" + etype;
+            if (etype.startsWith("des")) {
+                extraConfig += "\nallow_weak_crypto = true";
+            }
+        }
         KDC.saveConfig(KRB5_CONF, this,
                 "forwardable = true",
                 "default_keytab_name = " + KTAB,
-                etype == null ? "" : "default_tkt_enctypes=" + etype + "\ndefault_tgs_enctypes=" + etype);
+                extraConfig);
         System.setProperty("java.security.krb5.conf", KRB5_CONF);
         // Whatever krb5.conf had been loaded before, we reload ours now.
         Config.refresh();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/OnlyDesLogin.java	Thu Jun 13 09:59:29 2013 +0800
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8014310
+ * @summary JAAS/Krb5LoginModule using des encytypes failure with NPE after JDK-8012679
+ * @compile -XDignore.symbol.file OnlyDesLogin.java
+ * @run main/othervm OnlyDesLogin
+ */
+
+import sun.security.krb5.Config;
+
+import javax.security.auth.login.LoginException;
+
+public class OnlyDesLogin {
+
+    public static void main(String[] args) throws Exception {
+
+        OneKDC kdc = new OneKDC(null);
+        kdc.writeJAASConf();
+
+        KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+                "default_tkt_enctypes=des-cbc-md5",
+                "default_tgs_enctypes=des-cbc-md5",
+                "permitted_enctypes=des-cbc-md5");
+        Config.refresh();
+
+        try {
+            Context.fromJAAS("client");
+            throw new Exception("What?");
+        } catch (LoginException le) {
+            // This is OK
+        }
+    }
+}