/sys$common/syshlp/HELPLIB.HLB  —  LDAP
    LDAP is the C language application programming interface (API)
    for the Lightweight Directory Access Protocol (LDAP). This
    API supports Version 3 of the LDAP API (LDAPv3), and includes
    support for controls, information hiding, and thread safety. It
    is available on OpenVMS Alpha only.

1  –  Introduction

          The C LDAP API is designed to be powerful, yet simple
    to use. It defines compatible synchronous and asynchronous
    interfaces to LDAP to support a wide variety of applications.

1.1  –  Overview of the LDAP Model

    LDAP is the lightweight directory access protocol, which is based
    on a client-server model. In this model, 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 (for example, 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 (for example, ASCII
    characters or a jpeg photograph) and how those values behave
    during directory operations (for example, whether case is
    significant during comparisons).

    Entries may be organized in a tree structure, usually based on
    political, geographical, or 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
    the following:

    cn=Barbara Jensen, o=University of Michigan, c=US

    Operations are provided to authenticate, search for and retrieve
    information, modify information, and add and delete entries from
    the tree.

1.2  –  Overview of LDAP API Use

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

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

    o  Authenticate to the LDAP server. The ldap_bind() function
       supports a variety of authentication methods.

    o  Perform some LDAP operations and obtain some results. The
       ldap_search() function returns results that can be parsed
       by ldap_parse_result(), ldap_first_entry(),  and ldap_next_
       entry().

    o  Close the session. The ldap_unbind() function closes the
       connection.

    Operations can be performed either synchronously or
    asynchronously. The names of the synchronous functions 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 functions return an
    indication of the outcome of the operation (for example, the
    constant LDAP_SUCCESS or some other error code). The asynchronous
    functions make available to the caller 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()
    or ldap_abandon_ext().

    Results and errors are returned in an opaque structure called
    LDAPMessage. Functions are provided to parse this structure,
    step through entries and attributes returned. Functions are also
    provided to interpret errors.

    LDAPv3 servers may return referrals to other servers. By default,
    implementations of this API will attempt to follow referrals
    automatically for the application. This behavior can be disabled
    globally (using the ldap_set_option() call) or on a per-request
    basis through the use of a server control.

    As in the LDAPv3 protocol, all DNs and string values that are
    passed into or produced by the C LDAP API are represented as
    UTF-8 characters. Conversion functions are described in Encoded
    ASN.1.

    For compatibility with existing applications, implementations of
    this API will, by default, use Version 2 of the LDAP protocol.
    Applications that intend to take advantage of LDAPv3 features
    will need to use the ldap_set_option() call with a LDAP_OPT_
    PROTOCOL_VERSION switch set to Version 3.

    The file LDAP_EXAMPLE.C in SYS$EXAMPLES contains an example
    program that demonstrates how to use the LDAP API on OpenVMS.

1.3  –  LDAP API Use on OpenVMS Systems

    This release of the LDAP API provides support for client
    applications written in C or C++.

    In order to use the LDAP API, a program must use an include
    statement of the form:

    #include <ldap.h>

    The LDAP.H header file includes prototypes and data structures
    for all of the functions that are available in the LDAP API.

    The shareable image LDAP$SHR.EXE includes run-time support for
    LDAP applications. This shareable image resides in SYS$LIBRARY
    and should be included in the library IMAGELIB.OLB, which means
    that no special action is necessary to link or run your programs.
    For example:

      $ type myprog.c

      /* A not very useful program */
      #include <stdio.h>
      #include <ldap.h>
      void main(int argc, char *argv[])
      {
        LDAP *ld;
        if (argc != 2) {
          printf("usage: %s <hostname>\n",argv[0]);
          return;
        }
        ld = ldap_init(argv[1],LDAP_PORT);
        if (ld != NULL) {
          printf("ldap_init returned 0x%p\n",ld);
        } else {
          printf("ldap_init failed\n");
        }
      }

      $ cc myprog
      $ link myprog
      $ myprog :== $mydisk:[mydir]myprog.exe
      $ myprog fred
      ldap_init returned 0xA6748
      $

1.4  –  64-bit Addressing Support

    OpenVMS Alpha provides support for 64-bit virtual memory
    addressing. Applications that are built using a suitable compiler
    may take advantage of the 64-bit virtual address space to map and
    access large amounts of data.

1.4.1  –  Background

    The OpenVMS LDAP API supports both 32- and 64-bit client
    applications. In order to allow this, separate entry points are
    provided in the library for those functions that are sensitive to
    pointer size.

    When a user module is compiled, the header file LDAP.H determines
    the pointer size in effect and uses the C preprocessor to map
    the function names into the appropriate library entry point. This
    mapping is transparent to the user application and is effected by
    setting the /POINTER_SIZE qualifier at compilation time.

    For LDAP API users, switching between different pointer sizes
    should need only a recompilation-no code changes are necessary.

    This means that programs using the specification for the C LDAP
    API, as described in the Internet Engineering Task Force (IETF)
    documentation, can be built on OpenVMS with either 32-bit or
    64-bit pointer size, without having to change the source code.

1.4.2  –  Implementation

    The OpenVMS LDAP library uses 64-bit pointers internally and is
    capable of dealing with data structures allocated by the caller
    from 64-bit address space.

    Applications that use 32-bit pointers will use the 32-bit
    function entry points in the library. This means they can pass
    arguments that are based on 32-bit pointers and can assume that
    any pointers returned by the library will be 32-bit safe.

    While the mapping performed by LDAP.H is designed to be
    transparent, there may be occasions where it is useful (for
    example in debugging) to understand the consequences of having
    both 32- and 64-bit support in the same library.

1.4.2.1  –  Library Symbol Names

    The symbols exported by the LDAP$SHR OpenVMS run-time library
    differ from those specified in the IETF C LDAP API specification.

    The header file LDAP.H maps user references to LDAP API function
    names to the appropriate LDAP$SHR symbol name. Therefore, any
    application wishing to use the OpenVMS LDAP API must include the
    version of LDAP.H that ships with OpenVMS.

    All of the functions in the OpenVMS LDAP library are prefixed
    with the facility code "LDAP$".

    For those functions where the caller's pointer size is
    significant, the name of the 64-bit entry point will have a "_
    64" suffix, while the name of the 32-bit jacket will have a "_32"
    suffix. Functions that are not sensitive to pointer size have no
    special suffix.

    For example, the function ldap_modify() is sensitive to the
    caller's pointer size (because one of its arguments is an
    array of pointers). Therefore, the library exports symbols for
    LDAP$LDAP_MODIFY_64 and LDAP$LDAP_MODIFY_32. For the function
    ldap_simple_bind(), which is not sensitive to the caller's
    pointer size, a single entry point, LDAP$LDAP_SIMPLE_BIND, exists
    in the library.

    Because OpenVMS imposes a 31-character limit on the length of
    symbol names, certain functions in the library have names which
    are abbreviated versions of the public API name. For example,
    in the case of the function ldap_parse_sasl_bind_result(), the
    library provides two entry points, namely LDAP$LDAP_PRS_SASL_
    BIND_RES_32 and LDAP$LDAP_PRS_SASL_BIND_RES_64.

1.4.2.2  –  LDAP Data Structures

    The LDAP API defines various data structures which are used to
    pass information to and from a client application. Some of these
    structures are opaque; that is, their internal layout is not
    visible to a client application. In such cases, the API may
    return a pointer to such a structure, but the only use of such
    a pointer to a client application is as a parameter to subsequent
    library calls.

    Some structures are public. Their contents are defined by the
    API, and client applications may allocate and manipulate such
    structures or use them as parameters to LDAP functions.

    All data structures used by the API are defined with "natural"
    alignment; that is, each member of a data structure will be
    aligned on an address boundary appropriate to its type.

    Opaque Data Structures

    The following data structures are opaque. Applications should
    not make any assumptions about the contents or size of such data
    structures.

        typedef struct ldap
                LDAP;

        typedef struct ldapmsg
                LDAPMessage;

        typedef struct berelement
                BerElement;

    Public Data Structures

    The following data structures are described in the IETF documents
    relating to the LDAP API, and definitions are provided for
    them in LDAP.H. Applications may allocate and manipulate such
    structures, as well as use them in calls to the LDAP API.

        typedef struct berval { .. }
                BerValue;

        typedef struct ldapapiinfo { .. }
                LDAPAPIInfo;

        typedef struct ldap_apifeature_info { .. }
                LDAPAPIFeatureInfo;

        typedef struct ldapcontrol { .. }
                LDAPControl;

        typedef struct ldapmod { .. }
                LDAPMod;

    Note that the pointer size in effect at compilation time
    determines the layout of data structures, which themselves
    contain pointer fields. Since all of the public data structures
    listed here contain one or more pointers, their size and layout
    will differ depending on the pointer size.

    For example, in the case of the structure berval, the API
    provides the following definition:

     struct berval {
          ber_len_t      bv_len;
          char           *bv_val;
     } BerValue;

    (where ber_len_t is equivalent on OpenVMS to an unsigned 32-bit
    integer).

    The following code would therefore work correctly regardless of
    pointer size:

         #include <ldap.h>
         .
         .
         .
           char       *buff;
           BerValue   val;
         .
         .
         .
           buff = (char *)malloc(255);
         .
         .
         .
           val.bv_len = 255;
           val.bv_val = buff;
         .
         .
         .

1.4.3  –  Mixing Pointer Sizes

    Two modules that include LDAP.H can be compiled with different
    pointer sizes and linked together. While each module may use the
    LDAP API on its own, it may not be possible for both modules to
    share LDAP-related data.

    None of the public LDAP data structures is directly compatible
    between 32- and 64-bit modules. For example, a BerValue that
    has been allocated by a 32-bit module does not have the same
    layout as a BerValue which a 64-bit module expects to see, and
    consequently cannot be exchanged between two such modules without
    some sort of data conversion taking place.

    Opaque data structures (such as LDAP *) have only a single
    structure definition inside the library, and so pointers to such
    structures may be exchanged between 32- and 64-bit callers. Note
    that these structures are allocated only by the library itself,
    and, in the case of a 64-bit caller, these structures may be
    allocated in 64-bit space. So while the LDAP handle returned to
    a 32-bit caller of ldap_init() could safely be used by a 64-bit
    module, the reverse may not be true.

