Parse ldap filter to avoid special characters

The ejb service takes the ldap filter as a string and returns the result from ActiveDirectory.

The problem is that sometimes attribute values ​​contain special characters that must be escaped for the whole filter, as stated here:
https://msdn.microsoft.com/en-us/library/aa746475(v=vs.85). aspx
and for the distinguished name specify the values ​​shown here:
https://msdn.microsoft.com/en-us/library/aa366101(v=vs.85).aspx
To do this, the service must do the following:

  • Parse the string for dn values, separate them, and remove them according to the escape sequence rules, if not already escaped.
  • Search the remainder of the string for special characters in attribute values ​​and avoid them according to the general filter exclusion rules if they are not already escaped.
  • Combine the results as a new shielded filter and pass it in.

Java native javax.naming.ldap.Rdn

stores dn values ​​on the right, but is not idempotent. For other tasks, so far I have not been able to find a library that would allow me to accomplish them.

Right now I tend to think that the work of escaping the ldap filter should be done by the user of the service and not by the service itself, as it is very difficult for the service to tell the screens from the actual values.Also parsing a complex string like an ldap filter without a well tested libraries seems prone to errors to me.

Any ideas on how to solve this? Can this task be automated?

+3


source to share


2 answers


For escaping LDAP filters, I relied on this page to write the code below: http://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx#Special_Characters

String LdapEscape(String ldap)
{
    if(ldap == null) return "";
    return ldap.replace("\\", "\\5C").replace("*", "\\2A").replace("(", "\\28").replace(")", "\\29").replace("\000", "\\00");
}

      

The most important thing to remember is that the substitution \

for \5C

must happen first so that you don't double escape characters. Otherwise, it is very simple; there are no special tricks to follow.



I would like to point out that this is intended to exclude individual values ​​placed in LDAP filters, not the entire LDAP filter. However, if you want, you can use this function to avoid something like this so that it can be searched for:

LdapEscape("(!(sn=m*))"); // \28!\28sn=m\2A\29

      

+2


source


Pluto's answer is great and concise, but ASCII UTF-8 characters (like é, á, ö, etc.) also need special handling. Here is my verbose solution.



/** 
 * Filter components need to escape special chars.
 * Note that each piece of the filter needs to be escaped, 
 * not the whole filter expression, for example:
 * 
 * "(&(cn="+ esc("Admins") +")(member="+ esc("CN=Doe\\, Jöhn,OU=ImPeople,DC=ds,DC=augur,DC=com") +"))"
 * 
 * @see Oracle Directory Server Enterprise Edition 11g Reference doc
 * @see http://docs.oracle.com/cd/E29127_01/doc.111170/e28969/ds-ldif-search-filters.htm#gdxoy
 * @param s A String field within the search expression
 * @return The escaped string, safe for use in the search expression.
 */
public static String esc(String s)
{
    if(s == null) return "";
    StringBuilder sb = new StringBuilder(s.length());
    for (byte c : s.getBytes(StandardCharsets.UTF_8))
    {
        if (c=='\\') { sb.append("\\5c"); }
        else if (c=='*') { sb.append("\\2a"); }
        else if (c=='(') { sb.append("\\28"); }
        else if (c==')') { sb.append("\\29"); }
        else if (c==0) { sb.append("\\00"); }
        else if ((c&0xff)>127) { sb.append("\\").append(to2CharHexString((c&0xff))); } // UTF-8 non-7-bit characters, e.g. é, á, etc...
        else { sb.append((char)c); }
    }
    return sb.toString();
}

/** 
 * @return The least significant 16 bits as a two-character hex string, 
 * padded by a leading '0' if necessary.
 */
public static String to2CharHexString(int i)
{
    String s = Integer.toHexString(i & 0xff);
    if (s.length()==1) return "0"+s;
    else return s;
}

      

+1


source







All Articles