Network Working Group                                  Timothy A Howes
INTERNET-DRAFT                                            Mark C Smith
OBSOLETES: RFC 1823                      Netscape Communications Corp.


                 The LDAP Application Program Interface



1.  Status of this Memo

This draft document will be submitted to the RFC Editor as an informa-
tional document. Distribution of this memo is unlimited. Please send
comments to the authors.

This document is an Internet-Draft.  Internet-Drafts are working docu-
ments of the Internet Engineering Task Force (IETF), its areas, and its
working groups.  Note that other groups may also distribute working
documents as Internet-Drafts.

Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time.  It is inappropriate to use Internet-Drafts as reference material
or to cite them other than as ``work in progress.''

To learn the current status of any Internet-Draft, please check the
``1id-abstracts.txt'' listing contained in the Internet-Drafts Shadow
Directories on ds.internic.net (US East Coast), nic.nordu.net (Europe),
ftp.isi.edu (US West Coast), or munnari.oz.au (Pacific Rim).

2.  Introduction

This document defines a C language application program interface to the
lightweight directory access protocol (LDAP). This document replaces the
previous definition of this API, defined in RFC 1823, updating it to
include support for features found in version 3 of the LDAP protocol, as
well as other changes to support information hiding and thread safety.

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 applica-
tion program to obtain LDAP information.  The API calls are described in
detail, followed by an appendix that provides some example code demon-
strating the use of the API. This document provides information to the
Internet community. It does not specify any standard.





Expires 4/97                                                    [Page 1]


LDAP API                                                    October 1996


3.  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. LDAPv3 can also be
used over UDP transport.

The LDAP information model is based on the entry, which contains infor-
mation 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 attri-
bute (e.g., ASCII characters, a jpeg photograph, etc.) and how those
values behave during directory operations (e.g., is case significant
during comparisons).

Entries may be organized in a tree structure, usually based on politi-
cal, 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 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 entry up
to the root of the tree. 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 infor-
mation, 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 func-
tions.

4.  Overview of LDAP API Use

An application generally uses the LDAP API in four simple steps.

-    Initialize an LDAP session with a default LDAP server. The
     ldap_init() call returns a handle to the session, allowing multiple
     connections to be open at once.

-    Authenticate to the LDAP server. The ldap_bind() call and friends
     support a variety of authentication methods.



Expires 4/97                                                    [Page 2]


LDAP API                                                    October 1996


-    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.

-    Close the connection. The ldap_unbind() call closes the connection.

Operations can be performed either synchronously or asynchronously.  The
names of the 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 rou-
tines return an indication of the outcome of the operation (e.g, the
constant LDAP_SUCCESS or some other error code).  The asynchronous rou-
tines 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().

Results and errors are returned in an opaque structure called LDAPMes-
sage.  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.

5.  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 LDAPMes-
sage structure. These structures and others are described as needed
below.

5.1.  Initializing an LDAP Session

ldap_init() initializes a session with an LDAP server. The server is not
actually contacted until an operation is performed that requires it,
allowing various options to be set after initialization.

ldap_sslinit() functions the same as ldap_init(), but it also optionally
allows the caller to set up a secure LDAP connection over SSL to the
LDAP server.

        typedef struct ldap LDAP;

        LDAP *ldap_init( char *hostname, int portno );

        LDAP *ldap_sslinit( char *hostname, int portno, int secure );

Use of the following routine is deprecated.



Expires 4/97                                                    [Page 3]


LDAP API                                                    October 1996


        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.
         Note that only ldap_open() attempts to make the connection
         before returning to the caller. Neither ldap_init() or
         ldap_sslinit() connect to the LDAP server.

portno   Contains the TCP or UDP port number to connect to or contact.
         The default LDAP port of 389 can be obtained by supplying the
         constant LDAP_PORT. The default secure (LDAP over SSL) LDAP
         port of 636 can be selected by supplying the constant
         LDAPS_PORT.

secure   Is non-zero to intialize a secure LDAP session over SSL.  If
         secure is zero, regular LDAP session will be initialized.

ldap_init(), ldap_sslinit(), and ldap_open() all return a "session han-
dle," a pointer to an opaque structure that should be passed to subse-
quent calls pertaining to the session. These routines return NULL if the
session cannot be initialized.

One of the ldap_bind calls described below must be completed before
other operations can be performed on the session.

The calling program can set various attributes of the session by calling
the routines described in the next section.

5.2.  LDAP Session Handle Options