1.5  –  Multithreading Support

    The OpenVMS LDAP API may be used by a multi-threaded application.
    Two of the functions in the library, ldap_perror() and ldap_
    result2error(), are not thread-safe.

2  –  Data Structures

    The following are definitions of some data structures that are
    common to several LDAP API functions.

    typedef struct ldap LDAP;

    typedef struct berelement BerElement;

    typedef struct ldapmsg LDAPMessage;

    typedef struct berval {
        ber_len_t       bv_len;
        char            *bv_val;
    } BerValue;

    struct timeval;

    The LDAP structure is an opaque data type that represents an LDAP
    session. Typically, this corresponds to a connection to a single
    server, but it may encompass several server connections in LDAPv3
    referrals.

    The LDAPMessage structure is an opaque data type that is used
    to return entry, reference, result, and error information. An
    LDAPMessage structure may represent the beginning of a list or a
    chain of messages that contain a series of entries, references,
    and result messages that are returned by LDAP operations, such
    as search. LDAP API functions, such as ldap_parse_result(), that
    operate on message chains which may contain more than one result
    message, always operate on the first result message in the chain.
    See Results for more information.

    The BerElement structure is an opaque data type that is used to
    hold data and state information about encoded data.

    The berval structure is used to represent arbitrary binary data,
    and its fields have the following meanings:

    bv_len     Length of data in bytes.
    bv_val     A pointer to the data itself.

    The timeval structure is used to represent an interval of time,
    and its fields have the following meanings:

    tv_sec     Seconds component of time interval.
    tv_usec    Microseconds component of time interval.

    All memory that is allocated by a function in this C LDAP API
    and returned to the caller should be disposed of by calling the
    appropriate free function provided by this API.

    Memory that is allocated outside of the C LDAP API must not be
    disposed of using a function provided by this API.

    The following is a complete list of free functions that are used
    to dispose of allocated memory:

       ber_bvecfree()

       ber_bvfree()

       ber_free()

       ldap_control_free()

       ldap_controls_free()

       ldap_memfree()

       ldap_msgfree()

       ldap_value_free()

       ldap_value_free_len()

3  –  Error Codes

    Many of the LDAP API functions return LDAP error codes, some of
    which indicate local errors and some of which may be returned by
    servers. All of the LDAP error codes returned will be positive
    integers; those between 0x00 and 0x50 are returned from the
    LDAP server, those above 0x50 are generated by the API itself.
    Supported error codes are as follows (hexadecimal values are
    given in parentheses after the constant):

         LDAP_SUCCESS (0x00)

         LDAP_OPERATIONS_ERROR (0x01)

         LDAP_PROTOCOL_ERROR (0x02)

         LDAP_TIMELIMIT_EXCEEDED (0x03)

         LDAP_SIZELIMIT_EXCEEDED (0x04)

         LDAP_COMPARE_FALSE (0x05)

         LDAP_COMPARE_TRUE (0x06)

         LDAP_STRONG_AUTH_NOT_SUPPORTED (0x07)

         LDAP_STRONG_AUTH_REQUIRED (0x08)

         LDAP_REFERRAL (0x0a)                        -- new in LDAPv3

         LDAP_ADMINLIMIT_EXCEEDED (0x0b)             -- new in LDAPv3

         LDAP_UNAVAILABLE_CRITICAL_EXTENSION (0x0c)  -- new in LDAPv3

         LDAP_CONFIDENTIALITY_REQUIRED (0x0d)        -- new in LDAPv3

         LDAP_SASL_BIND_IN_PROGRESS (0x0e)           -- new in LDAPv3

         LDAP_NO_SUCH_ATTRIBUTE (0x10)

         LDAP_UNDEFINED_TYPE (0x11)

         LDAP_INAPPROPRIATE_MATCHING (0x12)

         LDAP_CONSTRAINT_VIOLATION (0x13)

         LDAP_TYPE_OR_VALUE_EXISTS (0x14)

         LDAP_INVALID_SYNTAX (0x15)

         LDAP_NO_SUCH_OBJECT (0x20)

         LDAP_ALIAS_PROBLEM (0x21)

         LDAP_INVALID_DN_SYNTAX (0x22)

         LDAP_IS_LEAF (0x23)                    -- not used in LDAPv3

         LDAP_ALIAS_DEREF_PROBLEM (0x24)

         LDAP_INAPPROPRIATE_AUTH (0x30)

         LDAP_INVALID_CREDENTIALS (0x31)

         LDAP_INSUFFICIENT_ACCESS (0x32)

         LDAP_BUSY (0x33)

         LDAP_UNAVAILABLE (0x34)

         LDAP_UNWILLING_TO_PERFORM (0x35)

         LDAP_LOOP_DETECT (0x36)

         LDAP_NAMING_VIOLATION (0x40)

         LDAP_OBJECT_CLASS_VIOLATION (0x41)

         LDAP_NOT_ALLOWED_ON_NONLEAF (0x42)

         LDAP_NOT_ALLOWED_ON_RDN (0x43)

         LDAP_ALREADY_EXISTS (0x44)

         LDAP_NO_OBJECT_CLASS_MODS (0x45)

         LDAP_RESULTS_TOO_LARGE (0x46)            -- reserved for CLDA

         LDAP_AFFECTS_MULTIPLE_DSAS (0x47)        -- new in LDAPv3

         LDAP_OTHER (0x50)

         LDAP_SERVER_DOWN (0x51)

         LDAP_LOCAL_ERROR (0x52)

         LDAP_ENCODING_ERROR (0x53)

         LDAP_DECODING_ERROR (0x54)

         LDAP_TIMEOUT (0x55)

         LDAP_AUTH_UNKNOWN (0x56)

         LDAP_FILTER_ERROR (0x57)

         LDAP_USER_CANCELLED (0x58)

         LDAP_PARAM_ERROR (0x59)

         LDAP_NO_MEMORY (0x5a)

         LDAP_CONNECT_ERROR (0x5b)

         LDAP_NOT_SUPPORTED (0x5c)

         LDAP_CONTROL_NOT_FOUND (0x5d)

         LDAP_NO_RESULTS_RETURNED (0x5e)

         LDAP_MORE_RESULTS_TO_RETURN (0x5f)

         LDAP_CLIENT_LOOP (0x60)

         LDAP_REFERRAL_LIMIT_EXCEEDED (0x61)

4  –  Initializing

    The ldap_init() function 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 *ldap_init(
                  const char    *hostname,
                  int           portno);

    Use of the following function is deprecated.

            LDAP *ldap_open(
                  const char    *hostname,
                  int           portno);

    Unlike ldap_init(), the ldap_open()  function attempts to make a
    server connection before returning to the caller. A more complete
    description can be found in RFC 1823.

    Parameters are as follows:

    hostname   Contains a space-separated list of hostnames or dotted
               strings representing the IP address of hosts running an
               LDAP server to connect to. Each hostname in the list
               can include an optional port number which is separated
               from the host itself with a colon (:) character. 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. ldap_init()
               does not connect to the LDAP server.
    portno     Contains the TCP port number to connect to. The default
               LDAP port of 389 can be obtained by supplying the
               constant LDAP_PORT. If a host includes a port number,
               then this parameter is ignored.

    The ldap_init() and ldap_open()  functions both return a session
    handle, a pointer to an opaque structure that should be passed
    to subsequent calls pertaining to the session. These functions
    return NULL if the session cannot be initialized, in which case
    the operating system error reporting mechanism can be checked to
    see why the call failed.

    Note that if you connect to an LDAP Version 2 server, one of the
    ldap_bind() calls must be completed before other operations can
    be performed on the session. LDAPv3 does not require that a bind
    operation be completed before other operations can be performed.

    The calling program can set various attributes of the session
    by calling the functions described in the Session Handles help
    topic.

5  –  Session Handles

    The LDAP session handle returned by ldap_init() 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.

    To insulate callers from inevitable changes to this structure,
    these aspects of the session are now accessed through a pair of
    accessor functions.

    The ldap_get_option() function is used to access the current
    value of various session-wide parameters. The ldap_set_option()
    function is used to set the value of these parameters. Note that
    some options are READ-ONLY and cannot be set; it is an error to
    call ldap_set_option() and attempt to set a READ-ONLY option.

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

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

    Parameters are as follows:

    ld         The session handle. If this is NULL, a set of global
               defaults is accessed. New LDAP session handles
               created with ldap_init() or ldap_open() inherit their
               characteristics from these global defaults.
    option     The name of the option being accessed or set. This
               parameter should be one of the following constants,
               which have the indicated meanings. After the constant,
               the actual hexadecimal value of the constant is listed
               in parentheses.
               LDAP_OPT_DESC      Type for invalue parameter: not
               (0x01)             applicable (option is read-only).
                                  Type for outvalue parameter: int *

                                  Description: The underlying socket
                                  descriptor corresponding to the
                                  primary LDAP connection. This
                                  option is read-only and cannot
                                  be set.
               LDAP_OPT_DEREF     Type for invalue parameter: int *
               (0x02)             Type for outvalue parameter: int *

                                  Description: Determines how aliases
                                  are handled during search. It can
                                  have one of the following values:
                                  LDAP_DEREF_NEVER (0x00), LDAP_
                                  DEREF_SEARCHING (0x01), LDAP_DEREF_
                                  FINDING (0x02), or LDAP_DEREF_
                                  ALWAYS (0x03). 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_          Type for invalue parameter: int *
               SIZELIMIT (0x03)   Type for outvalue parameter: int *

                                  Description: A limit on the number
                                  of entries to return from a search.
                                  A value of LDAP_NO_LIMIT (0) means
                                  no limit.
               LDAP_OPT_          Type for invalue parameter: int *
               TIMELIMIT (0x04)   Type for outvalue parameter: int *

                                  Description: A limit on the number
                                  of seconds to spend on a search. A
                                  value of LDAP_NO_LIMIT (0) means no
                                  limit.
               LDAP_OPT_          Type for invalue parameter: int
               REFERRALS (0x08)   (LDAP_OPT_ON or LDAP_OPT_OFF)
                                  Type for outvalue parameter: int *

                                  Description: Determines whether
                                  the LDAP library automatically
                                  follows referrals returned by LDAP
                                  servers. It can be set to one of
                                  the constants LDAP_OPT_ON (1) or
                                  LDAP_OPT_OFF (0).
               LDAP_OPT_RESTART   Type for invalue parameter: int
               (0x09)             (LDAP_OPT_ON or LDAP_OPT_OFF)
                                  Type for outvalue parameter: int *

                                  Description: Determines 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
                                  is interrupted prematurely, (for
                                  example, by a timer going off) or
                                  other interrupt.
               LDAP_OPT_          Type for invalue parameter: int *
               PROTOCOL_VERSION   Type for outvalue parameter: int *
               (0x11)
                                  Description: This option indicates
                                  the version of the LDAP protocol
                                  used when communicating with the
                                  primary LDAP server. It must be
                                  one of the constants LDAP_VERSION2
                                  (2) or LDAP_VERSION3 (3). If no
                                  version is set, the default is
                                  LDAP_VERSION2 (2).
               LDAP_OPT_SERVER_   Type for invalue parameter:
               CONTROLS (0x12)    LDAPControl **
                                  Type for outvalue parameter:
                                  LDAPControl ***

                                  Description: A default list of LDAP
                                  server controls to be sent with
                                  each request. See Controls for more
                                  information.
               LDAP_OPT_CLIENT_   Type for invalue parameter:
               CONTROLS (0x13)    LDAPControl **
                                  Type for outvalue parameter:
                                  LDAPControl ***

                                  Description: A default list of
                                  client controls that affect the
                                  LDAP session. See Controls for more
                                  information.
               LDAP_OPT_HOST_     Type for invalue parameter: char *
               NAME (0x30)        Type for outvalue parameter: char
                                  **

                                  Description: The host name (or
                                  list of host) for the primary LDAP
                                  server.
               LDAP_OPT_ERROR_    Type for invalue parameter: int *
               NUMBER (0x31)      Type for outvalue parameter: int *

                                  Description: The code of the most
                                  recent LDAP error that occurred for
                                  this session.
               LDAP_OPT_ERROR_    Type for invalue parameter: char *
               STRING (0x32)      Type for outvalue parameter: char
                                  **

                                  Description: The message returned
                                  with the most recent LDAP error
                                  that occurred for this session.
    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. For outvalues of type
               char ** and LDAPControl **, a pointer to data that
               is associated with the LDAP session ld is returned;
               callers should dispose of the memory by calling ldap_
               memfree() or ldap_controls_free().
    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.

               Both ldap_get_option() and ldap_set_option() return 0
               if successful and -1 if an error occurs.

