Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6832353

Krb5LoginModule: use the KRB5CCNAME when searching for Kerberos ticket cache

XMLWordPrintable

      A DESCRIPTION OF THE REQUEST :
      Krb5LoginModule: use the KRB5CCNAME when searching for Kerberos ticket cache

      According to the Javadocs (http://java.sun.com/javase/6/docs/jre/api/security/jaas/spec/com/sun/security/auth/module/Krb5LoginModule.html), when useTicketCache is set to true, Krb5LoginModule searches for the ticket cache file in /tmp/krb5cc_uid only.

      On most modern distribution of Linux (and supposedly any UNIX using a modern MIT Kerberos 5 release), when using the pam_krb5 PAM module, the user's ticket cache file's name is randomized for security reasons and its name is passed to the user's applications in the KRB5CCNAME environment variable. It usually has the form "FILE:/tmp/krb5cc_[UID]_[SOME_RANDOM_CHARS]".

      On such distributions, plain JAAS Authentication employing the Krb5LoginModule will fail with the following error:

      Principal is null
      null credentials from Ticket Cache
                      [Krb5LoginModule] authentication failed
      Unable to obtain Princpal Name for authentication
      Authentication error: Unable to obtain Princpal Name for authentication


      There are people who got irritating problems because of that:

      http://www.igniterealtime.org/community/thread/27282
      http://forums.sun.com/thread.jspa?threadID=773258 (note the mistake in the discussed variable name - KRB5CC_NAME is invalid, it should be KRB5CCNAME)

      It seems that IBM's JGSS makes proper use of the KRB5CCNAME (but maybe it's just using system's native krb5 libraries):
      http://publib.boulder.ibm.com/iseries/v5r2/ic2924/index.htm?info/rzaha/rzahajgssconfigs.htm

      The fix for this would be a trivial modification of Krb5LoginModule near line 586 (added lines denoted with ">"):

      try {
      if (useTicketCache) {
      // ticketCacheName == null implies the default cache
      > if (ticketCacheName == null) {
      > final String filePrefix = "FILE:";
      > String krb5CCName = System.getenv("KRB5CCNAME");
      > if ( krb5CCName != null && krb5CCName.startsWith(filePrefix)) {
      > ticketCacheName = krb5CCName.substring(filePrefix.length());
      > if (debug)
      > System.out.println("Located ticket cache " + ticketCacheName + " through environment variable KRB5CCNAME.");
      > }
      > }
      if (debug)
      System.out.println("Acquire TGT from Cache");
      cred = Credentials.acquireTGTFromCache
      (principal, ticketCacheName);

      if (cred != null) {

      The Javadoc shoud be updated too (see line 90).

      JUSTIFICATION :
      Client side Krb5LoginModule doesn't work on modern MIT Kerberos 5 installations and working around this problem is complex and labour intensive.

        Fix for the problem is trivial.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      If the location of the user's credentials cache is not specified in the ticketCache option, and the KRB5CCNAME environment variable is present, Krb5LoginModule should use it to discover the cache location.
      ACTUAL -
      Krb5LoginModule assumes a static location for the ticket cache:

      "On Solaris and Linux it will look for the ticket cache in /tmp/krb5cc_<code>uid</code> where the uid is numeric user identifier."

      ---------- BEGIN SOURCE ----------
      jaas.conf:

      JaasApp {
      com.sun.security.auth.module.Krb5LoginModule required useTicketCache=true debug=true doNotPrompt=true;
      };


      JaasApp.java:

      import javax.security.auth.login.LoginContext;
      import javax.security.auth.login.LoginException;
      import com.sun.security.auth.callback.TextCallbackHandler;

      public class JaasApp {

      public static void main(String[] args) {
      LoginContext lc = null;

      try {
      lc = new LoginContext("JaasApp", new TextCallbackHandler());
      } catch (LoginException le) {
      System.err
      .println("Cannot create LoginContext. " + le.getMessage());
      System.exit(-1);
      } catch (SecurityException se) {
      System.err
      .println("Cannot create LoginContext. " + se.getMessage());
      System.exit(-1);
      }

      try {
      lc.login();
      } catch (LoginException e) {

      System.err.println("Authentication error: " + e.getMessage());
      System.exit(-1);
      }

      System.out.println("Authentication succeeded!");
      }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Several workarounds are possible but all are suboptimal:
      * Generate jaas.conf on the fly and provide the ticketCache option there.
      * Subclass Krb5LoginModule and copy large part of its behaviour (no protected methods/fields...) in order to read the environment variable in one strategic fragment
      * Use JGSS and native krb5 libraries (-Dsun.security.jgss.native=true)

        There are no Sub-Tasks for this issue.

            weijun Weijun Wang
            weijun Weijun Wang
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: