Hi,<br><br>After reading the JDK6 code regarding JGSS and Kerberos 5 (Krb5LoginModule) I came to the conclusion that<br><br>you can not use more than one Login-Module in the login configuration entry named "com.sun.security.jgss.accept".<br>
<br>This entry is used to specify the principal name, the keytab location, etc....<br><br>My question is:<br>    Why limit it to one login module?<br>    If so, we should definitely throw a warning regarding the presence of more then one module.<br>
<br><br>Explanation:<br><br><br>*Background*<br>    Suppose we a have JBoss application server, and a client which uses Windows.<br>    JBoss used the NEGOTIATE protocol to receive a Service Ticket. <br>    Using sun implementation of JGSS, and Kerberos, I could connect to the Active Directory (KDC) and validate the Session Ticket.<br>
    I'm using JDK 1.5, but reading sources of Open-JDK6 since only the latter is open source.<br><br>*The Steps Taken to validate the session ticket*<br>1. GSSManaget.getInstance() is executed, to get a GSSManager.<br>
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.<br>3. manager.createContext(cred) using the credentials created in step 2.<br>
4. context.acceptSecContext using the Session Ticket obtained from the NEGOTIATE protocol earlier.<br><br>*Using more then one login module - problem source*<br><br>Krb5Context.acceptSecContext() contains the following code:<br>
<br>if (myCred == null) {<br>                    myCred = Krb5AcceptCredential.getInstance(caller, myName);<br><br>myName instance variable is always null in this call, and never get a chance to initialize before the call.<br>
<br>Krb5AcceptCredential.getInstance() - browsing through this method shows that:<br><br>        final String serverPrinc = (name == null? null:<br>            name.getKrb5PrincipalName().getName());<br>        final AccessControlContext acc = AccessController.getContext();<br>
<br>        KerberosKey[] keys;<br>        try {<br>            keys = AccessController.doPrivileged(<br>                        new PrivilegedExceptionAction<KerberosKey[]>() {<br>                public KerberosKey[] run() throws Exception {<br>
                    return Krb5Util.getKeys(<br>                        caller == GSSUtil.CALLER_UNKNOWN ? GSSUtil.CALLER_ACCEPT: caller,<br>                        serverPrinc, acc);<br>                }});<br><br>This section obtains the Secret key for "serverPrinc" (service Principle) by running a JAAS login on "com.sun.security.jgss.accept" login-config. <br>
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.<br>
<br>the Krb5Util.getKeys() will perform the login process, and search the subject for a matching secret key, based on the principle name.<br><br>After that:<br>        if (name == null) {<br>            String fullName = keys[0].getPrincipal().getName();<br>
            name = Krb5NameElement.getInstance(fullName,<br>                                       Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL);<br>        }<br><br>        return new Krb5AcceptCredential(name, keys);<br><br>Since name is always null, it takes the first secret key it finds in the subject.<br>
<br><br>* The correction *<br>There should be a place to initialize the context with the principle name. <br>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:<br>
<br>Krb5Context.acceptSeContext()<br>...<br>                if (myCred == null) {<br>                    myCred = Krb5AcceptCredential.getInstance(caller, myName);<br>                } else if (!myCred.isAcceptorCredential()) {<br>
                    throw new GSSException(GSSException.NO_CRED, -1,<br>                                           "No Secret Key available");<br>                }<br>                myName = (Krb5NameElement) myCred.getName();<br>
<br>                checkPermission(myName.getKrb5PrincipalName().getName(),<br>                                "accept");<br><br>                EncryptionKey[] secretKeys =<br>                 ((Krb5AcceptCredential) myCred).getKrb5EncryptionKeys();<br>
...<br><br>If you pass GSSCredentials to GSSManaget.getContext(), it will not activate Krb5AcceptCredential.getInstance(caller, myName), which runs the login process.<br><br><br>Thank you,<br><br>Asaf Mesika<br><br><br>