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

GssKrb5Client violates RFC 4752

XMLWordPrintable

    • b11
    • x86_64
    • windows_7

      FULL PRODUCT VERSION :
      java version "1.8.0_92"
      Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
      Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]
      Windows 7 64 bit, Enterprise Edition

      A DESCRIPTION OF THE PROBLEM :
      This is about the GSSAPI authentication plugin in Java's SASL implementation which is used in JNDI. Unfortunately, I haven't found a better category for this.

      The RFC 4752 decribes how Kerberos 5 is used with SASL. Chapter 3.1 "Client Side of Authentication Protocol Exchange" says:
      ====
      The client calls GSS_Init_sec_context, passing in
         input_context_handle of 0 (initially), mech_type of the Kerberos V5
         GSS-API mechanism [KRB5GSS], chan_binding of NULL, and targ_name
         equal to output_name from GSS_Import_Name called with input_name_type
         of GSS_C_NT_HOSTBASED_SERVICE (*) and input_name_string of
         "service@hostname" where "service" is the service name specified in
         the protocol's profile, and "hostname" is the fully qualified host
         name of the server. When calling the GSS_Init_sec_context, the
         client MUST pass the integ_req_flag of TRUE (**). If the client will
         be requesting a security layer, it MUST also supply to the
         GSS_Init_sec_context a mutual_req_flag of TRUE, and a
         sequence_req_flag of TRUE. If the client will be requesting a
         security layer providing confidentiality protection, it MUST also
         supply to the GSS_Init_sec_context a conf_req_flag of TRUE. The
         client then responds with the resulting output_token. If
         GSS_Init_sec_context returns GSS_S_CONTINUE_NEEDED, then the client
         should expect the server to issue a token in a subsequent challenge.
         The client must pass the token to another call to
         GSS_Init_sec_context, repeating the actions in this paragraph.
      ====

      Looking at the code http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/c5c0728e113d/src/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Client.java#l133 lines 133 through 147, you'll see that mutual is only set when a client requests too and conf is set unconditionally, though this is not requested by the client and the RFC does not require it.

      The implementation violates the RFC.

      Trying the very same with ldapsearch(1) yields to a correct behavior. More than that, if you try to disable mutual auth or auth-int, Cyrus SASL will fail. Check the source code of the GSSAPI Cyrus SASL plugin.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Create an InitialDirContext to a directory server which supports GSSAPI SASL mechanism, perform a lookup on RootDSE and watch the traffic in Wireshark.

      Review the code and alter it according to the RFC.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The TGS-REQ must always be set to mutual true which is intiated by the GSS context. As well as auth-conf only on request and not always. The context establishment must fail is mutual is set to false by the client and QOP is neither auth-int nor auth-conf.
      ACTUAL -
      Mutual auth is not enforced and even if requestConf and requestInteg are set to true, integrity is not apply if not requested by QOP auth-int.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.Properties;

      import javax.naming.Context;
      import javax.naming.NameClassPair;
      import javax.naming.NamingEnumeration;
      import javax.naming.NamingException;
      import javax.naming.directory.DirContext;
      import javax.naming.directory.InitialDirContext;

      public class SaslBug {

      public static void main(String[] args) throws NamingException {

      Properties props = new Properties();

      props.put(Context.PROVIDER_URL, "ldap://example.com");
      props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
      props.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");

      DirContext context = new InitialDirContext(props);

      NamingEnumeration<NameClassPair> ne = context.list("");

      while (ne.hasMore()) {
      System.out.println(ne.next());
      }

      ne.close();
      context.close();

      }

      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Workaround is to set mutual auth to true and QOP to auth-int.

            weijun Weijun Wang
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: