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.