Erlang Central

Difference between revisions of "How to talk LDAP from Erlang"

From ErlangCentral Wiki

m (Revert vandalism)
(4 intermediate revisions by 4 users not shown)
Line 1:Line 1:
 +
==Author==
 +
Tobbe
 +
 
==How to talk LDAP from Erlang==
 
==How to talk LDAP from Erlang==
 
===Introduction===
 
===Introduction===
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>THIS IS WORK IN PROGRESS !!</p></td></tr></table>
 
  
 
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:  
 
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:  
  
<table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
+
{{CodeSnippet|Code listing 1.1: An LDAP entry|<pre>
<tr><td class="infohead" bgcolor="#7a5ada"><p class="caption">
+
            Code listing 1.1: An LDAP entry</p></td></tr>
+
<tr><td bgcolor="#ddddff"><pre>
+
 
dn: uid=tobbe,ou=People,dc=bluetail,dc=com
 
dn: uid=tobbe,ou=People,dc=bluetail,dc=com
 
objectClass: inetOrgPerson
 
objectClass: inetOrgPerson
Line 18:Line 17:
 
telephoneNumber: +46 8 555 55 555
 
telephoneNumber: +46 8 555 55 555
 
facsimileTelephoneNumber: +46 8 444 44 44
 
facsimileTelephoneNumber: +46 8 444 44 44
</pre></td></tr>
+
</pre>}}
</table>
+
  
 
Note the attributes to left, where the <b>dn:</b> at the
 
Note the attributes to left, where the <b>dn:</b> at the
Line 42:Line 40:
 
should use the port 636).
 
should use the port 636).
  
<table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
+
{{CodeSnippet|Code listing 1.2: Authenticating a user|<pre>
<tr><td class="infohead" bgcolor="#7a5ada"><p class="caption">
+
            Code listing 1.2: Authenticating a user</p></td></tr>
+
<tr><td bgcolor="#ddddff"><pre>
+
 
1&gt; {_,S} = eldap:open(["192.168.128.51"], []).
 
1&gt; {_,S} = eldap:open(["192.168.128.51"], []).
 
{ok,&lt;0.32.0&gt;}
 
{ok,&lt;0.32.0&gt;}
Line 52:Line 47:
 
3&gt; eldap:simple_bind(S, DN, "qwe123").
 
3&gt; eldap:simple_bind(S, DN, "qwe123").
 
ok
 
ok
</pre></td></tr>
+
</pre>}}
</table>
+
  
 
===Searching for an entry.===
 
===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.  
 
Now, when we have authenticated ourself, we will perform a search of an entry where we will retrieve just one single attribute. file.  
  
<table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
+
{{CodeSnippet|Code listing 1.3: Searching for an LDAP entry|<pre>
<tr><td class="infohead" bgcolor="#7a5ada"><p class="caption">
+
            Code listing 1.3: Searching for an LDAP entry</p></td></tr>
+
<tr><td bgcolor="#ddddff"><pre>
+
 
4&gt; Base = {base,DN}.
 
4&gt; Base = {base,DN}.
 
{base,"uid=tobbe,ou=People,dc=bluetail,dc=com"}
 
{base,"uid=tobbe,ou=People,dc=bluetail,dc=com"}
Line 81:Line 72:
 
                     attributes = [{"cn",["Torbjorn Tornkvist"]}]}],
 
                     attributes = [{"cn",["Torbjorn Tornkvist"]}]}],
 
       referrals = []}}
 
       referrals = []}}
</pre></td></tr>
+
</pre>}}
</table>
+
  
 
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>Note that we have made use of the fantastic shell command <b>rr/1</b>
 
<table class="ncontent" width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td bgcolor="#bbffbb"><p class="note"><b>Note: </b>Note that we have made use of the fantastic shell command <b>rr/1</b>
Line 90:Line 80:
 
As a variation, let us see what happends if we don't specify any attributes to be retrieved.  
 
As a variation, let us see what happends if we don't specify any attributes to be retrieved.  
  
