<div dir="ltr">I came up with some better examples to illistrate the problem.<br><br><div class="gmail-post-text">

<p>The following PowerShell code works:</p>

<pre class="gmail-lang-py gmail-prettyprint gmail-prettyprinted"><code><span class="gmail-pln">$userdn </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-str">'CN=Whalen\, Sean,OU=Users,OU=Users and Groups,DC=example,DC=net'</span><span class="gmail-pln">
$strFilter </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-str">"(member:1.2.840.113556.1.4.1941:=$userdn)"</span><span class="gmail-pln">
$objDomain </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-typ">New</span><span class="gmail-pun">-</span><span class="gmail-typ">Object</span><span class="gmail-pln"> </span><span class="gmail-typ">System</span><span class="gmail-pun">.</span><span class="gmail-typ">DirectoryServices</span><span class="gmail-pun">.</span><span class="gmail-typ">DirectoryEntry</span><span class="gmail-pln">
$objSearcher </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-typ">New</span><span class="gmail-pun">-</span><span class="gmail-typ">Object</span><span class="gmail-pln"> </span><span class="gmail-typ">System</span><span class="gmail-pun">.</span><span class="gmail-typ">DirectoryServices</span><span class="gmail-pun">.</span><span class="gmail-typ">DirectorySearcher</span><span class="gmail-pln">
$objSearcher</span><span class="gmail-pun">.</span><span class="gmail-typ">SearchRoot</span><span class="gmail-pln"> </span><span class="gmail-pun">=</span><span class="gmail-pln"> $objDomain
$objSearcher</span><span class="gmail-pun">.</span><span class="gmail-typ">PageSize</span><span class="gmail-pln"> </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-lit">1000</span><span class="gmail-pln">
$objSearcher</span><span class="gmail-pun">.</span><span class="gmail-typ">Filter</span><span class="gmail-pln"> </span><span class="gmail-pun">=</span><span class="gmail-pln"> $strFilter
$objSearcher</span><span class="gmail-pun">.</span><span class="gmail-typ">SearchScope</span><span class="gmail-pln"> </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-str">"Subtree"</span><span class="gmail-pln">
$colProplist </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-str">"name"</span><span class="gmail-pln">
foreach </span><span class="gmail-pun">(</span><span class="gmail-pln">$i </span><span class="gmail-kwd">in</span><span class="gmail-pln"> $colPropList</span><span class="gmail-pun">){</span><span class="gmail-pln">
   $objSearcher</span><span class="gmail-pun">.</span><span class="gmail-typ">PropertiesToLoad</span><span class="gmail-pun">.</span><span class="gmail-typ">Add</span><span class="gmail-pun">(</span><span class="gmail-pln">$i</span><span class="gmail-pun">)</span><span class="gmail-pln"> </span><span class="gmail-pun">></span><span class="gmail-pln"> $nul
   </span><span class="gmail-pun">}</span><span class="gmail-pln">
$colResults </span><span class="gmail-pun">=</span><span class="gmail-pln"> $objSearcher</span><span class="gmail-pun">.</span><span class="gmail-typ">FindAll</span><span class="gmail-pun">()</span><span class="gmail-pln">
foreach </span><span class="gmail-pun">(</span><span class="gmail-pln">$objResult </span><span class="gmail-kwd">in</span><span class="gmail-pln"> $colResults</span><span class="gmail-pun">)</span><span class="gmail-pln">
    </span><span class="gmail-pun">{</span><span class="gmail-pln">
      $objItem </span><span class="gmail-pun">=</span><span class="gmail-pln"> $objResult</span><span class="gmail-pun">.</span><span class="gmail-typ">Properties</span><span class="gmail-pln">
      $objItem</span><span class="gmail-pun">.</span><span class="gmail-pln">name
      </span><span class="gmail-pun">}</span><span class="gmail-pln"> </span></code></pre>

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

<pre class="gmail-lang-py gmail-prettyprint gmail-prettyprinted"><code><span class="gmail-kwd">from</span><span class="gmail-pln"> __future__ </span><span class="gmail-kwd">import</span><span class="gmail-pln"> print_function

</span><span class="gmail-kwd">import</span><span class="gmail-pln"> ldap
</span><span class="gmail-kwd">from</span><span class="gmail-pln"> ldap</span><span class="gmail-pun">.</span><span class="gmail-pln">filter </span><span class="gmail-kwd">import</span><span class="gmail-pln"> escape_filter_chars

base </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-str">"DC=example,DC=net"</span><span class="gmail-pln">

username </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-str">"<a href="mailto:ADLookup@example.net">ADLookup@example.net</a>"</span><span class="gmail-pln">
password </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-str">"foobar"</span><span class="gmail-pln">

