6959292: regression: cannot login if session key and preauth does not use the same etype
Reviewed-by: xuelei, valeriep
--- a/jdk/src/share/classes/sun/security/krb5/Credentials.java Wed Jun 16 14:07:47 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/Credentials.java Thu Jun 17 13:46:15 2010 +0800
@@ -356,7 +356,6 @@
* @param princ the client principal. This value cannot be null.
* @param secretKey the secret key of the client principal.This value
* cannot be null.
- * @param password if null, caller is using a keytab
* @returns the TGT credentials
*/
public static Credentials acquireTGT(PrincipalName princ,
@@ -373,18 +372,8 @@
"Cannot have null secretKey to do AS-Exchange");
KrbAsRep asRep = null;
-
- // The etype field to be placed in AS-REQ. If caller is using keytab,
- // it must be limited to etypes in keytab. Otherwise, leave it null,
- // and KrbAsReq will populate it with all supported etypes.
-
- int[] eTypes = null;
- if (password == null) {
- eTypes = EncryptionKey.getETypes(secretKeys);
- }
-
try {
- asRep = sendASRequest(princ, secretKeys, eTypes, null);
+ asRep = sendASRequest(princ, secretKeys, null);
} catch (KrbException ke) {
if ((ke.returnCode() == Krb5.KDC_ERR_PREAUTH_FAILED) ||
(ke.returnCode() == Krb5.KDC_ERR_PREAUTH_REQUIRED)) {
@@ -407,7 +396,7 @@
princ.getSalt(), true,
error.getEType(), error.getParams());
}
- asRep = sendASRequest(princ, secretKeys, eTypes, ke.getError());
+ asRep = sendASRequest(princ, secretKeys, ke.getError());
} else {
throw ke;
}
@@ -417,18 +406,17 @@
/**
* Sends the AS-REQ
- * @param eTypes not null if caller using keytab
*/
private static KrbAsRep sendASRequest(PrincipalName princ,
- EncryptionKey[] secretKeys, int[] eTypes, KRBError error)
+ EncryptionKey[] secretKeys, KRBError error)
throws KrbException, IOException {
// %%%
KrbAsReq asReq = null;
if (error == null) {
- asReq = new KrbAsReq(princ, secretKeys, eTypes);
+ asReq = new KrbAsReq(princ, secretKeys);
} else {
- asReq = new KrbAsReq(princ, secretKeys, eTypes, true,
+ asReq = new KrbAsReq(princ, secretKeys, true,
error.getEType(), error.getSalt(), error.getParams());
}
--- a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java Wed Jun 16 14:07:47 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java Thu Jun 17 13:46:15 2010 +0800
@@ -76,26 +76,6 @@
private static final boolean DEBUG = Krb5.DEBUG;
- public static int[] getETypes(EncryptionKey[] keys) {
- int len = keys.length;
- int[] result = new int[len];
- int count = 0; // Number of elements in result. Might be less than
- // len if there are keys having the same etype
- loopi: for (int i=0; i<len; i++) {
- int eType = keys[i].getEType();
- for (int j=0; j<count; j++) {
- if (result[j] == eType) {
- continue loopi;
- }
- }
- result[count++] = eType;
- }
- if (count != len) {
- result = Arrays.copyOf(result, count);
- }
- return result;
- }
-
public synchronized int getEType() {
return keyType;
}
@@ -208,24 +188,13 @@
etypes = EType.getBuiltInDefaults();
}
- // set the preferred etype for preauth
- if ((pa_exists) && (pa_etype != EncryptedData.ETYPE_NULL)) {
- if (DEBUG) {
- System.out.println("Pre-Authentication: " +
- "Set preferred etype = " + pa_etype);
- }
- if (EType.isSupported(pa_etype)) {
- // reset etypes to preferred value
- etypes = new int[1];
- etypes[0] = pa_etype;
- }
- }
-
EncryptionKey[] encKeys = new EncryptionKey[etypes.length];
for (int i = 0; i < etypes.length; i++) {
if (EType.isSupported(etypes[i])) {
+ byte[] s2kparams = (pa_exists && etypes[i] == pa_etype)
+ ? pa_s2kparams : null;
encKeys[i] = new EncryptionKey(
- stringToKey(password, salt, pa_s2kparams, etypes[i]),
+ stringToKey(password, salt, s2kparams, etypes[i]),
etypes[i], null);
} else {
if (DEBUG) {
--- a/jdk/src/share/classes/sun/security/krb5/KrbAsReq.java Wed Jun 16 14:07:47 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbAsReq.java Thu Jun 17 13:46:15 2010 +0800
@@ -35,9 +35,11 @@
import sun.security.krb5.internal.crypto.EType;
import sun.security.krb5.internal.crypto.Nonce;
import sun.security.krb5.internal.crypto.KeyUsage;
+import sun.security.util.*;
import java.io.IOException;
+import java.io.ByteArrayInputStream;
import java.net.UnknownHostException;
-import java.util.Arrays;
+import java.util.StringTokenizer;
/**
* This class encapsulates the KRB-AS-REQ message that the client
@@ -62,13 +64,11 @@
/**
* Creates a KRB-AS-REQ to send to the default KDC
- * @param eTypes not null when using a keytab, this can make sure the etypes
- * in AS-REQ contains only those available on client
* @throws KrbException
* @throws IOException
*/
// Called by Credentials
- KrbAsReq(PrincipalName principal, EncryptionKey[] keys, int[] eTypes)
+ KrbAsReq(PrincipalName principal, EncryptionKey[] keys)
throws KrbException, IOException {
this(keys, // for pre-authentication
false, 0, null, null, // pre-auth values
@@ -78,7 +78,7 @@
null, // KerberosTime from
null, // KerberosTime till
null, // KerberosTime rtime
- eTypes, // int[] eTypes
+ null, // int[] eTypes
null, // HostAddresses addresses
null); // Ticket[] additionalTickets
}
@@ -86,10 +86,8 @@
/**
* Creates a KRB-AS-REQ to send to the default KDC
* with pre-authentication values
- * @param eTypes not null when using a keytab, this can make sure the etypes
- * in AS-REQ contains only those available on client
*/
- KrbAsReq(PrincipalName principal, EncryptionKey[] keys, int[] eTypes,
+ KrbAsReq(PrincipalName principal, EncryptionKey[] keys,
boolean pa_exists, int etype, String salt, byte[] s2kparams)
throws KrbException, IOException {
this(keys, // for pre-authentication
@@ -100,7 +98,7 @@
null, // KerberosTime from
null, // KerberosTime till
null, // KerberosTime rtime
- eTypes, // int[] eTypes
+ null, // int[] eTypes
null, // HostAddresses addresses
null); // Ticket[] additionalTickets
}
@@ -344,24 +342,18 @@
}
princName = cname;
-
- // keys might contain many etypes, or only one if in preauth mode,
- // coz EncryptionKey.acquireSecretKeys() with pa returns only one key.
-
+ int[] tktETypes = EType.getDefaults("default_tkt_enctypes", keys);
PAData[] paData = null;
if (PA_ENC_TIMESTAMP_REQUIRED) {
EncryptionKey key = null;
if (pa_etype != EncryptedData.ETYPE_NULL) {
if (DEBUG) {
- System.out.println("Pre-Authenticaton: " +
- "find key for etype = " + pa_etype);
+ System.out.println("Pre-Authenticaton: find key for etype = " + pa_etype);
}
key = EncryptionKey.findKey(pa_etype, keys);
} else {
- int[] availableETypes =
- EType.getDefaults("default_tkt_enctypes", keys);
- if (availableETypes.length > 0) {
- key = EncryptionKey.findKey(availableETypes[0], keys);
+ if (tktETypes.length > 0) {
+ key = EncryptionKey.findKey(tktETypes[0], keys);
}
}
if (DEBUG) {
@@ -384,7 +376,7 @@
}
if (eTypes == null) {
- eTypes = EType.getDefaults("default_tkt_enctypes");
+ eTypes = tktETypes;
}
// check to use addresses in tickets
--- a/jdk/src/share/classes/sun/security/krb5/internal/KRBError.java Wed Jun 16 14:07:47 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KRBError.java Thu Jun 17 13:46:15 2010 +0800
@@ -286,6 +286,19 @@
salt = info.getSalt();
if (DEBUG) {
System.out.println("\t PA-ETYPE-INFO etype = " + etype);
+ System.out.println("\t PA-ETYPE-INFO salt = " + salt);
+ }
+ while (der.data.available() > 0) {
+ value = der.data.getDerValue();
+ info = new ETypeInfo(value);
+ if (DEBUG) {
+ etype = info.getEType();
+ System.out.println("\t salt for " + etype
+ + " is " + info.getSalt());
+ }
+ if (salt == null || salt.isEmpty()) {
+ salt = info.getSalt();
+ }
}
}
break;
@@ -299,6 +312,19 @@
s2kparams = info2.getParams();
if (DEBUG) {
System.out.println("\t PA-ETYPE-INFO2 etype = " + etype);
+ System.out.println("\t PA-ETYPE-INFO salt = " + salt);
+ }
+ while (der.data.available() > 0) {
+ value = der.data.getDerValue();
+ info2 = new ETypeInfo2(value);
+ if (DEBUG) {
+ etype = info2.getEType();
+ System.out.println("\t salt for " + etype
+ + " is " + info2.getSalt());
+ }
+ if (salt == null || salt.isEmpty()) {
+ salt = info2.getSalt();
+ }
}
}
break;
--- a/jdk/src/windows/classes/sun/security/krb5/internal/tools/Kinit.java Wed Jun 16 14:07:47 2010 -0700
+++ b/jdk/src/windows/classes/sun/security/krb5/internal/tools/Kinit.java Thu Jun 17 13:46:15 2010 +0800
@@ -229,9 +229,7 @@
if (useKeytab) {
as_req = new KrbAsReq(skeys, opt,
principal, sname,
- null, null, null,
- EncryptionKey.getETypes(skeys),
- addresses, null);
+ null, null, null, null, addresses, null);
} else {
as_req = new KrbAsReq(psswd, opt,
principal, sname,
@@ -259,9 +257,7 @@
if (useKeytab) {
as_req = new KrbAsReq(skeys, true, etype, salt,
s2kparams, opt, principal, sname,
- null, null, null,
- EncryptionKey.getETypes(skeys),
- addresses, null);
+ null, null, null, null, addresses, null);
} else {
as_req = new KrbAsReq(psswd, true, etype, salt,
s2kparams, opt, principal, sname,
--- a/jdk/test/sun/security/krb5/auto/KDC.java Wed Jun 16 14:07:47 2010 -0700
+++ b/jdk/test/sun/security/krb5/auto/KDC.java Thu Jun 17 13:46:15 2010 +0800
@@ -155,9 +155,13 @@
*/
PREAUTH_REQUIRED,
/**
- * Onlyy issue TGT in RC4
+ * Only issue TGT in RC4
*/
ONLY_RC4_TGT,
+ /**
+ * Only use RC4 in preauth, enc-type still using eTypes[0]
+ */
+ ONLY_RC4_PREAUTH,
};
static {
@@ -905,7 +909,11 @@
ke.returnCode() == Krb5.KDC_ERR_PREAUTH_FAILED) {
PAData pa;
- ETypeInfo2 ei2 = new ETypeInfo2(eTypes[0], null, null);
+ int epa = eTypes[0];
+ if (options.containsKey(KDC.Option.ONLY_RC4_PREAUTH)) {
+ epa = EncryptedData.ETYPE_ARCFOUR_HMAC;
+ }
+ ETypeInfo2 ei2 = new ETypeInfo2(epa, null, null);
DerOutputStream eid = new DerOutputStream();
eid.write(DerValue.tag_Sequence, ei2.asn1Encode());
@@ -924,7 +932,7 @@
}
}
if (allOld) {
- ETypeInfo ei = new ETypeInfo(eTypes[0], null);
+ ETypeInfo ei = new ETypeInfo(epa, null);
eid = new DerOutputStream();
eid.write(DerValue.tag_Sequence, ei.asn1Encode());
pa = new PAData(Krb5.PA_ETYPE_INFO, eid.toByteArray());
--- a/jdk/test/sun/security/krb5/auto/W83.java Wed Jun 16 14:07:47 2010 -0700
+++ b/jdk/test/sun/security/krb5/auto/W83.java Thu Jun 17 13:46:15 2010 +0800
@@ -23,8 +23,9 @@
/*
* @test
- * @bug 6951366
+ * @bug 6932525 6951366 6959292
* @summary kerberos login failure on win2008 with AD set to win2000 compat mode
+ * and cannot login if session key and preauth does not use the same etype
*/
import com.sun.security.auth.module.Krb5LoginModule;
import java.io.File;
@@ -52,8 +53,6 @@
new File(OneKDC.KRB5_CONF).deleteOnExit();
new File(OneKDC.KTAB).deleteOnExit();
- kdc.setOption(KDC.Option.ONLY_RC4_TGT, true);
-
KeyTab ktab = KeyTab.getInstance(OneKDC.KTAB);
for (int etype: EType.getBuiltInDefaults()) {
if (etype != EncryptedData.ETYPE_ARCFOUR_HMAC) {
@@ -61,6 +60,15 @@
}
}
ktab.save();
+
+ // For 6932525 and 6951366, make sure the etypes sent in 2nd AS-REQ
+ // is not restricted to that of preauth
+ kdc.setOption(KDC.Option.ONLY_RC4_TGT, true);
+ x.go();
+
+ // For 6959292, make sure that when etype for enc-part in 2nd AS-REQ
+ // is different from that of preauth, client can still decrypt it
+ kdc.setOption(KDC.Option.ONLY_RC4_PREAUTH, true);
x.go();
}