2

I want to open a connection to a ldap directory using ldap url that will be given at run time. For example :

ldap://192.168.2.151/dc=directory,dc=example,dc=com

It is valid as far as I can tell. Python-ldap url parser ldapurl.LDAPUrl accepts it.

url = 'ldap://192.168.2.151/dc=directory,dc=example,dc=com'
parsed_url = ldapurl.LDAPUrl(url)
parsed_url.dn
'dc=directory,dc=example,dc=com'

But if I use it to initialize a LDAPObject, I get a ldap.LDAPError exception

ldap.initialize(url)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/dist-packages/ldap/functions.py", line 91, in initialize
    return LDAPObject(uri,trace_level,trace_file,trace_stack_limit)
  File "/usr/lib/python2.7/dist-packages/ldap/ldapobject.py", line 70, in __init__
    self._l = ldap.functions._ldap_function_call(ldap._ldap_module_lock,_ldap.initialize,uri)
File "/usr/lib/python2.7/dist-packages/ldap/functions.py", line 63, in _ldap_function_call
  result = func(*args,**kwargs)
ldap.LDAPError: (0, 'Error')

I found that if I manually encode the dn part of the url, it works :

url = 'ldap://192.168.2.151/dc=directory%2cdc=example%2cdc=com'

#url still valid
parsed_url = ldapurl.LDAPUrl(url)
parsed_url.dn
'dc=directory,dc=example,dc=com'

#and will return a valid connection
ldap.initialize(url)
<ldap.ldapobject.SimpleLDAPObject instance at 0x1400098>

How can I ensure robust url handling in ldap.initialize without encoding parts of the url myself ? (which, I'm afraid, won't be that robust anyway).

2 Answers 2

1

You can programatically encode the last part of the URL:

from urllib import quote       # works in Python 2.x
from urllib.parse import quote # works in Python 3.x

url = 'ldap://192.168.2.151/dc=directory,dc=paralint,dc=com'
idx = url.rindex('/') + 1
url[:idx] + quote(url[idx:], '=')
=> 'ldap://192.168.2.151/dc=directory%2Cdc=paralint%2Cdc=com'
Sign up to request clarification or add additional context in comments.

4 Comments

Forgot to mention : url are given at runtime. I would like to avoid any parsing or string splitting.
Tried it already, it gives me the same error. ldapurl.htmlHREF() does return a string that ldap.initialize() will accept, but wrapped in <a> tags. For now, I extract it with a <(.*)>(.*)<(.*)>$ regex.
mmm ok. I know you want to avoid splitting the string, but it shouldn't be a big deal, just find the rightmost '/' using rindex and just encode the text to the right of it
Thanks, I'll give it a try, +1. But I will did some more before accepting.
1

One can use LDAPUrl.unparse() method to get a properly encoded version of the URI, like this :

>>> import ldapurl
>>> url = ldapurl.LDAPUrl('ldap://192.168.2.151/dc=directory,dc=example,dc=com')
>>> url.unparse()
'ldap://192.168.2.151/dc%3Ddirectory%2Cdc%3Dparalint%2Cdc%3Dcom???'
>>> ldap.initialize(url.unparse())
<ldap.ldapobject.SimpleLDAPObject instance at 0x103d998>

And LDAPUrl.unparse() will not reencode an already encoded url :

>>> url = ldapurl.LDAPUrl('ldap://example.com/dc%3Dusers%2Cdc%3Dexample%2Cdc%3Dcom%2F???')
>>> url.unparse()
'ldap://example.com/dc%3Dusers%2Cdc%3Dexample%2Cdc%3Dcom%2F???'

So you can use it blindly on any ldap uri your program must handle.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.