Skip to content

Instantly share code, notes, and snippets.

@artem-smotrakov
Last active July 29, 2021 18:48
Show Gist options
  • Save artem-smotrakov/0316503009bd1d6a6ce39aa1be171235 to your computer and use it in GitHub Desktop.
Save artem-smotrakov/0316503009bd1d6a6ce39aa1be171235 to your computer and use it in GitHub Desktop.
A simple LDAP server based on Ldaptor
from twisted.application import service, internet
from twisted.internet.endpoints import serverFromString
from twisted.internet.protocol import ServerFactory
from twisted.python.components import registerAdapter
from twisted.python import log
from ldaptor.inmemory import fromLDIFFile
from ldaptor.interfaces import IConnectedLDAPEntry
from ldaptor.protocols.ldap import distinguishedname
from ldaptor.protocols.ldap.ldapserver import LDAPServer
import tempfile
from cStringIO import StringIO
import sys
LDIF = """\
dn: dc=org
dc: org
objectClass: dcObject
dn: dc=example,dc=org
dc: example
objectClass: dcObject
objectClass: organization
dn: ou=people,dc=example,dc=org
objectClass: organizationalUnit
ou: people
dn: cn=bob,ou=people,dc=example,dc=org
cn: bob
gn: Bob
mail: bob@example.org
objectclass: top
objectclass: person
sn: Roberts
telephoneNumber: 555-9999
uid: bob
userPassword: secret
1.1: ololo
dn: gn=John+sn=Doe,ou=people,dc=example,dc=org
objectClass: person
gn: John
sn: Doe
telephoneNumber: 555-7777
street: Back alley
postOfficeBox: 123
postalCode: 54321
postalAddress: Backstreet
st: NY
l: New York City
c: US
uid: johndoe
userPassword: terces
1.1: test
dn: gn=John+sn=Smith,ou=people, dc=example,dc=org
objectClass: person
gn: John
sn: Smith
telephoneNumber: 555-1234
facsimileTelephoneNumber: 555-1235
description: This is a description that can span multi
ple lines as long as the non-first lines are inden
ted in the LDIF.
uid: johnsmith
userPassword: eekretsay
1.1: test
"""
class Tree(object):
def __init__(self):
global LDIF
self.f = StringIO(LDIF)
d = fromLDIFFile(self.f)
d.addCallback(self.ldifRead)
def ldifRead(self, result):
self.f.close()
self.db = result
class LDAPServerFactory(ServerFactory):
protocol = LDAPServer
def __init__(self, root):
self.root = root
def buildProtocol(self, addr):
proto = self.protocol()
proto.debug = self.debug
proto.factory = self
return proto
if __name__ == '__main__':
from twisted.internet import reactor
if len(sys.argv) == 2:
port = int(sys.argv[1])
else:
port = 8080
# First of all, to show logging info in stdout :
log.startLogging(sys.stderr)
# We initialize our tree
tree = Tree()
# When the LDAP Server protocol wants to manipulate the DIT, it invokes
# `root = interfaces.IConnectedLDAPEntry(self.factory)` to get the root
# of the DIT. The factory that creates the protocol must therefore
# be adapted to the IConnectedLDAPEntry interface.
registerAdapter(
lambda x: x.root,
LDAPServerFactory,
IConnectedLDAPEntry)
factory = LDAPServerFactory(tree.db)
factory.debug = True
application = service.Application("ldaptor-server")
myService = service.IServiceCollection(application)
serverEndpointStr = "tcp:{0}".format(port)
e = serverFromString(reactor, serverEndpointStr)
d = e.listen(factory)
reactor.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment