[JDK-8223172] Incomplete/Unusable Kerberos Cross-Realm Referrals Support

Osipov, Michael michael.osipov at siemens.com
Thu Oct 10 15:09:48 UTC 2019


Mi Max,

looking at the commit, I see only this being relevant:
> +        ReferralsState() throws KrbException {
> +            if (Config.DISABLE_REFERRALS) {
> +                if (cname.getNameType() == PrincipalName.KRB_NT_ENTERPRISE) {
> +                    throw new KrbException("NT-ENTERPRISE principals only allowed" +
> +                            " when referrals are enabled.");
> +                }
> +                enabled = false;
> +            } else {
> +                enabled = true;
> +            }
> +            refreshComm = true;
> +        }

but I see no way to set cname with that name type.

Anyway, the change provided by Martin Balao is merely limited to the 
Kerberos mechanism and does no export any of those changes upto the JGSS 
interface.
I am excited to see these next steps.

My use case is the following: one upcoming application will require a 
change in authentication layers with two phases where phase two might or 
might not happen.

All changes happen on already existing code which works with Java for 
the last 8+ years and are freely available under ALv2.

Phase 1: A webapp (REST API) hosted on Tomcat shall support either 
optional certificate-based and/or mandatory SPNEGO-based authentication.
With SPNEGO I get the GSS name from the context, with the OID 
KRB5_NT_PRINCIPAL: 1.2.840.113554.1.2.2.1. Windows always canonicalizes 
and all Unix servers have "canonicalize = true" set.
With certificates we don't have a GSS name, but we use then SAN which 
contains SSL_CLIENT_SAN_Email_0 and SSL_CLIENT_SAN_OTHER_msUPN_0. We 
care for the UPN only which maps to AD's userPrincipalName attribute 
with the OID 1.3.6.1.4.1.311.20.2.3. Though, this OID does not exist in 
Kerberos space we can map it to KRB5_NT_ENTERPRISE_PRINCIPAL: 
1.2.840.113554.1.2.2.6 because in AD it is the same value. Similar to he 
MS-PAC data .

With this GSS name which can be distinguished by OID I can feed Tomcat's 
Realm#authenticate(GSSName, GSSCredential) (in development by me [1]).
My realm impl ActiveDirectoryRealm will happily pass this GSS name to a
UsernameSearchMapper [2] which will tell the realm how to search for 
this principal. The OID-based support is not there yet, but is trivial 
to implement.

After all that I can easily locate the user in the tree and read out all 
AD attributes including security groups.

Without the KRB5_NT_ENTERPRISE_PRINCIPAL OID I cannot construct the GSS 
name from the cert and reuse it properly. As I have mentioned one can 
write a WrappedGSSName, but that's ugly.

Phase 2: reuse the supplied principal to use S4U2 which may or may not 
be used. So this is optional.
The GSS name will be crucial here because when S4U2proxy will have the 
enterprise principal from the cert, it will fail with unsupported OID.

I would have to perform another AD search to construct the Kerberos 
principal or normalize in phase one to regular principals and throw away 
the enterprise principals which I don't want to do.

Side note: I still run on Java 8 and Java 11 won't happen that fast 
here. Cross-realm referrals were solved with krb5.conf in previous 
years. In AD terms, you can use enterprise principals w/o following 
referrals in my opinions if and only if the principal is in the same 
realm and the machine you are logged in.

Michael

[1] 
https://github.com/apache/tomcat/commit/6be96ebba4e7056d5c9621bada2c496f8c0a82d0
[2] 
http://tomcatspnegoad.sourceforge.net/xref/net/sf/michaelo/tomcat/realm/mapper/UsernameSearchMapper.html#UsernameSearchMapper