The LDAP session handle returned by ldap_init() and friends is a pointer
to an opaque data type representing an LDAP session. Formerly, this data
type was a structure exposed to the caller, and various fields in the
structure could be set to control aspects of the session, such as size
and time limits on searches.

In the interest of insulating callers from inevitable changes to this
structure, these aspects of the session are now accessed through a pair
of accessor functions, described below.

ldap_get_option() is used to access the current value of various
session-wide parameters. ldap_set_option() is used to set the value of
these parameters.




Expires 4/97                                                    [Page 4]


LDAP API                                                    October 1996


           int ldap_get_option( LDAP *ld, int option, void *outvalue );

           int ldap_set_option( LDAP *ld, int option, void *invalue );

Parameters are:

ld     The session handle.

option The name of the option being accessed or set. This parameter
       should be one of the following constants, which have the follow-
       ing meanings.

   LDAP_OPT_DESC
          The underlying socket descriptor corresponding to the default
          LDAP connection.

   LDAP_OPT_DEREF
          Controls how aliases are handled during search. It can have
          one of the following values: LDAP_DEREF_NEVER,
          LDAP_DEREF_SEARCHING, LDAP_DEREF_FINDING, or
          LDAP_DEREF_ALWAYS.  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.

   LDAP_OPT_SIZELIMIT
          A limit on the number of entries to return from a search. A
          value of zero means no limit.

   LDAP_OPT_TIMELIMIT
          A limit on the number of seconds to spend on a search. A value
          of zero means no limit

   LDAP_OPT_IO_FN_PTRS
          See the discussion of I/O environments in Section X.

   LDAP_OPT_THREAD_FN_PTRS
          See the discussion of threading environments in Section X.

   LDAP_OPT_REBIND_FN
          See the discussion of ldap_bind() and friends below.

   LDAP_OPT_REBIND_ARG
          See the discussion of ldap_bind() and friends below.

   LDAP_OPT_CACHE_FN_PTRS
          See the discussion of LDAP caching in Section X.



Expires 4/97                                                    [Page 5]


LDAP API                                                    October 1996


   LDAP_OPT_CACHE_STRATEGY
          See the discussion of LDAP caching in Section X.

   LDAP_OPT_CACHE_ENABLE
          See the discussion of LDAP caching in Section X.

   LDAP_OPT_REFERRALS
          This option controls whether the LDAP library automatically
          follows referrals returned by LDAP servers or not. It can be
          set to one of the constants LDAP_OPT_ON or LDAP_OPT_OFF.

   LDAP_OPT_SSL
          This option controls whether the default LDAP connection is
          made secure over SSL or not. It can be set to one of the con-
          stants LDAP_OPT_ON or LDAP_OPT_OFF. Note that if
          LDAP_OPT_REFERRALS is set to LDAP_OPT_ON and the LDAP library
          gets a referral to an SSL LDAP server, it will still do SSL if
          possible. This setting has no bearing on connections made when
          chasing referrals.

   LDAP_OPT_RESTART
          This option controls whether LDAP I/O operations should
          automatically be restarted if they abort prematurely. It
          should be set to one of the constants LDAP_OPT_ON or
          LDAP_OPT_OFF. This option is useful if an LDAP I/O operation
          may be interrupted prematurely, for example by a timer going
          off, or other interrrupt.

   LDAP_OPT_VERSION
          This option indicates the version of the default LDAP server.
          It can be one of the constants LDAP_VERSION2 or LDAP_VERSION3.

   LDAP_OPT_SORTKEYS
          This option indicates sort keys that should be sent to the
          server on subsequent search requests. The value of this option
          is a NULL-terminated array of pointers to structures with the
          following definition.

           struct ldapsortkey {
                   char    *sk_attrtype;
                   char    *sk_matchruleoid;
                   int     sk_reverseorder;
           };


outvalue The address of a place to put the value of the option. The
         actual type of this parameter depends on the setting of the
         option parameter.



Expires 4/97                                                    [Page 6]


LDAP API                                                    October 1996


invalue  A pointer to the value the option is to be given. The actual
         type of this parameter depends on the setting of the option
         parameter. The constants LDAP_OPT_ON and LDAP_OPT_OFF can be
         given for options that have on or off settings.

5.3.  Setting Session Parameters

