diff --git a/mvn-build/core/src/main/java/org/springframework/ldap/core/support/DefaultDirObjectFactory.java b/mvn-build/core/src/main/java/org/springframework/ldap/core/support/DefaultDirObjectFactory.java index 5f823c92..61df8948 100644 --- a/mvn-build/core/src/main/java/org/springframework/ldap/core/support/DefaultDirObjectFactory.java +++ b/mvn-build/core/src/main/java/org/springframework/ldap/core/support/DefaultDirObjectFactory.java @@ -18,6 +18,7 @@ package org.springframework.ldap.core.support; import java.util.Hashtable; +import javax.naming.CompositeName; import javax.naming.Context; import javax.naming.Name; import javax.naming.directory.Attributes; @@ -58,6 +59,15 @@ public class DefaultDirObjectFactory implements DirObjectFactory { } else { nameInNamespace = ""; } + + if(name instanceof CompositeName){ + // Which it most certainly will be, and therein lies the problem. + // CompositeName.toString() completely screws up the formatting in some cases, + // particularly when backslashes are involved. + CompositeName compositeName = (CompositeName) name; + name = new DistinguishedName(compositeName.get(0)); + } + DirContextAdapter dirContextAdapter = new DirContextAdapter(attrs, name, new DistinguishedName(nameInNamespace)); dirContextAdapter.setUpdateMode(true); @@ -82,7 +92,7 @@ public class DefaultDirObjectFactory implements DirObjectFactory { } } } - + /* * (non-Javadoc) * diff --git a/mvn-build/integration-tests/src/test/java/org/springframework/ldap/InvalidBackslashITest.java b/mvn-build/integration-tests/src/test/java/org/springframework/ldap/InvalidBackslashITest.java new file mode 100644 index 00000000..cb29a76f --- /dev/null +++ b/mvn-build/integration-tests/src/test/java/org/springframework/ldap/InvalidBackslashITest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2005-2007 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap; + +import static junit.framework.Assert.assertEquals; + +import java.util.List; + +import javax.naming.CompositeName; +import javax.naming.InvalidNameException; +import javax.naming.Name; +import javax.naming.ldap.LdapName; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ldap.core.DirContextAdapter; +import org.springframework.ldap.core.DirContextOperations; +import org.springframework.ldap.core.DistinguishedName; +import org.springframework.ldap.core.LdapTemplate; +import org.springframework.ldap.core.support.AbstractContextMapper; +import org.springframework.test.context.ContextConfiguration; + +/** + * Tests the rename methods of LdapTemplate. + * + * We rely on that the bind, unbind and lookup methods work as they should - + * that should be ok, since that is verified in a separate test class. * + * + * @author Ulrik Sandberg + */ +@ContextConfiguration(locations = { "/conf/ldapTemplateTestContext.xml" }) +public class InvalidBackslashITest extends AbstractLdapTemplateIntegrationTest { + + @Autowired + private LdapTemplate tested; + + private static DistinguishedName DN = new DistinguishedName("cn=Some\\\\Person6,ou=company1,c=Sweden"); + + @Before + public void prepareTestedInstance() throws Exception { + DirContextAdapter adapter = new DirContextAdapter(); + adapter.setAttributeValues("objectclass", new String[] { "top", "person" }); + adapter.setAttributeValue("cn", "Some\\Person6"); + adapter.setAttributeValue("sn", "Person6"); + adapter.setAttributeValue("description", "Some description"); + + tested.unbind(DN); + tested.bind(DN, adapter, null); + } + + @After + public void cleanup() throws Exception { + tested.unbind(DN); + } + + /** + * Test for LDAP-109, LDAP-50. When an entry has a distinguished name + * including a backslach ('\') the Name supplied to DefaultDirObjectFactory + * will be invalid. + *
+ * E.g. the distinguished name "cn=Some\\Person6,ou=company1,c=Sweden"
+ * (indicating that the cn value is 'Some\Person'), will be represented by a
+ * CompositeName with the string representation
+ * "cn=Some\\\Person6,ou=company1,c=Sweden", which is in fact an invalid DN.
+ * This will be supplied to DistinguishedName for parsing,
+ * causing it to fail. This test makes sure that Spring LDAP properly works
+ * around this bug.
+ *
+ * What happens under the covers is (in the Java LDAP Provider code): + * + *
+ * LdapName ldapname = new LdapName("cn=Some\\\\Person6,ou=company1,c=Sweden");
+ * compositeName compositeName = new CompositeName();
+ * compositeName.add(ldapname.get(ldapname.size() - 1)); // for some odd reason
+ *
+ * CompositeName#add() cannot handle this and the result is
+ * the spoiled DN.
+ *
+ * @throws InvalidNameException
+ */
+ @Test
+ public void testSearchForDnSpoiledByCompositeName() throws InvalidNameException {
+ List result = tested.search("", "(sn=Person6)", new AbstractContextMapper() {
+ @Override
+ protected Object doMapFromContext(DirContextOperations ctx) {
+ DistinguishedName dn = (DistinguishedName) ctx.getDn();
+ assertEquals("cn=Some\\\\Person6, ou=company1, c=Sweden", dn.toString());
+ assertEquals("Some\\Person6", dn.getLdapRdn("cn").getValue());
+ return new Object();
+ }
+ });
+
+ assertEquals(1, result.size());
+ }
+}