8014310: JAAS/Krb5LoginModule using des encytypes failure with NPE after JDK-8012679
Reviewed-by: valeriep
--- 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
+ }
+ }
+}