[security-dev 00115]: Multiple Login-Modules in com.sun.security.jgss.accept

Asaf Mesika asaf.mesika at gmail.com
Mon Mar 17 08:45:46 PDT 2008


Hi,

After reading the JDK6 code regarding JGSS and Kerberos 5 (Krb5LoginModule)
I came to the conclusion that

you can not use more than one Login-Module in the login configuration entry
named "com.sun.security.jgss.accept".

This entry is used to specify the principal name, the keytab location,
etc....

My question is:
    Why limit it to one login module?
    If so, we should definitely throw a warning regarding the presence of
more then one module.


Explanation:


*Background*
    Suppose we a have JBoss application server, and a client which uses
Windows.
    JBoss used the NEGOTIATE protocol to receive a Service Ticket.
    Using sun implementation of JGSS, and Kerberos, I could connect to the
Active Directory (KDC) and validate the Session Ticket.
    I'm using JDK 1.5, but reading sources of Open-JDK6 since only the
latter is open source.

*The Steps Taken to validate the session ticket*
1. GSSManaget.getInstance() is executed, to get a GSSManager.
2. manager.createCredential() is called, with null as GSSName and Oid, since
the name will be picked up by the JAAS login config. Oid is Kerberos 5 by
default.
3. manager.createContext(cred) using the credentials created in step 2.
4. context.acceptSecContext using the Session Ticket obtained from the
NEGOTIATE protocol earlier.

*Using more then one login module - problem source*

Krb5Context.acceptSecContext() contains the following code:

if (myCred == null) {
                    myCred = Krb5AcceptCredential.getInstance(caller,
myName);

myName instance variable is always null in this call, and never get a chance
to initialize before the call.

Krb5AcceptCredential.getInstance() - browsing through this method shows
that:

        final String serverPrinc = (name == null? null:
            name.getKrb5PrincipalName().getName());
        final AccessControlContext acc = AccessController.getContext();

        KerberosKey[] keys;
        try {
            keys = AccessController.doPrivileged(
                        new PrivilegedExceptionAction<KerberosKey[]>() {
                public KerberosKey[] run() throws Exception {
                    return Krb5Util.getKeys(
                        caller == GSSUtil.CALLER_UNKNOWN ?
GSSUtil.CALLER_ACCEPT: caller,
                        serverPrinc, acc);
                }});

This section obtains the Secret key for "serverPrinc" (service Principle) by
running a JAAS login on "com.sun.security.jgss.accept" login-config.
The login process, has no problem, if two login-modules (or more) are
defined in that login-configuration. It simply runs the login modules and
builds the subject. Each Krb5LoginModule adds the secret key and principle
name (as one object) to the subject.

the Krb5Util.getKeys() will perform the login process, and search the
subject for a matching secret key, based on the principle name.

After that:
        if (name == null) {
            String fullName = keys[0].getPrincipal().getName();
            name = Krb5NameElement.getInstance(fullName,
                                       Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL
);
        }

        return new Krb5AcceptCredential(name, keys);

Since name is always null, it takes the first secret key it finds in the
subject.


* The correction *
There should be a place to initialize the context with the principle name.
Intializing it with a GSSCredentials is not good enough since it cancel the
login process that uses "com.sun.security.jgss.accept", as this code
implies:

Krb5Context.acceptSeContext()
...
                if (myCred == null) {
                    myCred = Krb5AcceptCredential.getInstance(caller,
myName);
                } else if (!myCred.isAcceptorCredential()) {
                    throw new GSSException(GSSException.NO_CRED, -1,
                                           "No Secret Key available");
                }
                myName = (Krb5NameElement) myCred.getName();

                checkPermission(myName.getKrb5PrincipalName().getName(),
                                "accept");

                EncryptionKey[] secretKeys =
                 ((Krb5AcceptCredential) myCred).getKrb5EncryptionKeys();
...

If you pass GSSCredentials to GSSManaget.getContext(), it will not activate
Krb5AcceptCredential.getInstance(caller, myName), which runs the login
process.


Thank you,

Asaf Mesika
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/security-dev/attachments/20080317/a1903762/attachment.html 


More information about the security-dev mailing list