Given the following schema: Lets suppose that we want to get the address of the user Nick Tesla. In the case of MySQL, it would be accomplished by a query like this:
SELECT user.cn, ou.Address FROM User u, OrgUnit ou WHERE u.cn = "Nick Tesla" AND ou.name = u.EduPersonOrgUnitDNThis objective, can be easily completed in SQL by using a JOIN operation (an implicit inner join in this example), in order to combine the resulting sets that we are interested in. In the case of LDAP, this is simply not possible. In many textbooks and presentations, this is described as one of the major "common problems" with LDAP, actually!
The role and purpose of SQL databases is mainly to store large amounts of data and encapsulate business logic, which results in complex queries running concurrently. On the other hand, the main role of LDAP databases is that of authentication and address books, which concludes to many quick read requests. The main benefits of LDAP are its blinding speed and the interoperability offered by the enforcement of strict standards. But for all its advantages and for all intents ant purposes, LDAP is not relational. (A simple -yet good- explanation can be found here. A detailed analysis -from the developers of OpenLDAP themselves- can be found here)
Once upon a time, it was common practice to have a single ldap tree hierarchy, which would branch on the basis of organizations and then hang all the users under their respective organizational unit -schema 1- . Over the years, this was deemed inefficient (for a variety of reasons, such as moving entries or even entire subtrees due to changes in persons and/or organizational units, data replication and redundancy etc). The basic pattern of the best practice which emerged, is to hold all the people under a single arc -a.k.a. subtree- (such as ou=people) and organizations under another arc (such as ou=departments) -schema 2- .
The dereference plugin, is a pre op search plugin, provided by the control (see also) of the same name, with the experimental oid (see also) 1.3.6.1.4.1.4203.666.5.16 (for more information, you can read the corresponding RFC). With the usage of this plugin, a service can discover and retrieve extra attributes, not available in the main user object, with a single operation. In any other case, more steps would have to be added. Either by talking to the LDAP server itself -which would mean that the LDAP server itself must be available- or by talking to another service which would publish these extra attributes. These mechanisms, help to further the use of application isolation strategies and the streamlined use of the LDAP service.
For example, given these entries:
dn: cn=Nick Tesla,ou=people,dc=example,dc=org objectClass: inetOrgPerson cn: Nick Tesla sn: Tesla uid: nt eduPersonOrgUnitDN: cn=Faculty,ou=groups,dc=example,dc=org
dn: cn=Faculty,ou=groups,dc=example,dc=org objectClass: groupOfNames cn: Faculty member: cn=Nick Tesla,ou=people,dc=example,dc=org address: Panepistimioupolis AthensA search could be performed with a Dereference request control value specified as:
{ eduPersonOrgUntiDN.address, uid }and the "cn=Faculty" entry would be returned with the response control value -alongside the main entry's ("cn=Nick Tesla") attributes- :
{ { address, Panepistimoupolis Athens, { { uid, [nt] } } } }
Lets demonstrate how the dereference plugin works by an example.
Suppose you have the following simple ldap query:
ldapsearch -h example.com -b personID=001,ou=faculty,dc=example,dc=com uid=001Which would yield the following results (in extended ldif format):
# extended LDIF # # LDAPv3 # base <personID=001,ou=faculty,dc=example,dc=com> with scope subtree # filter: uid=001 # requesting: ALL # # 001, faculty, example.com dn: personID=001,ou=faculty,dc=example,dc=com personID: 001 FacultyDepartment:: Physics FacultyDepartmentID: 1856 ou:: Physics givenName:: Nick uid: 001 cn:: Nick Tesla personAffiliation: inventor extraordinaire eduPersonOrgUnitDN: ou=1856,ou=units,dc=example,dc=com # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1The same query, by adding a dereference control value in order to get the cn, ou and address attributes of the eduPersonPrimaryOrgUnit DN, would become like this:
ldapsearch -h example.com -b personID=001,ou=faculty,dc=example,dc=com uid=001 -E "deref=eduPersonPrimaryOrgUnitDN:cn,ou,address"And produce results like this:
# extended LDIF # # LDAPv3 # base <personID=001,ou=faculty,dc=example,dc=com> with scope subtree # filter: uid=001 # requesting: ALL # with dereference control # # 001, faculty, example.com dn: personID=001,ou=people,dc=example,dc=com control: 1.3.6.1.4.1.4203.666.5.16 false MIHSMIHPBBllZHVQZXJzb25QcmltYXJ5T3JnV W5pdEROBB5vdT00MTgsb3U9dW5pdHMsZGM9Z3VuZXQsZGM9Z3KggZEwYAQCY24xWgRYzqDOoc6fzp POoc6RzpzOnM6RIM6VzprOms6bzpfOo86ZzpHOo86kzpnOms6XzqMgzpzOn86lzqPOmc6azpfOoyD Oms6RzpkgzqjOkc6bzqTOmc6azpfOozALBAJvdTEFBAM0MTgwIAQQYnVzaW5lc3NDYXRlZ29yeTEM BApkZXBhcnRtZW50 # eduPersonOrgUnitDN: <cn:=Physics>;<ou=1856>;<address=Panepistimioupolis Athens>;ou=1856,ou=units,dc=example,dc=com # 001, faculty, example.com dn: personID=001,ou=faculty,dc=example,dc=com personID: 001 FacultyDepartment:: Physics FacultyDepartmentID: 1856 ou:: Physics givenName:: Nick uid: 001 cn:: Nick Tesla personAffiliation: professor eduPersonOrgUnitDN: ou=1856,ou=units,dc=example,dc=com # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1