-
Bug
-
Resolution: Cannot Reproduce
-
P3
-
6u31
-
x86
-
windows_7
FULL PRODUCT VERSION :
1.6.0_34
1.6.0_35
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
Linux 2.6.32-220.17.1.el6.x86_64 #1 SMP Thu Apr 26 13:37:13 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux
EXTRA RELEVANT SYSTEM CONFIGURATION :
Active Directory on Windows 2008 R2
A DESCRIPTION OF THE PROBLEM :
Code that has been working for years to do an LDAP search against Active Directory suddenly stopped working with our upgrade to 1.6.0_34. My assumption is that it has something to do with the fix for bug 7067974. From the description, it shouldn't affect us because we are using rc4-hmac encryption, but testing would indicate otherwise. The issue happens with 1.6.0_34 and 1.6.0_35 on either windows or linux. and the stacktrace is below. It does not happen with any version that we have used prior to 1.6.0_34, including 1.6.0_33.
REGRESSION. Last worked in version 6u31
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I included source code that I stripped out of our app to demonstrate the problem. We have another section of our code that just does an authentication and that works fine. The problem we have is when doing a search in a Subject.doAs method.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
A successful search of LDAP
ACTUAL -
Identifier doesn't match expected value (906)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
javax.naming.PartialResultException [Root exception is javax.naming.AuthenticationException: GSSAPI [Root exception is javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))]]]
at com.sun.jndi.ldap.LdapNamingEnumeration.hasMoreImpl(LdapNamingEnumeration.java:224)
at com.sun.jndi.ldap.LdapNamingEnumeration.hasMore(LdapNamingEnumeration.java:171)
at LdapTest$3.run(LdapTest.java:122)
at LdapTest$3.run(LdapTest.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:396)
at LdapTest.main(LdapTest.java:113)
Caused by: javax.naming.AuthenticationException: GSSAPI [Root exception is javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))]]
at com.sun.jndi.ldap.LdapReferralContext.<init>(LdapReferralContext.java:74)
at com.sun.jndi.ldap.LdapReferralException.getReferralContext(LdapReferralException.java:132)
at com.sun.jndi.ldap.LdapNamingEnumeration.hasMoreReferrals(LdapNamingEnumeration.java:339)
at com.sun.jndi.ldap.LdapNamingEnumeration.hasMoreImpl(LdapNamingEnumeration.java:208)
... 6 more
Caused by: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))]
at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:194)
at com.sun.jndi.ldap.sasl.LdapSasl.saslBind(LdapSasl.java:105)
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:212)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2720)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:296)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:134)
at com.sun.jndi.url.ldap.ldapURLContextFactory.getObjectInstance(ldapURLContextFactory.java:35)
at javax.naming.spi.NamingManager.getURLObject(NamingManager.java:584)
at javax.naming.spi.NamingManager.processURL(NamingManager.java:364)
at javax.naming.spi.NamingManager.processURLAddrs(NamingManager.java:344)
at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:316)
at com.sun.jndi.ldap.LdapReferralContext.<init>(LdapReferralContext.java:93)
... 9 more
Caused by: GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))
at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:663)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:230)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:162)
at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:175)
... 21 more
Caused by: KrbException: Server not found in Kerberos database (7)
at sun.security.krb5.KrbTgsRep.<init>(KrbTgsRep.java:61)
at sun.security.krb5.KrbTgsReq.getReply(KrbTgsReq.java:185)
at sun.security.krb5.internal.CredentialsUtil.serviceCreds(CredentialsUtil.java:294)
at sun.security.krb5.internal.CredentialsUtil.acquireServiceCreds(CredentialsUtil.java:106)
at sun.security.krb5.Credentials.acquireServiceCreds(Credentials.java:557)
at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:594)
... 24 more
Caused by: KrbException: Identifier doesn't match expected value (906)
at sun.security.krb5.internal.KDCRep.init(KDCRep.java:133)
at sun.security.krb5.internal.TGSRep.init(TGSRep.java:58)
at sun.security.krb5.internal.TGSRep.<init>(TGSRep.java:53)
at sun.security.krb5.KrbTgsRep.<init>(KrbTgsRep.java:46)
... 29 more
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import com.sun.security.auth.login.ConfigFile;
public final class LdapTest
{
private static final String ldapUrl = "ldap://SERVER/";
private static final String username = "USERNAME";
private static final String password = "PASSWORD";
public static void main(final String[] argv)
{
try
{
System.setProperty("java.security.krb5.conf", LdapTest.class.getResource("krb5.conf")
.getFile());
final Configuration config = new ConfigFile(LdapTest.class.getResource("login.conf").toURI());
final LoginContext loginContext = new LoginContext("default-client", null,
new CallbackHandler()
{
@Override
public void handle(final Callback[] callback) throws UnsupportedCallbackException
{
for (int i = 0; i < callback.length; i++)
{
if (callback[i] instanceof NameCallback)
{
final NameCallback nameCallback = (NameCallback) callback[i];
nameCallback.setName(username);
}
else if (callback[i] instanceof PasswordCallback)
{
final PasswordCallback passCallback = (PasswordCallback) callback[i];
passCallback.setPassword(password.toCharArray());
}
else
{
throw new UnsupportedCallbackException(callback[i]);
}
}
}
}, config);
loginContext.login();
final Subject subject = loginContext.getSubject();
final Hashtable<String, Object> props = new Hashtable<String, Object>();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
props.put(Context.REFERRAL, "follow");
props.put(Context.PROVIDER_URL, ldapUrl);
final DirContext context = Subject.doAs(subject, new PrivilegedExceptionAction<DirContext>()
{
@Override
public DirContext run() throws NamingException
{
return new InitialDirContext(props);
}
});
try
{
final KerberosPrincipal principal = subject.getPrincipals(KerberosPrincipal.class)
.iterator().next();
final String[] searchAttrs = new String[] { "distinguishedName", "cn", "sn", "givenName",
"displayName", "userPrincipalName", "lastLogon", "pwdLastSet", "msDS-PSOApplied",
"lockoutTime", "accountExpires", "whenChanged", "userAccountControl", "memberOf",
"objectSid", "mail", "o", "ou" };
final StringBuilder buf = new StringBuilder();
for (String token : principal.getRealm().split("\\."))
{
if (token.length() == 0)
continue;
if (buf.length() > 0)
buf.append(",");
buf.append("DC=").append(token);
}
final SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningAttributes(searchAttrs);
controls.setCountLimit(20);
try
{
Subject.doAs(subject, new PrivilegedExceptionAction<List<String>>()
{
@Override
public List<String> run() throws NamingException
{
final NamingEnumeration<SearchResult> renum = context.search(buf.toString(),
"(& (objectClass=user)(givenName=blah)(sn=blah) )", controls);
List<String> results = new ArrayList<String>();
while (renum.hasMore())
{}
return results;
}
});
}
catch (final PrivilegedActionException e)
{
throw (NamingException) e.getCause();
}
}
finally
{
context.close();
}
}
catch (final Exception e)
{
e.printStackTrace();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Changing Context.SECURITY_AUTHENTICATION to "simple" and passing the username and password in plain text will work but is not a valid solution for us. Currently, we are forced to stick with 1.6.0_33.
1.6.0_34
1.6.0_35
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]
Linux 2.6.32-220.17.1.el6.x86_64 #1 SMP Thu Apr 26 13:37:13 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux
EXTRA RELEVANT SYSTEM CONFIGURATION :
Active Directory on Windows 2008 R2
A DESCRIPTION OF THE PROBLEM :
Code that has been working for years to do an LDAP search against Active Directory suddenly stopped working with our upgrade to 1.6.0_34. My assumption is that it has something to do with the fix for bug 7067974. From the description, it shouldn't affect us because we are using rc4-hmac encryption, but testing would indicate otherwise. The issue happens with 1.6.0_34 and 1.6.0_35 on either windows or linux. and the stacktrace is below. It does not happen with any version that we have used prior to 1.6.0_34, including 1.6.0_33.
REGRESSION. Last worked in version 6u31
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I included source code that I stripped out of our app to demonstrate the problem. We have another section of our code that just does an authentication and that works fine. The problem we have is when doing a search in a Subject.doAs method.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
A successful search of LDAP
ACTUAL -
Identifier doesn't match expected value (906)
ERROR MESSAGES/STACK TRACES THAT OCCUR :
javax.naming.PartialResultException [Root exception is javax.naming.AuthenticationException: GSSAPI [Root exception is javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))]]]
at com.sun.jndi.ldap.LdapNamingEnumeration.hasMoreImpl(LdapNamingEnumeration.java:224)
at com.sun.jndi.ldap.LdapNamingEnumeration.hasMore(LdapNamingEnumeration.java:171)
at LdapTest$3.run(LdapTest.java:122)
at LdapTest$3.run(LdapTest.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:396)
at LdapTest.main(LdapTest.java:113)
Caused by: javax.naming.AuthenticationException: GSSAPI [Root exception is javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))]]
at com.sun.jndi.ldap.LdapReferralContext.<init>(LdapReferralContext.java:74)
at com.sun.jndi.ldap.LdapReferralException.getReferralContext(LdapReferralException.java:132)
at com.sun.jndi.ldap.LdapNamingEnumeration.hasMoreReferrals(LdapNamingEnumeration.java:339)
at com.sun.jndi.ldap.LdapNamingEnumeration.hasMoreImpl(LdapNamingEnumeration.java:208)
... 6 more
Caused by: javax.security.sasl.SaslException: GSS initiate failed [Caused by GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))]
at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:194)
at com.sun.jndi.ldap.sasl.LdapSasl.saslBind(LdapSasl.java:105)
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:212)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2720)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:296)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:134)
at com.sun.jndi.url.ldap.ldapURLContextFactory.getObjectInstance(ldapURLContextFactory.java:35)
at javax.naming.spi.NamingManager.getURLObject(NamingManager.java:584)
at javax.naming.spi.NamingManager.processURL(NamingManager.java:364)
at javax.naming.spi.NamingManager.processURLAddrs(NamingManager.java:344)
at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:316)
at com.sun.jndi.ldap.LdapReferralContext.<init>(LdapReferralContext.java:93)
... 9 more
Caused by: GSSException: No valid credentials provided (Mechanism level: Server not found in Kerberos database (7))
at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:663)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:230)
at sun.security.jgss.GSSContextImpl.initSecContext(GSSContextImpl.java:162)
at com.sun.security.sasl.gsskerb.GssKrb5Client.evaluateChallenge(GssKrb5Client.java:175)
... 21 more
Caused by: KrbException: Server not found in Kerberos database (7)
at sun.security.krb5.KrbTgsRep.<init>(KrbTgsRep.java:61)
at sun.security.krb5.KrbTgsReq.getReply(KrbTgsReq.java:185)
at sun.security.krb5.internal.CredentialsUtil.serviceCreds(CredentialsUtil.java:294)
at sun.security.krb5.internal.CredentialsUtil.acquireServiceCreds(CredentialsUtil.java:106)
at sun.security.krb5.Credentials.acquireServiceCreds(Credentials.java:557)
at sun.security.jgss.krb5.Krb5Context.initSecContext(Krb5Context.java:594)
... 24 more
Caused by: KrbException: Identifier doesn't match expected value (906)
at sun.security.krb5.internal.KDCRep.init(KDCRep.java:133)
at sun.security.krb5.internal.TGSRep.init(TGSRep.java:58)
at sun.security.krb5.internal.TGSRep.<init>(TGSRep.java:53)
at sun.security.krb5.KrbTgsRep.<init>(KrbTgsRep.java:46)
... 29 more
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.login.Configuration;
import javax.security.auth.login.LoginContext;
import com.sun.security.auth.login.ConfigFile;
public final class LdapTest
{
private static final String ldapUrl = "ldap://SERVER/";
private static final String username = "USERNAME";
private static final String password = "PASSWORD";
public static void main(final String[] argv)
{
try
{
System.setProperty("java.security.krb5.conf", LdapTest.class.getResource("krb5.conf")
.getFile());
final Configuration config = new ConfigFile(LdapTest.class.getResource("login.conf").toURI());
final LoginContext loginContext = new LoginContext("default-client", null,
new CallbackHandler()
{
@Override
public void handle(final Callback[] callback) throws UnsupportedCallbackException
{
for (int i = 0; i < callback.length; i++)
{
if (callback[i] instanceof NameCallback)
{
final NameCallback nameCallback = (NameCallback) callback[i];
nameCallback.setName(username);
}
else if (callback[i] instanceof PasswordCallback)
{
final PasswordCallback passCallback = (PasswordCallback) callback[i];
passCallback.setPassword(password.toCharArray());
}
else
{
throw new UnsupportedCallbackException(callback[i]);
}
}
}
}, config);
loginContext.login();
final Subject subject = loginContext.getSubject();
final Hashtable<String, Object> props = new Hashtable<String, Object>();
props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
props.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
props.put(Context.REFERRAL, "follow");
props.put(Context.PROVIDER_URL, ldapUrl);
final DirContext context = Subject.doAs(subject, new PrivilegedExceptionAction<DirContext>()
{
@Override
public DirContext run() throws NamingException
{
return new InitialDirContext(props);
}
});
try
{
final KerberosPrincipal principal = subject.getPrincipals(KerberosPrincipal.class)
.iterator().next();
final String[] searchAttrs = new String[] { "distinguishedName", "cn", "sn", "givenName",
"displayName", "userPrincipalName", "lastLogon", "pwdLastSet", "msDS-PSOApplied",
"lockoutTime", "accountExpires", "whenChanged", "userAccountControl", "memberOf",
"objectSid", "mail", "o", "ou" };
final StringBuilder buf = new StringBuilder();
for (String token : principal.getRealm().split("\\."))
{
if (token.length() == 0)
continue;
if (buf.length() > 0)
buf.append(",");
buf.append("DC=").append(token);
}
final SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
controls.setReturningAttributes(searchAttrs);
controls.setCountLimit(20);
try
{
Subject.doAs(subject, new PrivilegedExceptionAction<List<String>>()
{
@Override
public List<String> run() throws NamingException
{
final NamingEnumeration<SearchResult> renum = context.search(buf.toString(),
"(& (objectClass=user)(givenName=blah)(sn=blah) )", controls);
List<String> results = new ArrayList<String>();
while (renum.hasMore())
{}
return results;
}
});
}
catch (final PrivilegedActionException e)
{
throw (NamingException) e.getCause();
}
}
finally
{
context.close();
}
}
catch (final Exception e)
{
e.printStackTrace();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Changing Context.SECURITY_AUTHENTICATION to "simple" and passing the username and password in plain text will work but is not a valid solution for us. Currently, we are forced to stick with 1.6.0_33.