Erlang Central

How to talk LDAP from Erlang

From ErlangCentral Wiki




How to talk LDAP from Erlang


LDAP (Lightweight Directory Access Protocol) is described in RFC xxxx. It comprises of not just a protocol but also of an abstract model of the data. Basically, think of the data as being stored in a tree. Each node (or entry) has a name (a Relative Distinguished Name). By concatenating the RDN's, while traversing the tree, you get a path (or name) that uniquely identifies a particular entry (the Distinguished Name, DN). Data is modelled as object classes each class containing a number of mandatory and optional attributes. A particular LDAP entry can be seen as an instance of one (or more) class(es). Example of such an entry can be seen below:

Code listing 1.1: An LDAP entry

dn: uid=tobbe,ou=People,dc=bluetail,dc=com
objectClass: inetOrgPerson
cn: Torbjorn Tornkvist
sn: Tornkvist
uid: tobbe
userPassword: {SSHA}Rj4mgDuKguD1xqLRQ2V6YKEzRajNORA6
telephoneNumber: +46 8 555 55 555
facsimileTelephoneNumber: +46 8 444 44 44

Note the attributes to left, where the dn: at the top holds the unique name of the entry (the DN). As you can see, an entry may contain a (encrypted) password. This makes it possible to use LDAP for authentication of users. Normally it is often possible to search (or lookup) data without having to authenticate (it depends on how the LDAP server is configured). We will look at how we can use the eldap library to communicate with an LDAP server. </p>

In this example I have been using OTP-R10B-3 release and the jerl Jungerl start script. By using the Jungerl start script I automatically get eldap in my path.

Authenticate with eldap

We start by setting up a TCP socket to the LDAP server. The default port (389) will be used if you don't specify another port in the option list as {port,Port}. It is also possible to setup a SSL connection by using the {ssl,true} option (note that you then probably also should use the port 636).

Code listing 1.2: Authenticating a user

1> {_,S} = eldap:open([""], []).
2> DN = "uid=tobbe,ou=People,dc=bluetail,dc=com".
3> eldap:simple_bind(S, DN, "qwe123").

Searching for an entry.

Now, when we have authenticated ourself, we will perform a search of an entry where we will retrieve just one single attribute. file.

Code listing 1.3: Searching for an LDAP entry

4> Base = {base,DN}.
5> Scope = {scope, eldap:baseObject()}.
6> Filter = {filter, eldap:present("cn")}.
7> Attribute = {attributes, ["cn"]}.
8> Search = [Base, Scope, Filter, Attribute].
9> eldap:search(S, Search).
       entries = [#eldap_entry{
                     object_name = "uid=tobbe,ou=People,dc=bluetail,dc=com",
                     attributes = [{"cn",["Torbjorn Tornkvist"]}]}],
       referrals = []}}

Note: Note that we have made use of the fantastic shell command rr/1

(as in rr(eldap)) before issuing the call to eldap:search/2. This gives

us the output in a nice record format.

Note that as an 'empty filter', you can/should use

that corresponds to the default filter '(objectClass=*)' of ldapsearch.

As a variation, let us see what happens if we don't specify any attributes to be retrieved.

Code listing 1.4: Searching for an LDAP entry, take II

15> Search = [Base, Scope, Filter].
16> eldap:search(S, Search).
       entries = [#eldap_entry{
                     object_name = "uid=tobbe,ou=People,dc=bluetail,dc=com",
                     attributes = [
                        ["Torbjorn Tornkvist"]},
                        ["+46 8 545 55 023"]},
                        ["+46 8 654 70 71"]},
                        ["/o=Demo/ou=First Administrative Group/cn=hejsan/cn=Servers/cn=inside"]},
       referrals = []}}

As you can see we got back the whole entry.

Download xml