6  –  Controls

    LDAPv3 operations can be extended through the use of controls.
    Controls may be sent to a server or returned to the client
    with any LDAP message. These controls are referred to as server
    controls.

    The LDAP API also supports a client-side extension mechanism
    through the use of client controls. These controls affect the
    behavior of the LDAP API only and are never sent to a server.
    A common data structure is used to represent both types of
    controls:

            typedef struct ldapcontrol {
                    char                            *ldctl_oid;
                    struct berval                   ldctl_value;
                    char                            ldctl_iscritical;
            } LDAPControl, *PLDAPControl;

    The fields in the ldapcontrol structure have the following
    meanings:

    ldctl_oid      The control type, represented as a string.
    ldctl_value    The data associated with the control (if any).
                   To specify a zero-length value, set ldctl_
                   value.bv_len to zero and ldctl_value.bv_val to
                   a zero-length string. To indicate that no data is
                   associated with the control, set ldctl_value.bv_
                   val to NULL.
    ldctl_         Indicates whether the control is critical or not.
    iscritical     If this field is non-zero, the operation will only
                   be carried out if the control is recognized by the
                   server and/or client.

    Some LDAP API calls allocate an ldapcontrol structure or a
    NULL-terminated array of ldapcontrol structures. The following
    functions can be used to dispose of a single control or an array
    of controls:

         void ldap_control_free( LDAPControl *ctrl );

         void ldap_controls_free( LDAPControl **ctrls );

    A set of controls that affect the entire session can be set using
    the ldap_set_option() function. A list of controls can also be
    passed directly to some LDAP API calls, such as ldap_search_
    ext(), in which case any controls set for the session through
    the use of ldap_set_option() are ignored. Control lists are
    represented as a NULL-terminated array of pointers to ldapcontrol
    structures.

    Server controls are defined by LDAPv3 protocol extension
    documents; for example, a control has been proposed to support
    paging of search results. No client controls are currently
    implemented in this version of the API.

7  –  Authenticating

    The following functions are used to authenticate an LDAP client
    to an LDAP directory server.

    The ldap_sasl_bind() and ldap_sasl_bind_s()  functions can be
    used to do general and extensible authentication over LDAP
    through the use of the Simple Authentication Security Layer.
    The functions both take the DN to bind as, the method to use, as
    a dotted-string representation of an OID identifying the method,
    and a struct berval holding the credentials. The special constant
    value LDAP_SASL_SIMPLE (NULL) can be passed to request simple
    authentication, or the simplified functions ldap_simple_bind() or
    ldap_simple_bind_s() can be used.

      int ldap_sasl_bind(
              LDAP                                    *ld,
              const char                              *dn,
              const char                              *mechanism,
              const struct berval                     *cred,
              LDAPControl                             **serverctrls,
              LDAPControl                             **clientctrls,
              int                                     *msgidp
      );

      int ldap_sasl_bind_s(
              LDAP                                    *ld,
              const char                              *dn,
              const char                              *mechanism,
              const struct berval                     *cred,
              LDAPControl                             **serverctrls,
              LDAPControl                             **clientctrls,
              struct berval                           **servercredp
      );

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

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

    The use of the following functions 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 );

    Parameters are as follows:

    ld             The session handle.
    dn             The name of the entry to bind as.
    mechanism      Either LDAP_SASL_SIMPLE (NULL) to get simple
                   authentication, or a text string identifying the
                   SASL method.
    cred           The credentials with which to authenticate.
                   Arbitrary credentials can be passed using
                   this parameter. The format and content of
                   the credentials depends on the setting of the
                   mechanism parameter.
    passwd         For ldap_simple_bind(), the password to compare to
                   the entry's userPassword attribute.
    serverctrls    List of LDAP server controls.
    clientctrls    List of client controls.
    msgidp         This result parameter will be set to the message
                   id of the request if the ldap_sasl_bind() call
                   succeeds.
    servercredp    This result parameter will be filled in with the
                   credentials passed back by the server for mutual
                   authentication, if given. An allocated berval
                   structure is returned that should be disposed of
                   by calling ber_bvfree(). NULL may be passed to
                   ignore this field.

    Additional parameters for the deprecated functions are not
    described. See the RFC 1823 documentation for more information.

    The ldap_sasl_bind() function initiates an asynchronous bind
    operation and returns the constant LDAP_SUCCESS if the request
    was successfully sent or another LDAP error code if not. See
    Errors for more information about possible errors and how to
    interpret them. If successful, ldap_sasl_bind() places the
    message id of the request in *msgidp. A subsequent call to ldap_
    result() can be used to obtain the result of the bind.

    The ldap_simple_bind() function initiates a simple asynchronous
    bind operation and returns the message id of the operation
    initiated. A subsequent call to ldap_result() can be used to
    obtain the result of the bind. In case of error, ldap_simple_
    bind() will return -1, setting the session error parameters in
    the LDAP structure appropriately.

    The synchronous ldap_sasl_bind_s() and ldap_simple_bind_s()
    functions both return the result of the operation, either the
    constant LDAP_SUCCESS if the operation was successful, or another
    LDAP error code if it was not. See Errors for more information
    about possible errors and how to interpret them.

    Note that if an LDAP Version 2 server is contacted, no other
    operations over the connection should be attempted before a bind
    call has successfully completed.

    Subsequent bind calls can be used to reauthenticate over the
    same connection, and multistep SASL sequences can be accomplished
    through a sequence of calls to ldap_sasl_bind() or ldap_sasl_
    bind_s().

8  –  Closing

    The following functions are used to unbind from the directory,
    close the connection, and dispose of the session handle.

            int ldap_unbind( LDAP *ld );
            int ldap_unbind_s( LDAP *ld );

    Parameter is as follows:

    ld    The session handle.

    The ldap_unbind() and ldap_unbind_s()  functions both work
    synchronously, unbinding from the directory, closing the
    connection, and freeing up the ld structure before returning.
    There is no server response to an unbind operation. The ldap_
    unbind() function returns LDAP_SUCCESS (or another LDAP error
    code if the request cannot be sent to the LDAP server). After a
    call to ldap_unbind() or ldap_unbind_s(),  the session handle ld
    is invalid and it is illegal to make any further LDAP API calls
    using ld.

