< prev index next >
src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java
Print this page
@@ -29,28 +29,46 @@
*/
package sun.security.krb5;
import sun.security.krb5.internal.*;
+import sun.security.krb5.internal.crypto.KeyUsage;
+import sun.security.util.DerInputStream;
abstract class KrbKdcRep {
static void check(
boolean isAsReq,
KDCReq req,
- KDCRep rep
+ KDCRep rep,
+ EncryptionKey replyKey
) throws KrbApErrException {
- if (isAsReq && !req.reqBody.cname.equals(rep.cname)) {
+ // cname change in AS-REP is allowed only if the client
+ // sent CANONICALIZE and the server supports RFC 6806 - Section 11
+ // FAST scheme (ENC-PA-REP flag).
+ if (isAsReq && !req.reqBody.cname.equals(rep.cname) &&
+ (!req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) ||
+ !rep.encKDCRepPart.flags.get(Krb5.TKT_OPTS_ENC_PA_REP))) {
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
+ // sname change in TGS-REP is allowed only if client
+ // sent CANONICALIZE and new sname is a referral of
+ // the form krbtgt/TO-REALM.COM@FROM-REALM.COM.
if (!req.reqBody.sname.equals(rep.encKDCRepPart.sname)) {
+ String[] snameStrings = rep.encKDCRepPart.sname.getNameStrings();
+ if (isAsReq || !req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) ||
+ snameStrings == null || snameStrings.length != 2 ||
+ !snameStrings[0].equals(PrincipalName.TGS_DEFAULT_SRV_NAME) ||
+ !rep.encKDCRepPart.sname.getRealmString().equals(
+ req.reqBody.sname.getRealmString())) {
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
+ }
if (req.reqBody.getNonce() != rep.encKDCRepPart.nonce) {
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
@@ -116,7 +134,42 @@
rep.encKDCRepPart.key.destroy();
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
}
}
+
+ // RFC 6806 - Section 11 mechanism check
+ if (rep.encKDCRepPart.flags.get(Krb5.TKT_OPTS_ENC_PA_REP) &&
+ req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE)) {
+ boolean reqPaReqEncPaRep = false;
+ boolean repPaReqEncPaRepValid = false;
+
+ // PA_REQ_ENC_PA_REP only required for AS requests
+ for (PAData pa : req.pAData) {
+ if (pa.getType() == Krb5.PA_REQ_ENC_PA_REP) {
+ reqPaReqEncPaRep = true;
+ break;
+ }
+ }
+
+ for (PAData pa : rep.encKDCRepPart.pAData) {
+ if (pa.getType() == Krb5.PA_REQ_ENC_PA_REP) {
+ try {
+ Checksum repCksum = new Checksum(
+ new DerInputStream(pa.getValue()).getDerValue());
+ repPaReqEncPaRepValid = repCksum.verifyKeyedChecksum(
+ req.asn1Encode(), replyKey, KeyUsage.KU_AS_REQ);
+ } catch (Exception e) {
+ if (Krb5.DEBUG) {
+ e.printStackTrace();
+ }
+ }
+ break;
+ }
+ }
+
+ if (reqPaReqEncPaRep && !repPaReqEncPaRepValid) {
+ throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
+ }
+ }
}
}
< prev index next >