Am 2019-10-10 um 04:47 schrieb Weijun Wang:
> Hi Michael,
> 
> Thanks for trying this new feature, you are always the first one.
> 
> If I remember correctly, when Martin developed this new feature, he was thinking of adding as little as possible spec change at the beginning. Therefore although there is a new KerberosPrincipal::KRB_NT_ENTERPRISE constant, it was just an integer and anyone can hardcode it. His next steps will be `kinit -e` and a new Krb5LoginModule option.
> 
> And welcome to provide more detail on your usecase.
> 
> --Max
> 
>> On Sep 26, 2019, at 5:27 AM, Osipov, Michael <michael.osipov at siemens.com> wrote:
>>
>> Hi folks,
>>
>> apologies upfront that I wasn't able when Martin Balao asked for a review of the code. I finally made to test it and cannot see that it is working anyhow here.
>>
>> I won't dive into my usecase now, but will depict two simple cases which are not possible.
>>
>> All tests were performed with Oracle JDK 13 on Windows 7:
>>> java version "13" 2019-09-17
>>> Java(TM) SE Runtime Environment (build 13+33)
>>> Java HotSpot(TM) 64-Bit Server VM (build 13+33, mixed mode, sharing)
>>
>> 1. kinit (JDK bundled) does not work. It does neither provide an '-E' option, nor does it send NT-ENTERPRISE, but only NT-UNKNOWN:
>>
>>> 0000   30 25 a0 03 02 01 00 a1 1e 30 1c 1b 1a 6d 69 63   0%.......0...mic
>>> 0010   68 61 65 6c 2e 6f 73 69 70 6f 76 40 73 69 65 6d   hael.osipov at siem
>>> 0020   65 6e 73 2e 63 6f 6d                              ens.com
>>
>> In byte 0x06 is the name type NT-UNKNOWN (0). In contrast to this with MIT Kerberos 1.17 and 'kinit -E' I see in Wireshark:
>>
>>> 0000   30 25 a0 03 02 01 0a a1 1e 30 1c 1b 1a 6d 69 63   0%.......0...mic
>>> 0010   68 61 65 6c 2e 6f 73 69 70 6f 76 40 73 69 65 6d   hael.osipov at siem
>>> 0020   65 6e 73 2e 63 6f 6d                              ens.com
>>
>> byte 0x06 is now name type NT-ENTERPRISE-PRINCIPAL (10).
>>
>> Trying the very same with LSA on Windows with "run as user" I get for my implicit UPN osipovmi at AD001.SIEMENS.NET always type 10. It only uses NT-PRINCIPAL when I provide the local part (samAccountName).
>>
>> 2. Using the appropriate OID for the enterprise principal:
>>
>>> 	public static void main(String[] args) throws GSSException {
>>> 		GSSManager m = GSSManager.getInstance();
>>> 		Oid msUpnOid = new Oid("1.3.6.1.4.1.311.20.2.3");
>>> 		Oid krb5PrincipalOid = new Oid("1.2.840.113554.1.2.2.1");
>>> 		Oid krb5EnterprisePrincialOid = new Oid("1.2.840.113554.1.2.2.6");
>>> 		Oid krb5MechOid = new Oid("1.2.840.113554.1.2.2");
>>> 		GSSName upn = m.createName("michael.osipov at siemens.com", krb5EnterprisePrincialOid);
>>> 	}
>>
>> gives me:
>>> Exception in thread "main" GSSException: Name of unsupported type provided (Mechanism level: 1.2.840.113554.1.2.2.6 is an unsupported nametype)
>>> 	at java.security.jgss/sun.security.jgss.krb5.Krb5NameElement.getInstance(Krb5NameElement.java:87)
>>> 	at java.security.jgss/sun.security.jgss.krb5.Krb5MechFactory.getNameElement(Krb5MechFactory.java:99)
>>> 	at java.security.jgss/sun.security.jgss.GSSManagerImpl.getNameElement(GSSManagerImpl.java:184)
>>> 	at java.security.jgss/sun.security.jgss.GSSNameImpl.getElement(GSSNameImpl.java:478)
>>> 	at java.security.jgss/sun.security.jgss.GSSNameImpl.init(GSSNameImpl.java:201)
>>> 	at java.security.jgss/sun.security.jgss.GSSNameImpl.<init>(GSSNameImpl.java:170)
>>> 	at java.security.jgss/sun.security.jgss.GSSNameImpl.<init>(GSSNameImpl.java:151)
>>> 	at java.security.jgss/sun.security.jgss.GSSManagerImpl.createName(GSSManagerImpl.java:109)
>>> 	at com.siemens.dynamowerk.Main.main(Main.java:20)
>>
>> and yes, the OID has never been defined in that class [1], but is present in MIT Kerberos [2].
>>
>> I haven't tried a programmatical kinit, but as mentioned in the notes [3], Krb5LoginModule does not support it, so I don't even have to try.
>>
>>
>> Any insights?
>>
>> Beside that, it'd be very cool if this gets into 11u or better yet to 8u. I have talked with Weijun about this several times many years ago for Java 7+. I have no option to use anything else, but Java 8 for now.
>>
>> If someone  wants to know better about my usecase, I'd be happy to lay it out in detail. I do need at least krb5EnterprisePrincialOid and better msUpnOid for my usecase.
>>
>> The only option I see now is to write a delegating wrapper for this:
>>
>>> GSSName upn = m.createName("michael.osipov at siemens.com", krb5PrincipalOid);
>>> GSSName wrappedUpn = new WrappedGSSName(upn, krb5EnterprisePrincialOid);
>>> System.out.println(wrappedUpn);
>>> System.out.println(wrappedUpn.getStringNameType());
>>
>>> michael.osipov at siemens.com
>>> 1.2.840.113554.1.2.2.6
>>
>> Michael
>>
>> [1] https://github.com/AdoptOpenJDK/openjdk-jdk13u/blob/bb0786d980437800b9d6efe17e42d18241714ea1/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java#L51-L61
>> [2] https://web.mit.edu/kerberos/krb5-devel/doc/appdev/gssapi.html
>> [3] http://mail.openjdk.java.net/pipermail/security-dev/2018-December/018952.html
> 



More information about the security-dev mailing list