The ldap_session() and ldap_session_s() calls are used to request that
the LDAP server set certain session parameters.  These session parame-
ters are maintained by the server, as opposed to the LDAP * session
parameters described above, which are maintained by the client.

           struct ldapsessctl {
                   char            *sc_type;
                   struct berval   sc_value;
                   int             sc_critical;
           };

           int ldap_session(
                   LDAP                    *ld;
                   struct ldapsessctl      **controls;
           );

           int ldap_session_s(
                   LDAP                    *ld;
                   struct ldapsessctl      **controls;
                   LDAPMessage             **result;
           );

Parameters are:

ld       The session handle.

controls A NULL-terminated array of pointers to ldapsessctl structures
         indicating the requested session controls.

result   A result parameter that will be filled in with the result of
         the session control operation. This parameter is suitable for
         passing to ldap_parse_session_result(), described below.

The following constants are defined and may be assigned to the sc_type
field in the ldapsessctl structure. The controls have the following
meanings.

LDAP_SESSION_ATTR_SIZELIMIT
     This control sets a limit on the size of any attribute value the
     server will return to the client. The sc_value field should point
     to a string containing the decimal string representation of the



Expires 4/97                                                    [Page 7]


LDAP API                                                    October 1996


     size limit in bytes.

LDAP_SESSION_NO_COPY
     This control instructs the server not to perform operations against
     copies of the data, only to use the master version.  It can be set
     to LDAP_OPT_ON or LDAP_OPT_OFF.

LDAP_SESSION_PARTIAL_COPY
     This control instructs the server that it should return search
     results from partial replicas of the directory.  It can be set to
     LDAP_OPT_ON or LDAP_OPT_OFF.

LDAP_SESSION_REFERRING_SERVER
     This control tells the server which server (if any) referred the
     client to the server. It is useful in debugging, and should contain
     a URL.

LDAP_SESSION_NO_CHAINING
     This control instructs the server not to chain requests on the
     client's behalf. It should be set to either LDAP_OPT_ON or
     LDAP_OPT_OFF.

LDAP_SESSION_SUPPORTED_PROTOCOL
     This control instructs the server in which protocols the client
     supports for returned referrals. It should be a null-terminated
     array of string protocol names, such as "ldap", "cldap", etc.

LDAP_SESSION_ALIAS_ON_UPDATE
     This control instructs the server that it should follow aliases on
     update (add, delete, modify, modify dn) operations.  It should be
     set to LDAP_OPT_ON or LDAP_OPT_OFF.

LDAP_SESSION_MANAGE_SERVER
     This control instructs the server that the client wants to manage
     server data, such as knowledge references, rather than follow the
     links they provide. It should be set to LDAP_OPT_ON or
     LDAP_OPT_OFF.

LDAP_SESSION_PREFERRED_LANGUAGE
     This control tells the server the list of the client's preferred
     languages.

ldap_session_s() is synchronous and returns an LDAP error code indicat-
ing the success or failure of the operation.

ldap_session() is asynchronous and returns the message id of the opera-
tion it initiates, or -1 in case of trouble. The result of the operation
may be obtained by a subsequent call to ldap_result().



Expires 4/97                                                    [Page 8]


LDAP API                                                    October 1996


5.4.  Authenticating to the directory

ldap_bind() and friends are used to authenticate an LDAP client to an
LDAP directory server.

The ldap_extended_bind() and ldap_extended_bind_s() calls can be used to
do general and extensible authentication over LDAP.  The routines both
take the dn to bind as, the method to use, as a dotted-string represen-
tation of an OID identifying the method, and a struct berval holding the
credentials. The special constant value LDAP_AUTH_SIMPLE_OID can be
passed to request simple authentication, or the simplified routines
ldap_simple_bind() or ldap_simple_bind_s() can be used.

           typedef struct ldapmsg LDAPMessage;

           int ldap_extended_bind( LDAP *ld, char *dn, char *methodoid,
                   struct berval *credentials );

           int ldap_extended_bind_s( LDAP *ld, char *dn, char *methodoid,
                   struct berval *credentials, LDAPMessage **result );

           int ldap_simple_bind( LDAP *ld, char *dn, char *passwd );

           int ldap_simple_bind_s( LDAP *ld, char *dn, char *passwd );

   The use of the following routines is deprecated:

           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_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.

methodoid
       Either LDAP_AUTH_SIMPLE_OID, to get simple authentication, or a
       dotted text string representing an OID identifying the bind
       method.

credentials
       The credentials with which to authenticate. Arbitrary credentials



Expires 4/97                                                    [Page 9]


LDAP API                                                    October 1996


       can be passed using this parameter. The format and content of the
       credentials depends on the setting of the methodoid parameter.

