6959292: regression: cannot login if session key and preauth does not use the same etype
Reviewed-by: xuelei, valeriep
This commit is contained in:
parent
ce4febb72c
commit
5141220c5e
@ -356,7 +356,6 @@ public class Credentials {
|
||||
* @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 @@ public class Credentials {
|
||||
"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 @@ public class Credentials {
|
||||
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 @@ public class Credentials {
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
||||
|
@ -76,26 +76,6 @@ public class EncryptionKey
|
||||
|
||||
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 @@ public class EncryptionKey
|
||||
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) {
|
||||
|
@ -35,9 +35,11 @@ import sun.security.krb5.internal.*;
|
||||
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 @@ public class KrbAsReq extends KrbKdcReq {
|
||||
|
||||
/**
|
||||
* 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 @@ public class KrbAsReq extends KrbKdcReq {
|
||||
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 @@ public class KrbAsReq extends KrbKdcReq {
|
||||
/**
|
||||
* 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 @@ public class KrbAsReq extends KrbKdcReq {
|
||||
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 @@ public class KrbAsReq extends KrbKdcReq {
|
||||
}
|
||||
|
||||
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 @@ public class KrbAsReq extends KrbKdcReq {
|
||||
}
|
||||
|
||||
if (eTypes == null) {
|
||||
eTypes = EType.getDefaults("default_tkt_enctypes");
|
||||
eTypes = tktETypes;
|
||||
}
|
||||
|
||||
// check to use addresses in tickets
|
||||
|
@ -286,6 +286,19 @@ public class KRBError implements java.io.Serializable {
|
||||
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 @@ public class KRBError implements java.io.Serializable {
|
||||
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;
|
||||
|
@ -229,9 +229,7 @@ public class Kinit {
|
||||
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 @@ public class Kinit {
|
||||
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,
|
||||
|
@ -155,9 +155,13 @@ public class KDC {
|
||||
*/
|
||||
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 @@ public class KDC {
|
||||
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 @@ public class KDC {
|
||||
}
|
||||
}
|
||||
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());
|
||||
|
@ -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 @@ public class W83 {
|
||||
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 @@ public class W83 {
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user