9  –  Searching

    The following functions are used to search the LDAP directory,
    returning a requested set of attributes for each entry matched.
    There are five variations.

            int ldap_search_ext(
                    LDAP                      *ld,
                    const char                *base,
                    int                       scope,
                    const char                *filter,
                    char                      **attrs,
                    int                       attrsonly,
                    LDAPControl               **serverctrls,
                    LDAPControl               **clientctrls,
                    struct timeval            *timeout,
                    int                       sizelimit,
                    int                       *msgidp
            );

            int ldap_search_ext_s(
                    LDAP                      *ld,
                    const char                *base,
                    int                       scope,
                    const char                *filter,
                    char                      **attrs,
                    int                       attrsonly,
                    LDAPControl               **serverctrls,
                    LDAPControl               **clientctrls,
                    struct timeval            *timeout,
                    int                       sizelimit,
                    LDAPMessage               **res
            );

            int ldap_search(
                    LDAP                      *ld,
                    const char                *base,
                    int                       scope,
                    const char                *filter,
                    char                      **attrs,
                    int                       attrsonly
            );

            int ldap_search_s(
                    LDAP                      *ld,
                    const char                *base,
                    int                       scope,
                    const 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 as follows:

    ld             The session handle.
    base           The dn of the entry at which to start the search.
    scope          One of LDAP_SCOPE_BASE (0x00), LDAP_SCOPE_ONELEVEL
                   (0x01), or LDAP_SCOPE_SUBTREE (0x02), indicating
                   the scope of the search.
    filter         A character string representing the search filter.
                   The value NULL can be passed to indicate that the
                   filter (objectclass=*) that matches all entries
                   should be used.
    attrs          A NULL-terminated array of strings indicating
                   which attributes to return for each matching
                   entry. Passing NULL for this parameter causes
                   all available user attributes to be retrieved. The
                   special constant string LDAP_NO_ATTRS (1.1) can be
                   used as the only element in the array to indicate
                   that no attribute types should be returned by the
                   server. The special constant string LDAP_ALL_USER_
                   ATTRS (*), can be used in the attrs array along
                   with the names of some operational attributes to
                   indicate that all user attributes plus the listed
                   operational attributes should be returned.
    attrsonly      A boolean value that should be either zero if both
                   attribute types and values are to be returned or
                   non-zero if only types are wanted.
    timeout        For the ldap_search_st() function, this specifies
                   the local search timeout value (if it is NULL,
                   the timeout is infinite). For the ldap_search_
                   ext() and ldap_search_ext_s()  functions, this
                   specifies both the local search timeout value
                   and the operation time limit that is sent to the
                   server within the search request. For the ldap_
                   search_ext() and ldap_search_ext_s()  functions,
                   passing a NULL value for timeout causes the global
                   default timeout stored in the LDAP session handle
                   to be used (set using ldap_set_option() with the
                   LDAP_OPT_TIMELIMIT parameter).
    sizelimit      For the ldap_search_ext() and ldap_search_ext_s()
                   calls, this is a limit on the number of entries to
                   return from the search. A value of LDAP_NO_LIMIT
                   (0) means no limit.
    res            For the synchronous calls, this is a result
                   parameter which will contain the results of the
                   search upon completion of the call.
    serverctrls    List of LDAP server controls.
    clientctrls    List of client controls.
    msgidp         This result parameter will be set to the message
                   id of the request if the ldap_search_ext() call
                   succeeds.

    There are three options in the session handle ld that potentially
    affect how the search is performed. They are as follows:

    LDAP_OPT_        A limit on the number of entries to return from
    SIZELIMIT        the search. A value of LDAP_NO_LIMIT (0) means
                     no limit. Note that the value from the session
                     handle is ignored when using the ldap_search_
                     ext()  or ldap_search_ext_s() functions.
    LDAP_OPT_        A limit on the number of seconds to spend on
    TIMELIMIT        the search. A value of LDAP_NO_LIMIT (0) means
                     no limit. Note that the value from the session
                     handle is ignored when using the ldap_search_
                     ext()  or ldap_search_ext_s() functions.
    LDAP_OPT_DEREF   One of LDAP_DEREF_NEVER(0x00), LDAP_DEREF_
                     SEARCHING(0x01), LDAP_DEREF_FINDING (0x02),
                     or LDAP_DEREF_ALWAYS (0x03), 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.

    The ldap_search_ext() function initiates an asynchronous search
    operation and returns either the constant LDAP_SUCCESS if the
    request was successfully sent or another LDAP error code if
    not. See Errors for more information about possible errors and
    how to interpret them. If successful, ldap_search_ext() places
    the message id of the request in *msgidp. A subsequent call to
    ldap_result() can be used to obtain the results from the search.
    These results can be parsed using the result parsing functions
    described in Errors.

    Similar to ldap_search_ext(), the ldap_search()  function
    initiates an asynchronous search operation and returns the
    message id of the operation initiated. As for ldap_search_ext(),
    a subsequent call to ldap_result() can be used to obtain the
    result of the search. In case of error, ldap_search() will return
    -1, setting the session error parameters in the LDAP structure
    appropriately.

    The synchronous ldap_search_ext_s(), ldap_search_s(),  and ldap_
    search_st() functions all return the result of the operation,
    either the constant LDAP_SUCCESS if the operation was successful
    or another LDAP error code if it was not. See Errors for more
    information about possible errors and how to interpret them.
    Entries returned from the search (if any) are contained in the
    res parameter. This parameter is opaque to the caller. Entries,
    attributes, and values should be extracted by calling the parsing
    functions. The results contained in res should be freed when no
    longer in use by calling ldap_msgfree().

    The ldap_search_ext() and ldap_search_ext_s()  functions support
    LDAPv3 server controls, client controls, and allow varying size
    and time limits to be easily specified for each search operation.
    The ldap_search_st() function is identical to ldap_search_s()
    except that it takes an additional parameter specifying a local
    timeout for the search. The local search timeout is used to
    limit the amount of time the API implementation will wait for
    a search to complete. After the local search timeout the search
    operation will return LDAP_TIMEOUT if the search result has not
    been removed.

9.1  –  Reading and Listing the Children of 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=*)" or NULL. The attrs parameter contains the list
    of attributes to return.

    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=*)" or NULL. The attrs parameter contains the
    list of attributes to return for each child entry.

10  –  Attribute Value

    The following functions are used to compare a given attribute
    value assertion against an LDAP entry. There are four variations.

            int ldap_compare_ext(
                    LDAP                              *ld,
                    const char                        *dn,
                    const char                        *attr,
                    const struct berval               *bvalue
                    LDAPControl                       **serverctrls,
                    LDAPControl                       **clientctrls,
                    int                               *msgidp
            );

            int ldap_compare_ext_s(
                    LDAP                              *ld,
                    const char                        *dn,
                    const char                        *attr,
                    const struct berval               *bvalue,
                    LDAPControl                       **serverctrls,
                    LDAPControl                       **clientctrls
            );

            int ldap_compare(
                    LDAP                              *ld,
                    const char                        *dn,
                    const char                        *attr,
                    const char                        *value
            );

            int ldap_compare_s(
                    LDAP                              *ld,
                    const char                        *dn,
                    const char                        *attr,
                    const char                        *value
            );

    Parameters are as follows:

    ld             The session 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 given entry. This parameter is used in the
                   extended functions and is a pointer to a struct
                   berval so it is possible to compare binary values.
    value          A string attribute value to compare against,
                   used by the ldap_compare() and ldap_compare_s()
                   functions. Use ldap_compare_ext() or ldap_compare_
                   ext_s() if you need to compare binary values.
    serverctrls    List of LDAP server controls.
    clientctrls    List of client controls.
    msgidp         This result parameter will be set to the message
                   id of the request if the ldap_compare_ext() call
                   succeeds.

    The ldap_compare_ext() function initiates an asynchronous compare
    operation and returns either the constant LDAP_SUCCESS if the
    request was successfully sent, or another LDAP error code if not.
    See Errors for more information about possible errors and how
    to interpret them. If successful, ldap_compare_ext() places the
    message id of the request in *msgidp. A subsequent call to ldap_
    result() can be used to obtain the result of the compare.

    Similar to ldap_compare_ext(), the ldap_compare()  function
    initiates an asynchronous compare operation and returns the
    message id of the operation initiated. As for ldap_compare_ext(),
    a subsequent call to ldap_result() can be used to obtain the
    result of the compare. In case of error, ldap_compare() will
    return -1, setting the session error parameters in the LDAP
    structure appropriately.

    The synchronous ldap_compare_ext_s() and ldap_compare_s()
    functions both return the result of the operation, either
    the constants LDAP_COMPARE_TRUE or LDAP_COMPARE_FALSE if the
    operation was successful, or another LDAP error code if it was
    not. See Errors for more information about possible errors and
    how to interpret them.

    The ldap_compare_ext() and ldap_compare_ext_s()  functions
    support LDAPv3 server controls and client controls.

11  –  Modifying Entry

    The following functions are used to modify an existing LDAP
    entry. There are four variations.

            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_ext(
                    LDAP                              *ld,
                    const char                        *dn,
                    LDAPMod                           **mods,
                    LDAPControl                       **serverctrls,
                    LDAPControl                       **clientctrls,
                    int                               *msgidp
            );

            int ldap_modify_ext_s(
                    LDAP                              *ld,
                    const char                        *dn,
                    LDAPMod                           **mods,
                    LDAPControl                       **serverctrls,
                    LDAPControl                       **clientctrls

            );

            int ldap_modify(
                    LDAP                              *ld,
                    const char                        *dn,
                    LDAPMod                           **mods
            );

            int ldap_modify_s(
                    LDAP                              *ld,
                    const char                        *dn,
                    LDAPMod                           **mods
            );

    Parameters are as follows:

    ld             The session handle.
    dn             The name of the entry to modify.
    mods           A NULL-terminated array of modifications to make
                   to the entry.
    serverctrls    List of LDAP server controls.
    clientctrls    List of client controls.
    msgidp         This result parameter will be set to the message
                   id of the request if the ldap_modify_ext() call
                   succeeds.

    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(0x00), LDAP_MOD_DELETE (0x01), or
               LDAP_MOD_REPLACE(0x02). This field also indicates the
               type of values included in the mod_vals union. It is
               logically ORed with LDAP_MOD_BVALUES (0x80) 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. The mod_values field 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, or removed if the mod_vals field is NULL. All
    modifications are performed in the order in which they are
    listed.

    The ldap_modify_ext() function initiates an asynchronous modify
    operation and returns the constant LDAP_SUCCESS if the request
    was successfully sent, or another LDAP error code if not. See
    Errors for more information about possible errors and how to
    interpret them. If successful, ldap_modify_ext() places the
    message id of the request in *msgidp. A subsequent call to ldap_
    result() can be used to obtain the result of the modify.

    Similar to ldap_modify_ext(), the ldap_modify()  function
    initiates an asynchronous modify operation and returns the
    message id of the operation initiated. As for ldap_modify_ext(),
    a subsequent call to ldap_result() can be used to obtain the
    result of the modify. In case of error, ldap_modify() will return
    -1, setting the session error parameters in the LDAP structure
    appropriately.

    The synchronous ldap_modify_ext_s() and ldap_modify_s()
    functions both return the result of the operation, either the
    constant LDAP_SUCCESS if the operation was successful, or another
    LDAP error code if it was not.

    See Errors for more information about possible errors and how to
    interpret them.

    The ldap_modify_ext() and ldap_modify_ext_s()  functions support
    LDAPv3 server controls and client controls.

