1236 lines
41 KiB
Plaintext
1236 lines
41 KiB
Plaintext
|
||
|
||
|
||
|
||
|
||
|
||
Network Working Group T. Howes
|
||
Request for Comments: 1823 M. Smith
|
||
Category: Informational University of Michigan
|
||
August 1995
|
||
|
||
|
||
The LDAP Application Program Interface
|
||
|
||
Status of this Memo
|
||
|
||
This memo provides information for the Internet community. This memo
|
||
does not specify an Internet standard of any kind. Distribution of
|
||
this memo is unlimited.
|
||
|
||
1. Introduction
|
||
|
||
This document defines a C language application program interface to
|
||
the lightweight directory access protocol (LDAP). The LDAP API is
|
||
designed to be powerful, yet simple to use. It defines compatible
|
||
synchronous and asynchronous interfaces to LDAP to suit a wide
|
||
variety of applications. This document gives a brief overview of the
|
||
LDAP model, then an overview of how the API is used by an application
|
||
program to obtain LDAP information. The API calls are described in
|
||
detail, followed by an appendix that provides some example code
|
||
demonstrating the use of the API.
|
||
|
||
2. Overview of the LDAP Model
|
||
|
||
LDAP is the lightweight directory access protocol, described in [2]
|
||
and [7]. It can provide a lightweight frontend to the X.500 directory
|
||
[1], or a stand-alone service. In either mode, LDAP is based on a
|
||
client-server model in which a client makes a TCP connection to an
|
||
LDAP server, over which it sends requests and receives responses.
|
||
|
||
The LDAP information model is based on the entry, which contains
|
||
information about some object (e.g., a person). Entries are composed
|
||
of attributes, which have a type and one or more values. Each
|
||
attribute has a syntax that determines what kinds of values are
|
||
allowed in the attribute (e.g., ASCII characters, a jpeg photograph,
|
||
etc.) and how those values behave during directory operations (e.g.,
|
||
is case significant during comparisons).
|
||
|
||
Entries are organized in a tree structure, usually based on
|
||
political, geographical, and organizational boundaries. Each entry is
|
||
uniquely named relative to its sibling entries by its relative
|
||
distinguished name (RDN) consisting of one or more distinguished
|
||
attribute values from the entry. At most one value from each
|
||
attribute may be used in the RDN. For example, the entry for the
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 1]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
person Babs Jensen might be named with the "Barbara Jensen" value
|
||
from the commonName attribute. A globally unique name for an entry,
|
||
called a distinguished name or DN, is constructed by concatenating
|
||
the sequence of RDNs from the root of the tree down to the entry. For
|
||
example, if Babs worked for the University of Michigan, the DN of her
|
||
U-M entry might be "cn=Barbara Jensen, o=University of Michigan,
|
||
c=US". The DN format used by LDAP is defined in [4].
|
||
|
||
Operations are provided to authenticate, search for and retrieve
|
||
information, modify information, and add and delete entries from the
|
||
tree. The next sections give an overview of how the API is used and
|
||
detailed descriptions of the LDAP API calls that implement all of
|
||
these functions.
|
||
|
||
3. Overview of LDAP API Use
|
||
|
||
An application generally uses the LDAP API in four simple steps.
|
||
|
||
o Open a connection to an LDAP server. The ldap_open() call
|
||
returns a handle to the connection, allowing multiple
|
||
connections to be open at once.
|
||
|
||
o Authenticate to the LDAP server and/or the X.500 DSA. The
|
||
ldap_bind() call and friends support a variety of
|
||
authentication methods.
|
||
|
||
o Perform some LDAP operations and obtain some results.
|
||
ldap_search() and friends return results which can be parsed
|
||
by ldap_result2error(), ldap_first_entry(), ldap_next_entry(),
|
||
etc.
|
||
|
||
o Close the connection. The ldap_unbind() call closes the
|
||
connection.
|
||
|
||
Operations can be performed either synchronously or asynchronously.
|
||
Synchronous calls end in _s. For example, a synchronous search can be
|
||
completed by calling ldap_search_s(). An asynchronous search can be
|
||
initiated by calling ldap_search(). All synchronous routines return
|
||
an indication of the outcome of the operation (e.g, the constant
|
||
LDAP_SUCCESS or some other error code). The asynchronous routines
|
||
return the message id of the operation initiated. This id can be used
|
||
in subsequent calls to ldap_result() to obtain the result(s) of the
|
||
operation. An asynchronous operation can be abandoned by calling
|
||
ldap_abandon().
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 2]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
Results and errors are returned in an opaque structure called
|
||
LDAPMessage. Routines are provided to parse this structure, step
|
||
through entries and attributes returned, etc. Routines are also
|
||
provided to interpret errors. The next sections describe these
|
||
routines in more detail.
|
||
|
||
4. Calls for performing LDAP operations
|
||
|
||
This section describes each LDAP operation API call in detail. All
|
||
calls take a "connection handle", a pointer to an LDAP structure
|
||
containing per-connection information. Many routines return results
|
||
in an LDAPMessage structure. These structures and others are
|
||
described as needed below.
|
||
|
||
4.1. Opening a connection
|
||
|
||
ldap_open() opens a connection to the LDAP server.
|
||
|
||
typedef struct ldap {
|
||
/* ... opaque parameters ... */
|
||
int ld_deref;
|
||
int ld_timelimit;
|
||
int ld_sizelimit;
|
||
int ld_errno;
|
||
char *ld_matched;
|
||
char *ld_error;
|
||
/* ... opaque parameters ... */
|
||
} LDAP;
|
||
|
||
LDAP *ldap_open( char *hostname, int portno );
|
||
|
||
Parameters are:
|
||
|
||
hostname Contains a space-separated list of hostnames or dotted
|
||
strings representing the IP address of hosts running an
|
||
LDAP server to connect to. The hosts are tried in the
|
||
order listed, stopping with the first one to which a
|
||
successful connection is made;
|
||
|
||
portno contains the TCP port number to which to connect. The
|
||
default LDAP port can be obtained by supplying the
|
||
constant LDAP_PORT.
|
||
|
||
ldap_open() returns a "connection handle", a pointer to an LDAP
|
||
structure that should be passed to subsequent calls pertaining to the
|
||
connection. It returns NULL if the connection cannot be opened. One
|
||
of the ldap_bind calls described below must be completed before other
|
||
operations can be performed on the connection.
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 3]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
The calling program should assume nothing about the order of the
|
||
fields in the LDAP structure. There may be other fields in the
|
||
structure for internal library use. The fields shown above are
|
||
described as needed in the description of other calls below.
|
||
|
||
4.2. Authenticating to the directory
|
||
|
||
ldap_bind() and friends are used to authenticate to the directory.
|
||
|
||
int ldap_bind( LDAP *ld, char *dn, char *cred, int method );
|
||
|
||
int ldap_bind_s( LDAP *ld, char *dn, char *cred, int method );
|
||
|
||
int ldap_simple_bind( LDAP *ld, char *dn, char *passwd );
|
||
|
||
int ldap_simple_bind_s( LDAP *ld, char *dn, char *passwd );
|
||
|
||
int ldap_kerberos_bind( LDAP *ld, char *dn );
|
||
|
||
int ldap_kerberos_bind_s( LDAP *ld, char *dn );
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
dn The name of the entry to bind as;
|
||
|
||
cred The credentials with which to authenticate;
|
||
|
||
method One of LDAP_AUTH_SIMPLE, LDAP_AUTH_KRBV41, or
|
||
LDAP_AUTH_KRBV42, indicating the authentication method to use;
|
||
|
||
passwd For ldap_simple_bind(), the password to compare to the entry's
|
||
userPassword attribute;
|
||
|
||
There are three types of bind calls, providing simple authentication,
|
||
kerberos authentication, and general routines to do either one. In
|
||
the case of Kerberos version 4 authentication using the general
|
||
ldap_bind() routines, the credentials are ignored, as the routines
|
||
assume a valid ticket granting ticket already exists which can be
|
||
used to retrieve the appropriate service tickets.
|
||
|
||
Synchronous versions of the routines have names that end in _s.
|
||
These routines return the result of the bind operation, either the
|
||
constant LDAP_SUCCESS if the operation was successful, or another
|
||
LDAP error code if it was not. See the section below on error
|
||
handling for more information about possible errors and how to
|
||
interpret them.
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 4]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
Asynchronous versions of these routines return the message id of the
|
||
bind operation initiated. A subsequent call to ldap_result(),
|
||
described below, can be used to obtain the result of the bind. In
|
||
case of error, these routines will return -1, setting the ld_errno
|
||
field in the LDAP structure appropriately.
|
||
|
||
Note that no other operations over the connection should be attempted
|
||
before a bind call has successfully completed. Subsequent bind calls
|
||
can be used to re-authenticate over the same connection.
|
||
|
||
4.3. Closing the connection
|
||
|
||
ldap_unbind() is used to unbind from the directory and close the
|
||
connection.
|
||
|
||
int ldap_unbind( LDAP *ld );
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle.
|
||
|
||
ldap_unbind() works synchronously, unbinding from the directory,
|
||
closing the connection, and freeing up the ld structure before
|
||
returning. ldap_unbind() returns LDAP_SUCCESS (or another LDAP error
|
||
code if the request cannot be sent to the LDAP server). After a call
|
||
to ldap_unbind(), the ld connection handle is invalid.
|
||
|
||
4.4. Searching
|
||
|
||
ldap_search() and friends are used to search the LDAP directory,
|
||
returning a requested set of attributes for each entry matched.
|
||
There are three variations.
|
||
|
||
struct timeval {
|
||
long tv_sec;
|
||
long tv_usec;
|
||
};
|
||
int ldap_search(
|
||
LDAP *ld,
|
||
char *base,
|
||
int scope,
|
||
char *filter,
|
||
char *attrs[],
|
||
int attrsonly
|
||
);
|
||
int ldap_search_s(
|
||
LDAP *ld,
|
||
char *base,
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 5]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
int scope,
|
||
char *filter,
|
||
char *attrs[],
|
||
int attrsonly,
|
||
LDAPMessage **res
|
||
);
|
||
int ldap_search_st(
|
||
LDAP *ld,
|
||
char *base,
|
||
int scope,
|
||
char *filter,
|
||
char *attrs[],
|
||
int attrsonly,
|
||
struct timeval *timeout,
|
||
LDAPMessage **res
|
||
);
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
base The dn of the entry at which to start the search;
|
||
|
||
scope One of LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL, or
|
||
LDAP_SCOPE_SUBTREE, indicating the scope of the search;
|
||
|
||
filter A character string as described in RFC 1558 [3],
|
||
representing the search filter;
|
||
|
||
attrs A NULL-terminated array of strings indicating which
|
||
attributes to return for each matching entry. Passing
|
||
NULL for this parameter causes all available attributes
|
||
to be retrieved;
|
||
|
||
attrsonly A boolean value that should be zero if both attribute
|
||
types and values are to be returned, non-zero if only
|
||
types are wanted;
|
||
|
||
timeout For the ldap_search_st() call, this specifies the local
|
||
search timeout value;
|
||
|
||
res For the synchronous calls, this is a result parameter
|
||
which will contain the results of the search upon
|
||
completion of the call.
|
||
|
||
There are three fields in the ld connection handle which control how
|
||
the search is performed. They are:
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 6]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
ld_sizelimit A limit on the number of entries to return from the
|
||
search. A value of zero means no limit;
|
||
|
||
ld_timelimit A limit on the number of seconds to spend on the search.
|
||
A value of zero means no limit;
|
||
|
||
ld_deref One of LDAP_DEREF_NEVER, LDAP_DEREF_SEARCHING,
|
||
LDAP_DEREF_FINDING, or LDAP_DEREF_ALWAYS, specifying
|
||
how aliases should be handled during the search. The
|
||
LDAP_DEREF_SEARCHING value means aliases should be
|
||
dereferenced during the search but not when locating
|
||
the base object of the search. The LDAP_DEREF_FINDING
|
||
value means aliases should be dereferenced when
|
||
locating the base object but not during the search.
|
||
|
||
An asynchronous search is initiated by calling ldap_search(). It
|
||
returns the message id of the initiated search. The results of the
|
||
search can be obtained by a subsequent call to ldap_result(). The
|
||
results can be parsed by the result parsing routines described in
|
||
detail later. In case of error, -1 is returned and the ld_errno
|
||
field in the LDAP structure is set appropriately.
|
||
|
||
A synchronous search is performed by calling ldap_search_s() or
|
||
ldap_search_st(). The routines are identical, except that
|
||
ldap_search_st() takes an additional parameter specifying a timeout
|
||
for the search. Both routines return an indication of the result of
|
||
the search, either LDAP_SUCCESS or some error indication (see Error
|
||
Handling below). The entries returned from the search (if any) are
|
||
contained in the res parameter. This parameter is opaque to the
|
||
caller. Entries, attributes, values, etc., should be extracted by
|
||
calling the parsing routines described below. The results contained
|
||
in res should be freed when no longer in use by calling
|
||
ldap_msgfree(), described later.
|
||
|
||
4.5. Reading an entry
|
||
|
||
LDAP does not support a read operation directly. Instead, this
|
||
operation is emulated by a search with base set to the DN of the
|
||
entry to read, scope set to LDAP_SCOPE_BASE, and filter set to
|
||
"(objectclass=*)". attrs contains the list of attributes to return.
|
||
|
||
4.6. Listing the children of an entry
|
||
|
||
LDAP does not support a list operation directly. Instead, this
|
||
operation is emulated by a search with base set to the DN of the
|
||
entry to list, scope set to LDAP_SCOPE_ONELEVEL, and filter set to
|
||
"(objectclass=*)". attrs contains the list of attributes to return
|
||
for each child entry.
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 7]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
4.7. Modifying an entry
|
||
|
||
The ldap_modify() and ldap_modify_s() routines are used to modify an
|
||
existing LDAP entry.
|
||
|
||
typedef struct ldapmod {
|
||
int mod_op;
|
||
char *mod_type;
|
||
union {
|
||
char **modv_strvals;
|
||
struct berval **modv_bvals;
|
||
} mod_vals;
|
||
} LDAPMod;
|
||
#define mod_values mod_vals.modv_strvals
|
||
#define mod_bvalues mod_vals.modv_bvals
|
||
|
||
int ldap_modify( LDAP *ld, char *dn, LDAPMod *mods[] );
|
||
|
||
int ldap_modify_s( LDAP *ld, char *dn, LDAPMod *mods[] );
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
dn The name of the entry to modify;
|
||
|
||
mods A NULL-terminated array of modifications to make to the
|
||
entry.
|
||
|
||
The fields in the LDAPMod structure have the following meanings:
|
||
|
||
mod_op The modification operation to perform. It should be one of
|
||
LDAP_MOD_ADD, LDAP_MOD_DELETE, or LDAP_MOD_REPLACE. This
|
||
field also indicates the type of values included in the
|
||
mod_vals union. It is ORed with LDAP_MOD_BVALUES to select
|
||
the mod_bvalues form. Otherwise, the mod_values form is
|
||
used;
|
||
|
||
mod_type The type of the attribute to modify;
|
||
|
||
mod_vals The values (if any) to add, delete, or replace. Only one of
|
||
the mod_values or mod_bvalues variants should be used,
|
||
selected by ORing the mod_op field with the constant
|
||
LDAP_MOD_BVALUES. mod_values is a NULL-terminated array of
|
||
zero-terminated strings and mod_bvalues is a NULL-terminated
|
||
array of berval structures that can be used to pass binary
|
||
values such as images.
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 8]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
For LDAP_MOD_ADD modifications, the given values are added to the
|
||
entry, creating the attribute if necessary. For LDAP_MOD_DELETE
|
||
modifications, the given values are deleted from the entry, removing
|
||
the attribute if no values remain. If the entire attribute is to be
|
||
deleted, the mod_vals field should be set to NULL. For
|
||
LDAP_MOD_REPLACE modifications, the attribute will have the listed
|
||
values after the modification, having been created if necessary. All
|
||
modifications are performed in the order in which they are listed.
|
||
|
||
ldap_modify_s() returns the LDAP error code resulting from the
|
||
modify operation. This code can be interpreted by ldap_perror()
|
||
and friends.
|
||
|
||
ldap_modify() returns the message id of the request it initiates, or
|
||
-1 on error. The result of the operation can be obtained by calling
|
||
ldap_result().
|
||
|
||
4.8. Modifying the RDN of an entry
|
||
|
||
The ldap_modrdn() and ldap_modrdn_s() routines are used to change the
|
||
name of an LDAP entry.
|
||
|
||
int ldap_modrdn(
|
||
LDAP *ld,
|
||
char *dn,
|
||
char *newrdn,
|
||
int deleteoldrdn
|
||
);
|
||
int ldap_modrdn_s(
|
||
LDAP *ld,
|
||
char *dn,
|
||
char *newrdn,
|
||
int deleteoldrdn
|
||
);
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
dn The name of the entry whose RDN is to be changed;
|
||
|
||
newrdn The new RDN to give the entry;
|
||
|
||
deleteoldrdn A boolean value, if non-zero indicating that the old
|
||
RDN value(s) should be removed, if zero indicating that
|
||
the old RDN value(s) should be retained as non-
|
||
distinguished values of the entry.
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 9]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
The ldap_modrdn_s() routine is synchronous, returning the LDAP error
|
||
code indicating the outcome of the operation.
|
||
|
||
The ldap_modrdn() routine is asynchronous, returning the message id
|
||
of the operation it initiates, or -1 in case of trouble. The result
|
||
of the operation can be obtained by calling ldap_result().
|
||
|
||
4.9. Adding an entry
|
||
|
||
ldap_add() and ldap_add_s() are used to add entries to the LDAP
|
||
directory.
|
||
|
||
int ldap_add( LDAP *ld, char *dn, LDAPMod *attrs[] );
|
||
|
||
int ldap_add_s( LDAP *ld, char *dn, LDAPMod *attrs[] );
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
dn The name of the entry to add;
|
||
|
||
attrs The entry's attributes, specified using the LDAPMod structure
|
||
defined for ldap_modify(). The mod_type and mod_vals fields
|
||
should be filled in. The mod_op field is ignored unless ORed
|
||
with the constant LDAP_MOD_BVALUES, used to select the
|
||
mod_bvalues case of the mod_vals union.
|
||
|
||
Note that the parent of the entry must already exist.
|
||
|
||
ldap_add_s() is synchronous, returning the LDAP error code indicating
|
||
the outcome of the operation.
|
||
|
||
ldap_add() is asynchronous, returning the message id of the operation
|
||
it initiates, or -1 in case of trouble. The result of the operation
|
||
can be obtained by calling ldap_result().
|
||
|
||
4.10. Deleting an entry
|
||
|
||
ldap_delete() and ldap_delete_s() are used to delete entries from the
|
||
LDAP directory.
|
||
|
||
int ldap_delete( LDAP *ld, char *dn );
|
||
|
||
int ldap_delete_s( LDAP *ld, char *dn );
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 10]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
dn The name of the entry to delete.
|
||
|
||
Note that the entry to delete must be a leaf entry (i.e., it must
|
||
have no children). Deletion of entire subtrees is not supported by
|
||
LDAP.
|
||
|
||
ldap_delete_s() is synchronous, returning the LDAP error code
|
||
indicating the outcome of the operation.
|
||
|
||
ldap_delete() is asynchronous, returning the message id of the
|
||
operation it initiates, or -1 in case of trouble. The result of the
|
||
operation can be obtained by calling ldap_result().
|
||
|
||
5. Calls for abandoning an operation
|
||
|
||
ldap_abandon() is used to abandon an operation in progress.
|
||
|
||
int ldap_abandon( LDAP *ld, int msgid );
|
||
|
||
ldap_abandon() abandons the operation with message id msgid. It
|
||
returns zero if the abandon was successful, -1 otherwise. After a
|
||
successful call to ldap_abandon(), results with the given message id
|
||
are never returned from a call to ldap_result().
|
||
|
||
6. Calls for obtaining results
|
||
|
||
ldap_result() is used to obtain the result of a previous
|
||
asynchronously initiated operation. ldap_msgfree() frees the results
|
||
obtained from a previous call to ldap_result(), or a synchronous
|
||
search routine.
|
||
|
||
int ldap_result(
|
||
LDAP *ld,
|
||
int msgid,
|
||
int all,
|
||
struct timeval *timeout,
|
||
LDAPMessage **res
|
||
);
|
||
|
||
int ldap_msgfree( LDAPMessage *res );
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 11]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
msgid The message id of the operation whose results are to be
|
||
returned, or the constant LDAP_RES_ANY if any result is
|
||
desired;
|
||
|
||
all A boolean parameter that only has meaning for search
|
||
results. If non-zero it indicates that all results of a
|
||
search should be retrieved before any are returned. If zero,
|
||
search results (entries) will be returned one at a time as
|
||
they arrive;
|
||
|
||
timeout A timeout specifying how long to wait for results to be
|
||
returned. A NULL value causes ldap_result() to block until
|
||
results are available. A timeout value of zero second
|
||
specifies a polling behavior;
|
||
|
||
res For ldap_result(), a result parameter that will contain the
|
||
result(s) of the operation. For ldap_msgfree(), the result
|
||
chain to be freed, obtained from a previous call to
|
||
ldap_result() or ldap_search_s() or ldap_search_st().
|
||
|
||
Upon successful completion, ldap_result() returns the type of the
|
||
result returned in the res parameter. This will be one of the
|
||
following constants.
|
||
|
||
LDAP_RES_BIND
|
||
LDAP_RES_SEARCH_ENTRY
|
||
LDAP_RES_SEARCH_RESULT
|
||
LDAP_RES_MODIFY
|
||
LDAP_RES_ADD
|
||
LDAP_RES_DELETE
|
||
LDAP_RES_MODRDN
|
||
LDAP_RES_COMPARE
|
||
|
||
ldap_result() returns 0 if the timeout expired and -1 if an error
|
||
occurs, in which case the ld_errno field of the ld structure will be
|
||
set accordingly.
|
||
|
||
ldap_msgfree() frees the result structure pointed to be res and
|
||
returns the type of the message it freed.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 12]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
7. Calls for error handling
|
||
|
||
The following calls are used to interpret errors returned by other
|
||
LDAP API routines.
|
||
|
||
int ldap_result2error(
|
||
LDAP *ld,
|
||
LDAPMessage *res,
|
||
int freeit
|
||
);
|
||
|
||
char *ldap_err2string( int err );
|
||
|
||
void ldap_perror( LDAP *ld, char *msg );
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
res The result of an LDAP operation as returned by ldap_result()
|
||
or one of the synchronous API operation calls;
|
||
|
||
freeit A boolean parameter indicating whether the res parameter
|
||
should be freed (non-zero) or not (zero);
|
||
|
||
err An LDAP error code, as returned by ldap_result2error() or
|
||
one of the synchronous API operation calls;
|
||
|
||
msg A message to be displayed before the LDAP error message.
|
||
|
||
ldap_result2error() is used to convert the LDAP result message
|
||
obtained from ldap_result(), or the res parameter returned by one of
|
||
the synchronous API operation calls, into a numeric LDAP error code.
|
||
It also parses the ld_matched and ld_error portions of the result
|
||
message and puts them into the connection handle information. All the
|
||
synchronous operation routines call ldap_result2error() before
|
||
returning, ensuring that these fields are set correctly. The relevant
|
||
fields in the connection structue are:
|
||
|
||
ld_matched In the event of an LDAP_NO_SUCH_OBJECT error return, this
|
||
parameter contains the extent of the DN matched;
|
||
|
||
ld_error This parameter contains the error message sent in the
|
||
result by the LDAP server.
|
||
|
||
ld_errno The LDAP error code indicating the outcome of the
|
||
operation. It is one of the following constants:
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 13]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
LDAP_SUCCESS
|
||
LDAP_OPERATIONS_ERROR
|
||
LDAP_PROTOCOL_ERROR
|
||
LDAP_TIMELIMIT_EXCEEDED
|
||
LDAP_SIZELIMIT_EXCEEDED
|
||
LDAP_COMPARE_FALSE
|
||
LDAP_COMPARE_TRUE
|
||
LDAP_STRONG_AUTH_NOT_SUPPORTED
|
||
LDAP_STRONG_AUTH_REQUIRED
|
||
LDAP_NO_SUCH_ATTRIBUTE
|
||
LDAP_UNDEFINED_TYPE
|
||
LDAP_INAPPROPRIATE_MATCHING
|
||
LDAP_CONSTRAINT_VIOLATION
|
||
LDAP_TYPE_OR_VALUE_EXISTS
|
||
LDAP_INVALID_SYNTAX
|
||
LDAP_NO_SUCH_OBJECT
|
||
LDAP_ALIAS_PROBLEM
|
||
LDAP_INVALID_DN_SYNTAX
|
||
LDAP_IS_LEAF
|
||
LDAP_ALIAS_DEREF_PROBLEM
|
||
LDAP_INAPPROPRIATE_AUTH
|
||
LDAP_INVALID_CREDENTIALS
|
||
LDAP_INSUFFICIENT_ACCESS
|
||
LDAP_BUSY
|
||
LDAP_UNAVAILABLE
|
||
LDAP_UNWILLING_TO_PERFORM
|
||
LDAP_LOOP_DETECT
|
||
LDAP_NAMING_VIOLATION
|
||
LDAP_OBJECT_CLASS_VIOLATION
|
||
LDAP_NOT_ALLOWED_ON_NONLEAF
|
||
LDAP_NOT_ALLOWED_ON_RDN
|
||
LDAP_ALREADY_EXISTS
|
||
LDAP_NO_OBJECT_CLASS_MODS
|
||
LDAP_RESULTS_TOO_LARGE
|
||
LDAP_OTHER
|
||
LDAP_SERVER_DOWN
|
||
LDAP_LOCAL_ERROR
|
||
LDAP_ENCODING_ERROR
|
||
LDAP_DECODING_ERROR
|
||
LDAP_TIMEOUT
|
||
LDAP_AUTH_UNKNOWN
|
||
LDAP_FILTER_ERROR
|
||
LDAP_USER_CANCELLED
|
||
LDAP_PARAM_ERROR
|
||
LDAP_NO_MEMORY
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 14]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
ldap_err2string() is used to convert a numeric LDAP error code, as
|
||
returned by ldap_result2error() or one of the synchronous API
|
||
operation calls, into an informative NULL-terminated character string
|
||
message describing the error. It returns a pointer to static data.
|
||
|
||
ldap_perror() is used to print the message supplied in msg, followed
|
||
by an indication of the error contained in the ld_errno field of the
|
||
ld connection handle, to standard error.
|
||
|
||
8. Calls for parsing search entries
|
||
|
||
The following calls are used to parse the entries returned by
|
||
ldap_search() and friends. These entries are returned in an opaque
|
||
structure that should only be accessed by calling the routines
|
||
described below. Routines are provided to step through the entries
|
||
returned, step through the attributes of an entry, retrieve the name
|
||
of an entry, and retrieve the values associated with a given
|
||
attribute in an entry.
|
||
|
||
8.1. Stepping through a set of entries
|
||
|
||
The ldap_first_entry() and ldap_next_entry() routines are used to
|
||
step through a set of entries in a search result.
|
||
ldap_count_entries() is used to count the number of entries returned.
|
||
|
||
LDAPMesage *ldap_first_entry( LDAP *ld, LDAPMessage *res );
|
||
|
||
LDAPMesage *ldap_next_entry( LDAP *ld, LDAPMessage *entry );
|
||
|
||
int ldap_count_entries( LDAP *ld, LDAPMessage *res );
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
res The search result, as obtained by a call to one of the syn-
|
||
chronous search routines or ldap_result();
|
||
|
||
entry The entry returned by a previous call to ldap_first_entry() or
|
||
ldap_next_entry().
|
||
|
||
ldap_first_entry() and ldap_next_entry() will return NULL when no
|
||
more entries exist to be returned. NULL is also returned if an error
|
||
occurs while stepping through the entries, in which case the ld_errno
|
||
field of the ld connection handle will be set to indicate the error.
|
||
|
||
ldap_count_entries() returns the number of entries contained in a
|
||
chain of entries. It can also be used to count the number of entries
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 15]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
that remain in a chain if called with an entry returned by
|
||
ldap_first_entry() or ldap_next_entry().
|
||
|
||
8.2. Stepping through the attributes of an entry
|
||
|
||
The ldap_first_attribute() and ldap_next_attribute() calls are used
|
||
to step through the list of attribute types returned with an entry.
|
||
|
||
char *ldap_first_attribute(
|
||
LDAP *ld,
|
||
LDAPMessage *entry,
|
||
void **ptr
|
||
);
|
||
char *ldap_next_attribute(
|
||
LDAP *ld,
|
||
LDAPMessage *entry,
|
||
void *ptr
|
||
);
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
entry The entry whose attributes are to be stepped through, as
|
||
returned by ldap_first_entry() or ldap_next_entry();
|
||
|
||
ptr In ldap_first_attribute(), the address of a pointer used
|
||
internally to keep track of the current position in the entry.
|
||
In ldap_next_attribute(), the pointer returned by a previous
|
||
call to ldap_first_attribute().
|
||
|
||
ldap_first_attribute() and ldap_next_attribute() will return NULL
|
||
when the end of the attributes is reached, or if there is an error,
|
||
in which case the ld_errno field in the ld connection handle will be
|
||
set to indicate the error.
|
||
|
||
Both routines return a pointer to a per-connection buffer containing
|
||
the current attribute name. This should be treated like static data.
|
||
ldap_first_attribute() will allocate and return in ptr a pointer to a
|
||
BerElement used to keep track of the current position. This pointer
|
||
should be passed in subsequent calls to ldap_next_attribute() to step
|
||
through the entry's attributes.
|
||
|
||
The attribute names returned are suitable for passing in a call to
|
||
ldap_get_values() and friends to retrieve the associated values.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 16]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
8.3. Retrieving the values of an attribute
|
||
|
||
ldap_get_values() and ldap_get_values_len() are used to retrieve the
|
||
values of a given attribute from an entry. ldap_count_values() and
|
||
ldap_count_values_len() are used to count the returned values.
|
||
ldap_value_free() and ldap_value_free_len() are used to free the
|
||
values.
|
||
|
||
typedef struct berval {
|
||
unsigned long bv_len;
|
||
char *bv_val;
|
||
};
|
||
|
||
char **ldap_get_values(
|
||
LDAP *ld,
|
||
LDAPMessage *entry,
|
||
char *attr
|
||
);
|
||
|
||
struct berval **ldap_get_values_len(
|
||
LDAP *ld,
|
||
LDAPMessage *entry,
|
||
char *attr
|
||
);
|
||
|
||
int ldap_count_values( char **vals );
|
||
|
||
int ldap_count_values_len( struct berval **vals );
|
||
|
||
int ldap_value_free( char **vals );
|
||
|
||
int ldap_value_free_len( struct berval **vals );
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
entry The entry from which to retrieve values, as returned by
|
||
ldap_first_entry() or ldap_next_entry();
|
||
|
||
attr The attribute whose values are to be retrieved, as returned by
|
||
ldap_first_attribute() or ldap_next_attribute(), or a caller-
|
||
supplied string (e.g., "mail");
|
||
|
||
vals The values returned by a previous call to ldap_get_values() or
|
||
ldap_get_values_len().
|
||
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 17]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
Two forms of the various calls are provided. The first form is only
|
||
suitable for use with non-binary character string data only. The
|
||
second _len form is used with any kind of data.
|
||
|
||
Note that the values returned are malloc'ed and should be freed by
|
||
calling either ldap_value_free() or ldap_value_free_len() when no
|
||
longer in use.
|
||
|
||
8.4. Retrieving the name of an entry
|
||
|
||
ldap_get_dn() is used to retrieve the name of an entry.
|
||
ldap_explode_dn() is used to break up the name into its component
|
||
parts. ldap_dn2ufn() is used to convert the name into a more "user
|
||
friendly" format.
|
||
|
||
char *ldap_get_dn( LDAP *ld, LDAPMessage *entry );
|
||
|
||
char **ldap_explode_dn( char *dn, int notypes );
|
||
|
||
char *ldap_dn2ufn( char *dn );
|
||
|
||
Parameters are:
|
||
|
||
ld The connection handle;
|
||
|
||
entry The entry whose name is to be retrieved, as returned by
|
||
ldap_first_entry() or ldap_next_entry();
|
||
|
||
dn The dn to explode, as returned by ldap_get_dn();
|
||
|
||
notypes A boolean parameter, if non-zero indicating that the dn com-
|
||
ponents should have their type information stripped off
|
||
(i.e., "cn=Babs" would become "Babs").
|
||
|
||
ldap_get_dn() will return NULL if there is some error parsing the dn,
|
||
setting ld_errno in the ld connection handle to indicate the error.
|
||
It returns a pointer to malloc'ed space that the caller should free
|
||
by calling free() when it is no longer in use. Note the format of
|
||
the DNs returned is given by [4].
|
||
|
||
ldap_explode_dn() returns a char * array containing the RDN
|
||
components of the DN supplied, with or without types as indicated by
|
||
the notypes parameter. The array returned should be freed when it is
|
||
no longer in use by calling ldap_value_free().
|
||
|
||
ldap_dn2ufn() converts the DN into the user friendly format described
|
||
in [5]. The UFN returned is malloc'ed space that should be freed by a
|
||
call to free() when no longer in use.
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 18]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
9. Security Considerations
|
||
|
||
LDAP supports minimal security during connection authentication.
|
||
|
||
10. Acknowledgements
|
||
|
||
This material is based upon work supported by the National Science
|
||
Foundation under Grant No. NCR-9416667.
|
||
|
||
11. Bibliography
|
||
|
||
[1] The Directory: Selected Attribute Syntaxes. CCITT,
|
||
Recommendation X.520.
|
||
|
||
[2] Howes, T., Kille, S., Yeong, W., and C. Robbins, "The String
|
||
Representation of Standard Attribute Syntaxes", University of
|
||
Michigan, ISODE Consortium, Performance Systems International,
|
||
NeXor Ltd., RFC 1778, March 1995.
|
||
|
||
[3] Howes, T., "A String Representation of LDAP Search Filters", RFC
|
||
1558, University of Michigan, December 1993.
|
||
|
||
[4] Kille, S., "A String Representation of Distinguished Names", RFC
|
||
1779, ISODE Consortium, March 1995.
|
||
|
||
[5] Kille, S., "Using the OSI Directory to Achieve User Friendly
|
||
Naming", RFC 1781, ISODE Consortium, March 1995.
|
||
|
||
[6] S.P. Miller, B.C. Neuman, J.I. Schiller, J.H. Saltzer, "Kerberos
|
||
Authentication and Authorization System", MIT Project Athena
|
||
Documentation Section E.2.1, December 1987
|
||
|
||
[7] Yeong, W., Howes, T., and S. Kille, "Lightweight Directory Access
|
||
Protocol," RFC 1777, Performance Systems International,
|
||
University of Michigan, ISODE Consortium, March 1995.
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 19]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
12. Authors' Addresses
|
||
|
||
Tim Howes
|
||
University of Michigan
|
||
ITD Research Systems
|
||
535 W William St.
|
||
Ann Arbor, MI 48103-4943
|
||
USA
|
||
|
||
Phone: +1 313 747-4454
|
||
EMail: tim@umich.edu
|
||
|
||
|
||
Mark Smith
|
||
University of Michigan
|
||
ITD Research Systems
|
||
535 W William St.
|
||
Ann Arbor, MI 48103-4943
|
||
USA
|
||
|
||
Phone: +1 313 764-2277
|
||
EMail: mcs@umich.edu
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 20]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
13. Appendix A - Sample LDAP API Code
|
||
|
||
#include <ldap.h>
|
||
|
||
main()
|
||
{
|
||
LDAP *ld;
|
||
LDAPMessage *res, *e;
|
||
int i;
|
||
char *a, *dn;
|
||
void *ptr;
|
||
char **vals;
|
||
|
||
/* open a connection */
|
||
if ( (ld = ldap_open( "dotted.host.name", LDAP_PORT ))
|
||
== NULL )
|
||
exit( 1 );
|
||
|
||
/* authenticate as nobody */
|
||
if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
|
||
ldap_perror( ld, "ldap_simple_bind_s" );
|
||
exit( 1 );
|
||
}
|
||
|
||
/* search for entries with cn of "Babs Jensen",
|
||
return all attrs */
|
||
if ( ldap_search_s( ld, "o=University of Michigan, c=US",
|
||
LDAP_SCOPE_SUBTREE, "(cn=Babs Jensen)", NULL, 0, &res )
|
||
!= LDAP_SUCCESS ) {
|
||
ldap_perror( ld, "ldap_search_s" );
|
||
exit( 1 );
|
||
}
|
||
|
||
/* step through each entry returned */
|
||
for ( e = ldap_first_entry( ld, res ); e != NULL;
|
||
e = ldap_next_entry( ld, e ) ) {
|
||
/* print its name */
|
||
dn = ldap_get_dn( ld, e );
|
||
printf( "dn: %s0, dn );
|
||
free( dn );
|
||
|
||
/* print each attribute */
|
||
for ( a = ldap_first_attribute( ld, e, &ptr );
|
||
a != NULL;
|
||
a = ldap_next_attribute( ld, e, ptr ) ) {
|
||
printf( "attribute: %s0, a );
|
||
|
||
/* print each value */
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 21]
|
||
|
||
RFC 1823 LDAP API August 1995
|
||
|
||
|
||
vals = ldap_get_values( ld, e, a );
|
||
for ( i = 0; vals[i] != NULL; i++ ) {
|
||
printf( "value: %s0, vals[i] );
|
||
}
|
||
ldap_value_free( vals );
|
||
}
|
||
}
|
||
/* free the search results */
|
||
ldap_msgfree( res );
|
||
|
||
/* close and free connection resources */
|
||
ldap_unbind( ld );
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
Howes & Smith Informational [Page 22]
|
||
|