[python-ldap] Searching for nested membership in AD groups

Sean Whalen whalenster at gmail.com
Sat Oct 1 13:23:21 EDT 2016


I came up with some better examples to illistrate the problem.

The following PowerShell code works:

$userdn = 'CN=Whalen\, Sean,OU=Users,OU=Users and Groups,DC=example,DC=net'
$strFilter = "(member:1.2.840.113556.1.4.1941:=$userdn)"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree"
$colProplist = "name"
foreach ($i in $colPropList){
   $objSearcher.PropertiesToLoad.Add($i) > $nul
   }
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
    {
      $objItem = $objResult.Properties
      $objItem.name
      }

But, the following python-ldap code returns zero results after taking some
time:

from __future__ import print_function
import ldapfrom ldap.filter import escape_filter_chars

base = "DC=example,DC=net"

username = "ADLookup at example.net"
password = "foobar"

ad = ldap.initialize("ldap://ad.example.net")
ad.set_option(ldap.OPT_PROTOCOL_VERSION, ldap.VERSION3)
ad.set_option(ldap.OPT_REFERRALS, 0)
ad.bind_s(username, password)

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

filter_string =
"(memberof:1.2.840.113556.1.4.1941:={0})".format(escape_filter_chars(dn))
# (memberof:1.2.840.113556.1.4.1941:=CN=Whalen\5c,
Sean,OU=Users,OU=Users and Groups,DC=example,DC=net)
# The backslash that escapes the comma in the CN must be escaped in a
search filter string,# per RFC 2254, page 5

results = ad.search_s(base,
                      ldap.SCOPE_SUBTREE,
                      filterstr=filter_string,
                      attrlist=["distinguishedName"])
results = [entry for dn, entry in results if isinstance(entry,
dict)]print(results)

At first I thought this due to was a bug or compatibility problem in
python-ldap. However, running the same search using Microsoft's LDIFDE.EXE tool
also returns zero results.

LDIFDE.EXE -f results.txt -d "DC=example,DC=net" -r
"(memberof:1.2.840.113556.1.4.1941:=CN=Whalen\, Sean,
OU=Users,OU=Users and Groups,DC=example,DC=net)" -l "name"

Any idea what's going wrong, and how can I fix it?
Also, I was able to join the list. The confirmation email got buried.

On Fri, Sep 30, 2016 at 10:41 PM, Sean Whalen <whalenster at gmail.com> wrote:

> Right,
>
> but when I use
> (member:1.2.840.113556.1.4.1941:=CN=Whalen\, Sean,OU=Users,OU=Users and
> Groups,DC=redacted,DC=net)
>
> or
> filter = '(member:1.2.840.113556.1.4.1941:=CN={0},OU=Users,OU=Users and
> Groups,DC=redacted,DC=net)'.format(escape_dn_chars('Whalen, Sean'))
>
> I get
>
>   File "/usr/local/lib/python3.5/dist-packages/ldap/ldapobject.py", line
> 768, in search_s
>     return self.search_ext_s(base,scope,filterstr,attrlist,attrsonly,
> None,None,timeout=self.timeout)
>   File "/usr/local/lib/python3.5/dist-packages/ldap/ldapobject.py", line
> 761, in search_ext_s
>     msgid = self.search_ext(base,scope,filterstr,attrlist,attrsonly,
> serverctrls,clientctrls,timeout,sizelimit)
>   File "/usr/local/lib/python3.5/dist-packages/ldap/ldapobject.py", line
> 757, in search_ext
>     timeout,sizelimit,
>   File "/usr/local/lib/python3.5/dist-packages/ldap/ldapobject.py", line
> 263, in _ldap_call
>     result = func(*args,**kwargs)
> ldap.FILTER_ERROR: {'desc': 'Bad search filter'}
>
>
> On Fri, Sep 30, 2016 at 10:01 PM, Stephen J. Butler <
> stephen.butler at gmail.com> wrote:
>
>> \5C is blackslash itself, not comma. I think what he wants is really:
>>
>> r'(member:1.2.840.113556.1.4.1941:=CN=Whalen\, Sean,OU=Users,OU=Users
>> and Groups,DC=redacted,DC=net)'
>>
>> Notice the raw string. Otherwise, if you aren't using a raw string, then:
>>
>> "(member:1.2.840.113556.1.4.1941:=CN=Whalen\\, Sean,OU=Users,OU=Users
>> and Groups,DC=redacted,DC=net)"
>>
>>
>> IDK how you're building your DN's in general, but what you should be
>> doing is this when you have arbitrary input:
>>
>> from ldap.dn import escape_dn_chars
>>
>> filter = '(member:1.2.840.113556.1.4.1941:=CN={0},OU=Users,OU=Users and
>> Groups,DC=redacted,DC=net)'.format(escape_dn_chars('Whalen, Sean'))
>>
>> That will always do the right thing.
>>
>> On Fri, Sep 30, 2016 at 7:37 PM, Michael Ströder <michael at stroeder.com>
>> wrote:
>>
>>> Sean Whalen wrote:
>>> > Then I tried
>>> >
>>> > (member:1.2.840.113556.1.4.1941:=CN=Whalen\5c, Sean,OU=Users,OU=Users
>>> and
>>>                                             ^^^^
>>> Yes, you must escape the comma in the DN.
>>>
>>> But the escaped hex-encoded character \5C must fully *replace* the
>>> comma. Or
>>> simply escape the comma like \, (see RFC 4514).
>>>
>>> Bear in mind that you have to deal with extra escaping in Python string
>>> syntax
>>> when hard-coding a DN like this in your source code.
>>>
>>> Also note that there can be a bunch of specific performance differences
>>> depending on how and from where you connect and bind to Active Directory,
>>> especially if it's not well maintained (stale directory replicas / site
>>> topology).
>>>
>>> Ciao, Michael.
>>>
>>>
>>> _______________________________________________
>>> python-ldap mailing list
>>> python-ldap at python.org
>>> https://mail.python.org/mailman/listinfo/python-ldap
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ldap/attachments/20161001/2c11955d/attachment.html>


More information about the python-ldap mailing list