12  –  Modifying Name

    In LDAP Version 2, the ldap_modrdn() and ldap_modrdn_s()
    functions 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_rename() and ldap_rename_s()  functions
    are used to change the name of an entry, and the use of the ldap_
    modrdn() and ldap_modrdn_s()  functions is deprecated.

            int ldap_rename(
                    LDAP                              *ld,
                    const char                        *dn,
                    const char                        *newrdn,
                    const char                        *newparent,
                    int                               deleteoldrdn,
                    LDAPControl                       **serverctrls,
                    LDAPControl                       **clientctrls,
                    int                               *msgidp
            );

            int ldap_rename_s(
                    LDAP                              *ld,
                    const char                        *dn,
                    const char                        *newrdn,
                    const char                        *newparent,
                    int                               deleteoldrdn,
                    LDAPControl                       **serverctrls,
                    LDAPControl                       **clientctrls
            );

    Use of the following functions 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 as follows:

    ld             The session handle.
    dn             The name of the entry whose DN is to be changed.
    newrdn         The new RDN to give the entry.
    newparent      The new parent, or superior entry. If this
                   parameter is NULL, only the RDN of the entry is
                   changed. The root DN may be specified by passing
                   a zero length string, "". The newparent parameter
                   should always be NULL when using Version 2 of the
                   LDAP protocol; otherwise the server's behavior is
                   undefined.
    deleteoldrdn   This parameter only has meaning on the rename
                   functions if newrdn is different than the old
                   RDN. It is a boolean value. If it is non-zero,
                   it indicates that the old RDN value(s) should
                   be removed. If it is zero, it indicates that
                   the old RDN value(s) should be retained as non-
                   distinguished values of the entry.
    serverctrls    List of LDAP server controls.
    clientctrls    List of client controls.
    msgidp         This result parameter will be set to the message
                   id of the request if the ldap_rename() call
                   succeeds.

    The ldap_rename() function initiates an asynchronous modify DN
    operation and returns the constant LDAP_SUCCESS if the request
    was successfully sent, or another LDAP error code if not. See
    Errors for more information about possible errors and how to
    interpret them. If successful, ldap_rename() places the DN
    message id of the request in *msgidp. A subsequent call to ldap_
    result() can be used to obtain the result of the rename.

    The synchronous ldap_rename_s() returns the result of the
    operation, either the constant LDAP_SUCCESS if the operation was
    successful, or another LDAP error code if it was not. See Errors
    for more information about possible errors and how to interpret
    them.

    The ldap_rename() and ldap_rename_s()  functions both support
    LDAPv3 server controls and client controls.

13  –  Adding Entry

    The following functions are used to add entries to the LDAP
    directory. There are four variations.

            int ldap_add_ext(
                    LDAP                               *ld,
                    const char                         *dn,
                    LDAPMod                            **attrs,
                    LDAPControl                        **serverctrls,
                    LDAPControl                        **clientctrls,
                    int                                *msgidp
            );

            int ldap_add_ext_s(
                    LDAP                               *ld,
                    const char                         *dn,
                    LDAPMod                            **attrs,
                    LDAPControl                        **serverctrls,
                    LDAPControl                        **clientctrls
            );

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

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

    Parameters are as follows:

    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.
    serverctrls    List of LDAP server controls.
    clientctrls    List of client controls.
    msgidp         This result parameter will be set to the message
                   id of the request if the ldap_add_ext() call
                   succeeds.

    Note that the parent of the entry being added must already exist
    or the parent must be empty (that is, equal to the root DN) for
    an add to succeed.

    The ldap_add_ext() function initiates an asynchronous add
    operation and returns either the constant LDAP_SUCCESS if the
    request was successfully sent or another LDAP error code if not.
    See Errors for more information about possible errors and how to
    interpret them. If successful, ldap_add_ext() places the message
    id of the request in *msgidp. A subsequent call to ldap_result()
    can be used to obtain the result of the add.

    Similar to ldap_add_ext(), the ldap_add()  function initiates
    an asynchronous add operation and returns the message id of the
    operation initiated. As for ldap_add_ext(), a subsequent call
    to ldap_result() can be used to obtain the result of the add.
    In case of error, ldap_add() will return -1, setting the session
    error parameters in the LDAP structure appropriately.

    The synchronous ldap_add_ext_s() and ldap_add_s()  functions
    both return the result of the operation, either the constant
    LDAP_SUCCESS if the operation was successful, or another LDAP
    error code if it was not. See Errors for more information about
    possible errors and how to interpret them.

    The ldap_add_ext() and ldap_add_ext_s()  functions support LDAPv3
    server controls and client controls.

14  –  Deleting Entry

    The following functions are used to delete a leaf entry from the
    LDAP directory. There are four variations.

            int ldap_delete_ext(
                    LDAP                               *ld,
                    const char                         *dn,
                    LDAPControl                        **serverctrls,
                    LDAPControl                        **clientctrls,
                    int                                *msgidp
            );

            int ldap_delete_ext_s(
                    LDAP                               *ld,
                    const char                         *dn,
                    LDAPControl                        **serverctrls,
                    LDAPControl                        **clientctrls
            );

            int ldap_delete(
                    LDAP                               *ld,
                    const char                         *dn
            );

            int ldap_delete_s(
                    LDAP                               *ld,
                    const char                         *dn
            );

    Parameters are as follows:

    ld             The session handle.
    dn             The name of the entry to delete.
    serverctrls    List of LDAP server controls.
    clientctrls    List of client controls.
    msgidp         This result parameter will be set to the message
                   id of the request if the ldap_delete_ext() call
                   succeeds.

    Note that the entry to delete must be a leaf entry (that is, it
    must have no children). Deletion of entire subtrees in a single
    operation is not supported by LDAP.

    The ldap_delete_ext() function initiates an asynchronous delete
    operation and returns either the constant LDAP_SUCCESS if the
    request was successfully sent or another LDAP error code if not.
    See Errors for more information about possible errors and how
    to interpret them. If successful, ldap_delete_ext() places the
    message id of the request in *msgidp. A subsequent call to ldap_
    result() can be used to obtain the result of the delete.

    Similar to ldap_delete_ext(), the ldap_delete()  function
    initiates an asynchronous delete operation and returns the
    message id of the operation initiated. As for ldap_delete_ext(),
    a subsequent call to ldap_result() can be used to obtain the
    result of the delete. In case of error, ldap_delete() will return
    -1, setting the session error parameters in the LDAP structure
    appropriately.

    The synchronous ldap_delete_ext_s() and ldap_delete_s()
    functions both return the result of the operation, either the
    constant LDAP_SUCCESS if the operation was successful or another
    LDAP error code if it was not. See Errors for more information
    about possible errors and how to interpret them.

    The ldap_delete_ext() and ldap_delete_ext_s()  functions support
    LDAPv3 server controls and client controls.

15  –  Extensions

    The ldap_extended_operation() and ldap_extended_operation_s()
    functions allow extended LDAP operations to be passed to the
    server, providing a general protocol extensibility mechanism.

            int ldap_extended_operation(
                    LDAP                               *ld,
                    const char                         *requestoid,
                    const struct berval                *request data,
                    LDAPControl                        **serverctrls,
                    LDAPControl                        **clientctrls,
                    int                                *msgidp
            );

            int ldap_extended_operation_s(
                    LDAP                               *ld,
                    const char                         *requestoid,
                    const struct berval                *request data,
                    LDAPControl                        **serverctrls,
                    LDAPControl                        **clientctrls,
                    char                               **retoidp,
                    struct berval                      **retdatap
            );

    Parameters are as follows:

    ld             The session handle.
    requestoid     The dotted-OID text string naming the request.
    requestdata    The arbitrary data required by the operation (if
                   NULL, no data is sent to the server).
    serverctrls    List of LDAP server controls.
    clientctrls    List of client controls.
    msgidp         This result parameter will be set to the message
                   id of the request if the ldap_extended_operation()
                   call succeeds.
    retoidp        Pointer to a character string that will be set
                   to an allocated, dotted- OID text string returned
                   by the server. This string should be disposed of
                   using the ldap_memfree() function. If no OID was
                   returned, *retoidp is set to NULL.
    retdatap       Pointer to a berval structure pointer that will be
                   set to an allocated copy of the data returned by
                   the server. This struct berval should be disposed
                   of using ber_bvfree(). If no data is returned,
                   *retdatap is set to NULL.

    The ldap_extended_operation() function initiates an asynchronous
    extended operation and returns either the constant LDAP_SUCCESS
    if the request was successfully sent or another LDAP error code
    if not. See Errors for more information about possible errors and
    how to interpret them. If successful, ldap_extended_operation()
    places the message id of the request in *msgidp. A subsequent
    call to ldap_result() can be used to obtain the result of the
    extended operation which can be passed to ldap_parse_extended_
    result() to obtain the OID and data contained in the response.

    The synchronous ldap_extended_operation_s() function returns
    the result of the operation, either the constant LDAP_SUCCESS
    if the operation was successful or another LDAP error code if it
    was not. See Errors for more information about possible errors
    and how to interpret them. The retoid and retdata parameters are
    filled in with the OID and data from the response. If no OID or
    data was returned, these parameters are set to NULL.

    The ldap_extended_operation() and ldap_extended_operation_
    s() functions both support LDAPv3 server controls and client
    controls.

16  –  Abandoning

    The following calls are used to abandon an operation in progress:

            int ldap_abandon_ext(
                    LDAP                               *ld,
                    int                                msgid,
                    LDAPControl                        **serverctrls,
                    LDAPControl                        **clientctrls
            );

            int ldap_abandon(
                    LDAP                               *ld,
                    int                                msgid
            );

    Parameters are as follows:

    ld             The session handle.
    msgid          The message id of the request to be abandoned.
    serverctrls    List of LDAP server controls.
    clientctrls    List of client controls.

    The ldap_abandon_ext() function abandons the operation with
    message id msgid and returns either the constant LDAP_SUCCESS
    if the abandon was successful or another LDAP error code if not.
    See Errors for more information about possible errors and how to
    interpret them.

    The ldap_abandon() function is identical to ldap_abandon_ext()
    except that it does not accept client or server controls and it
    returns zero if the abandon was successful, -1 otherwise and does
    not support LDAPv3 server controls or client controls.

    After a successful call to ldap_abandon() or ldap_abandon_ext(),
    results with the given message id are never returned from a
    subsequent call to ldap_result(). There is no server response
    to LDAP abandon operations.

