OpenVMS Utility Routines Manual
12.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.
12.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.
12.2 Common Data Structures and Memory Handling
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
Section 12.17 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. The correct free function to call
is documented in each section of this chapter where a function that
allocates memory is described.
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()
|
12.3 LDAP 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)
|
12.4 Initializing an LDAP Session
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 next section.
12.5 LDAP Session Handle Options
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 (0x01)
|
Type for invalue parameter: not 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 (0x02)
|
Type for invalue parameter: int *
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_SIZELIMIT (0x03)
|
Type for invalue parameter: int *
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_TIMELIMIT (0x04)
|
Type for invalue parameter: int *
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_REFERRALS (0x08)
|
Type for invalue parameter: int (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 (0x09)
|
Type for invalue parameter: int (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_PROTOCOL_VERSION (0x11)
|
Type for invalue parameter: int *
Type for outvalue parameter: int *
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_CONTROLS (0x12)
|
Type for invalue parameter: LDAPControl **
Type for outvalue parameter: LDAPControl ***
Description: A default list of LDAP server controls to be sent with
each request. See Section 12.6 for more information.
|
|
LDAP_OPT_CLIENT_CONTROLS (0x13)
|
Type for invalue parameter: LDAPControl **
Type for outvalue parameter: LDAPControl ***
Description: A default list of client controls that affect the LDAP
session. See Section 12.6 for more information.
|
|
LDAP_OPT_HOST_NAME (0x30)
|
Type for invalue parameter: char *
Type for outvalue parameter: char **
Description: The host name (or list of host) for the primary LDAP
server.
|
|
LDAP_OPT_ERROR_NUMBER (0x31)
|
Type for invalue parameter: int *
Type for outvalue parameter: int *
Description: The code of the most recent LDAP error that occurred
for this session.
|
|
LDAP_OPT_ERROR_STRING (0x32)
|
Type for invalue parameter: char *
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.
|
12.6 Working with 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_iscritical
|
Indicates whether the control is critical or not. 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.
12.7 Authenticating to the Directory
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 Section 12.18 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 Section 12.18 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()
.
|