[PATCH] 8005819: Support cross-realm MSSFU

richard at pointon.org.uk richard at pointon.org.uk
Tue Mar 28 16:59:20 UTC 2017


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