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
-- 

Reply via email to