Welcome on my blog
I'll try to contribute my -modest- knowledge to the community.
Here you'll find samples of python twisted code but also some network configurations.

Hoping you'll find it usefull.

cat 'tonthon\'s brain' > /dev/null

Tuesday, February 8, 2011

Ldaptor : ldap with twisted, client side


Ldaptor is an ldap library build on top of python and twisted, it provides :

  • LDAP client logic

  • Separately-accessible LDAP and BER protocol message generation/parsing

  • ASCII-format LDAP filter generation and parsing

  • LDIF format data generation

  • Samba password changing logic

Here we will use the client-side tools to retrieve datas from our ldap server.
We will use the ldap server written there :
ldaptor : ldap with twisted, server-side

Quick overview

  • The connector
    A connector is used to wrap the ldap client, this connector looks up DNS SRV records.

    >>> from ldaptor.protocols.ldap.ldapconnector import LDAPClientCreator
    >>> from ldaptor.protocols.ldap.ldapclient import LDAPClient
    >>> from twisted.internet import reactor
    >>> clientBuilder = LDAPClientCreator(reactor, LDAPClient)
    >>> print clientBuilder
    <ldaptor.protocols.ldap.ldapconnector.LDAPClientCreator instance at 0xb753830c>

    You can then build clients for different ldap servers.

  • The DN object

    >>> from ldaptor.protocols.ldap.distinguishedname import DistinguishedName as DN
    >>> dn = DN('dc=example,dc=com')
    >>> print dn
    >>> print dn.getDomainName()

  • Bind to a remote server
    You then build a client for that given DN

    >>> binded_client = clientBuilder.connectAnonymously(dn, overrides={dn:('localhost', 8080)})
    >>> print binded_client
    <Deferred at 0xa44268c>

    The connectAnonymously method connect to the remote host and binds automatically.
    Note : Here we override the remote's adress to avoid DNS lookup.

    To make authenticated bindings :

    >>> userdn = DN('uid=esteban,ou=people,dc=example,dc=fr')
    >>> client = clientBuilder.connect(dn, {dn:('localhost', 8080)})
    >>> client.addCallback(lambda client:LDAPEntry(client=client,

    We first connect to the remote and then build an ldapentry with our userdn which we bind with the given password.

Here is a full example retrieving datas from the previous-described server.
Put all this stuff into a file you call client.py, run the server and launch a `python client.py`

Simple Ldaptor client
import sys

from twisted.python import log
from twisted.internet import reactor

from ldaptor.protocols.ldap.distinguishedname import DistinguishedName as DN
from ldaptor.ldapfilter import parseFilter
from ldaptor.protocols.ldap.ldapsyntax import LDAPEntry
from ldaptor.protocols.ldap.ldapconnector import LDAPClientCreator
from ldaptor.protocols.ldap.ldapclient import LDAPClient

class Client:
Simple Ldap client to retrieve user's informations
def __init__(self, dn, host, port):
dn = DN(dn)
self.config = dict(base=dn,
server={dn:(host, port)})
self.clientBuilder = LDAPClientCreator(reactor, LDAPClient)
def bind(self):
returns a deferred anonymous connection
return self.clientBuilder.connectAnonymously(
def _unbindAndReturn(result, client):
Unbind the binded client
return result
def buildBase(self, client):
return the base ldap entry the search will
be run from
return LDAPEntry(client=client, dn=self.config['base'])
def _search(self, client, login):
Launch our search
ldapFilter = parseFilter('(uid=%s)' % login)
base = self.buildBase(client)
return base.search(filterObject=ldapFilter).addBoth(
self._unbindAndReturn, client)
def _formatRes(results, attributes):
Format results to get only the attributes we wanted to keep
for result in results:
yield dict([(attr, list(result.get(attr)))
for attr in attributes])
def getUser(self, login, attributes):
Public method used to retrieve ldap user's infos
deferred = self.bind()
deferred.addCallback(self._search, login)
deferred.addCallback(self._formatRes, attributes)
return deferred

def main():
def printRes(results):
for res in results:
client = Client('dc=fr', '', 8080)
datas = client.getUser('yoen', ('mail','sn'))
reactor.callLater(3, reactor.stop)

if __name__ == '__main__':

No comments:

Post a Comment