result For the synchronous version of extended bind,
       ldap_extended_bind_s(), this is a result-parameter that will be
       set to the LDAPMessage containing the result of the bind. This
       result is suitable for passing to ldap_parse_result() or
       ldap_parse_bind_result(), both described below.

passwd For ldap_simple_bind(), the password to compare to the entry's
       userPassword attribute.

Additional parameters for the deprecated routines are not described.
Interested readers are referred to RFC 1823.

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 informa-
tion about possible errors and how to interpret them.

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 session error parameters 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.

5.5.  Closing the connection

ldap_unbind() is used to unbind from the directory, close the connec-
tion, and dispose of the connection handle.

           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.




Expires 4/97                                                   [Page 10]


LDAP API                                                    October 1996


5.6.  Searching

ldap_search() and friends are used to search the LDAP directory, return-
ing 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,
                   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 1960 [3], representing



Expires 4/97                                                   [Page 11]


LDAP API                                                    October 1996


          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 options in the ld connection handle which control how
the search is performed. They are:

LDAP_OPT_SIZELIMIT
             A limit on the number of entries to return from the search.
             A value of zero means no limit.

LDAP_OPT_TIMELIMIT
             A limit on the number of seconds to spend on the search. A
             value of zero means no limit.

LDAP_OPT_DEREFOne 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 derefer-
             enced 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 session error parameters in the
LDAP structure are 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 local
timeout for the search.  Both routines return an indication of the



Expires 4/97                                                   [Page 12]


LDAP API                                                    October 1996


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 cal-
ling the parsing routines described below. The results contained in res
should be freed when no longer in use by calling ldap_msgfree(),
described later.

5.7.  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.

5.8.  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.

5.9.  Returning Search Results a Page at a Time

New to LDAPv3 is support in the protocol for retrieving search results a
page at a time. The ldap_search_init_page() and ldap_search_get_page()
routines provide an API interface to this capability.

           typedef struct ldapsearch LDAPSearch;

           LDAPSearch *ldap_search_init_page(
                   LDAP                    *ld,
                   char                    *base,
                   int                     scope,
                   char                    *filter,
                   char                    *attrs[],
                   int                     attrsonly,
                   struct ldapsortkey      **sortkeys
           );

           int ldap_search_get_page(
                   LDAP            *ld,
                   LDAPSearch      *searchhandle,
                   int             startatentry,
                   int             pagesize,
                   int             *totalcount
           );




Expires 4/97                                                   [Page 13]


LDAP API                                                    October 1996


           int ldap_search_get_page_s(
                   LDAP            *ld,
                   LDAPSearch      *searchhandle,
                   int             startatentry,
                   int             pagesize,
                   int             *totalcount,
                   LDAPMessage     **result
           );

           int ldap_search_abandon_page(
                   LDAP            *ld,
                   LDAPSearch      *searchhandle
           );

The parameters to ldap_search_init_page() are exactly the same as those
to ldap_search(), except for the additional sortkeys parameter. This
parameter and parameters to ldap_search_get_page() are:

ld       The connection handle.

sortkeys If the results of the search are desired back in sorted order,
         this parameter is a NULL-terminated array of pointers to struct
         sortkeys, indicating the attribute types and matching rules by
         which the results are to be sorted. If this parameter is NULL,
         the default value for sortkeys, if any, is taken from the LDAP
         session parameter LDAP_OPT_SORTKEYS.

searchhandle
         A handle to an opaque data type returned from a successful call
         to ldap_search_init_page(). This parameter should be passed to
         all subsequent calls to ldap_search_get_page() or
         ldap_search_get_page_s() pertaining to the same search.

startatentry
         The number of entries in the search result before which the
         page to be retrieved begins. To start at the beginning of the
         search result, supply 0 (zero) for startatentry. To begin in
         the middle of a 100-entry search result, supply 50 for starta-
         tentry.

pagesize The number of entries that should be returned in the page.  No
         more than this many entries will be returned from the search,
         though fewer can be returned if the page extends beyond the
         total size of the result set.

totalcount  A result-parameter that will be set to the total number of
            entries in the search result. This parameter may change on
            subsequent calls to ldap_search_get_page() or



Expires 4/97                                                   [Page 14]


LDAP API                                                    October 1996


            ldap_search_get_page_s(), if the size of the result set
            changes (for example, because of additions or deletions to
            the directory between calls).

result   A result-parameter that will be set to an LDAPMessage contain-
         ing the result of the search, which will be either a "page" of
         entries, suitable for passing to ldap_first_entry() and friends
         (just like a result from ldap_search_s()), or or an LDAPMessage
         containing an explanation of an error that occurred, suitable
         for passing to ldap_parse_result().

