In setting out to implement LDAP we had three goals in mind:
- provide a freely available reference implementation of the protocol;
- enable the development of LDAP clients on a wide variety of platforms;
and
- solve the problem of providing access to our campus X.500 directory.
In addition, we have found our implementation has been incorporated into
a number of vendor offerings, increasing the availability of LDAP products.
Our LDAP implementation has three main components: a server, a client library,
and various clients. Our LDAP server, ldapd, is based on the popular
ISO Development Environment (ISODE) package. We use the ISODE OSI stack
implementation and DAP client library to access X.500. The ldapd server
supports connections to multiple X.500 servers, providing efficient handling
of referrals.
The ldapd server can be run as a UNIX stand-alone daemon or from
inetd, the UNIX Internet protocol daemon. It accepts connections
from LDAP clients, forking off a copy of itself to handle each connection.
It also supports connectionless LDAP (CLDAP) [10], a version of LDAP that
runs over UDP or other connectionless transport. CLDAP is useful in applications
where speed is paramount, the information desired is small, and the connection
setup overhead of LDAP is too large.
Key to the success of our LDAP implementation has been libldap, the
LDAP client library. The libldap library gives programmers a simple yet
powerful C Language API for accessing the X.500 directory through LDAP.
The library is self-contained, including the necessary ASN.1/BER routines
for producing and reading LDAP protocol elements. It contains routines to
begin and end sessions with the directory, perform searches and other operations,
and parse and display the results obtained from the directory. Figure 4
is a C code fragment showing a simple use of libldap. It illustrates
the synchronous interface provided by libldap. Asynchronous routines
are also provided.
#include <ldap.h>
LDAP *ld;
LDAPMessage *e, *r;
char *a, *dn;
/* open a connection and authenticate */
if ((ld = ldap_open("hostname", LDAP_PORT))
== NULL)
fail();
if (ldap_simple_bind_s(ld, NULL, NULL) !=
LDAP_SUCCESS)
fail();
/* search for entries, return all attrs */
if (ldap_search_s(ld, "c=US", LDAP_SCOPE_ONELEVEL,
"o=*michigan*", NULL, 0, &r) != LDAP_SUCCESS)
fail();
/* step through each entry returned */
for (e = ldap_first_entry(ld, r); e != NULL;
e = ldap_next_entry(ld, e)) {
/* get and print the entry name */
dn = ldap_getdn(ld, e);
printf("entry: %s\n", dn);
free(dn);
/* step through each attribute */
for (a = ldap_first_attribute(ld, e);
a != NULL;
a = ldap_next_attribute(ld, e, a)) {
printf("attr: %s\n", a);
/* get and print vals */
v = ldap_get_values(ld, e, a);
for (i = 0; v[i] != NULL; i++) {
printf("val: %s\n", v[i]);
}
ldap_value_free(v);
}
Figure 4. Sample libldap code