[PATCH] 8005819: Support cross-realm MSSFU
Weijun Wang
weijun.wang at oracle.com
Tue Mar 28 23:25:00 UTC 2017
Hi Richard
I'll look into it. I used to think Kerberos referral is a must to
support cross-realm MSSFU but I could be wrong.
What platforms have you tested this on? MSAD? MIT krb5?
Two reminders:
1. We don't have time for JDK 9 now. So this can only go into JDK 10.
2. Have you signed the Oracle Contribution Agreement at
http://www.oracle.com/technetwork/community/oca-486395.html?
Thanks
Max
On 03/29/2017 12:59 AM, richard at pointon.org.uk wrote:
> Hi,
>
> I have developed a fix for the lack of cross-realm S4USelf support in
> OpenJDK 8 which I would like to contribute.
>
> The fix does not address realm referral as discussed in the bug and so
> requires both realms to be present in the krb5.conf file.
>
>
> Bug: https://bugs.openjdk.java.net/browse/JDK-8005819
>
> Diff:
>
> ---
> ../jdk8u/jdk/src/share/classes/sun/security/krb5/internal/CredentialsUtil.java
> 2016-08-22 15:58:34.720949000 +0100
> +++
> ../jdkpatch/jdk/src/share/classes/sun/security/krb5/internal/CredentialsUtil.java
> 2016-09-16 15:11:02.967278000 +0100
> @@ -54,19 +54,57 @@
> Credentials ccreds) throws KrbException, IOException {
> String uRealm = client.getRealmString();
> String localRealm = ccreds.getClient().getRealmString();
> + KrbTgsReq req;
> if (!uRealm.equals(localRealm)) {
> - // TODO: we do not support kerberos referral now
> - throw new KrbException("Cross realm impersonation not
> supported");
> + //get a cross realm TGT
> + String tname = PrincipalName.TGS_DEFAULT_SRV_NAME +
> PrincipalName.NAME_COMPONENT_SEPARATOR_STR +
> + uRealm + PrincipalName.NAME_REALM_SEPARATOR_STR +
> uRealm;
> +
> + Credentials foreignTGT = acquireServiceCreds(tname, ccreds);
> +
> + //get a referral TGT from the foreign realm for the user
> + String [] svcUPN =
> ccreds.getClient().getNameStrings().clone();
> + svcUPN[svcUPN.length-1] +=
> PrincipalName.NAME_REALM_SEPARATOR_STR + localRealm;
> +
> + PrincipalName svcPrinc = new
> PrincipalName(PrincipalName.KRB_NT_ENTERPRISE, svcUPN, new Realm(uRealm));
> +
> + req = new KrbTgsReq(
> + foreignTGT,
> + svcPrinc,
> + new PAData(Krb5.PA_FOR_USER,
> + new PAForUserEnc(client,
> + foreignTGT.getSessionKey()).asn1Encode()),
> + client);
> +
> + if (!foreignTGT.isForwardable()) {
> + throw new KrbException("S4U2self needs a FORWARDABLE
> ticket");
> + }
> +
> + Credentials referralTGT = req.sendAndGetCreds();
> +
> + //create request to local realm for user in foreign realm
> using the referral TGT from the
> + //foreign realm
> + req = new KrbTgsReq(
> + referralTGT,
> + ccreds.getClient(),
> + new PAData(Krb5.PA_FOR_USER,
> + new PAForUserEnc(client,
> +
> referralTGT.getSessionKey()).asn1Encode()));
> }
> - if (!ccreds.isForwardable()) {
> - throw new KrbException("S4U2self needs a FORWARDABLE ticket");
> + else {
> + //same realm
> + req = new KrbTgsReq(
> + ccreds,
> + ccreds.getClient(),
> + new PAData(Krb5.PA_FOR_USER,
> + new PAForUserEnc(client,
> + ccreds.getSessionKey()).asn1Encode()));
> +
> + if (!ccreds.isForwardable()) {
> + throw new KrbException("S4U2self needs a FORWARDABLE
> ticket");
> + }
> }
> - KrbTgsReq req = new KrbTgsReq(
> - ccreds,
> - ccreds.getClient(),
> - new PAData(Krb5.PA_FOR_USER,
> - new PAForUserEnc(client,
> - ccreds.getSessionKey()).asn1Encode()));
> +
> Credentials creds = req.sendAndGetCreds();
> if (!creds.getClient().equals(client)) {
> throw new KrbException("S4U2self request not honored by KDC");
> --- ../jdk8u/jdk/src/share/classes/sun/security/krb5/KrbTgsReq.java
> 2016-08-22 15:58:34.718972000 +0100
> +++
> ../jdkpatch/jdk/src/share/classes/sun/security/krb5/KrbTgsReq.java
> 2016-09-16 15:11:02.979473000 +0100
> @@ -45,6 +45,7 @@
>
> private PrincipalName princName;
> private PrincipalName servName;
> + private PrincipalName targetName;
> private TGSReq tgsReqMessg;
> private KerberosTime ctime;
> private Ticket secondTicket = null;
> @@ -109,8 +110,31 @@
> null,
> null,
> null,
> - extraPA); // the PA-FOR-USER
> + extraPA,// the PA-FOR-USER
> + null);
> }
> +
> + public KrbTgsReq(Credentials asCreds,
> + PrincipalName sname,
> + PAData extraPA,
> + PrincipalName tname)
> + throws KrbException, IOException {
> + this(KDCOptions.with(KDCOptions.FORWARDABLE, KDCOptions.CANONICALIZE),
> + asCreds,
> + asCreds.getClient(),
> + sname,
> + null,
> + null,
> + null,
> + null,
> + null,
> + null,
> + null,
> + null,
> + extraPA,// the PA-FOR-USER
> + tname);
> + }
> +
>
> // Called by Credentials, KrbCred
> KrbTgsReq(
> @@ -127,7 +151,7 @@
> EncryptionKey subKey) throws KrbException, IOException {
> this(options, asCreds, asCreds.getClient(), sname,
> from, till, rtime, eTypes, addresses,
> - authorizationData, additionalTickets, subKey, null);
> + authorizationData, additionalTickets, subKey, null, null);
> }
>
> private KrbTgsReq(
> @@ -143,10 +167,12 @@
> AuthorizationData authorizationData,
> Ticket[] additionalTickets,
> EncryptionKey subKey,
> - PAData extraPA) throws KrbException, IOException {
> + PAData extraPA,
> + PrincipalName tname) throws KrbException, IOException {
>
> princName = cname;
> servName = sname;
> + targetName = tname;
> ctime = KerberosTime.now();
>
> // check if they are valid arguments. The optional fields
> @@ -240,8 +266,13 @@
> */
> public void send() throws IOException, KrbException {
> String realmStr = null;
> - if (servName != null)
> + if (targetName != null){
> + realmStr = targetName.getRealmString();
> + }
> + else if (servName != null) {
> realmStr = servName.getRealmString();
> + }
> +
> KdcComm comm = new KdcComm(realmStr);
> ibuf = comm.send(obuf);
> }
> --- ../jdk8u/jdk/src/share/classes/sun/security/krb5/KrbKdcRep.java
> 2016-08-22 15:58:34.801487000 +0100
> +++
> ../jdkpatch/jdk/src/share/classes/sun/security/krb5/KrbKdcRep.java
> 2016-09-16 15:11:02.986718000 +0100
> @@ -45,7 +45,8 @@
> throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
> }
>
> - if (!req.reqBody.sname.equals(rep.encKDCRepPart.sname)) {
> + if (!req.reqBody.kdcOptions.get(KDCOptions.CANONICALIZE) &&
> + !req.reqBody.sname.equals(rep.encKDCRepPart.sname)) {
> rep.encKDCRepPart.key.destroy();
> throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
> }
> ---
> ../jdk8u/jdk/src/share/classes/sun/security/krb5/internal/KDCOptions.java
> 2016-08-22 15:58:34.758240000 +0100
> +++
> ../jdkpatch/jdk/src/share/classes/sun/security/krb5/internal/KDCOptions.java
> 2016-09-16 15:11:02.990754000 +0100
> @@ -140,6 +140,7 @@
> public static final int UNUSED10 = 10;
> public static final int UNUSED11 = 11;
> public static final int CNAME_IN_ADDL_TKT = 14;
> + public static final int CANONICALIZE = 15;
> public static final int RENEWABLE_OK = 27;
> public static final int ENC_TKT_IN_SKEY = 28;
> public static final int RENEW = 30;
> @@ -160,7 +161,8 @@
> "UNUSED11", //11;
> null,null,
> "CNAME_IN_ADDL_TKT",//14;
> - null,null,null,null,null,null,null,null,null,null,null,null,
> + "CANONICALIZE", //15;
> + null,null,null,null,null,null,null,null,null,null,null,
> "RENEWABLE_OK", //27;
> "ENC_TKT_IN_SKEY", //28;
> null,
> ---
> ../jdk8u/jdk/src/share/classes/sun/security/krb5/PrincipalName.java
> 2016-08-22 15:58:34.708329000 +0100
> +++
> ../jdkpatch/jdk/src/share/classes/sun/security/krb5/PrincipalName.java 2016-09-16
> 15:11:02.995791000 +0100
> @@ -89,6 +89,11 @@
> * Unique ID
> */
> public static final int KRB_NT_UID = 5;
> +
> + /**
> + * Enterprise name; may be mapped to principal name
> + */
> + public static final int KRB_NT_ENTERPRISE = 10;
>
> /**
> * TGS Name
More information about the security-dev
mailing list