-
Bug
-
Resolution: Fixed
-
P3
-
8, 9, 11
-
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.
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.