How should I escape ldap special characters?

Question:

I’m using python-ldap to query Active Directory

I have this DN

CN=Whalen, Sean,OU=Users,OU=Users and Groups,DC=example,DC=net

That works fine as a base in a query, but if I try to use it in a search filter like this

(&(objectClass=group)(memberof:1.2.840.113556.1.4.1941:=CN=Whalen, Sean,OU=Users,OU=Users and Groups,DC=example,DC=net))

I get a Bad search filter error. From my testing, the comma in the CN seems to be the culprit, even though I escaped it with a backslash (). But, comma isn’t listed in the Microsoft documentation as a character that needs escaped in filters.

What am I missing?

Asked By: Sean W.

||

Answers:

The LDAP filter specification assigns special meaning to the following characters * ( ) NUL that should be escaped with a backslash followed by the two character ASCII hexadecimal representation of the character when used in a search filter (rfc2254) :

*   2A
(   28
)   29
   5C
Nul 0

That means any backslash used for escaping a Distinguished Name’ special character (including commas) must be represented by 5c in a search filter :

(&(objectClass=group)(memberof:1.2.840.113556.1.4.1941:=CN=Whalen5c, Sean,OU=Users,OU=Users and Groups,DC=example,DC=net))

Here is the list of dn special characters that must be escaped with , or whith 5C when used in a search filter :

    +-------------------------------+---+
    | comma                         | , |
    +-------------------------------+---+
    | Backslash character           |  |
    +-------------------------------+---+
    | Pound sign (hash sign)        | # |
    +-------------------------------+---+
    | Plus sign                     | + |
    +-------------------------------+---+
    | Less than symbol              | < |
    +-------------------------------+---+
    | Greater than symbol           | > |
    +-------------------------------+---+
    | Semicolon                     | ; |
    +-------------------------------+---+
    | Double quote (quotation mark) | " |
    +-------------------------------+---+
    | Equal sign                    | = |
    +-------------------------------+---+
    | Leading or trailing spaces    |   |
    +-------------------------------+---+
Answered By: EricLavault

I have experienced very odd behaviour when searching with member:1.2.840.113556.1.4.1941 with escaped characters.

It seems that the search fails when the search term is escaped ‘properly’, but succeeds when the search term is not escaped!

In contrast, a plain search using member works whether the search term is escaped or not.

Here’s a PowerShell example.

function Find-AdObjects([string]$Filter) {

    $DirectorySearcher = New-Object System.DirectoryServices.DirectorySearcher
    $DirectorySearcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry
    $DirectorySearcher.SearchScope = [System.DirectoryServices.SearchScope]::Subtree
    $DirectorySearcher.PropertiesToLoad.Add('distinguishedname') > $null
    $DirectorySearcher.PageSize = 100
    $DirectorySearcher.Filter = $Filter

    $SearchResultCollection = $DirectorySearcher.FindAll()

    foreach ($r in $SearchResultCollection) {
        $r.Properties['distinguishedname']
    }

    $SearchResultCollection.Dispose()
    $DirectorySearcher.Dispose()
}

$UserDn        = 'CN=Rees, John,OU=Tier3,DC=big,DC=com'
$EscapedUserDn = 'CN=Rees5C, John,OU=Tier3,DC=big,DC=com'

# Returns expected results with escaped search term
Find-AdObjects "(&(member=$EscapedUserDn))"

# Returns same results even though search term is NOT escaped correctly
Find-AdObjects "(&(member=$UserDn))"

# Returns NO results even though search term is escaped correctly
Find-AdObjects "(&(member:1.2.840.113556.1.4.1941:=$EscapedUserDn))"

# Returns recursive results even though search term is NOT escaped correctly
Find-AdObjects "(&(member:1.2.840.113556.1.4.1941:=$UserDn))"

So I do not see an acceptable workaround, since there does not seem to be a reliable way to escape a DN that could contain a variety of special characters: *()

Answered By: John Rees