Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

SEC-1661: LDAP search base should not require JNDI escaping in addition to LDAP escaping for special characters #1899

spring-issuemaster opened this Issue Jan 25, 2011 · 7 comments


None yet
1 participant

Jason Konicki (Migrated from SEC-1661) said:

Having double quotes in the base dn (search base) does not work.

The following base dn value is valid, but does not work:

  • OU="Admin Users",OU=TEST-NC,DC=TESTCustomers,DC=Com

Luke Taylor said:

If you are reporting an issue, please check with the latest release (3.0.5 in this case).

The DN you've given here is not valid - it would be rejected if you entered it in an LDIF file and attempted to import it into a directory. Likewise if you used it as an argument to any LDAP operation. Quotes in DNs need to be escaped. If the name in the directory contains quotes then you need to use ou= "Admin Users".

Escaping is further complicated when used from Java, because of JNDI, see:


so it wouldn't surprise me if there were other bugs in this area, but "does not work" isn't much to go on. Please explain what the directory entries contain, what configuration parameters you are using (make sure DN strings are LDAP escaped), what exceptions occur (if any) and what actually goes wrong.

Jason Konicki said:

Sorry about the lack of information:

I also tested with latest code from git and modified the BindAuthenticatorTests to test the quoted string, but it failed.

Here is the stacktrace when the quoted string is used instead of the non-quoted string:
org.springframework.security.authentication.BadCredentialsException: Bad credentials
at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.authenticate(LdapAuthenticationProvider.java:266)
at com.hyperic.hq.security.LdapHQAuthenticationProvider.authenticateFromSearchBase(LdapHQAuthenticationProvider.java:198)
at com.hyperic.hq.security.LdapHQAuthenticationProvider.authenticate(LdapHQAuthenticationProvider.java:165)
at org.hyperic.hq.security.InternalAuthenticationProvider.authenticate(InternalAuthenticationProvider.java:88)
at org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:121)
at org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:49)
at org.hyperic.hq.auth.server.session.AuthManagerImpl.authenticate(AuthManagerImpl.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80)
at org.hyperic.hq.monitor.aop.aspects.PerformanceMonitor.monitorServiceMethod(PerformanceMonitor.java:84)
at sun.reflect.GeneratedMethodAccessor324.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:622)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:611)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:108)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy46.authenticate(Unknown Source)

Luke Taylor said:

Ok, this still doesn't clear up what the directory contains or what the configuration valuues are. If you write a basic Java LDAP test:

    Hashtable<String,String> env = new Hashtable<String,String>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, "ldap://,dc=com"); // use your URL
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=springsource,dc=com"); // use whatever username and credentials you need to perform the search
    env.put(Context.SECURITY_CREDENTIALS, "password");

    InitialDirContext idc = new InitialDirContext(env);
    SearchControls searchControls = new SearchControls();

    String baseDn = ?
    String username = ?

    NamingEnumeration<SearchResult> matches = idc.search(baseDn, "(cn={0})", new Object[] {username}, searchControls);

    while(matches.hasMore()) {
        SearchResult match = matches.next();
        System.out.println("**** Match: " +match.getName());


Then what value of the string "baseDn" gives you a match on a valid username?

Luke Taylor said:

I've added the use of an LDAP DistinguishedName to the baseDn to avoid the need for JNDI escaping (see the link to the Java Tutorial above). However, the string still needs to be LDAP escaped in the configuration if it contains any special characters.

Luke Taylor said:

Does the DN in the directory actually contain quotes?

If not, then they shouldn't be there in the configuration (either escaped or otherwise).

It looks like you are saying that the system should treat one with quotes as if they weren't there - i.e. that the original system treated DNs with and without the quotes in the same way. I'd regard that as a bug in the original system. Since quotes are valid content in a DN, if the actual value contained in the directory doesn't have any nor should the value you use to represent it elsewhere.

Jason Konicki said:


I received feedback from the customer, their DN was "OU=Admin-Users,OU=TEST-NC,DC=TESTCustomers,DC=Com" (without the quotes around Admin-Users).
So it appears that the other 3rdparty Ldap must have been stripping off the quotes which would not be correct as you said.

Thanks for the clarification on this issue.

Luke Taylor said:

The initial report is essentially invalid, so changing the title to reflect the minor change to the code that has actually been made - i.e. the search base should now only require LDAP escaping.

@spring-issuemaster spring-issuemaster added this to the 3.1.0.RC1 milestone Feb 5, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment