[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