ldap_search_init_page() returns a pointer to an opaque data structure
representing the search, or NULL on error. The non-NULL return value
should be passed to a subsequent call to ldap_search_get_page() or
ldap_search_get_page_s() to retrieve the actual pages of results from
the search.

ldap_search_get_page_s() is synchronous and returns the LDAP error code
resulting from the search operation. This code can be interpreted by
ldap_perror() and friends.

ldap_search_get_page() is asynchronous and 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().

ldap_search_abandon_page() abandons the current search-page sequence
begun by calling ldap_search_init_page(). It frees the searchhandle
structure, which is invalid after the call.

5.10.  Comparing a Value Against an Entry

The ldap_compare() and ldap_compare_s() routines are used to compare a
given attribute value assertion against an LDAP entry.

           int ldap_compare(
                   LDAP            *ld,
                   const char      *dn,
                   const char      *attr,
                   struct berval   *bvalue
           );

           int ldap_compare_s(
                   LDAP            *ld,
                   const char      *dn,
                   const char      *attr,
                   struct berval   *bvalue,
                   char            **matchedtype
           );



Expires 4/97                                                   [Page 15]


LDAP API                                                    October 1996


Parameters are:

ld       The connection handle.

dn       The name of the entry to compare against.

attr     The attribute to compare against.

bvalue   The attribute value to compare against those found in the
         entry. This parameter is a pointer to a struct berval so it is
         possible to compare binary values.

matchedtype
         This result-parameter will be set to the attribute type actu-
         ally used to match the compare. This is useful if attribute
         sub-typing is involved, and the attr given is a parent type. If
         no attribute sub-typing is involed (or is not supported, as in
         the case of LDAPv2 servers), this result-parameter will be set
         to NULL.

5.11.  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.




Expires 4/97                                                   [Page 16]


LDAP API                                                    October 1996


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.

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() is synchronous and returns the LDAP error code resulting
from the modify operation. This code can be interpreted by ldap_perror()
and friends.

ldap_modify() is asynchronous and 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().

5.12.  Modifying the Name of an Entry

In LDAPv2, the ldap_modrdn() and ldap_modrdn_s() routines were used to
change the name of an LDAP entry. They could only be used to change the
least significant component of a name (the RDN or relative distinguished
name). LDAPv3 provides the Modify DN protocol operation that allows more
general name change access. The ldap_moddn() and ldap_moddn_s() routines
are used to change the name of an entry, and the use of the
ldap_modrdn() and ldap_modrdn_s() routines is deprecated.

           int ldap_moddn(
                   LDAP    *ld,
                   char    *dn,



Expires 4/97                                                   [Page 17]


LDAP API                                                    October 1996


                   char    *newdn,
                   int     deleteoldrdn
           );
           int ldap_moddn_s(
                   LDAP    *ld,
                   char    *dn,
                   char    *newdn,
                   int     deleteoldrdn
           );

   Use of the following routines is deprecated.

           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 session handle.

dn       The name of the entry whose DN is to be changed.

newdn    The new DN to give the entry.

deleteoldrdn
         This parameter only has meaning on the modify DN routines if
         the newdn has a different RDN than the old DN. It is 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.

Parameters of the deprecated routines are not described.  Interested
readers are referred to RFC 1823.

The ldap_moddn_s() routine is synchronous, returning the LDAP error code
indicating the outcome of the operation.

The ldap_moddn() routine is asynchronous, returning the message id of
the operation it initiates, or -1 in case of trouble. The result of the



Expires 4/97                                                   [Page 18]


LDAP API                                                    October 1996


operation can be obtained by calling ldap_result().

5.13.  Adding an entry

ldap_add() and ldap_add_s() are used to add entries to the LDAP direc-
tory.

           int ldap_add( LDAP *ld, char *dn, LDAPMod *attrs[] );

           int ldap_add_s( LDAP *ld, char *dn, LDAPMod *attrs[] );

Parameters are:

ld    The session 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().

5.14.  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 );

Parameters are:

ld       The session 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



Expires 4/97                                                   [Page 19]


LDAP API                                                    October 1996


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.15.  Extended Operations

The ldap_extended() and ldap_extended_s() routines allow extended LDAP
operations to be passed to the server, providing a general protocol
extensibility mechanism.

           int ldap_extended(
                   LDAP            *ld,
                   char            *requestoid,
                   struct berval   *requestdata
           );

           int ldap_extended_s(
                   LDAP            *ld,
                   char            *requestoid,
                   struct berval   *requestdata,
                   LDAPMessage     **result
           );

