On Fri, Dec 07, 2018 at 10:45:02AM +0800, Weijun Wang wrote: > Your detailed analysis is very valuable and I've included the whole text into > https://bugs.openjdk.java.net/browse/JDK-8214988. I knew GSSName was > complicated at the beginning and I remember I've especially asked you to look > at it in my initial code review request. I think I have a better > understanding now but unfortunately we are not likely to fix the native > library very soon since RDP 1 for JDK 12 is near [1].
If we could apply OOP to a GSSv3 abstract API we'd say that a NAME has a subclass called CANONICAL_NAME. This would allow us to declare that canonicalizing a name and inquiring a securoty context output only CANONICAL_NAMEs. (For those following along, the GSS-API has an "abstract" API defined in RFC 2743, and then bindings for various programming languages. The Java GSSName class is called NAME in the abstract API.) > Let's come back to this bug. Yesterday I sent out a plan (pasted below): OK. > > Since GSSName::isMN is always true, every gss_name_t must be a MN and I > > decide the name to be always krb5 style and the type to be always > > NT_KRB5_NAME. However, somewhere in the JGSS native bridge implementation > > the name and type are cached on the Java side, therefore the result of > > gSSMananger.createName("service@host", NT_HOSTBASED_SERVICE) does have > > toString() being service@host and type being NT_HOSTBASED_SERVICE. When > > canonicalize() is called, even if the GSS-API canonicalize_name() is not > > called a new gss_name_t is created and the Java side cache will be > > recreated, and this time name becomes service/host and type becomes > > NT_KRB5_NAME. > > > > Is this what you like to see? Yes it is! > > As for export(), I can also output a/b@. When the result is imported as a > > NT_EXPORT_NAME, I'll remember to remove the @ at the end. Exported name tokens and the "empty realm" thing don't play well: they won't memcmp() equal to any exported name tokens exported from a name output by gss_accept_sec_context() or gss_inquire_context(). The only way to compare such a name would be to import() it and then use equals(). This is a symptom of gss_canonicalize_name() being a bad interface. In Kerberos the only reliable way to canonicalize a non-MN is to call gss_init_sec_context(), inquire the security context to get the target's canonical name, then throw away the context and initial security token. This trick would not work for PKU2U or the Globus mechanism. Of course, you still need a credential handle to init with, so you'll use the default credential because gss_canonicalize_name() doesn't have an input credential handle :( > > The result is: > > > > GSSManager m = GSSManager.getInstance(); > > GSSName n = m.createName("service@host", GSSName.NT_HOSTBASED_SERVICE); > > // n is now (service@host, NT_HOSTBASED_SERVICE) > > n = n.canonicalize(new Oid("1.2.840.113554.1.2.2")); > > // n is now (service/host, NT_KRB5_NAME) > > byte[] x = n.export(); > > // 0000: 04 01 00 0B 06 09 2A 86 48 86 F7 12 01 02 02 00 > > ......*.H....... > > // 0010: 00 00 0D 73 65 72 76 69 63 65 2F 68 6F 73 74 40 > > ...service/host@ > > n = m.createName(x, GSSName.NT_EXPORT_NAME); > > // n is now (service/host, NT_KRB5_NAME) > > I think the result is quite good. It's like the native bridge itself has > stored a non-MN (except that its isMN() is true) although inside the new > library there is only MN. Yes, it's looking good. > And you mentioned about ServicePermission check, this means I cannot export > a/b@ only and the realm is needed. The latest webrev is at At some point we need to talk about revamping ServicePermission. What I'd suggest is that we say that ServicePermission is intended to work with any mechanism that supports GSS_C_NT_USERNAME and GSS_C_NT_HOSTBASED_SERVICE, and any other name type that can be mapped onto Kerberos naming style, and that in ServicePermission names are Kerberos style. We could add a ServicePermission() constructor that takes a GSS name-type Oid and a generic syntax name and then maps to Kerberos style names. And we could add a GSSName and GSSNameSpi methods to get Kerberos-style name forms for any non-Kerberos mechanism. Then we could say that an empty realm in a ServicePermission matches any realm. (Kerberos actually has a notion of X.500-style realm names too, so we could even have that in ServicePermission for any GSS mechanisms that use PKIX.) > https://cr.openjdk.java.net/~weijun/6722928/webrev.02/ > > Any other comment? You said you wanted to check the krb5 <-> SPNEGO > token translation codes. I'll need a bit more time to do a thorough review. Nico --