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

Sean Whalen whalenster at gmail.com
Sat Oct 1 14:49:13 EDT 2016


Michael,

I've tried with both python-ldap and pyldap and gotten the same results. If
you can help me troubleshoot on python-ldap, I can probably make it work
with pyldap. I really want to support Python 2 and 3.

Aron,

Escaping the whole search string also escaped the parentheses around my
statement, generating an invalid search string. Thanks for the suggestion.

On Sat, Oct 1, 2016 at 2:01 PM, Aron Patel <aron.patel at ikea.com> wrote:

> Could it be that your already trying to escaping the \ in your dn. So it
> will translate to \\\\ Once you escape your full DN using the
> escape_filter_chars.
>
> I would wrap my entire filter with the escape_filter_chars(filter_string)
> instead of just trying to escape the DN manually. Just make sure you remove
> any of your own escaping characters from the dn before applying the method.
>
> /Aron
>
>
>
>
> Sent with Good (www.good.com)
>
>
>
> -----Original Message-----
> *From: *Sean Whalen [whalenster at gmail.com]
> *Sent: *Saturday, October 01, 2016 07:32 PM W. Europe Standard Time
> *To: *python-ldap at python.org
> *Subject: *Re: [python-ldap] Searching for nested membership in AD groups
>
> 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,No
>> ne,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,serv
>> erctrls,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/be4b1068/attachment-0001.html>


More information about the python-ldap mailing list