javakerberosjndijaasgssapi

Understanding and exploring how JAAS-GSSAPI-JNDI work together behind the hood


I have been trying to understand how these different APIs glue together behind the scenes. Though this question might seem to be a broad one, I also want to understand a particular scenario. Any pointers on this this can further be debugged will be appreciated.

I am following this basic tutorial - https://docs.oracle.com/javase/jndi/tutorial/ldap/security/src/Mutual.java

In this, I am particularly trying to understand, what this line actually means, during the creation of DirContext

// Request the use of the "GSSAPI" SASL mechanism Authenticate by using already established Kerberos credentials env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");

What are the high level steps done during the creation DirContext/LDAPContext when Context.SECURITY_AUTHENTICATION is set to GSSAPI in the environment hashtable?

  1. Is the TGT of the Subject required for this LDAPContext creation?
  2. What is the role of the TGT/Subject/Private-public credentials of the Subject acquired during the LoginContext#login() process?

Let us start from the beginning:

 LoginContext lc = new LoginContext(...)
 lc.login() 

What this piece of code does is that, it communicates with the KDC server, and obtains a TGT from it, if the authentication is successful! The login context has a Subject(authenticated) populated in it, which has all the information of the Credentials.

Once that is done, the following code is used to perform the JNDI.

  1. What does it actually mean to execute the code as the PrivilegedAction of the Subject as follows?

    Subject.doAs(lc.getSubject(), new JndiAction(args));
    

I am failing to understand what will happen to the objects returned from the Subject.doAs(...)?

Scenario:

  1. Consider that the DirContext is returned by the Subject.doAs(...) method by using PrivilegedAction{....} so that the the context can be used later on.

  2. What will happen to this context if the Subject through which it was created was logged out or its credentials are invalidated or changed? Will it still continue to work?

  3. Are the TGTs used for any of the later ctx operations like search() or is the GSSAPI in the picture for any of these operations?

  4. How does active directory validate this context valid?


Requirement

a. We don't want to perform any JNDI operation within the PrivilegedAction#run. We just want to return the context object which we want to cache or use later.

b. We have a peculiar requirement that we can't have on single krb.conf file due to some reasons. We create and destroy krb.conf for every subsequent request.

c. The reason for me asking question #5 is that - once the krb.conf file is re-generated as explained above, all the credentials from the in-memory LoginContext#Subject objects are invalidated and can't be used further.

d. In this case, can we use the cached context?

Any help to understand the real working is appreciated


Solution

  • I am particularly trying to understand, what this line actually means, during the creation of DirContext

    // Request the use of the "GSSAPI" SASL mechanism Authenticate by using already established Kerberos credentials 
    env.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
    

    This part is pretty simple, it is just telling the ldap client to use GSSAPI authentication, instead of "simple" or "none".
    While in theory "GSSAPI" is supposed to support a range of different implementations, in this Java implementation, it only supports kerberosV5.
    Simple auth, would be just passing the username/password directly to the LDAP server.
    None would be, if the LDAP server does not require auth to be queried.
    GSSAPI, here uses the kerberos credentials stored in the previously obtained subject.

    1. Is the TGT of the Subject required for this LDAPContext creation?

    This will depend on the LDAP server config, but in general, no, it's not required.

    To use simple auth you could do the following:

    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.SECURITY_PRINCIPAL, "Administrator@corp.example.com");
    env.put(Context.PROVIDER_URL, "ldap://WIN-MKR9VI69FT4.corp.example.com/");
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    env.put(Context.SECURITY_CREDENTIALS, "password".toCharArray());
    DirContext ctx = new InitialDirContext(env);
    

    What is the role of the TGT/Subject/Private-public credentials of the Subject acquired during the LoginContext#login() process?

    In the original example, they are used to acquire a service ticket to use with the LDAP server.

    What does it actually mean to execute the code as the PrivilegedAction of the Subject as follows?

    Java's SecurityManager architecture is complicated and antiquated, without getting into all the details, what is happening here is more or less, just making the Subject object available to code that runs within the privileged action.

    When the kerberos code looks for the credentials, it checks the AccessControlContext and uses credentials from it if available.

    1. Consider that the DirContext is returned by the Subject.doAs(...) method by using PrivilegedAction{....} so that the context can be used later on.

    The credentials/ticket is not bound to the DirContext object, so it will not continue to work, without also using the Subject.doAs.

    1. What will happen to this context if the Subject through which it was created was logged out or its credentials are invalidated or changed? Will it still continue to work?

    The credentials/ticket may or may not continue to work if the user is logged out or disabled, will depend on the ldap server implementation.

    1. Are the TGTs used for any of the later ctx operations like search() or is the GSSAPI in the picture for any of these operations?

    They can be, but you will need to access them via the Subject.doAs, they aren't attached to the DirContext.

    The first time you access the context, a service ticket will be acquired, using the TGT, and that service ticket will continue to be used so long as it is valid.

    a. We don't want to perform any JNDI operation within the PrivilegedAction#run. We just want to return the context object which we want to cache or use later.

    Should be possible using simple auth.
    You also have the option of using the system kerberos credential cache, but I imagine that would be much more work, and more file juggling.

    b. We have a peculiar requirement that we can't have on single krb.conf file due to some reasons. We create and destroy krb.conf for every subsequent request.

    That's not ideal, sadly the Java kerberos implementation does not support any better way to use multiple kerberos configurations.

    c. The reason for me asking question #5 is that - once the krb.conf file is re-generated as explained above, all the credentials from the in-memory LoginContext#Subject objects are invalidated and can't be used further.

    Not true, the credentials are still valid, but you will need to change the krb.conf back to the correct settings for the subject you are using, as the config file is still referenced after the initial login.

    d. In this case, can we use the cached context?

    Yes, but you will need to change the krb5.conf back to the correct value first.
    You can call sun.security.krb5.Config.refresh(); manually before using the context, to ensure the file config is loaded.
    The config is normally only refreshed on login.