17  –  Results

    The ldap_result() function is used to obtain the result of a
    previous asynchronously initiated operation. Note that depending
    on how it is called, ldap_result() may actually return a list or
    "chain" of result messages. Once a chain of messages has been
    returned to the caller, it is no longer tied in any caller-
    visible way to the LDAP request that produced it. Therefore,
    a chain of messages returned by calling ldap_result() or by
    calling a synchronous search function will never be affected
    by subsequent LDAP API calls (except for ldap_msgfree(), which is
    used to dispose of a chain of messages).

    The ldap_msgfree() function frees the result messages (possibly
    an entire chain of messages) obtained from a previous call to
    ldap_result() or from a call to a synchronous search function.

    The ldap_msgtype() function returns the type of an LDAP message.
    The ldap_msgid() function returns the message ID 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 );

            int ldap_msgid( LDAPMessage *res );

    Parameters are as follows:

    ld             The session handle.
    msgid          The message id of the operation whose results are
                   to be returned, or the constant LDAP_RES_ANY (-1)
                   if any result is desired.
    all            Specifies how many messages will be retrieved in
                   a single call to ldap_result(). This parameter
                   only has meaning for search results. Pass the
                   constant LDAP_MSG_ONE (0x00) to retrieve one
                   message at a time. Pass LDAP_MSG_ALL (0x01) to
                   request that all results of a search be received
                   before returning all results in a single chain.
                   Pass LDAP_MSG_RECEIVED (0x02) to indicate that all
                   results retrieved so far should be returned in the
                   result chain.
    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 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(), ldap_
                   search_s(), or ldap_search_st().

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

            LDAP_RES_BIND (0x61)

            LDAP_RES_SEARCH_ENTRY (0x64)

            LDAP_RES_SEARCH_REFERENCE (0x73)      -- new in LDAPv3

            LDAP_RES_SEARCH_RESULT (0x65)

            LDAP_RES_MODIFY (0x67)

            LDAP_RES_ADD (0x69)

            LDAP_RES_DELETE (0x6B)

            LDAP_RES_MODDN (0x6D)

            LDAP_RES_COMPARE (0x6F)

            LDAP_RES_EXTENDED (0x78)              -- new in LDAPv3

    The ldap_result() function 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.

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

    The ldap_msgtype() function 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.

    The ldap_msgid() function returns the message ID associated with
    the LDAP message passed as a parameter.

18  –  Errors

    The following calls are used to extract information from results
    and handle errors returned by other LDAP API functions. Note that
    ldap_parse_sasl_bind_result() and ldap_parse_extended_result()
    must typically be used in addition to ldap_parse_result() to
    retrieve all the result information from SASL bind and extended
    operations, respectively.

            int ldap_parse_result(
                    LDAP                               *ld,
                    LDAPMessage                        *res,
                    int                                *errcodep,
                    char                               **matcheddnp,
                    char                               **errmsgp,
                    char                               ***referralsp,
                    LDAPControl                        ***serverctrlsp,
                    int                                freeit
            );

            int ldap_parse_sasl_bind_result(
                    LDAP                               *ld,
                    LDAPMessage                        *res,
                    struct berval                      **servercredp,
                    int                                freeit
            );

            int ldap_parse_extended_result(
                    LDAP                               *ld,
                    LDAPMessage                        *res,
                    char                               **resultoidp,
                    struct berval                      **resultdata,
                    int                                freeit
            );

            char *ldap_err2string( int err );

    The use of the following functions is deprecated.

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

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

    Parameters are as follows:

    ld             The session handle.
    res            The result of an LDAP operation as returned by
                   ldap_result() or one of the synchronous API
                   operation calls.
    errcodep       This result parameter will be filled in with the
                   LDAP error code field from the LDAPMessage result.
                   This is the indication from the server of the
                   outcome of the operation. NULL may be passed to
                   ignore this field.
    matcheddnp     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. The matched DN string should be freed by
                   calling ldap_memfree().
    errmsgp        This result parameter will be filled in with the
                   contents of the error message field from the
                   LDAPMessage result. The error message string
                   should be freed by calling ldap_memfree(). NULL
                   may be passed to ignore this field.
    referralsp     This result parameter will be filled in with
                   the contents of the referrals field from the
                   LDAPMessage result, indicating zero or more
                   alternate LDAP servers where the request should
                   be retried. The referrals array should be freed by
                   calling ldap_value_free(). NULL may be passed to
                   ignore this field.
    serverctrlsp   This result parameter will be filled in with an
                   allocated array of controls copied out of the
                   LDAPMessage result. The control array should be
                   freed by calling ldap_controls_free().
    freeit         A boolean that determines whether or not the res
                   parameter is disposed of. Pass any non-zero value
                   to have these functions free res after extracting
                   the requested information. This option is provided
                   as a convenience; you can also use ldap_msgfree()
                   to free the result later. If freeit is non-zero,
                   the entire chain of messages represented by res is
                   disposed of.
    servercredp    For SASL bind results, this result parameter will
                   be filled in with the credentials passed back by
                   the server for mutual authentication, if given. An
                   allocated berval structure is returned that should
                   be disposed of by calling ber_bvfree(). NULL may
                   be passed to ignore this field.
    resultoidp     For extended results, this result parameter
                   will be filled in with the dotted-OID text
                   representation of the name of the extended
                   operation response. This string should be disposed
                   of by calling ldap_memfree(). NULL may be passed
                   to ignore this field.
    resultdatap    For extended results, this result parameter will
                   be filled in with a pointer to a struct berval
                   containing the data in the extended operation
                   response. It should be disposed of by calling ber_
                   bvfree(). NULL may be passed to ignore this field.
    err            For ldap_err2string(), an LDAP error code, as
                   returned by ldap_parse_result() or another LDAP
                   API call.

    Additional parameters for the deprecated functions are not
    described. See RFC 1823 for more information.

    All three of the ldap_parse_*_result() functions skip over
    messages of type LDAP_RES_SEARCH_ENTRY and LDAP_RES_SEARCH_
    REFERENCE when looking for a result message to parse. They return
    either the constant LDAP_SUCCESS if the result was successfully
    parsed or another LDAP error code if not. Note that the LDAP
    error code that indicates the outcome of the operation performed
    by the server is placed in the errcodep ldap_parse_result()
    parameter. If a chain of messages that contains more than one
    result message is passed to these functions, they always operate
    on the first result in the chain.

    The ldap_err2string() function is used to convert a numeric LDAP
    error code, as returned by either one of the three ldap_parse_*_
    result() functions or one of the synchronous API operation calls,
    into an informative zero-terminated character string message
    describing the error. It returns a pointer to static data.

18.1  –  Stepping Through a List of Results

    The ldap_first_message() and ldap_next_message()  functions are
    used to step through the list of messages in a result chain
    returned by ldap_result(). For search operations, the result
    chain may actually include referral messages, entry messages,
    and result messages. The ldap_count_messages() function is used
    to count the number of messages returned. The ldap_msgtype()
    function can be used to distinguish between the different message
    types.

     LDAPMessage *ldap_first_message( LDAP *ld, LDAPMessage *res );
     LDAPMessage *ldap_next_message ( LDAP *ld, LDAPMesage *msg );
     int ldap_count_messages( LDAP *ld, LDAPMessage *res );

    Parameters are as follows:

    ld    The session handle.
    res   The result chain, as obtained by a call to one of the
          synchronous search functions or ldap_result().
    msg   The message returned by a previous call to ldap_first_
          message()  or ldap_next_message().

    The ldap_first_message() and ldap_next_message()  functions will
    return NULL when no more messages 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
    session handle ld will be set to indicate the error.

    The ldap_count_messages() function returns the number of messages
    contained in a chain of results. It can also be used to count
    the number of messages that remain in a chain if called with a
    message, entry, or reference returned by ldap_first_message(),
    ldap_next_message(), ldap_first_entry(),  ldap_next_entry(),
    ldap_first_reference(), ldap_next_reference().

19  –  Search Results

    The following calls are used to parse the entries and references
    returned by ldap_search(). These results are returned in an
    opaque structure that should only be accessed by calling the
    functions. Functions 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.

19.1  –  Stepping Through a List of Entries

    The ldap_first_entry() and ldap_next_entry()  functions are
    used to step through and retrieve the list of entries from a
    search result chain. The ldap_first_reference() and ldap_next_
    reference() functions are used to step through and retrieve the
    list of continuation references from a search result chain. The
    ldap_count_entries() function is used to count the number of
    entries returned. The ldap_count_references() function is used to
    count the number of references returned.

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

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

     LDAPMessage *ldap_first_reference( LDAP *ld, LDAPMessage *res );

     LDAPMessage *ldap_next_reference( LDAP *ld, LDAPMessage *ref );

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

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

    Parameters are as follows:

    ld    The session handle.
    res   The search result, as obtained by a call to one of the
          synchronous search functions or ldap_result().
    entry The entry returned by a previous call to ldap_first_
          entry()  or ldap_next_entry().

    The ldap_first_entry() and ldap_next_entry()  functions 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 session handle ld will be set to indicate
    the error.

    The ldap_count_entries() function 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 a
    message, entry or reference returned by ldap_first_message(),
    ldap_next_message(), ldap_first_entry(),  ldap_next_entry(),
    ldap_first_reference(), ldap_next_reference().

    The ldap_count_references() function 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.

19.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 as follows:

    ld    The session 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().
    mem   A pointer to memory allocated by the LDAP library, such
          as the attribute type names returned by ldap_first_
          attribute()  and ldap_next_attribute(), or the DN returned
          by ldap_get_dn().

    The ldap_first_attribute() and ldap_next_attribute()  functions
    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
    session handle ld will be set to indicate the error.

    Both functions return a pointer to an allocated buffer containing
    the current attribute name. This should be freed when no longer
    in use by calling ldap_memfree().

    The ldap_first_attribute() function 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_
    attribute(), 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, since the buffer
    associated with the BerElement does not point to separately
    allocated memory.

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

