Describe the bug
When given a valid URL such as ldap://server/dc=org%20with%20space,dc=com, the DefaultSpringSecurityContextSource sets the baseDN to dc=org%20with%20space,dc=com and not dc=org with space,dc=com.
This causes lookups to fail when setting the baseDN as it will be set to an invalid DN.
https://github.com/spring-projects/spring-security/blob/02474fdd842c63e6fa1d129d4a7e88afe12c387b/ldap/src/main/java/org/springframework/security/ldap/DefaultSpringSecurityContextSource.java#L69 gets the baseDN raw path ie URL encoded https://github.com/spring-projects/spring-security/blob/02474fdd842c63e6fa1d129d4a7e88afe12c387b/ldap/src/main/java/org/springframework/security/ldap/LdapUtils.java#L135 which just about works as it is then used to manipulate the URL as a String.
However later on it is just persisted to the Base DN.
https://github.com/spring-projects/spring-security/blob/02474fdd842c63e6fa1d129d4a7e88afe12c387b/ldap/src/main/java/org/springframework/security/ldap/DefaultSpringSecurityContextSource.java#L77
To Reproduce
using commit 39c4195c3557985f34dc725b79e8f3ed3d767e20 from https://github.com/jenkinsci/ldap-plugin/pull/93/commits/39c4195c3557985f34dc725b7
run mvn test -Dtest=LDAPDNEscapingTest#testSpacesInDNWithRootDN
The URL being provided to DefaultSpringSecurityContextSource in this case is ldap://localhost:52752/dc=planet%20express,dc=com
Expected behavior
The lookup of any user succeeds
but it fails.
4.977 [id=31] WARNING h.security.LDAPSecurityRealm#throwUnlessConfigIsIgnorable: Failed communication with ldap server Ve2UCorQ7HhmkQyz783bXg== (ldap://localhost:52752), will _not_ try the next configuration
javax.naming.NameNotFoundException: [LDAP: error code 32 - NO_SUCH_OBJECT: failed for MessageType : SEARCH_REQUEST
Message ID : 2
SearchRequest
baseDn : 'dc=planet%20express,dc=com'
filter : '(uid=fry)'
scope : whole subtree
typesOnly : false
Size Limit : no limit
Time Limit : no limit
Deref Aliases : deref Always
attributes : '*', '+'
org.apache.directory.api.ldap.model.message.SearchRequestImpl@f86c2029: ERR_268 Cannot find a partition for dc=planet%20express,dc=com]; remaining name '/'
note the completely invalid baseDn
Sample
A link to a GitHub repository with a minimal, reproducible sample.
https://github.com/jenkinsci/ldap-plugin/pull/93/commits/39c4195c3557985f34dc725b7
Reports that include a sample will take priority over reports that do not. At times, we may require a sample, so it is good to try and include a sample up front.
Comment From: jzheaux
Thanks, @jtnord, this sounds like a reasonable change to make.
To resolve the issue, I think the rootDn needs to be correctly computed. To test it, the LDAP integration tests should stand up a container and accompanying LDIF entries whose root contains a space.
Comment From: jtnord
FWIW there is a LDIF here which was modified from the planet express which is MIT licenced.
Comment From: sjohnr
Hi @jtnord,
I see you've already worked around your issue in the meantime (so this suggestion may not be too valuable), but I wanted to check if you saw this as a viable workaround as well:
String providerUrl = "ldap://myhost:10389/dc=spring%20framework,dc=org";
DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(providerUrl);
contextSource.setBase(URI.create(LdapUtils.parseRootDnFromUrl(providerUrl)).getPath());
// ...
Comment From: jtnord
Hi @jtnord,
I see you've already worked around your issue in the meantime (so this suggestion may not be too valuable), but I wanted to check if you saw this as a viable workaround as well:
java String providerUrl = "ldap://myhost:10389/dc=spring%20framework,dc=org"; DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(providerUrl); contextSource.setBase(URI.create(LdapUtils.parseRootDnFromUrl(providerUrl)).getPath()); // ...
Damn that's certainly cleaner than my workaround! Thanks
Comment From: sjohnr
Perhaps it will help if anyone encounters this in the meantime. Thanks for the feedback!