ad </span><span class="gmail-pun">=</span><span class="gmail-pln"> ldap</span><span class="gmail-pun">.</span><span class="gmail-pln">initialize</span><span class="gmail-pun">(</span><span class="gmail-str">"ldap://<a href="http://ad.example.net">ad.example.net</a>"</span><span class="gmail-pun">)</span><span class="gmail-pln">
ad</span><span class="gmail-pun">.</span><span class="gmail-pln">set_option</span><span class="gmail-pun">(</span><span class="gmail-pln">ldap</span><span class="gmail-pun">.</span><span class="gmail-pln">OPT_PROTOCOL_VERSION</span><span class="gmail-pun">,</span><span class="gmail-pln"> ldap</span><span class="gmail-pun">.</span><span class="gmail-pln">VERSION3</span><span class="gmail-pun">)</span><span class="gmail-pln">
ad</span><span class="gmail-pun">.</span><span class="gmail-pln">set_option</span><span class="gmail-pun">(</span><span class="gmail-pln">ldap</span><span class="gmail-pun">.</span><span class="gmail-pln">OPT_REFERRALS</span><span class="gmail-pun">,</span><span class="gmail-pln"> </span><span class="gmail-lit">0</span><span class="gmail-pun">)</span><span class="gmail-pln">
ad</span><span class="gmail-pun">.</span><span class="gmail-pln">bind_s</span><span class="gmail-pun">(</span><span class="gmail-pln">username</span><span class="gmail-pun">,</span><span class="gmail-pln"> password</span><span class="gmail-pun">)</span><span class="gmail-pln">

dn </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-str">"CN=Whalen\\, Sean,OU=Users,OU=Users and Groups,DC=example,DC=net"</span><span class="gmail-pln">

filter_string </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-str">"(memberof:1.2.840.113556.1.4.1941:={0})"</span><span class="gmail-pun">.</span><span class="gmail-pln">format</span><span class="gmail-pun">(</span><span class="gmail-pln">escape_filter_chars</span><span class="gmail-pun">(</span><span class="gmail-pln">dn</span><span class="gmail-pun">))</span><span class="gmail-pln">

</span><span class="gmail-com"># (memberof:1.2.840.113556.1.4.1941:=CN=Whalen\5c, Sean,OU=Users,OU=Users and Groups,DC=example,DC=net)</span><span class="gmail-pln">

</span><span class="gmail-com"># The backslash that escapes the comma in the CN must be escaped in a search filter string,</span><span class="gmail-pln">
</span><span class="gmail-com"># per RFC 2254, page 5</span><span class="gmail-pln">

results </span><span class="gmail-pun">=</span><span class="gmail-pln"> ad</span><span class="gmail-pun">.</span><span class="gmail-pln">search_s</span><span class="gmail-pun">(</span><span class="gmail-pln">base</span><span class="gmail-pun">,</span><span class="gmail-pln">
                      ldap</span><span class="gmail-pun">.</span><span class="gmail-pln">SCOPE_SUBTREE</span><span class="gmail-pun">,</span><span class="gmail-pln">
                      filterstr</span><span class="gmail-pun">=</span><span class="gmail-pln">filter_string</span><span class="gmail-pun">,</span><span class="gmail-pln">
                      attrlist</span><span class="gmail-pun">=[</span><span class="gmail-str">"distinguishedName"</span><span class="gmail-pun">])</span><span class="gmail-pln">
results </span><span class="gmail-pun">=</span><span class="gmail-pln"> </span><span class="gmail-pun">[</span><span class="gmail-pln">entry </span><span class="gmail-kwd">for</span><span class="gmail-pln"> dn</span><span class="gmail-pun">,</span><span class="gmail-pln"> entry </span><span class="gmail-kwd">in</span><span class="gmail-pln"> results </span><span class="gmail-kwd">if</span><span class="gmail-pln"> isinstance</span><span class="gmail-pun">(</span><span class="gmail-pln">entry</span><span class="gmail-pun">,</span><span class="gmail-pln"> dict</span><span class="gmail-pun">)]</span><span class="gmail-pln">
</span><span class="gmail-kwd">print</span><span class="gmail-pun">(</span><span class="gmail-pln">results</span><span class="gmail-pun">)</span></code></pre>

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

<pre class="gmail-lang-py gmail-prettyprint gmail-prettyprinted"><code><span class="gmail-pln">LDIFDE</span><span class="gmail-pun">.</span><span class="gmail-pln">EXE </span><span class="gmail-pun">-</span><span class="gmail-pln">f results</span><span class="gmail-pun">.</span><span class="gmail-pln">txt </span><span class="gmail-pun">-</span><span class="gmail-pln">d </span><span class="gmail-str">"DC=example,DC=net"</span><span class="gmail-pln"> </span><span class="gmail-pun">-</span><span class="gmail-pln">r </span><span class="gmail-str">"(memberof:1.2.840.113556.1.4.1941:=CN=Whalen\, Sean,
OU=Users,OU=Users and Groups,DC=example,DC=net)"</span><span class="gmail-pln"> </span><span class="gmail-pun">-</span><span class="gmail-pln">l </span><span class="gmail-str">"name"</span></code></pre>