Parameters are:

ld       The session handle.

requestoidThe dotted-oid text string naming the request.

requestdata
         The arbitrary data required by the operation.

result   A result parameter that will be filled in with the result of
         the operation, suitable for passing to
         ldap_parse_extended_result().

The ldap_extended_s() routine is synchronous and returns an LDAP error
code indicating the success or failure of the extended operation.

The ldap_extended() routine is asynchronous and returns 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().




Expires 4/97                                                   [Page 20]


LDAP API                                                    October 1996


6.  Calls for abandoning an operation

ldap_abandon() is used to abandon an operation in progress.

           int ldap_abandon( LDAP *ld, int msgid );


ld     The session handle.

msgid  The message id of the request to be abandoned.

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().

7.  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.
ldap_msgtype() returns the type of an LDAP message.

           int ldap_result(
                   LDAP            *ld,
                   int             msgid,
                   int             all,
                   struct timeval  *timeout,
                   LDAPMessage     **res
           );

           int ldap_msgfree( LDAPMessage *res );

           int ldap_msgtype( LDAPMessage *res );

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;




Expires 4/97                                                   [Page 21]


LDAP API                                                    October 1996


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 seconds speci-
         fies 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(), ldap_search_s(), ldap_search_st(), or
         ldap_search_get_page_s().

Upon successful completion, ldap_result() returns the type of the result
returned in the res parameter. This will be one of the following con-
stants.

             LDAP_RES_BIND
             LDAP_RES_SEARCH_ENTRY
             LDAP_RES_SEARCH_REFERENCE     -- new
             LDAP_RES_SEARCH_RESULT
             LDAP_RES_MODIFY
             LDAP_RES_ADD
             LDAP_RES_DELETE
             LDAP_RES_MODRDN
             LDAP_RES_COMPARE
             LDAP_RES_SESSION              -- new
             LDAP_RES_EXTENDED             -- new

ldap_result() returns 0 if the timeout expired and -1 if an error
occurs, in which case the error parameters of the LDAP session handle
will be set accordingly.

ldap_msgfree() frees the result structure pointed to be res and returns
the type of the message it freed.

ldap_msgtype() returns the type of the LDAP message it is passed as a
parameter. The type will be one of the types listed above, or -1 on
error.

8.  Calls for Error and Result Handling

The following calls are used to interpret errors returned by other LDAP
API routines.

           int ldap_parse_result(
                   LDAP            *ld,
                   LDAPMessage     *result,
                   char            **matched,
                   char            **errmsg,



Expires 4/97                                                   [Page 22]


LDAP API                                                    October 1996


                   char            ***referrals
           );
           int ldap_parse_bind_result(
                   LDAP            *ld,
                   LDAPMessage     *result,
                   char            **matched,
                   char            **errmsg,
                   char            ***referrals,
                   int             *version,
                   char            *serverurl,
                   struct berval   **servercreds
           );
           int ldap_parse_search_result(
                   LDAP            *ld,
                   LDAPMessage     *result,
                   char            **matched,
                   char            **errmsg,
                   char            ***referrals,
                   int             *totalcount
           );
           int ldap_parse_compare_result(
                   LDAP            *ld,
                   LDAPMessage     *result,
                   char            **matched,
                   char            **errmsg,
                   char            ***referrals,
                   char            **matchedtype
           );
           int ldap_parse_session_result(
                   LDAP            *ld,
                   LDAPMessage     *result,
                   char            **matched,
                   char            **errmsg,
                   char            ***referrals,
                   char            ***unsupported
           );
           int ldap_parse_extended_result(
                   LDAP            *ld,
                   LDAPMessage     *result,
                   char            **matched,
                   char            **errmsg,
                   char            ***referrals,
                   char            **resultoid,
                   struct berval   **resultdata
           );

           char *ldap_err2string( int err );




Expires 4/97                                                   [Page 23]


LDAP API                                                    October 1996


           void ldap_perror( LDAP *ld, char *msg );

   The use of the following routines is deprecated.

           int ldap_result2error(
                   LDAP            *ld,
                   LDAPMessage     *result,
                   int             freeit
           );

Parameters are:

ld       The connection handle.

result   The result of an LDAP operation as returned by ldap_result() or
         one of the synchronous API operation calls.