<table class="ntable" width="100%" cellspacing="0" cellpadding="0" border="0">
+
{{CodeSnippet|Code listing 1.4: Searching for an LDAP entry, take II|<pre>
<tr><td class="infohead" bgcolor="#7a5ada"><p class="caption">
+
            Code listing 1.4: Searching for an LDAP entry, take II</p></td></tr>
+
<tr><td bgcolor="#ddddff"><pre>
+
 
15&gt; Search = [Base, Scope, Filter].
 
15&gt; Search = [Base, Scope, Filter].
 
[{base,"uid=tobbe,ou=People,dc=bluetail,dc=com"},
 
[{base,"uid=tobbe,ou=People,dc=bluetail,dc=com"},
Line 131:Line 118:
 
                       {"isdUserPrefs",[[131,104,3|...]]}]}],
 
                       {"isdUserPrefs",[[131,104,3|...]]}]}],
 
       referrals = []}}
 
       referrals = []}}
</pre></td></tr>
+
</pre>}}
</table>
+
  
 
As you can see we got back the whole entry.
 
As you can see we got back the whole entry.
Line 140:Line 126:
  
 
[[Category:HowTo]]
 
[[Category:HowTo]]
 +
[[Category:Interfacing Erlang]]

Revision as of 07:32, 11 June 2007

Contents

Author

Tobbe

How to talk LDAP from Erlang

Introduction

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
mail: tobbe@bluetail.com
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(["192.168.128.51"], []).
{ok,<0.32.0>}
2> DN = "uid=tobbe,ou=People,dc=bluetail,dc=com".
"uid=tobbe,ou=People,dc=bluetail,dc=com"
3> eldap:simple_bind(S, DN, "qwe123").
ok

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}.
{base,"uid=tobbe,ou=People,dc=bluetail,dc=com"}
5> Scope = {scope, eldap:baseObject()}.
{scope,baseObject}
6> Filter = {filter, eldap:present("cn")}.
{filter,{present,"cn"}}
7> Attribute = {attributes, ["cn"]}.
{attributes,["cn"]}
8> Search = [Base, Scope, Filter, Attribute].
[{base,"uid=tobbe,ou=People,dc=bluetail,dc=com"},
 {scope,baseObject},
 {filter,{present,"cn"}},
 {attributes,["cn"]}]
9> eldap:search(S, Search).
{ok,#eldap_search_result{
       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.

As a variation, let us see what happends 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].
[{base,"uid=tobbe,ou=People,dc=bluetail,dc=com"},
 {scope,baseObject},
 {filter,{present,"cn"}}]
16> eldap:search(S, Search).
{ok,#eldap_search_result{
       entries = [#eldap_entry{
                     object_name = "uid=tobbe,ou=People,dc=bluetail,dc=com",
                     attributes = [
                       {"objectClass",
                        ["inetOrgPerson",
                         "nortelSSLOffload",
                         "extensibleObject"]},
                       {"cn",
                        ["Torbjorn Tornkvist"]},
                       {"sn",
                        ["Tornkvist"]},
                       {"uid",
                        ["tobbe"]},
                       {"listName",
                        ["contacts"]},
                       {"mail",
                        ["tobbe@bluetail.com"]},
                       {"telephoneNumber",
                        ["+46 8 545 55 023"]},
                       {"facsimileTelephoneNumber",
                        ["+46 8 654 70 71"]},
                       {"description",
                        ["/o=Demo/ou=First Administrative Group/cn=hejsan/cn=Servers/cn=inside"]},
                       {"title",
                        ["inside"]},
                       {"employeeType",
                        ["guest"]},
                       {"userPassword",
                        ["{SSHA}/tsm+Mz8fQi/dBFzHpV2iXfO1O7LVPt3"]},
                       {"isdUserPrefs",[[131,104,3|...]]}]}],
       referrals = []}}

As you can see we got back the whole entry.

Download xml

howto_talking_ldap.xml