<p>Any idea what's going wrong, and how can I fix it?</p>
    Also, I was able to join the list. The confirmation email got buried.<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 30, 2016 at 10:41 PM, Sean Whalen <span dir="ltr"><<a href="mailto:whalenster@gmail.com" target="_blank">whalenster@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div>Right,<br><br></div>but when I use <br><span class="">(member:1.2.840.113556.1.4.<wbr>1941:=CN=Whalen\, Sean,OU=Users,OU=Users and Groups,DC=redacted,DC=net)<br><br></span></div>or<span class=""><br><div><span style="font-size:12.8px">filter = '</span><span style="font-size:12.8px">(member:1.2.840.113556.1.4.</span><span style="font-size:12.8px">19<wbr>41:=CN={0},OU=Users,OU=Users and Groups,DC=redacted,DC=net)'.fo<wbr>rmat(escape_dn_chars('</span><span style="font-size:12.8px">Whalen, Sean'))<br><br></span></div></span><div><span style="font-size:12.8px">I get<br><br>  File "/usr/local/lib/python3.5/<wbr>dist-packages/ldap/ldapobject.<wbr>py", line 768, in search_s<br>    return self.search_ext_s(base,scope,<wbr>filterstr,attrlist,attrsonly,<wbr>None,None,timeout=self.<wbr>timeout)<br>  File "/usr/local/lib/python3.5/<wbr>dist-packages/ldap/ldapobject.<wbr>py", line 761, in search_ext_s<br>    msgid = self.search_ext(base,scope,<wbr>filterstr,attrlist,attrsonly,<wbr>serverctrls,clientctrls,<wbr>timeout,sizelimit)<br>  File "/usr/local/lib/python3.5/<wbr>dist-packages/ldap/ldapobject.<wbr>py", line 757, in search_ext<br>    timeout,sizelimit,<br>  File "/usr/local/lib/python3.5/<wbr>dist-packages/ldap/ldapobject.<wbr>py", line 263, in _ldap_call<br>    result = func(*args,**kwargs)<br>ldap.FILTER_ERROR: {'desc': 'Bad search filter'}<br><br></span></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 30, 2016 at 10:01 PM, Stephen J. Butler <span dir="ltr"><<a href="mailto:stephen.butler@gmail.com" target="_blank">stephen.butler@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">\5C is blackslash itself, not comma. I think what he wants is really:<div><br></div><div>r'<span style="font-size:12.8px">(member:1.2.840.113556.1.4.</span><span style="font-size:12.8px">1<wbr>941:=CN=Whalen\, Sean,OU=Users,OU=Users and Groups,DC=redacted,DC=net)'</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">Notice the raw string. Otherwise, if you aren't using a raw string, then:</span></div><div><span style="font-size:12.8px"><br></span></div><div><div>"<span style="font-size:12.8px">(member:1.2.840.113556.1.4.</span><span style="font-size:12.8px">19<wbr>41:=CN=Whalen\\, Sean,OU=Users,OU=Users and Groups,DC=redacted,DC=net)"</span></div></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">IDK how you're building your DN's in general, but what you should be doing is this when you have arbitrary input:</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">from ldap.dn import escape_dn_chars</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">filter = '</span><span style="font-size:12.8px">(member:1.2.840.113556.1.4.</span><span style="font-size:12.8px">19<wbr>41:=CN={0},OU=Users,OU=Users and Groups,DC=redacted,DC=net)'.fo<wbr>rmat(escape_dn_chars('</span><span style="font-size:12.8px">Whalen, Sean'))</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">That will always do the right thing.</span></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="m_-1380627584247695038h5">On Fri, Sep 30, 2016 at 7:37 PM, Michael Ströder <span dir="ltr"><<a href="mailto:michael@stroeder.com" target="_blank">michael@stroeder.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="m_-1380627584247695038h5"><span>Sean Whalen wrote:<br>
> Then I tried<br>
><br>
> (member:1.2.840.113556.1.4.194<wbr>1:=CN=Whalen\5c, Sean,OU=Users,OU=Users and<br>
</span>                                            ^^^^<br>
Yes, you must escape the comma in the DN.<br>
<br>
But the escaped hex-encoded character \5C must fully *replace* the comma. Or<br>
simply escape the comma like \, (see RFC 4514).<br>
<br>
Bear in mind that you have to deal with extra escaping in Python string syntax<br>
when hard-coding a DN like this in your source code.<br>
<br>
Also note that there can be a bunch of specific performance differences<br>
depending on how and from where you connect and bind to Active Directory,<br>
especially if it's not well maintained (stale directory replicas / site topology).<br>
<br>
Ciao, Michael.<br>
<br>
<br></div></div>______________________________<wbr>_________________<br>
python-ldap mailing list<br>
<a href="mailto:python-ldap@python.org" target="_blank">python-ldap@python.org</a><br>
<a href="https://mail.python.org/mailman/listinfo/python-ldap" rel="noreferrer" target="_blank">https://mail.python.org/mailma<wbr>n/listinfo/python-ldap</a><br>
<br></blockquote></div><br></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>