matched  In the case of a return of LDAP_NO_SUCH_OBJECT, this result
         parameter will be filled in with a DN indicating how much of
         the name in the request was recognized. NULL may be passed to
         ignore this field.

errmsg   This result parameter will be filled in with the contents of
         the error message field from the LDAPResult message. NULL may
         be passed to ignore this field.

referralsThis result parameter will be filled in with the contents of
         the referrals field from the LDAPResult message, indicating
         zero or more alternate LDAP servers where the request should be
         retried. NULL may be passed to ignore this field.

version  For bind results, this result parameter will be filled in with
         the version number returned by the LDAP server, indicating the
         highest version number the server supports. NULL may be passed
         to ignore this field.

serverurlFor bind results, this result parameter will be filled in with
         the official LDAP URL for accessing this server, if given. NULL
         may be passed to ignore this field.

servercreds
         For bind results, this result parameter will be filled in with
         the credentials passed back by the server for mutual authenti-
         cation, if given. NULL may be passed to ignore this field.

totalcountFor search results, this result parameter will be filled in
         with the total count from a paged search request. NULL may be
         passed to ignore this field.



Expires 4/97                                                   [Page 24]


LDAP API                                                    October 1996


matchedtype
         For compare results, this result parameter will be filled in
         with the name of the attribute type actually used in the com-
         pare match. NULL may be passed to ignore this field.

unsupported
      For session results, this result parameter will be filled in with
      a NULL-terminated array of string OIDs identifying unsupported
      session controls from the corresponding session request.  NULL may
      be passed to ignore this field.

resultoidFor extended results, this result parameter will be filled in
         with the dotted-OID text representation of the name of the
         extended operation response.  NULL may be passed to ignore this
         field.

resultdataFor extended results, this result parameter will be filled in
         with a pointer to a struct berval containing the data in the
         extended operation response. NULL may be passed to ignore this
         field.

err      For ldap_err2string(), an LDAP error code, as returned by
         ldap_result2error() or one of the synchronous API operation
         calls.

msg      For ldap_perror(), a message to be displayed before the LDAP
         error message.

Parameters for the deprecated calls are not described.  Interested
readers are referred to RFC 1823.

All of the ldap_parse*_result() routines return an LDAP error code indi-
cating the outcome of the operation. This is one of the following con-
stants:

           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_REFERRAL                           -- new
           LDAP_ADMIN_LIMIT_EXCEEDED               -- new
           LDAP_UNAVAILALBLE_EXTENSION             -- new
           LDAP_NO_SUCH_ATTRIBUTE



Expires 4/97                                                   [Page 25]


LDAP API                                                    October 1996


           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_AFFECTS_MULTIPLE_SERVERS           -- new
           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
           LDAP_CONNECT_ERROR

In case of trouble (failure to parse the result), -1 is returned.

ldap_err2string() is used to convert a numeric LDAP error code, as
returned by one of the ldap_parse*_result() routines, or one of the syn-
chronous API operation calls, into an informative NULL-terminated char-
acter 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



Expires 4/97                                                   [Page 26]


LDAP API                                                    October 1996


connection handle, to standard error.

9.  Calls for Parsing Search Entries

The following calls are used to parse the entries and references
returned by ldap_search() and friends. These results 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 and
references 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.

9.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 and references in a search result.
ldap_count_entries() is used to count the number of entries returned.
ldap_count_references() is used to count the number of references
returned. ldap_msgtype(), described above, can be used to distinguish
between entries and references.

           LDAPMesage *ldap_first_entry( LDAP *ld, LDAPMessage *res );

           LDAPMesage *ldap_next_entry( LDAP *ld, LDAPMessage *entry );

           int ldap_count_entries( LDAP *ld, LDAPMessage *res );

           int ldap_count_references( LDAP *ld, LDAPMessage *res );

Parameters are:

ld     The connection handle;

res    The search result, as obtained by a call to one of the synchro-
       nous 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 or references exist in the result set to be returned.  NULL is
also returned if an error occurs while stepping through the entries, in
which case the error parameters in the ld session 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 that
remain in a chain if called with an entry or reference returned by



Expires 4/97                                                   [Page 27]


LDAP API                                                    October 1996


ldap_first_entry() or ldap_next_entry().

ldap_count_refernces() returns the number of references contained in a
chain of search results. It can also be used to count the number of
references that remain in a chain if called with an entry or references
returned by ldap_first_entry() or ldap_next_entry().

