< prev index next >
test/jdk/sun/security/krb5/auto/KDC.java
Print this page
rev 54745 : 8215032: Support Kerberos cross-realm referrals (RFC 6806)
Reviewed-by: weijun
@@ -163,10 +163,18 @@
// different s2kparams for different etypes, pretend they are the same
// at the moment.
private TreeMap<String,byte[]> s2kparamses = new TreeMap<>
(String.CASE_INSENSITIVE_ORDER);
+ // Alias for referrals.
+ private TreeMap<String,KDC> aliasReferrals = new TreeMap<>
+ (String.CASE_INSENSITIVE_ORDER);
+
+ // Alias for local resolution.
+ private TreeMap<String,PrincipalName> alias2Principals = new TreeMap<>
+ (String.CASE_INSENSITIVE_ORDER);
+
// Realm name
private String realm;
// KDC
private String kdc;
// Service port number
@@ -551,10 +559,33 @@
*/
public int getPort() {
return port;
}
+ /**
+ * Register an alias name to be referred to a different KDC for
+ * resolution, according to RFC 6806.
+ * @param alias Alias name (i.e. user@REALM.COM).
+ * @param referredKDC KDC to which the alias is referred for resolution.
+ */
+ public void registerAlias(String alias, KDC referredKDC) {
+ aliasReferrals.remove(alias);
+ aliasReferrals.put(alias, referredKDC);
+ }
+
+ /**
+ * Register an alias to be resolved to a Principal Name locally,
+ * according to RFC 6806.
+ * @param alias Alias name (i.e. user@REALM.COM).
+ * @param user Principal Name to which the alias is resolved.
+ */
+ public void registerAlias(String alias, String user)
+ throws RealmException {
+ alias2Principals.remove(alias);
+ alias2Principals.put(alias, new PrincipalName(user));
+ }
+
// Private helper methods
/**
* Private constructor, cannot be called outside.
* @param realm
@@ -776,10 +807,21 @@
EncTicketPart etp = null;
PrincipalName cname = null;
boolean allowForwardable = true;
+ if (body.kdcOptions.get(KDCOptions.CANONICALIZE)) {
+ KDC referral = aliasReferrals.get(body.sname.getNameString());
+ if (referral != null) {
+ service = new PrincipalName(
+ PrincipalName.TGS_DEFAULT_SRV_NAME +
+ PrincipalName.NAME_COMPONENT_SEPARATOR_STR +
+ referral.getRealm(), PrincipalName.KRB_NT_SRV_INST,
+ this.getRealm());
+ }
+ }
+
if (pas == null || pas.length == 0) {
throw new KrbException(Krb5.KDC_ERR_PADATA_TYPE_NOSUPP);
} else {
PrincipalName forUserCName = null;
for (PAData pa: pas) {
@@ -962,11 +1004,12 @@
tFlags,
timeAfter(0),
from,
till, renewTill,
service,
- body.addresses
+ body.addresses,
+ null
);
EncryptedData edata = new EncryptedData(ckey, enc_part.asn1Encode(),
KeyUsage.KU_ENC_TGS_REP_PART_SESSKEY);
TGSRep tgsRep = new TGSRep(null,
cname,
@@ -1006,10 +1049,11 @@
* @return the response
* @throws java.lang.Exception for various errors
*/
protected byte[] processAsReq(byte[] in) throws Exception {
ASReq asReq = new ASReq(in);
+ byte[] asReqbytes = asReq.asn1Encode();
int[] eTypes = null;
List<PAData> outPAs = new ArrayList<>();
PrincipalName service = asReq.reqBody.sname;
if (options.containsKey(KDC.Option.RESP_NT)) {
@@ -1028,10 +1072,28 @@
if (eTypes.length == 0) {
throw new KrbException(Krb5.KDC_ERR_ETYPE_NOSUPP);
}
int eType = eTypes[0];
+ if (body.kdcOptions.get(KDCOptions.CANONICALIZE) &&
+ body.cname.getNameType() == PrincipalName.KRB_NT_ENTERPRISE) {
+ PrincipalName principal = alias2Principals.get(
+ body.cname.getNameString());
+ if (principal != null) {
+ body.cname = principal;
+ } else {
+ KDC referral = aliasReferrals.get(body.cname.getNameString());
+ if (referral != null) {
+ body.cname = new PrincipalName(
+ PrincipalName.TGS_DEFAULT_SRV_NAME,
+ PrincipalName.KRB_NT_SRV_INST,
+ referral.getRealm());
+ throw new KrbException(Krb5.KRB_ERR_WRONG_REALM);
+ }
+ }
+ }
+
EncryptionKey ckey = keyForUser(body.cname, eType, false);
EncryptionKey skey = keyForUser(service, eType, true);
if (options.containsKey(KDC.Option.ONLY_RC4_TGT)) {
int tgtEType = EncryptedData.ETYPE_ARCFOUR_HMAC;
@@ -1209,28 +1271,40 @@
eid.putSequence(pas);
outPAs.add(new PAData(Krb5.PA_ETYPE_INFO, eid.toByteArray()));
}
PAData[] inPAs = KDCReqDotPAData(asReq);
+ List<PAData> enc_outPAs = new ArrayList<>();
if (inPAs == null || inPAs.length == 0) {
Object preauth = options.get(Option.PREAUTH_REQUIRED);
if (preauth == null || preauth.equals(Boolean.TRUE)) {
throw new KrbException(Krb5.KDC_ERR_PREAUTH_REQUIRED);
}
} else {
+ EncryptionKey pakey = null;
try {
EncryptedData data = newEncryptedData(
new DerValue(inPAs[0].getValue()));
- EncryptionKey pakey
- = keyForUser(body.cname, data.getEType(), false);
+ pakey = keyForUser(body.cname, data.getEType(), false);
data.decrypt(pakey, KeyUsage.KU_PA_ENC_TS);
} catch (Exception e) {
KrbException ke = new KrbException(Krb5.KDC_ERR_PREAUTH_FAILED);
ke.initCause(e);
throw ke;
}
bFlags[Krb5.TKT_OPTS_PRE_AUTHENT] = true;
+ for (PAData pa : inPAs) {
+ if (pa.getType() == Krb5.PA_REQ_ENC_PA_REP) {
+ Checksum ckSum = new Checksum(
+ Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128,
+ asReqbytes, ckey, KeyUsage.KU_AS_REQ);
+ enc_outPAs.add(new PAData(Krb5.PA_REQ_ENC_PA_REP,
+ ckSum.asn1Encode()));
+ bFlags[Krb5.TKT_OPTS_ENC_PA_REP] = true;
+ break;
+ }
+ }
}
TicketFlags tFlags = new TicketFlags(bFlags);
EncTicketPart enc = new EncTicketPart(
tFlags,
@@ -1257,11 +1331,12 @@
tFlags,
timeAfter(0),
from,
till, rtime,
service,
- body.addresses
+ body.addresses,
+ enc_outPAs.toArray(new PAData[enc_outPAs.size()])
);
EncryptedData edata = new EncryptedData(ckey, enc_part.asn1Encode(),
KeyUsage.KU_ENC_AS_REP_PART);
ASRep asRep = new ASRep(
outPAs.toArray(new PAData[outPAs.size()]),
@@ -1305,12 +1380,14 @@
+ " " +ke.returnCodeMessage());
byte[] eData = null;
if (kerr == null) {
if (ke.returnCode() == Krb5.KDC_ERR_PREAUTH_REQUIRED ||
ke.returnCode() == Krb5.KDC_ERR_PREAUTH_FAILED) {
+ outPAs.add(new PAData(Krb5.PA_ENC_TIMESTAMP, new byte[0]));
+ }
+ if (outPAs.size() > 0) {
DerOutputStream bytes = new DerOutputStream();
- bytes.write(new PAData(Krb5.PA_ENC_TIMESTAMP, new byte[0]).asn1Encode());
for (PAData p: outPAs) {
bytes.write(p.asn1Encode());
}
DerOutputStream temp = new DerOutputStream();
temp.write(DerValue.tag_Sequence, bytes);
< prev index next >