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, [email protected] 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

Reply via email to