9.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,
                   BerElement      **ptr
           );

           char *ldap_next_attribute(
                   LDAP            *ld,
                   LDAPMessage     *entry,
                   BerElement      *ptr
           );

           void ldap_memfree( char *mem );

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 inter-
       nally 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().

mem    A pointer to memory allocated by the LDAP library, such as the
       attribute names returned by ldap_first_attribute() and
       ldap_next_attribute, or the DN returned by ldap_get_dn().

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 error parameters in the ld session handle will be set to indi-
cate the error.

Both routines return a pointer to an allocated buffer containing the



Expires 4/97                                                   [Page 28]


LDAP API                                                    October 1996


current attribute name. This should be freed when no longer in use by
calling ldap_memfree().

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. After a set of calls to
ldap_first_attribute() and ldap_next_attibute(), if ptr is non-NULL, it
should be freed by calling ber_free( ptr, 0 ). Note that it is very
important to pass the second parameter as 0 (zero) in this call.

The attribute names returned are suitable for passing in a call to
ldap_get_values() and friends to retrieve the associated values.

9.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:




Expires 4/97                                                   [Page 29]


LDAP API                                                    October 1996


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().

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 dynamically allocated and should be
freed by calling either ldap_value_free() or ldap_value_free_len() when
no longer in use.

9.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_explode_rdn( char *rdn, 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, such as returned by ldap_get_dn().

rdn     The rdn to explode, such as returned in the components of the
        array returned by ldap_explode_dn().

notypes A boolean parameter, if non-zero indicating that the dn or rdn



Expires 4/97                                                   [Page 30]


LDAP API                                                    October 1996


        components 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 error parameters in the ld session 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 NULL-terminated 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_explode_rdn() returns a NULL-terminated char * array containing the
components of the RDN 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.

10.  Security Considerations

LDAP supports security through protocol-level authentication, using
clear-text passwords or other more secure mechanisms.  It also supports
running over SSL, which provides strong security at the transport layer.

11.  Acknowledgements

Many members of the IETF ASID working group as well as members of the
Internet at large have provided useful comments and suggestions that
have been incorporated into this revision.

This original material upon which this revision is based was based upon
work supported by the National Science Foundation under Grant No.  NCR-
9416667.

12.  Bibliography

[1]  The Directory: Selected Attribute Syntaxes.  CCITT, Recommendation
     X.520.

[2]  M. Wahl, A. Coulbeck, T. Howes, S. Kille, "Lightweight Directory
     Access Protocol: Standard and Pilot Attribute Definitions", Inter-
     net Draft draft-ietf-asid-ldapv3-attributes-03.txt, October 1996




Expires 4/97                                                   [Page 31]


LDAP API                                                    October 1996


[3]  T. Howes, "A String Representation of LDAP Search Filters," RFC
     1960, June 1996.

[4]  S. Kille, "A String Representation of Distinguished Names," RFC
     1779, March 1995.

[5]  S. Kille, "Using the OSI Directory to Achieve User Friendly Nam-
     ing," RFC 1781, March 1995.

[7]  M. Wahl, T. Howes, S. Kille, "Lightweight Directory Access Protocol
     (v3)", Internet Draft draft-ietf-asid-ldapv3-protocol-03.txt,
     October 1996.

13.  Author's Addresses

   Tim Howes
   Netscape Communications Corp.
   501 E. Middlefield Rd.
   Mountain View, CA 94043
   USA
   +1 415 937-3419
   howes@netscape.com

   Mark Smith
   Netscape Communications Corp.
   501 E. Middlefield Rd.
   Mountain View, CA 94043
   USA
   +1 313 937-3477
   mcs@netscape.com

14.  Appendix A - Sample LDAP API Code

   #include <ldap.h>

   main()
   {
           LDAP            *ld;
           LDAPMessage     *res, *e;
           int             i;
           char            *a, *dn;
           BerElement      *ptr;
           char            **vals;

           /* open a connection */
           if ( (ld = ldap_init( "dotted.host.name", LDAP_PORT )) == NULL )
                   exit( 1 );




Expires 4/97                                                   [Page 32]


LDAP API                                                    October 1996


           /* 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: %s\n", 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: %s\n", a );

                           /* print each value */
                           vals = ldap_get_values( ld, e, a );
                           for ( i = 0; vals[i] != NULL; i++ ) {
                                   printf( "value: %s\n", vals[i] );
                           }
                           ldap_value_free( vals );
                   }
           }
           /* free the search results */
           ldap_msgfree( res );

           /* close and free connection resources */
           ldap_unbind( ld );
   }










Expires 4/97                                                   [Page 33]