19.3  –  Retrieving the Values of an Attribute

    The ldap_get_values() and ldap_get_values_len()  functions are
    used to retrieve the values of a given attribute from an entry.
    The ldap_count_values() and ldap_count_values_len()  functions
    are used to count the returned values. The ldap_value_free() and
    ldap_value_free_len() functions are used to free the values.

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

            void ldap_value_free( char **vals );

            void ldap_value_free_len( struct berval **vals );

    Parameters are as follows:

    ld    The session 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 (for example, "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. The
    second _len form is used with any kind of data.

    The ldap_get_values() and ldap_get_values_len()  functions return
    NULL if no values are found for attr or if an error occurs.

    The ldap_count_values() and ldap_count_values_len()  functions
    return -1 if an error occurs such as the vals parameter being
    invalid.

    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.

19.4  –  Retrieving the Name of an Entry

    The ldap_get_dn() function is used to retrieve the name of an
    entry. The ldap_explode_dn() and ldap_explode_rdn()  functions
    are used to break up a name into its component parts. The ldap_
    dn2ufn() function is used to convert the name into a more user-
    friendly format.

            char *ldap_get_dn( LDAP *ld, LDAPMessage *entry );

            char **ldap_explode_dn( const char *dn, int notypes );

            char **ldap_explode_rdn( const char *rdn, int notypes );

            char *ldap_dn2ufn( const char *dn );

    Parameters are as follows:

    ld         The session 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 components should have their type information
               stripped off (i.e., "cn=Babs" would become "Babs").

    The ldap_get_dn() function will return NULL if there is some
    error parsing the dn, setting error parameters in the session
    handle ld to indicate the error. It returns a pointer to newly
    allocated space that the caller should free by calling ldap_
    memfree() when it is no longer in use.

    The ldap_explode_dn() function 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
    components are returned in the order they appear in the dn. The
    array returned should be freed when it is no longer in use by
    calling ldap_value_free().

    The ldap_explode_rdn() function returns a NULL-terminated char
    * array containing the components of the RDN supplied, with
    or without types as indicated by the notypes parameter. The
    components are returned in the order they appear in the rdn.
    The array returned should be freed when it is no longer in use by
    calling ldap_value_free().

    The ldap_dn2ufn() function converts the DN into the user friendly
    format. The UFN returned is newly allocated space that should be
    freed by a call to ldap_memfree() when no longer in use.

19.5  –  Retrieving Controls from an Entry

    The ldap_get_entry_controls() function is used to extract LDAP
    controls from an entry.

      int ldap_get_entry_controls(
              LDAP                                    *ld,
              LDAPMessage                             *entry,
              LDAPControl                             ***serverctrlsp
      );

    Parameters are as follows:

    ld             The session handle.
    entry          The entry to extract controls from, as returned by
                   ldap_first_entry() or ldap_next_entry().
    serverctrlsp   This result parameter will be filled in with an
                   allocated array of controls copied out of entry.
                   The control array should be freed by calling
                   ldap_controls_free(). If serverctrlsp is NULL,
                   no controls are returned.

    The ldap_get_entry_controls() function returns an LDAP error code
    that indicates whether the reference could be successfully parsed
    (LDAP_SUCCESS if all goes well).

19.6  –  Parsing References

    The ldap_parse_reference() function is used to extract referrals
    and controls from a SearchResultReference message.

            int ldap_parse_reference(
                    LDAP                            *ld,
                    LDAPMessage                     *ref,
                    char                            ***referralsp,
                    LDAPControl                     ***serverctrlsp,
                    int                             freeit
            );

    Parameters are as follows:

    ld             The session handle.
    ref            The reference to parse, as returned by ldap_
                   result(), ldap_first_reference(),  or ldap_next_
                   reference().
    referralsp     This result parameter will be filled in with an
                   allocated array of character strings. The elements
                   of the array are the referrals (typically LDAP
                   URLs) contained in ref. The array should be freed
                   when no longer in used by calling ldap_value_
                   free(). If referralsp is NULL, the referral URLs
                   are not returned.
    serverctrlsp   This result parameter will be filled in with an
                   allocated array of controls copied out of ref.
                   The control array should be freed by calling
                   ldap_controls_free(). If serverctrlsp is NULL,
                   no controls are returned.
    freeit         A boolean that determines whether or not the ref
                   parameter is disposed of. Pass any non-zero value
                   to have these functions free ref after extracting
                   the requested information. This option is provided
                   as a convenience; you can also use ldap_msgfree()
                   to free the result later.

    The ldap_parse_reference() function returns an LDAP error code
    that indicates whether the reference could be successfully parsed
    (LDAP_SUCCESS if all goes well).

20  –  Encoded ASN.1

    LDAP contains functions that may be used to encode and decode
    BER-encoded ASN.1 values, which are often used inside of control
    and extension values.

    The following additional integral types are defined for use in
    manipulation of BER encoded ASN.1 values:

    typedef unsigned long ber_tag_t; /* for BER tags */

    typedef long     ber_int_t; /* for BER ints, enums, and Booleans */

    With the exceptions of two new functions, ber_flatten() and ber_
    init(), these functions are compatible with the University of
    Michigan LDAP 3.3 implementation of BER.

            typedef struct berval {
                    ber_len_t            bv_len;
                    char                 *bv_val;
            } BerValue;

    A struct berval contains a sequence of bytes and an indication
    of its length. The bv_val is not null terminated. A bv_len must
    always be a nonnegative number. Applications may allocate their
    own berval structures.

            typedef struct berelement {
                 /* opaque */
            } BerElement;

    The BerElement structure contains not only a copy of the encoded
    value, but also state information used in encoding or decoding.
    Applications cannot allocate their own BerElement structures.
    The internal state is neither thread-specific nor locked, so
    two threads should not manipulate the same BerElement value
    simultaneously.

    A single BerElement value cannot be used for both encoding and
    decoding.

            void ber_bvfree( struct berval *bv );

    The ber_bvfree() function frees a berval returned from this
    API. Both the bv->bv_val string and the berval itself are freed.
    Applications should not use ber_bvfree() with bervals which the
    application has allocated.

            void ber_bvecfree ( struct berval **bv );

    The ber_bvecfree() function frees an array of bervals returned
    from this API. Each of the bervals in the array are freed using
    ber_bvfree(), then the array itself is freed.

            struct berval *ber_bvdup (struct berval *bv );

    The ber_bvdup() function returns a copy of a berval. The bv_val
    field in the returned berval points to a different area of memory
    as the bv_val field in the argument berval. The null pointer is
    returned on error (for example, out of memory).

            void ber_free ( BerElement *ber, int fbuf );

    The ber_free() function frees a BerElement which is returned from
    the API calls ber_alloc_t() or ber_init().  Each BerElement must
    be freed by the caller. The second argument fbuf should always
    be set to 1 to ensure that the internal buffer used by the BER
    functions is freed as well as the BerElement container itself.

20.1  –  Encoding

    The following is an example of encoding:

            BerElement *ber_alloc_t(int options);

    The ber_alloc_t() function constructs and returns BerElement.
    The null pointer is returned on error. The options field contains
    a bitwise-or of options which are to be used when generating
    the encoding of this BerElement. One option is defined and must
    always be supplied:

            #define LBER_USE_DER 0x01

    When this option is present, lengths will always be encoded
    in the minimum number of octets. Note that this option does
    not cause values of sets and sequences to be rearranged in
    tag and byte order, so these functions are not sufficient for
    generating DER output as defined in X.509 and X.680. If the
    caller takes responsibility for ordering values of sets and
    sequences correctly, DER output as defined in X.509 and X.680
    can be produced.

    Unrecognized option bits are ignored.

    The BerElement returned by ber_alloc_t() is initially empty.
    Calls to ber_printf() will append bytes to the end of the
    BerElement.

            int ber_printf(BerElement *ber, char *fmt, ... )

    The ber_printf() function is used to encode a BER element in
    much the same way that sprintf() works. One important difference,
    though, is that state information is kept in the BER argument so
    that multiple calls can be made to ber_printf() to append to the
    end of the BER element. BER must be a pointer to a BerElement
    returned by ber_alloc_t(). The ber_printf()  function interprets
    and formats its arguments according to the format string fmt.
    The ber_printf() function returns -1 if there is an error during
    encoding and a positive number if successful. As with sprintf(),
    each character in fmt refers to an argument to ber_printf().

    The format string can contain the following format characters:

    t     Tag. The next argument is a ber_tag_t specifying the tag
          to override the next element to be written to the ber. This
          works across calls. The value must contain the tag class,
          constructed bit, and tag value. The tag value must fit in
          a single octet (tag value is less than 32). For example, a
          tag of "[3]" for a constructed type is 0xA3.
    b     Boolean. The next argument is a ber_int_t, containing
          either 0 for FALSE or 0xff for TRUE. A boolean element
          is output. If this format character is not preceded by the
          't' format modifier, the tag 0x01 is used for the element.
    e     Enumerated. The next argument is a ber_int_t, containing
          the enumerated value in the host's byte order. An
          enumerated element is output. If this format character
          is not preceded by the 't' format modifier, the tag 0x0A is
          used for the element.
    i     Integer. The next argument is a ber_int_t, containing the
          integer in the host's byte order. An integer element is
          output. If this format character is not preceded by the 't'
          format modifier, the tag 0x02 is used for the element.
    B     Bitstring. The next two arguments are a char * pointer
          to the start of the bitstring, followed by a ber_len_t
          containing the number of bits in the bitstring. A bitstring
          element is output, in primitive form. If this format
          character is not preceded by the 't' format modifier, the
          tag 0x03 is used for the element.
    n     Null. No argument is required. An ASN.1 NULL element is
          output. If this format character is not preceded by the 't'
          format modifier, the tag 0x05 is used for the element.
    o     Octet string. The next two arguments are a char *, followed
          by a ber_len_t with the length of the string. The string
          may contain null bytes and need not by zero-terminated.
          An octet string element is output, in primitive form. If
          this format character is not preceded by the 't' format
          modifier, the tag 0x04 is used for the element.
    s     Octet string. The next argument is a char * pointing
          to a zero-terminated string. An octet string element
          in primitive form is output, which does not include
          the trailing '\0' byte. If this format character is not
          preceded by the 't' format modifier, the tag 0x04 is used
          for the element.
    v     Several octet strings. The next argument is a char **,
          an array of char * pointers to zero-terminated strings.
          The last element in the array must be a null pointer. The
          octet strings do not include the leading SEQUENCE OF octet
          strings. The 't' format modifier cannot be used with this
          format character.
    V     Several octet strings. A NULL-terminated array of struct
          berval *'s is supplied. Note that a construct like '{V}'
          is required to get an actual SEQUENCE OF octet strings.
          The 't' format modifier cannot be used with this format
          character.
    {     Begin sequence. No argument is required. If this format
          character is not preceded by the 't' format modifier, the
          tag 0x30 is used.
    }     End sequence. No argument is required. The 't' format
          modifier cannot be used with this format character.
    [     Begin set. No argument is required. If this format
          character is not preceded by the 't' format modifier, the
          tag 0x31 is used.
    ]     End set. No argument is required. The 't' format modifier
          cannot be used with this format character.

    Each use of a '{' format character must be matched by a '}'
    character, either later in the format string, or in the format
    string of a subsequent call to ber_printf() for that BerElement.
    The same applies to the '[' and ']'.

    Sequences and sets nest, and implementations of this API must
    maintain internal state to be able to properly calculate the
    lengths.

            int ber_flatten (BerElement *ber, struct berval **bvPtr);

    The ber_flatten() function allocates a struct berval whose
    contents are a BER encoding taken from the ber argument. The
    bvPtr pointer points to the returned berval, which must be freed
    using ber_bvfree(). This function returns 0 on success and -1 on
    error.

    The ber_flatten() API call is not present in U-M LDAP 3.3.

    The use of ber_flatten() on a BerElement in which all '{' and '}'
    format modifiers have not been properly matched is an error (that
    is, -1 will be returned by ber_flatten() if this situation is
    exists).

20.2  –  Decoding

    The following two symbols are available to applications.

            #define LBER_ERROR   0xffffffffL
            #define LBER_DEFAULT 0xffffffffL

            BerElement *ber_init (struct berval *bv);

    The ber_init() function constructs a BerElement and returns a new
    BerElement containing a copy of the data in the bv argument. The
    ber_init() function returns the null pointer on error.

            ber_tag_t ber_scanf (BerElement *ber, char *fmt, ... );

    The ber_scanf() function is used to decode a BER element in much
    the same way that sscanf() works. One important difference,
    though, is that some state information is kept with the ber
    argument so that multiple calls can be made to ber_scanf() to
    sequentially read from the BER element. The ber argument must
    be a pointer to a BerElement returned by ber_init(). The ber_
    scanf() function interprets function the bytes according to
    the format string fmt, and stores the results in its additional
    arguments. The ber_scanf() function returns LBER_ERROR on error,
    and a different value on success.

    The format string contains conversion specifications which are
    used to direct the interpretation of the BER element. The format
    string can contain the following characters:

    a     Octet string. A char ** argument should be supplied. Memory
          is allocated, filled with the contents of the octet string,
          null- terminated, and the pointer to the string is stored
          in the argument. The returned value must be freed using
          ldap_memfree().  The tag of the element must indicate the
          primitive form (constructed strings are not supported) but
          is otherwise ignored and discarded during the decoding.
          This format cannot be used with octet strings which could
          contain null bytes.
    O     Octet string. A struct berval ** argument should be
          supplied, which upon return points to a allocated struct
          berval containing the octet string and its length. The
          ber_bvfree()  function must be called to free the allocated
          memory. The tag of the element must indicate the primitive
          form (constructed strings are not supported) but is
          otherwise ignored during the decoding.
    b     Boolean. A pointer to a ber_int_t should be supplied. The
          value stored will be 0 for FALSE or nonzero for TRUE. The
          tag of the element must indicate the primitive form but is
          otherwise ignored during the decoding.
    e     Enumerated value stored will be in host byte order. The
          tag of the element must indicate the primitive form but is
          otherwise ignored during the decoding. The ber_scanf()
          function will return an error if the enumerated value
          cannot be stored in a ber_int_t.
    i     Integer. A pointer to a ber_int_t should be supplied. The
          value stored will be in host byte order. The tag of the
          element must indicate the primitive form but is otherwise
          ignored during the decoding. The ber_scanf()  function will
          return an error if the integer cannot be stored in a ber_
          int_t.
    B     Bitstring. A char ** argument should be supplied which
          will point to the allocated bits, followed by a ber_len_t *
          argument, which will point to the length (in bits) of the
          bit-string returned. The ldap_memfree()  function must be
          called to free the bit-string. The tag of the element must
          indicate the primitive form (constructed bitstrings are not
          supported) but is otherwise ignored during the decoding.
    n     Null. No argument is required. The element is simply
          skipped if it is recognized as a zero-length element. The
          tag is ignored.
    v     Several octet strings. A char *** argument should be
          supplied, which upon return points to a allocated null-
          terminated array of char *'s containing the octet strings.
          NULL is stored if the sequence is empty. The ldap_
          memfree()  function must be called to free each element
          of the array and the array itself. The tag of the sequence
          and of the octet strings are ignored.
    V     Several octet strings (which could contain null bytes).
          A struct berval *** should be supplied, which upon
          return points to a allocated null-terminated array of
          struct berval *'s containing the octet strings and their
          lengths. NULL is stored if the sequence is empty. The ber_
          bvecfree()  function can be called to free the allocated
          memory. The tag of the sequence and of the octet strings
          are ignored.
    x     Skip element. The next element is skipped. No argument is
          required.
    {     Begin sequence. No argument is required. The initial
          sequence tag and length are skipped.
    }     End sequence. No argument is required.
    [     Begin set. No argument is required. The initial set tag and
          length are skipped.
    ]     End set. No argument is required.

      ber_tag_t ber_peek_tag (BerElement *ber, ber_len_t *lenPtr);

    The ber_peek_tag() function returns the tag of the next element
    to be parsed in the BerElement argument. The length of this
    element is stored in the *lenPtr argument. LBER_DEFAULT is
    returned if there is no further data to be read. The ber argument
    is not modified.

      ber_tag_t ber_skip_tag (BerElement *ber, ber_len_t *lenPtr);

    The ber_skip_tag() function is similar to ber_peek_tag(),  except
    that the state pointer in the BerElement argument is advanced
    past the first tag and length, and is pointed to the value part
    of the next element. This function should only be used with
    constructed types and situations when a BER encoding is used as
    the value of an OCTET STRING. The length of the value is stored
    in *lenPtr.

            ber_tag_t ber_first_element(BerElement *ber,
                    ber_len_t *lenPtr, char **opaquePtr);

            ber_tag_t ber_next_element  (BerElement *ber,
                    ber_len_t *lenPtr, char *opaque);

    The ber_first_element() and ber_next_element()  functions are
    used to traverse a SET, SET OF, SEQUENCE or SEQUENCE OF data
    value. The ber_first_element() function calls ber_skip_tag(),
    stores internal information in *lenPtr and *opaquePtr, and calls
    ber_peek_tag() for the first element inside the constructed
    value. LBER_DEFAULT is returned if the constructed value is
    empty. The ber_next_element() function positions the state at the
    start of the next element in the constructed type. LBER_DEFAULT
    is returned if there are no further values.

    The len and opaque values should not be used by applications
    other than as arguments to ber_next_element(). (Refer to the VSI
    OpenVMS Utility Routines Manual for an example of this usage.)

21  –  Using SSL

    Secure Sockets Layer (SSL) is the open standard security protocol
    for the secure transfer of sensitive information over the
    Internet.

    You can establish SSL on an LDAP session if the server supports
    such sessions. SSL uses X.509 public key technology to provide
    the following security functions:

    o  Integrity and confidentiality of the LDAP dialog

       This is the most common use of SSL. The bytes sent over the
       wire are encrypted.

    o  Authentication of the client

       Some servers use SSL to authenticate the client and make
       access control decisions based on the client identity. In
       this case, the client must have access to its private key and
       its certificate. The client certificate subject is a DN.

    o  Authentication of the server

       It might be important for the client to verify the identity
       of the server to which it is talking. In this case, the client
       must have access to the appropriate certification authority
       (CA) public keys.

    There are several versions of SSL: SSLv2 (2.0), SSLv3 (3.0), and
    TLSv1 (3.1). TLS is the latest Internet standard. It does not
    require the use of RSA algorithms. Usually the client specifies
    the highest version it supports, and the server negotiates
    downward, if necessary. The client library supports all the
    versions listed here.

    You can establish SSL over LDAP two different ways:

    o  LDAPS

       This older, de facto standard uses a separate TCP/IP port
       (usually 636) specifically for SSL over LDAP. In this case,
       the second parameter to the ldap_tls_start() function must be
       set to zero.

    o  StartTLS

       This proposed Internet standard uses a regular LDAP port
       (usually 389) and requires the client to request the use
       of SSL. In this case, the second parameter to the ldap_tls_
       start() function must be set to 1.

21.1  –  SSL Certificate Options

    The following session-handle options are specific to SSL and can
    be set by the ldap_set_option() function:

    o  LDAP_OPT_TLS_CERT_REQUIRED (0x7001) void *

       Set to LDAP_OPT_ON if the client library requires a server
       certificate to be present the next time the ldap_tls_start()
       function is called. The default value is LDAP_OPT_OFF; a
       server certificate is not required.

    o  LDAP_OPT_TLS_VERIFY_REQUIRED (0x7002) void *

       Set to LDAP_OPT_ON if the client library requires that a
       server certificate path be validated the next time the ldap_
       tls_start() function is called. The default value is LDAP_OPT_
       OFF; the server certificate, if any, is not verified.

    o  LDAP_OPT_TLS_CERT_FILE (0x7003) char *

       Set to the name of a file containing the client's certificate
       for use by the ldap_tls_start() function.

    o  LDAP_OPT_TLS_PKEY_FILE (0x7004) char *

       Set to the name of a file containing the client's private key
       for use by the ldap_tls_start() function.

    o  LDAP_OPT_TLS_CA_FILE (0x7005) char *

       Set to the name of a file containing CA public keys used for
       validation of the server by the ldap_tls_start() function.

    o  LDAP_OPT_TLS_CA_PATH (0x7006) char *

       Set to the name of a directory on disk containing CA public
       key files used for validation of the server by the ldap_tls_
       start() function.

    o  LDAP_OPT_TLS_VERSION (0x7007) int *

       Set to the desired SSL protocol version. This option takes one
       of the following values:

           1: TLSv1 only
          20: SSLv2 only
          23: SSLv2 or SSLv3
          30: SSLv3 only (default)
          31: TLSv1 only

    If LDAP_OPT_TLS_VERIFY_REQUIRED is set to ON, either the LDAP_
    OPT_TLS_CA_FILE or the LDAP_OPT_TLS_CA_PATH option must be set.

    If client authentication is required, both LDAP_OPT_TLS_CERT_FILE
    and LDAP_OPT_TLS_PKEY_FILE must be set.

21.2  –  Obtaining a Key Pair

    In order for TLS to authenticate a client, the client must have
    a private key and a certificate. Obtain these from either a
    Certification Authority or a self-sign program. A self-sign
    program is included in the Open Source Security for OpenVMS
    product.
Close Help