Search code examples
javaescapingldapjndi

Forward slashes in the names returned by JNDI query to LDAP server


I need to make several queries to LDAP directory server and I'm using JNDI directory facilities for it. Then I need to do some work with the objects from the query result using their distinguished names. Some of the entries returned by the server contain forward slash character, and because of this JNDI escapes the whole name with double quotes:

NamingEnumeration<SearchResult> results = dirContext.search(queryRoot, queryFilter, controls);
for (SearchResult result : Collections.list(results)) {
    String objectName = result.getName();
    System.out.println(objectName);
}

If one of the objects in the query results has a name, say, 'b=id/10,a=1', it is printed like this

"b=id/10,a=1"

Note the double quotes around the name. Because of these quotes I cannot create javax.naming.ldap.LdapName from it directly: it fails with NamingException "Invalid name".

I understand that I can remove these quotes manually, but this feels hacky. Is there a way to avoid such escaping? Or maybe there are cleaner methods to do what I need?

P.S. It is funny that official JNDI tutorial suggests using LdapName to achieve "easy name manipulation" and even mentions the escape problem but does not provide any links on the problem described above.


Solution

  • If an AttributeValue has LDAP-specific syntax, the characters are converted (using the defined syntax specification) to UTF-8 and only the following characters must be escaped:

    • ' ' (space) at the beginning of the string
    • ' ' (space) at the end of the string
    • '"'
    • '+' (the plus character indicates a multi-valued RDN)
    • , (the comma character separates components of the distinguished name)
    • ;
    • <
    • >
    • \

    The forward slash is a valid character and need not be escaped, therefore it must be handled by the application and the API used by that application. As you noted, the forward slash has "special meaning" to JNDI. JNDI is poorly designed in many respects, this is only one of the many. Consider using the UnboundID LDAP SDK for new code.

    For example, add the following entry:

    dn: uid=abc/def,ou=people,dc=example,dc=com
    objectClass: top
    objectClass: person
    objectClass: inetOrgPerson
    uid: abc/def
    cn: abc/def
    sn: abc/def
    userPassword: this entry is used to test http://stackoverflow.com/questions/11690529/forward-slashes-in-the-names-returned-by-jndi-query-to-ldap-server
    

    retrieve the entry just added:

    ldapsearch -h localhost -p 10389 -D 'cn=RootDn'  -b dc=example,dc=com -s sub '(uid=abc/def)' 1.1
    Enter bind password: 
    version: 1
    dn: uid=abc/def,ou=people,dc=example,dc=com
    

    see also