User:MarkCraig: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
m (Line end fix)
(Last chapter formatted)
Line 21,851: Line 21,851:
prldap_get_socket_info()
prldap_get_socket_info()


== Directory SDK for C Result Codes<br> ==
== Directory SDK for C Result Codes ==


This section lists some of the result codes that can be returned by functions in the Directory SDK for C. For ease of use, they are first listed in numerical order, then in alphabetical order.<br>
This section lists some of the result codes that can be returned by functions in the Directory SDK for C. For ease of use, they are first listed in numerical order, then in alphabetical order.  


LDAP result codes are extensible; thus, LDAP v3 extensions may define their own error codes, and register them with the Internet Assigned Numbers Authority (IANA). The IANA maintains a [http://www.iana.org/assignments/ldap-parameters list of registered LDAP parameters], including result codes. This list includes what Directory SDK for C currently knows in terms of result codes. More information can be found in RFC 4520, ''Internet Assigned Numbers Authority (IANA) Considerations for the Lightweight Directory Access Protocol (LDAP)''.<br>
LDAP result codes are extensible; thus, LDAP v3 extensions may define their own error codes, and register them with the Internet Assigned Numbers Authority (IANA). The IANA maintains a [http://www.iana.org/assignments/ldap-parameters list of registered LDAP parameters], including result codes. This list includes what Directory SDK for C currently knows in terms of result codes. More information can be found in RFC 4520, ''Internet Assigned Numbers Authority (IANA) Considerations for the Lightweight Directory Access Protocol (LDAP)''.  


TODO
=== Result Codes Summary in Numerical Order  ===
 
The following table gives the decimal and hexadecimal value of all result codes. Values missing from the sequence are not assigned to a result code.
 
{| cellspacing="1" cellpadding="1" border="1" summary="Numerical Listing of Result Codes"
|+ Numerical Listing of Result Codes
|-
! scope="col" | Decimal
! scope="col" | Hexadecimal
! scope="col" | Defined Name
|-
| 0
| 0x00
| LDAP_SUCCESS
|-
| 1
| 0x01
| LDAP_OPERATIONS_ERROR
|-
| 2
| 0x02
| LDAP_PROTOCOL_ERROR
|-
| 3
| 0x03
| LDAP_TIMELIMIT_EXCEEDED
|-
| 4
| 0x04
| LDAP_SIZELIMIT_EXCEEDED
|-
| 5
| 0x05
| LDAP_COMPARE_FALSE
|-
| 6
| 0x06
| LDAP_COMPARE_TRUE
|-
| 7
| 0x07
| LDAP_STRONG_AUTH_NOT_SUPPORTED
|-
| 8
| 0x08
| LDAP_STRONG_AUTH_REQUIRED
|-
| 9
| 0x09
| LDAP_PARTIAL_RESULTS
|-
| 10
| 0x0a
| LDAP_REFERRAL
|-
| 11
| 0x0b
| LDAP_ADMINLIMIT_EXCEEDED
|-
| 12
| 0x0c
| LDAP_UNAVAILABLE_CRITICAL_EXTENSION
|-
| 13
| 0x0d
| LDAP_CONFIDENTIALITY_REQUIRED
|-
| 14
| 0x0e
| LDAP_SASL_BIND_IN_PROGRESS
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 16
| 0x10
| LDAP_NO_SUCH_ATTRIBUTE
|-
| 17
| 0x11
| LDAP_UNDEFINED_TYPE
|-
| 18
| 0x12
| LDAP_INAPPROPRIATE_MATCHING
|-
| 19
| 0x13
| LDAP_CONSTRAINT_VIOLATION
|-
| 20
| 0x14
| LDAP_TYPE_OR_VALUE_EXISTS
|-
| 21
| 0x15
| LDAP_INVALID_SYNTAX
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 32
| 0x20
| LDAP_NO_SUCH_OBJECT
|-
| 33
| 0x21
| LDAP_ALIAS_PROBLEM
|-
| 34
| 0x22
| LDAP_INVALID_DN_SYNTAX
|-
| 35
| 0x23
| LDAP_IS_LEAF
|-
| 36
| 0x24
| LDAP_ALIAS_DEREF_PROBLEM
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 48
| 0x30
| LDAP_INAPPROPRIATE_AUTH
|-
| 49
| 0x31
| LDAP_INVALID_CREDENTIALS
|-
| 50
| 0x32
| LDAP_INSUFFICIENT_ACCESS
|-
| 51
| 0x33
| LDAP_BUSY
|-
| 52
| 0x34
| LDAP_UNAVAILABLE
|-
| 53
| 0x35
| LDAP_UNWILLING_TO_PERFORM
|-
| 54
| 0x36
| LDAP_LOOP_DETECT
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 60
| 0x3C
| LDAP_SORT_CONTROL_MISSING
|-
| 61
| 0x3D
| LDAP_INDEX_RANGE_ERROR
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 64
| 0x40
| LDAP_NAMING_VIOLATION
|-
| 65
| 0x41
| LDAP_OBJECT_CLASS_VIOLATION
|-
| 66
| 0x42
| LDAP_NOT_ALLOWED_ON_NONLEAF
|-
| 67
| 0x43
| LDAP_NOT_ALLOWED_ON_RDN
|-
| 68
| 0x44
| LDAP_ALREADY_EXISTS
|-
| 69
| 0x45
| LDAP_NO_OBJECT_CLASS_MODS
|-
| 70
| 0x46
| LDAP_RESULTS_TOO_LARGE
|-
| 71
| 0x47
| LDAP_AFFECTS_MULTIPLE_DSAS
|-
| &nbsp;
| &nbsp;
| &nbsp;
|-
| 80
| 0x50
| LDAP_OTHER
|-
| 81
| 0x51
| LDAP_SERVER_DOWN
|-
| 82
| 0x52
| LDAP_LOCAL_ERROR
|-
| 83
| 0x53
| LDAP_ENCODING_ERROR
|-
| 84
| 0x54
| LDAP_DECODING_ERROR
|-
| 85
| 0x55
| LDAP_TIMEOUT
|-
| 86
| 0x56
| LDAP_AUTH_UNKNOWN
|-
| 87
| 0x57
| LDAP_FILTER_ERROR
|-
| 88
| 0x58
| LDAP_USER_CANCELLED
|-
| 89
| 0x59
| LDAP_PARAM_ERROR
|-
| 90
| 0x5a
| LDAP_NO_MEMORY
|-
| 91
| 0x5b
| LDAP_CONNECT_ERROR
|-
| 92
| 0x5c
| LDAP_NOT_SUPPORTED
|-
| 93
| 0x5d
| LDAP_CONTROL_NOT_FOUND
|-
| 94
| 0x5e
| LDAP_NO_RESULTS_RETURNED
|-
| 95
| 0x5f
| LDAP_MORE_RESULTS_TO_RETURN
|-
| 96
| 0x60
| LDAP_CLIENT_LOOP
|-
| 97
| 0x61
| LDAP_REFERRAL_LIMIT_EXCEEDED
|}
 
=== Result Codes Reference in Alphabetical Order  ===
 
The following section contains the detailed reference information for each result code listed in alphabetical order by code name.
 
<tt>LDAP_ADMINLIMIT_EXCEEDED</tt>
 
This result code indicates that the look-through limit on a search operation has been exceeded. The ''look-through limit'' is the maximum number of entries that the server will check when gathering a list of potential search result candidates.
 
'''Note:''' When working with Directory Server, keep in mind the following:
 
*If you are bound as the root DN, the server sets an infinite look-through limit.
*If you are not bound as the root DN, the server sets a time limit.
 
<tt>#define LDAP_ADMINLIMIT_EXCEEDED 0x0b /* 11 */</tt>
 
----
 
<tt>LDAP_AFFECTS_MULTIPLE_DSAS</tt>
 
This result code indicates that the requested operation needs to be performed on multiple servers, where this operation is not permitted.
 
<tt>#define LDAP_AFFECTS_MULTIPLE_DSAS 0x47 /* 71 */</tt>
 
----
 
<tt>LDAP_ALIAS_DEREF_PROBLEM</tt>
 
This result code indicates that a problem occurred when dereferencing an alias.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_ALIAS_DEREF_PROBLEM 0x24 /* 36 */</tt>
 
----
 
<tt>LDAP_ALIAS_PROBLEM</tt>
 
This result code indicates that the alias is invalid.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_ALIAS_PROBLEM 0x21 /* 33 */</tt>
 
----
 
<tt>LDAP_ALREADY_EXISTS</tt>
 
This result code indicates that the request is attempting to add an entry that already exists in the directory. Directory Server sends this result code back to the client in the following situations:
 
*The request is an add request, and the entry already exists in the directory.
*The request is a modify DN request, and the new DN of the entry already identifies another entry.
*The request is adding an attribute to the schema, and an attribute with the specified name or object identifier (OID) already exists.
 
<tt>#define LDAP_ALREADY_EXISTS 0x44 /* 68 */</tt>
 
----
 
<tt>LDAP_AUTH_UNKNOWN</tt>
 
This result code indicates that an unknown authentication method was specified.
 
'''Note:''' Directory SDK For C library sets this result code if ldap_bind() or ldap_bind_s() are called and an authentication method other than <tt>LDAP_AUTH_SIMPLE</tt> is specified. These functions only allow you to use simple authentication.
 
<tt>#define LDAP_AUTH_UNKNOWN 0x56 /* 86 */</tt>
 
----
 
<tt>LDAP_BUSY</tt>
 
This result code indicates that the server is currently too busy to perform the requested operation.
 
<tt>#define LDAP_BUSY 0x33 /* 51 */</tt>
 
----
 
<tt>LDAP_CLIENT_LOOP</tt>
 
This result code indicates that the LDAP client detected a loop, for example, when following referrals.
 
<tt>#define LDAP_CLIENT_LOOP 0x60 /* 96 */</tt>
 
----
 
<tt>LDAP_COMPARE_FALSE</tt>
 
This result code is returned after an LDAP compare operation is completed. The result indicates that the specified attribute value is not present in the specified entry.
 
<tt>#define LDAP_COMPARE_FALSE 0x05 /* 5 */</tt>
 
----
 
<tt>LDAP_COMPARE_TRUE</tt>
 
This result code is returned after an LDAP compare operation is completed. The result indicates that the specified attribute value is present in the specified entry.
 
<tt>#define LDAP_COMPARE_TRUE 0x06 /* 6 */</tt>
 
----
 
<tt>LDAP_CONFIDENTIALITY_REQUIRED</tt>
 
This result code indicates that confidentiality is required for the operation.
 
<tt>#define LDAP_CONFIDENTIALITY_REQUIRED 0x0d /* 13 */</tt>
 
----
 
<tt>LDAP_CONNECT_ERROR</tt>
 
This result code indicates that the LDAP client cannot establish a connection, or has lost the connection, with the LDAP server. Directory SDK For C sets this result code. If you have not established an initial connection with the server, verify that you have specified the correct host name and port number and that the server is running.
 
<tt>#define LDAP_CONNECT_ERROR 0x5b /* 91 */</tt>
 
----
 
<tt>LDAP_CONSTRAINT_VIOLATION</tt>
 
This result code indicates that a value in the request does not comply with certain constraints. Directory Server sends this result code back to the client in the following situations:
 
*The request adds or modifies the <tt>userpassword</tt> attribute, and one of the following is true:
**The server is configured to check the password syntax, and the length of the new password is less than the minimum password length.
**The server is configured to check the password syntax, and the new password is the same as one of the values of the <tt>uid</tt>, <tt>cn</tt>, <tt>sn</tt>, <tt>givenname</tt>, <tt>ou</tt>, or <tt>mail</tt> attributes.
**The server is configured to keep a history of previous passwords, and the new password is the same as one of the previous passwords. The request is a bind request, and the user is locked out of the account. (For example, the server can be configured to lock a user out of the account after a given number of failed attempts to bind to the server.)
 
<tt>#define LDAP_CONSTRAINT_VIOLATION 0x13 /* 19 */</tt>
 
----
 
<tt>LDAP_CONTROL_NOT_FOUND</tt>
 
This result code indicates that a requested LDAP control was not found. Directory SDK For C sets this result code when parsing a server response for controls and not finding the requested controls. For example:
 
*ldap_parse_entrychange_control() is called, but no entry change notification control is found in the server’s response.
*ldap_parse_sort_control() is called, but no server-side sorting control is found in the server’s response.
*ldap_parse_virtuallist_control() is called, but no virtual list view response control is found in the server’s response.
 
<tt>#define LDAP_CONTROL_NOT_FOUND 0x5d /* 93 */</tt>
 
----
 
<tt>LDAP_DECODING_ERROR</tt>
 
This result code indicates that the LDAP client encountered an error when decoding the LDAP response received from the server.
 
<tt>#define LDAP_DECODING_ERROR 0x54 /* 84 */</tt>
 
----
 
<tt>LDAP_ENCODING_ERROR</tt>
 
This result code indicates that the LDAP client encountered an error when encoding the LDAP request to be sent to the server.
 
<tt>#define LDAP_ENCODING_ERROR 0x53 /* 83 */</tt>
 
----
 
<tt>LDAP_FILTER_ERROR</tt>
 
This result code indicates that an error occurred when specifying the search filter. Directory SDK For C sets this result code if it cannot encode the specified search filter in an LDAP search request.
 
<tt>#define LDAP_FILTER_ERROR 0x57 /* 87 */</tt>
 
----
 
<tt>LDAP_INAPPROPRIATE_AUTH</tt>
 
This result code indicates that the type of credentials are not appropriate for the method of authentication used. Directory Server sends this result code back to the client if simple authentication is used in a bind request, but the entry has no <tt>userpassword</tt> attribute; also, if <tt>LDAP_SASL_EXTERNAL</tt> is attempted on a non-SSL connection.
 
<tt>#define LDAP_INAPPROPRIATE_AUTH 0x30 /* 48 */</tt>
 
----
 
<tt>LDAP_INAPPROPRIATE_MATCHING</tt>
 
This result code indicates that an extensible match filter in a search request contained a matching rule that does not apply to the specified attribute type.
 
<tt>#define LDAP_INAPPROPRIATE_MATCHING 0x12 /* 18 */</tt>
 
----
 
<tt>LDAP_INDEX_RANGE_ERROR</tt>
 
This result code indicates that the search results exceeded the range specified by the requested offsets. This result code applies to search requests that contain ''virtual list view'' controls.
 
<tt>#define LDAP_INDEX_RANGE_ERROR 0x3D /* 61 */</tt>
 
----
 
<tt>LDAP_INSUFFICIENT_ACCESS</tt>
 
This result code indicates that the client has insufficient access to perform the operation. Check that the user you are authenticating as has the appropriate permissions.
 
<tt>#define LDAP_INSUFFICIENT_ACCESS 0x32 /* 50 */</tt>
 
----
 
<tt>LDAP_INVALID_CREDENTIALS</tt>
 
This result code indicates that the credentials provided in the request are invalid. Directory Server sends this result code back to the client if a bind request contains the incorrect credentials for a user or if a user’s password has already expired.
 
<tt>#define LDAP_INVALID_CREDENTIALS 0x31 /* 49 */</tt>
 
----
 
<tt>LDAP_INVALID_DN_SYNTAX</tt>
 
This result code indicates than an invalid DN has been specified. Directory Server sends this result code back to the client if an add request or a modify DN request specifies an invalid DN. It also sends this code when an <tt>LDAP_SASL_EXTERNAL</tt> bind is attempted but certification to DN mapping fails.
 
<tt>#define LDAP_INVALID_DN_SYNTAX 0x22 /* 34 */</tt>
 
----
 
<tt>LDAP_INVALID_SYNTAX</tt>
 
This result code indicates that the request contains invalid syntax. Directory Server sends this result code back to the client in the following situations:
 
*The server encounters an access control instruction (ACI) with invalid syntax.
*The request attempts to add or modify an <tt>aci</tt> attribute, and the value of the attribute is an ACI with invalid syntax.
*The request is a search request with a substring filter, and the syntax of the filter is invalid.
*The request is a modify request that is attempting to modify the schema, but no values are provided (for example, the request might be attempting to delete all values of the <tt>objectclass</tt> attribute).
 
<tt>#define LDAP_INVALID_SYNTAX 0x15 /* 21 */</tt>
 
----
 
<tt>LDAP_IS_LEAF</tt>
 
This result code indicates that the specified entry is a leaf entry.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_IS_LEAF 0x23 /* 35 */</tt>
 
----
 
<tt>LDAP_LOCAL_ERROR</tt>
 
This result code indicates that an error occurred in the LDAP client, though it may also be returned by Directory Server.
 
<tt>#define LDAP_LOCAL_ERROR 0x52 /* 82 */</tt>
 
----
 
<tt>LDAP_LOOP_DETECT</tt>
 
This result code indicates that the server was unable to perform the requested operation because of an internal loop.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_LOOP_DETECT 0x36 /* 54 */</tt>
 
----
 
<tt>LDAP_MORE_RESULTS_TO_RETURN</tt>
 
This result code indicates that there are more results in the chain of results. The Directory SDK For C sets this result code when the ldap_parse_sasl_bind_result() function is called to retrieve the result code of an operation, and additional result codes from the server are available in the LDAP structure.
 
<tt>#define LDAP_MORE_RESULTS_TO_RETURN 0x5f /* 95 */</tt>
 
----
 
<tt>LDAP_NAMING_VIOLATION</tt>
 
This result code indicates that the request violates the structure of the DIT.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_NAMING_VIOLATION 0x40 /* 64 */</tt>
 
----
 
<tt>LDAP_NO_MEMORY</tt>
 
This result code indicates that no memory is available. Directory SDK For C sets this result code if a function cannot allocate memory (for example, when creating an LDAP request or an LDAP control).
 
<tt>#define LDAP_NO_MEMORY 0x5a /* 90 */</tt>
 
----
 
<tt>LDAP_NO_OBJECT_CLASS_MODS</tt>
 
This result code indicates that the request is attempting to modify an object class that should not be modified (for example, a structural object class).
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_NO_OBJECT_CLASS_MODS 0x45 /* 69 */</tt>
 
----
 
<tt>LDAP_NO_RESULTS_RETURNED</tt>
 
This result code indicates that no results were returned from the server. The Directory SDK For C sets this result code when the ldap_parse_result() function is called but no result code is included in the server’s response.
 
<tt>#define LDAP_NO_RESULTS_RETURNED 0x5E /* 94 */</tt>
 
----
 
<tt>LDAP_NO_SUCH_ATTRIBUTE</tt>
 
This result code indicates that the specified attribute does not exist in the entry. Directory Server might send this result code back to the client if, for example, a modify request specifies the modification or removal of a non-existent attribute or if a compare request specifies a non-existent attribute.
 
<tt>#define LDAP_NO_SUCH_ATTRIBUTE 0x10 /* 16 */</tt>
 
----
 
<tt>LDAP_NO_SUCH_OBJECT</tt>
 
This result code indicates that the server cannot find an entry specified in the request. Directory Server sends this result code back to the client if it cannot find a requested entry and it cannot refer your client to another LDAP server.
 
<tt>#define LDAP_NO_SUCH_OBJECT 0x20 /* 32 */</tt>
 
----
 
<tt>LDAP_NOT_ALLOWED_ON_NONLEAF</tt>
 
This result code indicates that the requested operation is allowed only on entries that do not have child entries (''leaf'' entries as opposed to ''branch'' entries). Directory Server sends this result code back to the client if the request is a delete request or a modify DN request and the entry is a parent entry. You cannot delete or move a branch of entries in a single operation.
 
<tt>#define LDAP_NOT_ALLOWED_ON_NONLEAF 0x42 /* 66 */</tt>
 
----
 
<tt>LDAP_NOT_ALLOWED_ON_RDN</tt>
 
This result code indicates that the requested operation will affect the RDN of the entry. Directory Server sends this result code back to the client if the request is a modify request that deletes attribute values from the entry that are used in the RDN of the entry. (For example, the request removes the attribute value <tt>uid=bjensen</tt> from the entry <tt>uid=bjensen,ou=People,dc=example,dc=com</tt>.)
 
<tt>#define LDAP_NOT_ALLOWED_ON_RDN 0x43 /* 67 */</tt>
 
----
 
<tt>LDAP_NOT_SUPPORTED</tt>
 
This result code indicates that the LDAP client is attempting to use functionality that is not supported. Directory SDK For C sets this result code if the client identifies itself as an LDAP v2 client, and the client is attempting to use functionality available in LDAP v3. For example:
 
*You are passing LDAP controls to a function.
*You are calling ldap_extended_operation() , ldap_extended_operation_s(), or ldap_parse_extended_result() to request an extended operation or to parse an extended response.
*You are calling ldap_rename() or ldap_rename_s(), and you are specifying a new superior DN as an argument.
*You are calling ldap_sasl_bind(), ldap_sasl_bind_s(), or ldap_parse_sasl_bind_result() to request Simple Authentication and Security Layer (SASL) authentication or to parse a SASL bind response.
*You are calling ldap_parse_virtuallist_control() to parse a virtual list control from the server’s response.
 
If you want to use these features, make sure to specify that your LDAP client is an LDAP v3 client.
 
<tt>#define LDAP_NOT_SUPPORTED 0x5c /* 92 */</tt>
 
----
 
<tt>LDAP_OBJECT_CLASS_VIOLATION</tt>
 
This result code indicates that the request specifies a new entry or a change to an existing entry that does not comply with the server’s schema. Directory Server sends this result code back to the client in the following situations:
 
*The request is an add request, and the new entry does not comply with the schema. For example, the new entry does not have all the required attributes, or the entry has attributes that are not allowed in the entry.
*The request is a modify request, and the change will make the entry non compliant with the schema. For example, the change removes a required attribute or adds an attribute that is not allowed.
 
Check the server error logs for more information, and the schema for the type of entry that you are adding or modifying.
 
<tt>#define LDAP_OBJECT_CLASS_VIOLATION 0x41 /* 65 */</tt>
 
----
 
<tt>LDAP_OPERATIONS_ERROR</tt>
 
This is a general result code indicating that an error has occurred. Directory Server might send this code if, for example, memory cannot be allocated on the server. To troubleshoot this type of error, check the server’s error logs. You may need to increase the log level of the server to get additional information.
 
<tt>#define LDAP_OPERATIONS_ERROR 0x01 /* 1 */</tt>
 
----
 
<tt>LDAP_OTHER</tt>
 
This result code indicates than an unknown error has occurred. This error may be returned by Directory Server when an error occurs that is not better described using another LDAP error code. When this error occurs, check the server's error logs. You may need to increase the log level of the server to get additional information.
 
<tt>#define LDAP_OTHER 0x50 /* 80 */</tt>
 
----
 
<tt>LDAP_PARAM_ERROR</tt>
 
This result code indicates that an invalid parameter was specified. Directory SDK For C sets this result code if a function was called and invalid parameters were specified, for example, if the LDAP structure is <tt>NULL</tt>.
 
<tt>#define LDAP_PARAM_ERROR 0x59 /* 89 */</tt>
 
----
 
<tt>LDAP_PARTIAL_RESULTS</tt>
 
Directory Server sends this result code to LDAP v2 clients to refer them to another LDAP server. When sending this code to a client, the server includes a new line-delimited list of LDAP URLs that identifies another LDAP server. If the client identifies itself as an LDAP v3 client in the request, an LDAP_REFERRAL result code is sent instead of this result code.
 
<tt>#define LDAP_PARTIAL_RESULTS 0x09 /* 9 */</tt>
 
----
 
<tt>LDAP_PROTOCOL_ERROR</tt>
 
This result code indicates that the LDAP client’s request does not comply with the LDAP. Directory Server sends this result code back to the client in the following situations:
 
*The server cannot parse the incoming request.
*The request specifies an attribute type that uses a syntax not supported by the server.
*The request is a SASL bind request, but your client identifies itself as an LDAP v2 client.
*The request is a bind request that specifies an unsupported version of the LDAP. Make sure to specify whether your LDAP client is an LDAP v2 client or an LDAP v3 client.
*The request is an add or a modify request that specifies the addition of an attribute type to an entry, but no values are specified.
*The request is a modify request, and one of the following is true:
**An unknown modify operation is specified (an operation other than <tt>LDAP_MOD_ADD</tt>, <tt>LDAP_MOD_DELETE</tt>, and <tt>LDAP_MOD_REPLACE</tt>).
**No modifications are specified.
*The request is a modify DN request, and one of the following is true:
**The new RDN is not a valid RDN.
**A new superior DN is specified, but your client identifies itself as an LDAP v2 client.
*The request is a search request, and one of the following is true:
**An unknown scope is specified, meaning a scope other than <tt>LDAP_SCOPE_BASE</tt> , <tt>LDAP_SCOPE_ONELEVEL</tt>, or <tt>LDAP_SCOPE_SUBTREE </tt>.
**An unknown filter type is specified.
**The filter type <tt>LDAP_FILTER_GE</tt> or <tt>LDAP_FILTER_LE </tt> is specified, but the type of attribute contains values that cannot be ordered. (For example, if the attribute type uses a binary syntax, the values of the attribute contain binary data, which cannot be sorted.)
**The request contains an extensible filter (a filter using matching rules), but your client identifies itself as an LDAP v2 client.
**The request contains an extensible filter (a filter using matching rules), but the matching rule is not supported by the server.
*The request is a search request with a server-side sorting control, and one of the following is true:
**The server does not have a syntax plug-in that supports the attribute used for sorting.
**The syntax plug-in does not have a function for comparing values of the attribute. (This compare function is used for sorting.)
**The type of attribute specified for sorting contains values that cannot be sorted in any order. For example, if the attribute type uses a binary syntax, the values of the attribute contain binary data, which cannot be sorted.
**The server encounters an error when creating the sorting response control (the control to be sent back to the client).
**When sorting the results, the time limit or the look-through limit is exceeded. The look-through limit is the maximum number of entries that the server will check when gathering a list of potential search result candidates.
*The request is an extended operation request, and the server does not support the extended operation. In Directory Server, extended operations are supported through extended operation server plug-ins. Make sure that the server is loading a plug-in that supports the extended operation. Check the OID of the extended operation in your LDAP client to make sure that it matches the OID of the extended operation registered in the server plug-in.
*An authentication method other than <tt>LDAP_AUTH_SIMPLE</tt> or <tt>LDAP_AUTH_SASL</tt> is specified.
 
To troubleshoot this type of error, check the server’s error logs. You may need to increase the log level of the server to get additional information.
 
<tt>#define LDAP_PROTOCOL_ERROR 0x02 /* 2 */</tt>
 
----
 
<tt>LDAP_REFERRAL</tt>
 
This result code indicates that the server is referring the client to another LDAP server. When sending this code to a client, the server includes a list of LDAP URLs that identify another LDAP server. This result code is part of the LDAP v3. For LDAP v2 clients, Directory Server sends an LDAP_PARTIAL_RESULTS result code instead.
 
<tt>#define LDAP_REFERRAL 0x0a /* 10 */</tt>
 
----
 
<tt>LDAP_REFERRAL_LIMIT_EXCEEDED</tt>
 
This result code indicates that the referral hop limit''was exceeded. Directory SDK For C sets this'' result code, when following referrals, if the client is referred to other servers more times than allowed by the ''referral hop limit''.
 
<tt>#define LDAP_REFERRAL_LIMIT_EXCEEDED 0x61 /* 97 */</tt>
 
----
 
<tt>LDAP_RESULTS_TOO_LARGE</tt>
 
This result code indicates that the results of the request are too large.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_RESULTS_TOO_LARGE 0x46 /* 70 */</tt>
 
----
 
<tt>LDAP_SASL_BIND_IN_PROGRESS</tt>
 
This result code is used in multi stage SASL bind operations. The server sends this result code back to the client to indicate that the authentication process has not yet completed.
 
<tt>#define LDAP_SASL_BIND_IN_PROGRESS 0x0E /* 14 */</tt>
 
----
 
<tt>LDAP_SERVER_DOWN</tt>
 
This result code indicates that Directory SDK For C cannot establish a connection with, or lost the connection to, the LDAP server. If you have not established an initial connection with the server, verify that you have specified the correct host name and port number and that the server is running.
 
<tt>#define LDAP_SERVER_DOWN 0x51 /* 81 */</tt>
 
----
 
<tt>LDAP_SIZELIMIT_EXCEEDED</tt>
 
This result code indicates that the maximum number of search results to return has been exceeded. This limit is specified in the search request. If you specify no size limit, the server will set one. When working with Directory Server, keep in mind the following:
 
*If you are bound as the root DN and specify no size limit, the server enforces no size limit at all.
*If you are not bound as the root DN and specify no size limit, the server sets the size limit to the value specified by the <tt>sizelimit</tt> directive in the server’s <tt>slapd.conf</tt> configuration file.
*If the size limit that you specify exceeds the value specified by the <tt>sizelimit</tt> directive in the server’s <tt>slapd.conf </tt> configuration file, the server uses the size limit specified in the configuration file.
 
<tt>#define LDAP_SIZELIMIT_EXCEEDED 0x04 /* 4 */</tt>
 
----
 
<tt>LDAP_SORT_CONTROL_MISSING</tt>
 
This result code indicates that server did not receive a required server-side sorting control. Directory Server sends this result code back to the client if the server receives a search request with a ''virtual list view'' control but no server-side sorting control as the ''virtual list view'' control requires a server-side sorting control.
 
<tt>#define LDAP_SORT_CONTROL_MISSING 0x3C /* 60 */</tt>
 
----
 
<tt>LDAP_STRONG_AUTH_NOT_SUPPORTED</tt>
 
This result code is returned as the result of a bind operation. It indicates that the server does not recognize or support the specified authentication method.
 
<tt>#define LDAP_STRONG_AUTH_NOT_SUPPORTED 0x07 /* 7 */</tt>
 
----
 
<tt>LDAP_STRONG_AUTH_REQUIRED</tt>
 
This result code indicates that a stronger method of authentication is required to perform the operation.
 
<tt>#define LDAP_STRONG_AUTH_REQUIRED 0x08 /* 8 */</tt>
 
----
 
<tt>LDAP_SUCCESS</tt>
 
This result code indicates that the LDAP operation was successful.
 
<tt>#define LDAP_SUCCESS 0x00 /* 0 */</tt>
 
----
 
<tt>LDAP_TIMELIMIT_EXCEEDED</tt>
 
This result code indicates that the time limit on a search operation has been exceeded. The time limit is specified in the search request. If you specify no time limit, the server will set one. When working with Directory Server, keep in mind the following:
 
*If you are bound as the root DN and specify no time limit, the server enforces no limit at all.
*If you are not bound as the root DN and specify no time limit, the server sets the time limit.
*If the time limit that you specify exceeds the time limit specified for the server configuration, the server uses the time limit specified in its configuration.
 
<tt>#define LDAP_TIMELIMIT_EXCEEDED 0x03 /* 3 */</tt>
 
----
 
<tt>LDAP_TIMEOUT</tt>
 
This result code indicates that the LDAP client timed out while waiting for a response from the server. Directory SDK For C sets this result code in the LDAP structure if the time-out period (for example, in a search request) has been exceeded and the server has not responded.
 
<tt>#define LDAP_TIMEOUT 0x55 /* 85 */</tt>
 
----
 
<tt>LDAP_TYPE_OR_VALUE_EXISTS</tt>
 
This result code indicates that the request attempted to add an attribute type or value that already exists. Directory Server sends this result code back to the client in the following situations:
 
*The request attempts to add values that already exist in the attribute.
*The request is adding an attribute to the schema of the server, but the OID of the attribute is already used by an object class in the schema.
*The request is adding an object class to the schema of the server, and one of the following occurs:
**The object class already exists.
**The OID of the object class is already used by another object class or an attribute in the schema.
**The superior object class for this new object class does not exist.
 
<tt>#define LDAP_TYPE_OR_VALUE_EXISTS 0x14 /* 20 */</tt>
 
----
 
<tt>LDAP_UNAVAILABLE</tt>
 
This result code indicates that the server is unavailable to perform the requested operation.
 
'''Note:''' At this point, neither Directory SDK For C nor Directory Server return this result code.
 
<tt>#define LDAP_UNAVAILABLE 0x34 /* 52 */</tt>
 
----
 
<tt>LDAP_UNAVAILABLE_CRITICAL_EXTENSION</tt>
 
This result code indicates that the specified control or matching rule is not supported by the server. Directory Server might send back this result code if the request includes an unsupported control or if the filter in the search request specifies an unsupported matching rule.
 
<tt>#define LDAP_UNAVAILABLE_CRITICAL_EXTENSION 0x0c /* 12 */</tt>
 
----
 
<tt>LDAP_UNDEFINED_TYPE</tt>
 
This result code indicates that the request specifies an undefined attribute type.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_UNDEFINED_TYPE 0x11 /* 17 */</tt>
 
----
 
<tt>LDAP_UNWILLING_TO_PERFORM</tt>
 
This result code indicates that the server is unwilling to perform the requested operation. Directory Server sends this result code back to the client in the following situations:
 
*The client has logged in for the first time and needs to change its password, but the client is requesting to perform other LDAP operations. In this situation, the result code is accompanied by an expired password control.
*The request is a modify DN request, and a superior DN is specified.
*The database is in read-only mode, and the request attempts to write to the directory.
*The request is a delete request that attempts to delete the root DSE.
*The request is a modify DN request that attempts to modify the DN of the root DSE.
*The request is a modify request to modify the schema entry, and one of the following occurs:
**The operation is <tt>LDAP_MOD_REPLACE</tt>. (The server does not allow you to replace schema entry attributes.)
**The request attempts to delete an object class that is the parent of another object class.
**The request attempts to delete a read-only object class or attribute.
*The server uses a database plug-in that does not implement the operation specified in the request. For example, if the database plug-in does not implement the add operation, sending an add request will return this result code.
 
<tt>#define LDAP_UNWILLING_TO_PERFORM 0x35 /* 53 */</tt>
 
----
 
<tt>LDAP_USER_CANCELLED</tt>
 
This result code indicates that the user cancelled the LDAP operation.
 
'''Note:''' Directory Server does not currently send this result code back to LDAP clients.
 
<tt>#define LDAP_USER_CANCELLED 0x58 /* 88 */</tt>
 
----
 
<br>

Revision as of 19:55, 6 February 2011

My name's Mark Craig. I used to work for Sun Microsystems, leading the Directory Services documentation effort.


Trying the rich text editor with and HTML version of the LDAP C SDK guide that Rich Megginson uploaded after I worked with Sun legal to get it licensed Creative Commons. Finally getting back to this after about 4 years...

LDAP C SDK Programmer's Guide

Copyright © 2000-2007 Sun Microsystems, Inc. All Rights Reserved.

This Programmer's Guide shows you how to create LDAP client applications in the C language to connect to LDAP servers. This guide also shows you how to perform standard LDAP operations.

License - The contents of this document are subject to the terms of the Creative Commons Attribution-ShareAlike 2.5 license or any later version (the "License"). You may not use this document except in compliance with the License.

See the License for the specific language governing permissions and limitations under the License. The full text of the License is provided at the end of this document.

Copyright 2000-2007 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California 95054, U.S.A. All rights reserved. Portions copyright 1999 Netscape Communications Corporations. All rights reserved.

Sun Microsystems, Inc. has intellectual property rights relating to technology embodied in the product that is described in this document. In particular, and without limitation, these intellectual property rights may include one or more U.S. patents or pending patent applications in the U.S. and in other countries.

U.S. Government Rights - Commercial software. Government users are subject to the Sun Microsystems, Inc. standard license agreement and applicable provisions of the FAR and its supplements.

This distribution may include materials developed by third parties.

Parts of the product may be derived from Berkeley BSD systems, licensed from the University of California. UNIX is a registered trademark in the U.S. and in other countries, exclusively licensed through X/Open Company, Ltd.

Sun, Sun Microsystems, the Sun logo, Java, Solaris, JavaBeans, JavaScript and the SunTone Certified logo are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries.

All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. in the U.S. and other countries. Products bearing SPARC trademarks are based upon architecture developed by Sun Microsystems, Inc.

Mozilla, Netscape, and Netscape Navigator are trademarks or registered trademarks of Netscape Communications Corporation in the United States and other countries.

Products covered by and information contained in this service manual are controlled by U.S. Export Control laws and may be subject to the export or import laws in other countries. Nuclear, missile, chemical biological weapons or nuclear maritime end uses or end users, whether direct or indirect, are strictly prohibited. Export or reexport to countries subject to U.S. embargo or to entities identified on U.S. export exclusion lists, including, but not limited to, the denied persons and specially designated nationals lists is strictly prohibited.

DOCUMENTATION IS PROVIDED AS IS AND ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD TO BE LEGALLY INVALID.

Copyright 2000-2007 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California 95054, Etats-Unis. Tous droits rservs. Certaines parties copyright 1999 Netscape Communications Corporations. Tous droits rservs.

Sun Microsystems, Inc. dtient les droits de proprit intellectuelle relatifs la technologie incorpore dans le produit qui est dcrit dans ce document. En particulier, et ce sans limitation, ces droits de proprit intellectuelle peuvent inclure un ou plusieurs brevets amricains ou des applications de brevet en attente aux Etats-Unis et dans d'autres pays.

Cette distribution peut comprendre des composants dvelopps par des tierces parties.

Des parties de ce produit pourront tre drives des systmes Berkeley BSD licencis par l'Universit de Californie. UNIX est une marque dpose aux Etats-Unis et dans d'autres pays et licencie exclusivement par X/Open Company, Ltd.

Sun, Sun Microsystems, le logo Sun, Java, Solaris, JavaBeans, JavaScript et le logo SunTone Certified sont des marques de fabrique ou des marques dposes de Sun Microsystems, Inc. aux Etats-Unis et dans d'autres pays.

Toutes les marques SPARC sont utilises sous licence et sont des marques de fabrique ou des marques dposes de SPARC International, Inc. aux Etats-Unis et dans d'autres pays. Les produits portant les marques SPARC sont bass sur une architecture dveloppe par Sun Microsystems, Inc.

Mozilla, Netscape, et Netscape Navigator sont des marques de Netscape Communications Corporation aux Etats-Unis et dans d'autres pays.

Les produits qui font l'objet de ce manuel d'entretien et les informations qu'il contient sont regis par la legislation americaine en matiere de controle des exportations et peuvent etre soumis au droit d'autres pays dans le domaine des exportations et importations. Les utilisations finales, ou utilisateurs finaux, pour des armes nucleaires, des missiles, des armes biologiques et chimiques ou du nucleaire maritime, directement ou indirectement, sont strictement interdites. Les exportations ou reexportations vers des pays sous embargo des Etats-Unis, ou vers des entites figurant sur les listes d'exclusion d'exportation americaines, y compris, mais de maniere non exclusive, la liste de personnes qui font objet d'un ordre de ne pas participer, d'une facon directe ou indirecte, aux exportations des produits ou des services qui sont regi par la legislation americaine en matiere de controle des exportations et la liste de ressortissants specifiquement designes, sont rigoureusement interdites.

LA DOCUMENTATION EST FOURNIE EN L'ETAT ET TOUTES AUTRES CONDITIONS, DECLARATIONS ET GARANTIES EXPRESSES OU TACITES SONT FORMELLEMENT EXCLUES, DANS LA MESURE AUTORISEE PAR LA LOI APPLICABLE, Y COMPRIS NOTAMMENT TOUTE GARANTIE IMPLICITE RELATIVE A LA QUALITE MARCHANDE, A L'APTITUDE A UNE UTILISATION PARTICULIERE OU A L'ABSENCE DE CONTREFACON.

Preface

This Programmer's Guide shows you how to create LDAP client applications in the C language to connect to LDAP servers. This guide also shows you how to perform standard LDAP operations.

Who Should Use This Book

This guide is intended for developers creating directory client applications.

  • Directory Server functionality
  • Developing programs in the C programming language
  • Specifications for LDAP and related protocols, such as DSML v2
  • Internet and World Wide Web technologies

Before You Read This Book

Before developing directory client applications, install the LDAP C SDK.

Additional Recommended Reading

  • LDAP Programming with Java by Weltman and Dabhura (ISBN 0-201-65758-96)
  • LDAP Programming, Management and Integration by Donley (ISBN 1930110405)
  • LDAP: Programming Directory-Enabled Applications with Lightweight Directory Access Protocol by Howes and Smith (ISBN 1-57870-000-00)
  • Understanding and Deploying LDAP Directory Services by Howes, et al. (ISBN 1-57870-070-10)
  • RFC 2251, Lightweight Directory Access Protocol (v3)
  • RFC 2252, Lightweight Directory Access Protocol (v3): Attribute Syntax Definitions
  • RFC 2253, Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names
  • RFC 2254, The String Representation of LDAP Search Filters
  • RFC 2255, The LDAP URL Format
  • RFC 2256, A Summary of the X.500(96) User Schema for use with LDAPv3
  • RFC 2829, Authentication Methods for LDAP
  • RFC 2830, Lightweight Directory Access Protocol (v3): Extension for Transport Layer Security
  • RFC 2849, The LDAP Data Interchange Format (LDIF) - Technical Specification
  • RFC 3377, Lightweight Directory Access Protocol (v3): Technical Specification

Related Reading

The SLAMD Distributed Load Generation Engine (SLAMD) is a Java™ application that is designed to stress test and analyze the performance of network-based applications. It was originally developed by Sun Microsystems, Inc. to benchmark and analyze the performance of LDAP directory servers. SLAMD is available as an open source application under the Sun Public License, an OSI-approved open source license. To obtain information about SLAMD, go to http://www.slamd.com/. SLAMD is also available as a java.net project. See https://slamd.dev.java.net/.

Java Naming and Directory Interface (JNDI) technology supports accessing the Directory Server using LDAP and DSML v2 from Java applications. For information about JNDI, see http://java.sun.com/products/jndi/. The JNDI Tutorial contains detailed descriptions and examples of how to use JNDI. This tutorial is at http://java.sun.com/products/jndi/tutorial/.

Understanding LDAP

Lightweight Directory Access Protocol (LDAP) is the Internet directory protocol. Developed at the University of Michigan at Ann Arbor in conjunction with the Internet Engineering Task Force, LDAP is a protocol for accessing and managing directory services.

How Directory Services Work

A directory consists of entries that contain descriptive information. For example, a directory might contain entries that describe people or network resources, such as printers or fax machines.

The descriptive information is stored in the attributes of the entry. Each attribute describes a specific type of information. For example, attributes that describe a person might include her name, also referred to as her common name (CN), telephone number, and email address.

The entry for Barbara Jensen might have the following attributes:

cn: Barbara Jensen
mail: babs@example.com
telephoneNumber: 555-1212
roomNumber: 3995

An attribute can have more than one value. For example, a person might have two common names, both a formal name and also a nickname:

cn: Barbara Jensen
cn: Babs Jensen
mail: babs@example.com
telephoneNumber: 555-1212
roomNumber: 3995

Attributes can also contain binary data. For example, a person's attributes might include her photo in JPEG format, a recording of her voice as an audio file, or her SSL certificate.

A directory service is a distributed database application for managing the entries and attributes in a directory. A directory service also makes the entries and attributes available to users and other applications.

Directory Server is an example of a directory service. For example, a user might use the directory service to look up someone's telephone number. Another application might use the directory service to retrieve a list of email addresses.

LDAP is a protocol that defines a directory service and access to that service. LDAP is based on a client-server model. LDAP servers provide the directory service. LDAP clients use the directory service to access entries and attributes.

Directory Server is an example of an LDAP server that manages and provides information about users and organizational structures. Examples of LDAP clients include Identity Manager, Access Manager, Solaris™ naming services, Messaging Server, Portal Server, NameFinder, and the Mozilla mail client. Such clients use Directory Server to find, update, and add information about users.

How LDAP Servers Organize Directories

Because LDAP is intended to be a global directory service, data is organized hierarchically, starting at a root and branching down into individual entries.

At the top level of the hierarchy, entries represent larger organizations. Under larger organizations in the hierarchy, you might find entries for smaller organizations. The hierarchy might end with entries for individual people, or resources, as shown in the following figure.

Hierarchy of Entries in a Directory

Each entry is uniquely identified by a distinguished name (DN). A DN includes a relative distinguished name (RDN), that uniquely identifies the entry at that hierarchical level. For example, bjensen and kjensen are different user IDs that identify different entries at the same level. Following the RDN is a path of names that trace the entry back to the root of the tree, such as ou=People,dc=example,dc=com. DC is short for domain component. The full DN for this example would be uid=bjensen,ou=People,dc=example,dc=com. Here, uid is the user ID of the entry. ou is short for organizational unit.

The data stored in a directory can be distributed among several LDAP servers. For example, one LDAP server at Example.com might contain entries representing North American organizational units and employees, while another LDAP server might contain entries representing European organizational units and employees.

Some LDAP servers are set up to refer requests to other LDAP servers. For example, if the LDAP server at Example.com receives a request for information about an employee in a Pacific Rim branch, that server can refer the request to the LDAP server at the Pacific Rim branch. In this way, LDAP servers can appear to be a single source of directory information. Even if an LDAP server does not contain the information you request, the server can refer you to another server that does contain the information.

How LDAP Clients and Servers Work

In the LDAP client-server model, LDAP servers such as Directory Server make information about people, organizations, and resources accessible to LDAP clients. LDAP defines operations that clients use to search and update the directory.

  • Search for and retrieve entries from the directory
  • Add new entries to the directory
  • Update entries in the directory
  • Delete entries from the directory
  • Rename entries in the directory

For example, to update an entry, an LDAP client submits the distinguished name of the entry with updated attribute information to the LDAP server. The LDAP server uses the distinguished name to find the entry. The server then performs a modify operation to update the entry in the directory.

To perform any of these LDAP operations, an LDAP client needs to establish a connection with an LDAP server. The LDAP protocol specifies the use of TCP/IP port number 389, although servers can run on other ports.

The LDAP protocol also defines a simple method for authentication. LDAP servers can be set up to restrict permissions to the directory. Before an LDAP client can perform an operation on an LDAP server, the client must authenticate to the server. Clients typically authenticate by supplying a distinguished name and password. If the user identified by the distinguished name does not have permission to perform the operation, the server does not execute the operation.

Understanding LDAP v3

RFC 4511 specifies LDAP version 3. Use this version of the protocol when writing new client applications.

Many LDAP servers continue to support LDAP version 2 for use with legacy clients. This version of the protocol is specified in RFC 1777.

Clients and servers can specify controls that extend the functionality of an LDAP operation.

Clients can request that the server perform extended operations, operations not included in the list of standard LDAP operations.

Clients can use Simple Authentication and Security Layer (SASL) mechanisms to authenticate to the directory. SASL is specified in RFC 4422.

Servers, known as Directory System Agents (DSAs), have DSA-specific entries (DSEs). DSEs provide information about the versions of the LDAP protocol that the server supports. DSEs also provide a list of the controls, extended operations, and SASL mechanisms supported by the server. Finally, DSEs specify the naming contexts of the server. Naming contexts are portions of the directory information tree managed by the server.

Servers make their schemas, which define the object classes, attributes, syntaxes, and matching rules enforced by the directory, available to clients through the root DSE.

Both client and server applications can support data in UTF-8. UTF-8 is a transformation format of the Universal Character Set standard. UTF-8 is specified in RFC 3269. With UTF-8, clients can request and receive data that is tagged with language information.

Choosing a Client SDK

This chapter discusses software development kits to help you select the appropriate directory SDK for your particular situation.

Java Naming and Directory Interface

Java Naming and Directory Interface (JNDI) technology supports directory access through LDAP and DSML v2 from Java™ applications, and is part of the Java platform. With JNDI, you can build powerful, portable, directory-enabled applications that do not depend on classes outside the Java platform.

JNDI provides an abstract model that lets you access not only directories, but also naming services in general, including DNS, RMI, COS, and file systems.

For information about JNDI, see http://java.sun.com/products/jndi/. The JNDI Tutorial contains descriptions and examples of how to use JNDI. The tutorial is at http://java.sun.com/products/jndi/tutorial/.

Directory SDK for C

Directory SDK for C lets you access LDAP directories from C and C++ applications. Directory SDK for C applications depend on Directory SDK for C libraries, which are available on a wide range of platforms.

Directory SDK for C was the subject of Internet-Draft work but never became a standard API. Directory SDK for C closely follows LDAP v3, providing support for core LDAP operations and for LDAP v3 extensions and widely used controls. Directory SDK for C offers a rich API to the C and C++ developer familiar with the LDAP model. Directory Server relies on Directory SDK for C.

This document demonstrates how to use Directory SDK for C. Directory SDK for C code is published in open source form as part of the Mozilla Directory SDK project.

Directory SDK for Java

Directory SDK for Java lets you access LDAP directories from Java applications, but it is not part of the Java platform.

Although not a standard API, Directory SDK for Java closely follows LDAP v3 idioms. Directory SDK for Java provides a rich set of interfaces to the Java developer familiar with the LDAP model.

This document demonstrates how to use Directory SDK for Java. Directory SDK for Java code is published in open source form as part of the Mozilla Directory SDK project.

Operating System libldap Library

The native LDAP library on Solaris™ systems provides essentially the same API as Directory SDK for C. Many Directory SDK for C need only be recompiled to work with libldap.

The LDAP library is sometimes not compatible with libldap on many GNU/Linux distributions. Many GNU/Linux distributions provide OpenLDAP support by default.

Support for Other Programming Languages

Support for directory access is available in a number of contexts where you do not choose to use the C or Java languages.

For example, Perl has the PerLDAP module and the Net::LDAP collection of modules. Python has the python-ldap package. PHP can be compiled with LDAP support. Ruby has the Ruby/LDAP extension module. In many cases, you can choose the language that fits the task and find that LDAP support is available.

Best Practices for Writing Client Applications

The section covers what to keep in mind when creating and debugging LDAP client applications.

Specify LDAP v3

With JNDI, you could use LDAP v3 as shown here.

import java.util.Hashtable;
import javax.naming.ldap.InitialLdapContext;

Hashtable env = new Hashtable();
env.put("java.naming.ldap.version", "3");
InitialLdapContext ctx = new InitialLdapContext(env, null);

With Directory SDK for C, you could use LDAP v3 as shown here.

#include "ldap.h"

int version = LDAP_VERSION3;
ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version );

Directory SDK for C uses LDAP v3 by default.

With Directory SDK for Java, you could use LDAP v3 as shown here.

import netscape.ldap.LDAPConnection;

LDAPConnection ld = new LDAPConnection();
ld.setOption(LDAPv3.PROTOCOL_VERSION, new Integer(3));

Authenticate Correctly

Your SDK uses terminology that is slightly different from LDAP v3. In LDAP v3, you connect, then you bind and perform LDAP operations, then you unbind and disconnect. The bind is the authentication operation in LDAP. Your application can hold onto a connection but change the authentication credentials by using the bind operation again.

Some directories do not allow anonymous access, even for reads. When you build your application, keep the option that allows users to authenticate to the directory. Furthermore, the information sent across the network can be sensitive. You can protect sensitive data by allowing the application to secure the connection by using Secure Sockets Layer (SSL) or Start Transport Layer Security (TLS).

If your application needs to authenticate, obtain a regular account to authenticate with the directory, rather than using the directory superuser account such as cn=Directory Manager. When you authenticate as directory superuser, you often bypass normal access control mechanisms. Bypassing normal access control renders auditing directory access more difficult.

When authenticating, have your application use SSL or SASL DIGEST MD5 to avoid sending passwords over the network in clear text. Furthermore, when using password-based authentication, have your application check password policy controls, especially to determine when a password must be renewed.

Limit Connection Overhead

A new connection requires system resources. The LDAP model allows you to reuse connections by binding again with a different identity on the same connection. Thus, you can avoid the costs of new connections, particularly negotiated connections such as connections that use SSL, by reusing connections. Your application can use a pool of connections, rebinding when necessary. Your application can alternatively use the proxy authorization control to remain authenticated as the application but perform operations on behalf of a particular user.

When establishing a connection, your application can provide alternate server host names and port numbers to facilitate failover that is transparent to the application. You can also set time limits for LDAP operations to avoid getting blocked.

When finished with a connection, your application should perform an unbind.

Handle Potential Inactivity Timeouts

Most network equipment can use timeouts to drop stale connections, ensuring the equipment keeps a maximum number of connections that are available.

If your application pools connections or opens connections for persistent search, than guard against timeouts that drop those connections. Use the connections occasionally to reset inactivity timers present in the network.

Alternatively, if you have control over the connection, consider disabling inactivity time outs for your applications that need to keep persistent connections open. Load balancers and proxy software often use inactivity timeouts.

Retrieve Entries Intelligently

Directory Server typically responds quickly to requests for entries. Yet, Directory Server can respond most quickly when your application asks it to do only necessary work. If you need to read only a few attributes in an entry, request each attribute explicitly. Avoid reading the entire entry, then parsing the entire entry to obtain the required data.

Furthermore, when you do request attributes in an entry, retrieve all the required attributes at once. Each new request involves a new operation on the server.

If any of the attributes that you require are operational attributes, you must request those attributes specifically. Such attributes are identifiable in directory schema by their USAGE, which is directoryOperation or dsaOperation.

When retrieving entries and attributes, recognize that you might not have access to all the attributes that exist.

Write Simple, Conforming LDAP Filters

The best filters use attributes that are indexed according to the way the attributes are indexed. For example, if employeeNumber is indexed for equality, your filter should be an equality filter such as (employeeNumber=123456). Do not use a substring filter instead.

Avoid deeply nested complex filters when you can. When you must use complex filters, place the most specific filters first to narrow the list of candidate entries the directory must check. For best results, use not, !, only with and, &, for example (&(cn=Barbara)(!(sn=Jensen))). When you use not with or in a filter, the directory must construct a candidate list of everything except what your filter specifies.

Performing Specific Modifications

Modifications are atomic on the entry to which the modifications apply. When modifying multivalued attributes, delete and replace specific values. Do not replace an entire list of multiple values to change only a few values. Replacing specific values is particularly good practice when the changes must be replicated across a set of servers.

Moreover, when you have large values to store in an attribute, store a reference to the data instead of storing the data object.

Trust Result Codes

Directory Server trades tight consistency across replica servers for very high performance, availability, and scalability. By allowing loose consistency of data across sets of replica servers, Directory Server instances can respond very quickly to your application. Yet, data replication is not instantaneous. A short but detectable delay can ensue after a server returns success for a write operation, but before the effects are seen on other replicas.

Therefore, when your application receives a result code from Directory Server to indicate that an operation was successful, your application should trust the result code. When application requests are balanced across replicas, reading from another replica might result in errors due to a slight delay in replication.

Limit Dealings With Groups and Roles

When you want to know whether an account belongs to a group or a role, read only the necessary attribute values. Do not read the entire list of group members.

  1. Read the URL from the group definition.
  2. Examine the host, DN, and scope of the URL.
  3. Apply the filter part of the URL to the entry for the account.

For roles, compare the DN of the role to the nsRole attribute of the entry for the account, such as (nsrole=cn=management,ou=people,dc=example,dc=com). You can then retrieve all the values of the nsRole attribute for the account.

Read the DSE

The root DSE is the entry that is retrieved by ldapsearch -b "" -s base "(objectclass=*)". The root DSE describes server capabilities. The root DSE contains information about supported LDAP protocol versions, naming contexts (suffixes), LDAP v3 controls, LDAP v3 extensions, and authentication mechanisms. The root DSE can contain information about the server version.

Some directory administrators protect access to the root DSE. Yet, applications might read the root DSE to confirm that the server in fact supports functionality required by applications.

Use Resource-Intensive Features Sparingly

Directories offer powerful features that can nevertheless place a heavy load on the server. Two such features are persistent search, and server-side sorting.

Persistent search lets you start a search that does not stop when complete, but instead allows you to receive updates when entries are modified. To provide this feature, the server must handle your search when anything happens to an entry in its scope.

Server-side sorting requires that the server sort the entries that are returned during a search. Instead of returning entries as quickly as possible, the server must therefore get the list to return, and sort the list.

Avoid Hard Coding Certain Information

The container entry for a subtree might be not be identical on different directories. Rather than hard code the container entry throughout your application, locate the container entry. Then navigate beneath the container entry in the tree.

Object classes and attribute types for the same information can also differ from directory to directory. Use configuration files, properties files, or other easily modifiable variables rather than hard coding object class and attribute type identifiers into your application.

Be aware as well that object class and attribute type identifiers are not case-sensitive in LDAP. Your application should therefore recognize that inetOrgPerson and inetorgperson are equivalent, as are isMemberOf and ismemberof.

Define Schemas Only When Necessary

Schemas define the object classes and attribute types that are recognized by the directory. If your application can use a standard schema, use the standard schema. Directory Server contains schemas that define numerous standard object classes, and attribute types.

  • Extend existing object classes by using AUXILIARY classes.
  • Create new attributes rather than redefining existing attributes.
  • Other applications might depend on existing attributes to keep their existing semantics.
  • Obtain new object identifiers for the schema elements you define, rather than reusing existing object identifiers.
  • Obtain new names for the schema elements you define, rather than reusing existing names.
  • Update Directory Server schema over LDAP if you can.

Handle Referrals

LDAP v3 allows directories that are unable to handle your request to refer your application to other directories. Your application should follow those referrals.

When following referrals, realize that authentication procedures might not be exactly the same on different directories. Also, directories that refer to each other could potentially cause a referral loop. With Directory SDK for C and Directory SDK for Java, you can limit referral hops to prevent your application from being referred endlessly from one directory to another directory. The JNDI interface enables you to follow referrals automatically.

Treat a Directory as a Directory

A directory is typically a repository for identity data, and for information that you expect to keep for awhile and read often. You might typically find relational databases better adapted to hold transient data such as session keys and presence information, or voluminous accumulated data such as application logs.

Check Result Codes

When an LDAP request from your application fails on the server, the server sends back a result code, and possibly an explanatory message. Your application should check the result codes, and for explanatory messages. Common failure result codes include the following, which are expressed as decimal values. Others result codes are defined as well.

1
LDAP operations error. The server encountered an error while processing your request.

32
No such object. The entry is not present on the server. Also, no referral is defined for the entry.

49
Invalid credentials. Your application failed to authenticate properly.

53
LDAP unwilling to perform. The directory does not support the request. Alternatively, the directory is not currently in a state in which to complete your request. For example, the directory might be in read-only mode when your application requests a modification.

65
Object class violation. Your write request would cause an entry to no longer conform to the schema defined for the directory.

68
Already exists. Your application is requesting to add an entry that has the same DN as an entry already present in the directory.

RFC 4511 defines LDAP error codes.

Check Server Log Files

Directory Server logs messages related to server operation in its logs/errors file. If you have access to this file, you might find useful troubleshooting information there.

When debugging your application against Directory Server, you can adjust the log level, as well. See the server documentation for instructions.

Inspect Network Packets

Although LDAP is not a textual protocol, tools such as snoop, ethereal, and tcpdump can decode the packets, sometimes providing you with important debugging information.

About Directory SDK for C

This section introduces the LDAP C SDK.

Overview of Directory SDK for C

Directory SDK for C includes the C libraries for the LDAP API as well as sample code that demonstrates how to call many functions. The APIs are defined by the header files that declare all of the functions, data types, and code values in the SDK. You use the functions in this API to write C or C++ client applications that take full advantage of server capabilities.

The APIs are built around core functions of the LDAP v2 and v3 standards. Therefore, the APIs can be used to interact with any conforming LDAP server. This API conforms to the standard that is proposed in The C LDAP Application Programming Interface.

LDAP API

RFC 4511, Lightweight Directory Access Protocol (v3), defines a set of operations to access data in an LDAP v3 compliant directory server. The functionality implemented in Directory SDK for C closely follows these operations because a C API is defined for each operation.

  • Search for and retrieve a list of entries.
  • Add new entries to the database.
  • Update existing directory entries.
  • Delete entries.
  • Rename entries.

For example, if you are writing an email application, you can use the functions in the API to retrieve email addresses from an LDAP server.

Synchronous and Asynchronous Operations

The API functions allow you to perform LDAP operations synchronously or asynchronously. The only differences between these two options are in the calling convention. The LDAP exchanges are identical.

  • Call a synchronous function to wait for the operation to complete before receiving the return value of a function.
  • Call an asynchronous function to perform other work while waiting for an operation to complete. Your application must then poll for results.

For more information, see Synchronous Examples, and Asynchronous Examples. TODO LINKS

Files Provided With Directory SDK for C

Directory SDK for C includes a number of sample files, headers, libraries, and tools. This section helps you to locate the files. All locations are relative to the directory where the software is installed, which depends on your operating system.

Directory SDK for C Content
Directory Location
Description
etc/
Contains miscellaneous files for you to use.
examples/
Contains sample source code and Makefiles for LDAP clients. See the README file in this directory for more information.
include/
Contains the header files. You must include the files in this directory in your client source files.
include-nspr/
Contains Netscape Portable Runtime (NSPR) header files. NSPR provides a platform-neutral API for systemlevel and libcstyle functions.
include-private/
Contains private header files that are not documented in this guide.
lib/
Contains the C library files. The specific library used is dependent on the type of application you are building.
lib-private/
Contains private header files that are not documented in this guide.
tools/
Contains the LDAP command-line tools. To use these applications, you must ensure that the tools can find the LDAP API shared library or dynamic link library.

Directory SDK for C Header Files

The following table describes Directory SDK for C header files that are in the include/ directory.

Note: All locations are relative to the directory where the software is installed, which depends on your operating system.

Directory SDK for C Header Files
Header File
Description
disptmpl.h
A header file related to the templates (ldaptemplates.conf).
lber.h
Contains prototypes for the standard Basic Encoding Rules (BER) functions, structures, and defines.
ldap-deprecated.h
Contains deprecated functions that should not be used.
ldap-extension.h
Contains functions, structures, and defines that extend the standard LDAP C API specification.
ldap-platform.h
A private header file that contains platform-specific definitions, which allow abstraction from the underlying system.
ldap-standard.h
Contains the standard LDAP functions, structures, and defines.
ldap-to-be-deprecated.h
Contains functions, structures, and defines that might be deprecated in future releases.
ldap.h
This base header contains LDAP functions, structures, and defines to mirror the latest LDAP C API specifications. Includes: ldap-deprecated.h, ldap-extension.h, ldap-standard.h, ldap-to-be-deprecated.h
ldap_ssl.h
Contains prototypes for LDAP over SSL functions, structures, and defines.
ldappr.h
Contains prototypes for the functions, structures, and defines that are contained in the Netscape Portable Runtime (NSPR) API.
srchpref.h
A header file related to the search preferences (ldapsearchprefs.conf).
ldap.h Header File

To make use of the Directory SDK for C functions, include the ldap.h header file in your C source files as shown in this line of code:

#include "ldap.h"
lber.h Header File

lber.h is included in ldap-standard.h. You do not need to include the header explicitly. Basic Encoding Rules (BER) is a simple tag-value scheme to encode requests and decode results.

ldap_ssl.h Header File

If you are calling LDAP over SSL functions, you also need to include the ldap_ssl.h header file, as follows:

#include "ldap_ssl.h"
ldappr.h Header File

To make use of the Netscape Portable Runtime (NSPR) API with your LDAP applications, you must include the ldappr.h file. The NSPR is a set of platform-neutral APIs that provides system functions such as threads, thread synchronization, I/O, interval timing, and atomic operations. This header file contains prototypes for functions that tie the LDAP libraries to NSPR. You include the header file as follows:

#include "ldappr.h"

For more information about NSPR, see the ldappr.h header file and the Netscape Portable Runtime project page at http://www.mozilla.org/projects/nspr/.

Miscellaneous Files

Directory SDK for C includes the sample files described in the following table. Sample files can be retrieved when using certain APIs. Sample files are located in the etc/ directory. All locations are relative to the directory where the software is installed, which depends on your operating system.

Sample Configuration Files
File Name
Description
ldapfilter.conf
This filter configuration file can be used in context with ldap_init_getfilter().
ldapfriendly
This file is used to map the twoletter country codes to their full names by ldap_friendly_name().
ldapsearchprefs.conf
This configuration file was used in context with a deprecated function.
ldaptemplates.conf
This configuration file was used in context with a deprecated function.

Directory SDK for C Libraries

Directory SDK for C includes several different libraries. A library is a set of ready-made functions that are linked into a program. Directory SDK for C uses shared libraries. Shared libraries are dynamically loaded into memory when needed, reducing the size of the executable.

Library Naming Conventions

Libraries on different systems have different naming conventions. The following table shows the Directory SDK for C naming conventions.

Library Naming Convention by Operating System
Operating System
Static Library Name
Shared Library Name
Solaris and Red Hat systems
liblibraryname.a
liblibraryname.so.versionnumber
HP-UX systems
liblibraryname.a
liblibraryname.sl
Windows systems
nslibraryname.lib
nslibraryname.dll

On UNIX® systems, the shared library file name can be fully qualified by prefixing path information.

Installed Shared Libraries

The following table describes the installed libraries that are in the lib/ directory. All locations are relative to the directory where the software is installed, which depends on your operating system.

Shared Libraries
UNIX Library
Windows Library
Description
libldap60.so
nsldap32v60.dll
LDAP library
libprldap60.so
nsldappr32v60.dll
LDAP library built with NSPR.
This library requires the libnspr4.so library in the lib-private/ directory.
libssldap60.so
nsldapssl32v60.dll
LDAP library that is built with support for the Secure Sockets Layer protocol.
This library depends on the libnss3.so and libnspr4.so libraries in the lib-private/ directory.
Directory SDK for C Dependencies
  • Netscape Portable Runtime (NSPR) provides core cross-platform functions.
  • Netscape Security Services (NSS) provides encryption, cryptographic, Secure Sockets Layer (SSL), and Public Key Infrastructure (PKI) support.
  • Simple Authentication and Security Layer (SASL) provides support for applications that require SASL.

LDAP Tools

Directory SDK for C includes several utilities to help you work with LDAP data sets. These utilities are installed in the tools/ directory. For details on each tool described in the following table, see the corresponding man pages. A list of options can be retrieved by typing the tool name at the command line.

Directory SDK for C LDAP Tools
Command
Description
ldapcmp
Compares the contents of a single LDAP entry or subtree in two directories.
ldapcompare
Compares an attribute value against the contents of a given LDAP entry.
ldapdelete
Deletes existing LDAP entries.
ldapmodify
Edits the contents of an LDAP directory, either by adding new entries or modifying existing ones.
ldappasswd
Changes user passwords on LDAP entries.
ldapsearch
Issues search requests to an LDAP directory, then displays the result as LDAP Data Interchange Format (LDIF) text.

Compiling Applications with Directory SDK for C

When compiling applications, you must include the header files and link to the libraries required. Information about including the header files is in Directory SDK for C Header Files. Linking to shared libraries is covered in this section. Directory SDK for C is qualified to work with C compilers.

Note: Directory SDK for C is not guaranteed to work with C++ compilers.

Compiling on UNIX Platforms

When compiling clients on UNIX platforms, specify link options correctly to link the application to the appropriate shared libraries. See the Makefile in the examples/ directory for details on compiling your applications on UNIX platforms.

Compiling on Windows Systems With Directory SDK for C

  • _CONSOLE if you are writing a console application
  • _WINDOWS if you are writing a standard Windows GUI application

Linking Dependencies

When you run LDAP clients, you must ensure that the operating system can find the shared libraries that support the functions called by your application. Generally, these files are referred to as runtime libraries. Any of the following options ensure that the operating system can find the shared libraries.

  • Make sure that the shared library file, such as libldap60.so, is in a location specified by environment variables.
  • On some platforms, clients can be complied with flags that let you set the runtime path to load libraries as an environment variable.
    • On Solaris™ and Red Hat systems, you can use the LD_LIBRARY_PATH environment variable if you use the -Wl,+s+b flag when compiling and linking.
    • On HP-UX system, use the SHLIB_PATH environment variable.
    1. The directory from which the application loaded
    2. The current directory
    3. The Windows system directory, typically winnt\system32\
      To avoid potential conflicts, do not copy the DLL to this directory
    4. The directories listed in the PATH environment variable
  • Use a link flag that specifies the path where the executable can find the library. For example, on Solaris systems, you can use the -R flag to specify the path where the executable can find the library.
    See the Makefile in the examples/ directory for examples of additional settings for compiling and linking your LDAP client. Different platforms might require different sets of define statements.

Sample Programs for Directory SDK for C

Directory SDK for C includes several examples that demonstrate the use of the functions that the SDK provides. The examples are located in the examples/ directory. The example code is designed to run against the LDAP v3 compliant Directory Server. Furthermore, the example code is designed to work with sample data that has been properly loaded. For details on the source files, refer to the README in the examples/ directory.

The samples use synchronous LDAP calls and their asynchronous counterparts. Because synchronous LDAP calls are more straightforward than their asynchronous counterparts, look at the synchronous examples first.

Synchronous Examples

The synchronous calls block the calling process until all results have been returned. As these programs usually rely on event loops, the programs are not appropriate for use with clients that implement a GUI in a single-threaded environment. However, these sample programs do work with command-line clients and CGI programs.

Synchronous Example Programs
Example Source
Description
authzid.c
Shows how to use the authorization ID control, which allows you to get the authorization ID for an LDAP operation.
compare.c
Shows how to use ldap_compare_s(), which allows you to test if a particular value is contained in an attribute of an entry.
crtfilt.c
Shows how to use the ldap_create_filter() function to generate LDAP filters.
csearch.c
Like search.c, but enables an in-memory cache.
effright.c
Shows how to use the get effective rights control, which allows you to determine access rights to entries and their attributes.
getattrs.c
Retrieves specific attributes from an entry.
getfilt.c
Shows how to use the ldap_getfilter*() family of functions, which generate LDAP filters that are based on an arbitrary search string provided by a user.
modattrs.c
Shows how to use ldap_modify_s() to replace and add to values in an attribute.
modrdn.c
Shows how to use ldap_modrdn2_s() to change the relative distinguished name (RDN) of an entry.
pwdextop.c
Shows how to use the LDAP password modify extended operation to change a password.
pwdpolicy.c
Shows how to use the password policy control. This control allows you to retrieve information about the password policy that applies to the user binding to the directory.
rdentry.c
Shows how to use ldap_search_s() to retrieve a particular entry from the directory.
realattr.c
Shows how to use the control to retrieve only real attributes during a search.
search.c
Shows how to use ldap_search_s() to search for all entries that have an attribute value that exactly matches what you search for.
srvrsort.c
Shows how to use server-side sorting in conjunction with the ldap_search_ext_s() function.
ssearch.c
Like ssnoauth.c, but includes certificate-based authentication.
ssnoauth.c
Like search.c, but the search is done over an SSL-protected TCP connection.
starttls.c
Shows how to use the Start TLS extended operation.
userstatus.c
Shows how to use the account status control to retrieve information about the account of the user binding to the directory.
virtattr.c
Shows how to use the control to retrieve only virtual attributes during a search.
whoami.c
Shows how to use the Who am I? extended operation to retrieve the authorization ID.

Asynchronous Examples

These examples use the asynchronous LDAP calls. You begin an operation. You then periodically poll to see if any results have been returned.

Asynchronous Example Programs
Example Source
Description
add.c
Adds an entry to the directory.
asearch.c
Initiates a search for entries, printing the results on arrival.
del.c
Deletes an entry from the directory.
nsprio.c
Like asearch. but uses the PerLDAP routines to incorporate the Netscape Portable Runtime (NSPR) API.
ppolicy.c
Attempts to bind to the directory and reports back any password expiration information received. This program demonstrates how clients can process password policy information.
psearch.c
Shows how to use Persistent Search, an LDAP v3 extension, to monitor a directory for changes.

Getting Started With Directory SDK for C

This section shows how to create a first client application.

Sample Directory Client Code

The following sample source code is for a command-line program that retrieves the full name, last name, email address, and telephone number of Barbara Jensen.

#include <stdio.h>
#include "ldap.h"

/* Adjust these setting for your own LDAP server */
#define HOSTNAME "localhost"
#define PORT_NUMBER  LDAP_PORT
#define FIND_DN "uid=bjensen,ou=People,dc=example,dc=com"

int
main( int argc, char **argv )
{
  LDAP         *ld;
  LDAPMessage  *result, *e;
  BerElement   *ber;
  char         *a;
  char         **vals;
  int          i, rc;

  /* Get a handle to an LDAP connection. */
  /* To get the handle on an IPv6 network, use prldap_init() instead. */
  if ( (ld = ldap_init( HOSTNAME, PORT_NUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }

  /* Bind anonymously to the LDAP server. */
  rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc != LDAP_SUCCESS ) {
    fprintf(stderr, "ldap_simple_bind_s: %s\n", ldap_err2string(rc));
    return( 1 );
  }

  /* Search for the entry. */
  if ( ( rc = ldap_search_ext_s( ld, FIND_DN, LDAP_SCOPE_BASE,
    "(objectclass=*)", NULL, 0, NULL, NULL, LDAP_NO_LIMIT,
    LDAP_NO_LIMIT, &result ) ) != LDAP_SUCCESS ) {
    fprintf(stderr, "ldap_search_ext_s: %s\n", ldap_err2string(rc));
    return( 1 );
  }

  /* Since we are doing a base search, there should be only
     one matching entry.  */
  e = ldap_first_entry( ld, result );
  if ( e != NULL ) {
    printf( "\nFound %s:\n\n", FIND_DN );

    /* Iterate through each attribute in the entry. */
    for ( a = ldap_first_attribute( ld, e, &ber );
      a != NULL; a = ldap_next_attribute( ld, e, ber ) ) {

      /* For each attribute, print the attribute name and values. */
      if ((vals = ldap_get_values( ld, e, a)) != NULL ) {
        for ( i = 0; vals[i] != NULL; i++ ) {
          printf( "%s: %s\n", a, vals[i] );
        }
        ldap_value_free( vals );
      }
      ldap_memfree( a );
    }
    if ( ber != NULL ) {
      ber_free( ber, 0 );
    }
  }
  ldap_msgfree( result );
  ldap_unbind( ld );
  return( 0 );
}

Compiling Directory SDK for C Client Applications

The method used to compile the source code depends on the operating system on which you run the application. The following sections include instructions for compiling on UNIX and Windows systems.

Compiling Programs on UNIX Systems

The Directory SDK for C examples/ directory contains a UNIX Makefile. You can modify the Makefile to compile the sample by adjusting the flags in the file. The Makefile assumes that the Directory SDK for C header files are located in the ../include/ directory.

Compiling Programs on Windows Systems

  • If you are using Microsoft development tools, create a new project workspace for a console application. Then add the source file to the project.
  • Set your options to include lib\ as one of the directories for library files, and include\ as one of the directories for include files.
  • Link to nsldap32v60.lib, the LDAP API import library for Windows.

Running the Client

Before running the sample client, make sure that your LDAP server is set up with the entry the sample attempts to find. Unless you change the source code in Example 51, the entry would be for the full name, last name, email address, and telephone number of Barbara Jensen.

Running Programs on UNIX Systems

If you have linked the client on a UNIX platform, the client requires the SDK library file. Make sure to set your LD_LIBRARY_PATH to locate the libldap60.so library file and its dependencies.

As an alternative, when linking the file, specify the option that identifies the library directories that the runtime linker should search for. For example, on Solaris systems use the -R option to specify the location of the libldap60.so file.

Running Programs on Windows Systems

If you have linked the client with the nsldap32v60.lib library on a Windows system, copy the Directory SDK for C DLL files to one of the following directories:

  • The directory where the application was loaded
  • The current directory
  • The Windows system directory, such as winnt\system32\
  • The Windows directory
  • The directories listed in the PATH environment variable

What's New In Directory SDK for C

This section compares the current version of Directory SDK for C API with the previous version.

Deprecated and Changed Directory SDK for C Features

This section covers the following changes and deprecated features in this release. Where possible, Directory SDK for C provides replacement features for deprecated features.

liblber API

The Basic Encoding Rules library, liblber, changed for portability reasons and to comply with The C LDAP Application Program Interface Internet draft. In particular, according to section 17.1., BER Data Structures and Types, the following structures have changed.

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

typedef <impl_tag_t> ber_tag_t;     /* for BER tags */
typedef <impl_int_t> ber_int_t;     /* for BER ints, enums, and Booleans */
typedef <impl_unit_t> ber_uint_t;   /* unsigned equivalent of ber_uint_t */
typedef <impl_slen_t> ber_slen_t;   /* signed equivalent of ber_len_t */

Note that the actual definition for these four integral types is imple-
mentation specific; that is, `<impl_tag_t>', `<impl_int_t>',
`<impl_uint_t>', and `<impl_slen_t>' MUST each be replaced with an
appropriate implementation-specific type.

Programs that do not use the liblber API directly need not be changed. You can continue to build and use those applications as before.

If, however, your programs call the liblber API directly, you must change your application code to reflect the type definitions in include/lber.h. Compilers typically issue type mismatch warnings when compiling old code that has not been fixed.

File Layout

The file layout has changed. All files are unpacked in a base directory that is named according to the platform and to the operating system of the binary distribution. The file layout is covered in the section on Files Provided With Directory SDK for C.

IPv6 Support

IPv6 support is provided by means of the NSPR library. Therefore, to use LDAP over IPv6, use prldap_init instead of ldap_init.

NSS and NSPR Version Updates

This version of Directory SDK for C uses NSS 3.11and NSPR 4.6. Both components are included in binary form for your convenience.

NSS Security Tools

NSS security tools, used to maintain NSS databases so your application can do LDAP over SSL, are not delivered with Directory SDK for C.

For access to NSS security tools, refer to the NSS security tools project.

New Directory SDK for C Features

This section covers additional features provided in this release.

LDAP Version 3 Default

Directory SDK for C now uses LDAP v3 by default. You can therefore use LDAP v3 features in your applications even if you do not specifically set the version to 3.

Supported Controls

This version of Directory SDK for C adds support for developing client applications, including more than 10 LDAP v3 controls.

For instructions on using controls supported by Directory SDK for C, see LDAP Controls With Directory SDK for C.

Supported Extended Operations

This version of Directory SDK for C adds support for developing client applications that use the following extended operations.

LDAP Password Modify Extended Operation

The LDAP Password Modify extended operation lets your client application modify a user password through LDAP. A user can modify his password even if the password is not stored as an attribute in the directory, the user is not identified by a DN, or the user does not have an entry in the directory. The LDAP Password Modify extended operation is defined in RFC 3062.

The extended operation has identifier 1.3.6.1.4.1.4203.1.11.1.

Start TLS Extended Operation

The Start TLS extended operation lets your client application connect to a nonsecure port, and then request transport layer security.

The extended operation has identifier 1.3.6.1.4.1.1466.20037.

Who Am I? Extended Operation

The “Who am I?” extended operation lets your client application determine the authorization identity that the server currently associates with your client.

The extended operation has identifier 1.3.6.1.4.1.4203.1.11.3.

For instructions on using extended operations supported by Directory SDK For C, see Extended Operations With Directory SDK for C.

Additional Directory SDK for C Examples

More sample code is provided in the examples/ directory. The additional samples demonstrate newly supported controls and extended operations.

Writing an LDAP Client With Directory SDK for C

With Directory SDK for C, you can write a new application. You can also enable an existing application to interact with a Lightweight Directory Access Protocol (LDAP) server. This chapter explains how to connect to an LDAP server, authenticate, request operations, and disconnect from the server.

Designing an LDAP Client With Directory SDK for C

The following procedure outlines a typical process for communicating with an LDAP server.

To Communicate With an LDAP Server

  1. Initialize an LDAP session.
    See Initializing an LDAP Session With Directory SDK for C for details.
  2. Bind to the LDAP server, if necessary.
    See Binding and Authenticating to an LDAP Server With Directory SDK for C for details.
  3. Perform LDAP operations, such as searching the directory or modifying entries in the directory.
    See Performing LDAP Operations With Directory SDK for C for details.
  4. Close the connection to the LDAP server when finished.
    See Closing the Connection to an LDAP Server With Directory SDK for C for details.

This sample source code shows a client that requests an LDAP search operation from a server. The LDAP server runs on the local system on port 389. The client searches the directory for entries with the last name Jensen (sn=Jensen), and prints the distinguished name (DN) of any matching entry.

#include <stdio.h>
#include "ldap.h"

/* Specify the search criteria here. */
#define HOSTNAME "localhost"
#define PORTNUMBER 389
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"

int
main( int argc, char **argv )
{
  LDAP          *ld;
  LDAPMessage   *result, *e;
  char          *dn;
  int           version, rc;
  /* Print out an informational message. */
  printf( "Connecting to host %s at port %d...\n\n", HOSTNAME,
    PORTNUMBER );

  /* STEP 1: Get a handle to an LDAP connection and
    set any session preferences. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }

  /* Use the LDAP_OPT_PROTOCOL_VERSION session preference to specify
    that the client is an LDAPv3 client. */
  version = LDAP_VERSION3;
  ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );

  /* STEP 2: Bind to the server.
    In this example, the client binds anonymously to the server
    (no DN or credentials are specified). */
  rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc != LDAP_SUCCESS ) {
    fprintf(stderr, "ldap_simple_bind_s: %s\n", ldap_err2string(rc));
    return( 1 );
  }

  /* Print out an informational message. */
  printf( "Searching the directory for entries\n"
    " starting from the base DN %s\n"
    " within the scope %d\n"
    " matching the search filter %s...\n\n",
    BASEDN, SCOPE, FILTER );

  /* STEP 3: Perform the LDAP operations.
    In this example, a simple search operation is performed.
    The client iterates through each of the entries returned and
    prints out the DN of each entry. */
  rc = ldap_search_ext_s( ld, BASEDN, SCOPE, FILTER, NULL, 0,
    NULL, NULL, NULL, 0, &result );
  if ( rc != LDAP_SUCCESS ) {
    fprintf(stderr, "ldap_search_ext_s: %s\n", ldap_err2string(rc));
    return( 1 );
  }
  for ( e = ldap_first_entry( ld, result ); e != NULL;
      e = ldap_next_entry( ld, e ) ) {
    if ( (dn = ldap_get_dn( ld, e )) != NULL ) {
      printf( "dn: %s\n", dn );
      ldap_memfree( dn );
    }
  }
  ldap_msgfree( result );

  /* STEP 4: Disconnect from the server. */
  ldap_unbind( ld );
  return( 0 );
}
...

Initializing an LDAP Session With Directory SDK for C

Before connecting to an LDAP server, you must initialize a session. As part of this process, you create an LDAP structure that contains information about the LDAP server and session. You then pass this LDAP structure, usually as a pointer, to all subsequent functions in order to identify the LDAP server with which you are working. Sample code for initializing an LDAP session is provided in Example Session Initialization.

Note: If you plan to connect to the LDAP server over the Secure Sockets Layer (SSL) protocol, the procedure for initializing an LDAP session is different. For details, see SSL Connections With Directory SDK for C.

Specifying a Single LDAP Server

To initialize an LDAP session, call ldap_init(), or prldap_init() for IPv6 support, with the host name and port number of the LDAP server. If the server is using the default port 389 for the LDAP server, pass LDAP_PORT as the value for the defport parameter as shown here.

...
LDAP *ld
...
ld = ldap_init( "directory.example.com", LDAP_PORT );

If successful, ldap_init(), or prldap_init(), returns a connection handle to the LDAP server. A connection handle is a pointer to the LDAP structure that contains information about the connection. You must pass this pointer to the API for connecting, authenticating, and performing LDAP operations on a server. For example, when you search the directory, you pass the connection handle as a parameter to provide a context for the connection.

Note: The initialization function does not open a connection to the LDAP server. The actual opening of a connection occurs when the first operation is attempted.

Specifying a List of LDAP Servers

When initializing the LDAP session, you can also specify a list of LDAP servers for which you want to attempt connections. If the first LDAP server in the list does not respond, the client attempts to connect to the next server in the list. To specify a list of LDAP servers, pass a space-delimited list of the host names as the first argument to the ldap_init() or prldap_init() function. In the following example, the LDAP client attempts to connect to the LDAP server on ld1.example.com, port 389. If that server does not respond, the client attempts to connect to the LDAP server on ld2.example2.com, port 389. If that server does not respond, the client uses the server on ld3.example.com, port 389.

...
LDAP *ld
...
ld = ldap_init( "ld1.example.com ld2.example2.com
  ld3.example.com", LDAP_PORT );

If any servers do not use the default LDAP port, use the host:port format to specify the server name and port number. In the following example, that means ld1.example.com, port 389. If that server does not respond, the client attempts to connect to the LDAP server on ld2.example.com, port 1389.

...
LDAP *ld
...
ld = ldap_init( "ld1.example.com ld2.example.com:1389",
   LDAP_PORT );

Example Session Initialization

The following example initializes a session with an LDAP server, specifying a list of LDAP servers to try: ldap.example.com:389 and directory.example.com:1389. The example also sets a session preference that identifies the client as an LDAP v3 client. This session initialization code uses the prldap_init function, which works on IPv6 networks. Notice that prldap_init does not connect to the LDAP server right away.

After you initialize a session with an LDAP server, you can set session preferences. For information, see Setting Session Preferences With Directory SDK for C.

#include <stdio.h>
#include "ldappr.h"
#include "ldap.h"
...
LDAP *ld;
int ldap_default_port, version;

/* Specify list of LDAP servers that you want to try connecting to. */
char *ldap_host = "ldap.example.com directory.example.com:1389";

/* If the LDAP server is running on the standard LDAP port (port 389),
 * you can use LDAP_PORT to identify the port number. */
ldap_default_port = LDAP_PORT;
...
/* Initialize the session with the LDAP servers. */
if ( ( ld = prldap_init( ldap_host, ldap_default_port, NULL ) ) == NULL ) {
  perror( "prldap_init" );
  return( 1 );
}

/* Specify the LDAP version supported by the client. */
version = LDAP_VERSION3;
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );

...
/* Subsequent calls pass ld as argument to identify the LDAP server. */

...

Setting Session Preferences With Directory SDK for C

With Directory SDK for C, you can set preferences for your client that you want applied to all LDAP sessions. To get or set the value of a preference, call the ldap_get_option() or ldap_set_option() functions respectively.

  • The option parameter identifies the option that you want to get or set.
  • The value parameter is either a pointer to a place to put the value to get, or a pointer to the value to set.

You can set a preference for all connections by passing NULL as the first argument, not an LDAP structure that specifies the connection.

Reconnecting Automatically

If communication with the LDAP server is interrupted, the server returns LDAP_SERVER_DOWN. If you want your client to continue to attempt communication with the server, you can set the LDAP_OPT_RECONNECT preference for the session. Once set, if your connection is lost, the client attempts another bind with the same authentication to reestablish the connection.

The following example shows that to set the reconnect preference, call the ldap_set_option() function and pass LDAP_OPT_RECONNECT as the value of the option parameter. To resume LDAP I/O operations automatically, set the optdata parameter to LDAP_OPT_ON. This setting specifies the same connection handle that can be used to reconnect to the server.

ldap_set_option( ld, LDAP_OPT_RECONNECT, LDAP_OPT_ON );

To avoid resuming I/O operations, you would set the optdata parameter to LDAP_OPT_OFF. This setting specifies that you want to create a new connection handle to connect to the server. By default, the optdata parameter is set to LDAP_OPT_OFF. Both LDAP_OPT_OFF and LDAP_OPT_ON are cast to (void *).

Specifying the LDAP Version of Your Client

If you plan to call functions that use LDAP v3 features such as controls or extended operations, set the protocol version to LDAP v3. By default, clients built with Directory SDK for C identify themselves to LDAP servers as LDAP v3 clients, but that was not the case with previous versions.

To specify the LDAP version supported by your client, call the ldap_set_option() function and set the LDAP_OPT_PROTOCOL_VERSION option to the value 3.

...
version = LDAP_VERSION3;
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );
...

After setting this option, as part of the authentication process, your client sends the supported LDAP version number to the server. By setting the version, you allow the server to determine whether or not to enable LDAP v3 features.

LDAP v3 allows you to perform LDAP operations without first binding to the server. An LDAP v3 server assumes that the client is LDAP v3 compliant if the client issues non-bind operations before the client issues a bind.

Setting Connection Timeout

Clients that use Directory SDK for C can control the TCP/IP level timeout. When the TCP/IP timeout option is not set, an attempt to connect to a server blocks until the connection completes or the system times out. By using the LDAP_X_OPT_CONNECT_TIMEOUT option, you can adjust how long to wait for a connection.

You specify the timeout as an int number of milliseconds, then call the ldap_set_option() function, passing the LDAP_X_OPT_CONNECT_TIMEOUT option.

The following example sets the connection timeout to one second.

int timeout = 1000; /* 1000 milliseconds == 1 second */
ldap_set_option( ld, LDAP_X_OPT_CONNECT_TIMEOUT, timeout );
  • LDAP_X_IO_TIMEOUT_NO_WAIT
    Return immediately if the server cannot be reached.
  • LDAP_X_IO_TIMEOUT_NO_TIMEOUT
    Wait indefinitely for the server to connect.

By passing NULL as the first parameter to the ldap_set_option() function, you can set the default timeout for all connections used by your application.

Binding and Authenticating to an LDAP Server With Directory SDK for C

When connecting to the LDAP server, your client might need to send a bind request.

  • You want to authenticate to the server to add or modify entries in a directory that requires authentication as a user with certain access privileges.
  • You are connecting to an LDAP v2 server. LDAP v2 servers typically require clients to bind before any operations can be performed.
  • LDAP version of the client
  • Method of authentication to use
  • DN that the client is attempting to authenticate as
  • Credentials to be used for authentication

LDAP clients can also bind anonymously to the LDAP server if, for example, the server is configured not to require authentication for a simple directory search.

Using Simple Authentication With Directory SDK for C

  • ldap_simple_bind_s() is a synchronous function for use if you want to wait for the bind operation to complete before the function returns.
  • ldap_simple_bind() is an asynchronous function for use if you do not want to wait for the bind operation to complete. With this function, you can perform other work while periodically checking for the results of the bind operation.

For more information about the differences between the types of functions, see Synchronous and Asynchronous Functions.

Performing a Synchronous Authentication Operation

If you want to wait for the bind operation to complete before continuing, call ldap_simple_bind_s(). This function returns LDAP_SUCCESS if the operation completed successfully, or an LDAP result code if a problem occurred. See ldap_simple_bind_s() in ldap_simple_bind_s() for a list of result codes returned.

If you specify a DN but no password, your client binds to the server anonymously. If you want a NULL password to be rejected as incorrect, you must write code to perform the check before you call ldap_simple_bind_s().

The following example uses the synchronous ldap_simple_bind_s() function to authenticate user Barbara Jensen to the LDAP server.

<#include stdio.h>
#include "ldap.h"

/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define BIND_PW "hifalutin"

LDAP      *ld;
int      rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
}

/* Print out an informational message. */
printf( "Binding to server %s:%d\n", HOSTNAME, PORTNUMBER );
printf( "as the DN %s ...\n", BIND_DN );

/* Bind to the LDAP server. */
rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
if ( rc != LDAP_SUCCESS ) {
  fprintf(stderr, "ldap_simple_bind_s: %s\n\n", ldap_err2string(rc));
  return( 1 );
} else {
  printf( "Bind operation successful.\n" );
}

...
/* If you want, you can perform LDAP operations here. */
...

/* Disconnect from the server when done. */
ldap_unbind( ld );
return( 0 );
...
Performing an Asynchronous Authentication Operation

If you want to perform other work in parallel while waiting for the bind operation to complete, call ldap_simple_bind(). This function sends an LDAP bind request to the server and returns a message ID identifying the bind operation. To see if your client has received the results of the bind operation, call the ldap_result() function with the message ID. If your client has received the results, ldap_result() passes back the information in an LDAPMessage structure. To retrieve error information from LDAPMessage, you can pass the message ID to the ldap_parse_result() function. ldap_parse_result() gets the LDAP result code of the operation and any error messages sent back from the server. This function also retrieves any controls sent back.

If you specify a DN but no password, your client binds to the server anonymously. If you want a NULL password to be rejected as incorrect, you need to write code to perform the check before you call ldap_simple_bind().

The following example uses the asynchronous ldap_simple_bind function() to authenticate user Barbara Jensen to the LDAP server.

#include <stdio.h>
#include "ldap.h"

void do_other_work();
int global_counter = 0;
...

#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define BIND_PW "hifalutin"

...
LDAP            *ld;
LDAPMessage     *res;
int             msgid = 0, rc = 0, parse_rc = 0, finished = 0;
char            *matched_msg = NULL, *error_msg = NULL;
char            **referrals;
LDAPControl     **serverctrls;
struct timeval  zerotime;

/* Specify the timeout period for ldap_result(),
   which specifies how long the function should block when waiting
   for results from the server. */
zerotime.tv_sec = zerotime.tv_usec = 0L;

/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}

/* Print out an informational message. */
printf( "Binding to server %s:%d\n", HOSTNAME, PORTNUMBER );
printf( "as the DN %s ...\n", BIND_DN );

/* Send an LDAP bind request to the server. */
msgid = ldap_simple_bind( ld, BIND_DN, BIND_PW );

/* If the returned message ID is less than zero, an error occurred. */
if ( msgid  0  ) {
  rc = ldap_get_lderrno( ld, NULL, NULL );
  fprintf(stderr, "ldap_simple_bind : %s\n", ldap_err2string(rc));
  ldap_unbind( ld );
  return( 1 );
}

/* Check to see if the bind operation completed. */
while ( !finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  /* If ldap_result() returns -1, error occurred. */
  case -1:
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return ( 1 );

    /* If ldap_result() returns 0, the timeout (specified by the
      timeout argument) has been exceeded before the client received
      the results from the server. Continue calling ldap_result()
      to poll for results from the server. */
  case 0:
    break;

  default:
    /* The client has received the result of the bind operation. */
    finished = 1;

    /* Parse this result to determine if the operation was successful.
      Note that a non-zero value is passed as the last parameter,
      which indicates that the LDAPMessage structure res should be
      freed when done.  (No need to call ldap_msgfree().) */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result: %s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }
    /* Check the results of the operation. */
    if ( rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_simple_bind: %s\n",
        ldap_err2string( rc ) );

      /* If the server sent an additional error message,
        print it out. */
      if ( error_msg != NULL  *error_msg != '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }

      /* If an entry specified by a DN could not be found,
        the server may also return the portion of the DN
        that identifies an existing entry. */
      if ( matched_msg != NULL  *matched_msg != '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry: %s\n",
          matched_msg );
      }
      ldap_unbind( ld );
      return( 1 );
    } else {
      printf( "Bind operation successful.\n" );
      printf( "Counted to %d while waiting for bind op.\n",
        global_counter );
    }
    break;
  }
  /* Do other work here while waiting for results from the server. */
  if ( !finished ) {
    do_other_work();
  }
}

...
/* If you want, you can perform LDAP operations here. */
...

/* Disconnect from the server when done. */
ldap_unbind( ld );
return( 0 );
...
/* Function that does work while waiting for results from the server. */
void do_other_work() {
  global_counter++;
}
...
Binding Anonymously With Directory SDK for C

In some cases, you do not need to authenticate to the LDAP server. For example, if users are performing a search that has no special access permissions, you need not authenticate before performing the search. To bind as an anonymous user, call ldap_simple_bind() or ldap_simple_bind_s(), and pass NULL values for the who and passwd parameters.

rc = ldap_simple_bind_s( ld, NULL, NULL );

With LDAP v2, the client is required to send a bind request, even when binding anonymously. That is, bind without specifying a name or password. With LDAP v3, the client is no longer required to bind to the server if the client does not need to authenticate.

Performing LDAP Operations With Directory SDK for C

After initializing a session with a server and completing the authentication process, you can perform LDAP operations. The LDAP operations include searching the directory, adding new entries, updating existing entries, and removing entries. The following lists LDAP operations and the functions that you can call to perform the operations.

Functions for Performing LDAP Operations
To Perform This Operation
Call This API Function
Search for entries
ldap_search_ext(), ldap_search_ext_s()
Determine an attribute value
ldap_compare_ext(), ldap_compare_ext_s()
Add entries
ldap_add_ext(), ldap_add_ext_s()
Modify entries
ldap_modify_ext(), ldap_modify_ext_s()
Delete entries
ldap_delete_ext(), ldap_delete_ext_s()
Change DN of entries
ldap_rename_ext(), ldap_rename_ext_s()

Most LDAP operations can be performed synchronously or asynchronously. The functions with names that end in _s are synchronous. The remaining ones are asynchronous. For more information about the distinction between the functions, see Synchronous and Asynchronous Operations.

Closing the Connection to an LDAP Server With Directory SDK for C

When you have finished performing all necessary LDAP operations, you need to close the connection to the LDAP server. After you close the connection, you can no longer use the LDAP structure because the structure is freed from memory.

  • ldap_unbind()
  • ldap_unbind_s()
  • ldap_unbind_ext()

Both ldap_unbind() and ldap_unbind_s() are identical synchronous functions. These functions use different names so that each function has a corresponding authentication function, ldap_simple_bind() and ldap_simple_bind_s(), to close the server connection.

The ldap_unbind_ext() function allows you to include explicitly both server and client controls in your unbind request. However, as the server does not respond to an unbind request, you cannot receive a response from a server control attached to your unbind request.

The following example closes the current connection with the LDAP server.

#include <stdio.h>
#include "ldap.h"
...
LDAP      *ld;
int      rc;
...
/* After completing your LDAP operations with the server, close
  the connection. */
rc = ldap_unbind( ld );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_unbind: %s\n", ldap_err2string( rc ) );
}
...

Using the LDAP C API

This section covers features of the LDAP C API to use when writing an LDAP client application with Directory SDK for C.

Synchronous and Asynchronous Functions

You can perform most operations with synchronous or with asynchronous functions. For example, to search the directory, you can call either the synchronous ldap_search_ext_s() function or the asynchronous ldap_search_ext() function. In general, all synchronous functions have names that end with _s.

The difference between the synchronous and asynchronous functions is the calling convention. The LDAP exchanges are identical.

Calling Synchronous Functions

When you call a synchronous function, your client waits for the operation to complete before executing any subsequent lines of code. Synchronous functions return LDAP_SUCCESS when they are successful. Synchronous functions return an LDAP error code when they are not successful. The following example deletes the entry in the directory.

#include <stdio.h>
#include "ldap.h"
...
LDAP      *ld;
char      *matched_msg = NULL, *error_msg = NULL;
int        rc;
...
/* Perform an LDAP delete operation. */
rc = ldap_delete_ext_s( ld, DELETE_DN, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_delete_ext_s: %s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg != NULL  *error_msg != '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }

  /* If the server cannot find an entry with the specified DN,
     it may send back the portion of the DN that matches an
     existing entry.*/
  if ( matched_msg != NULL  *matched_msg != '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry: %s\n",
      matched_msg );
  }
} else {
  printf( "%s deleted successfully.\n", DELETE_DN );
}
...

To see other sample programs that call synchronous functions, view the source files in the examples/ directory.

Calling Asynchronous Functions

When you call an asynchronous function, your client does not need to wait for the operation to complete. The client can continue performing other tasks, such as initiating other LDAP operations, while the asynchronous operation is executing. An asynchronous function passes back a unique message ID to identify the operation being performed. You can pass this message ID to the ldap_result() function to check the status of the operation. The following sections explain how to call an asynchronous function and how to check the results of the operation. To see other sample programs that call asynchronous functions, view the source files in the examples/ directory.

Verifying that an LDAP Request Was Sent

Asynchronous functions return an LDAP result code indicating whether or not the LDAP request was successfully sent to the server. If the function returns LDAP_SUCCESS, the function has successfully sent the request to the server. The following example sends an LDAP delete request to the server and checks if the result was sent successfully. The example uses the asynchronous ldap_delete_ext() function.

#include <stdio.h>
#include "ldap.h"
...
/* Change these as needed. */
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
...
LDAP       *ld;
int        rc, msgid;
...
/* Send an LDAP delete request to the server. */
rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, msgid );
if ( rc != LDAP_SUCCESS ) {
  /* If the request was not sent successfully,
    print an error message and return. */
  fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
...
Retrieving the Server Response

If the request was sent successfully, the function passes the message ID of the LDAP operation back to the client. Use the message ID to determine if the server has sent back results for this operation. Call ldap_result(), passing the message ID as a parameter.

  • -1 indicates that an error occurred.
  • 0 indicates that the timeout period has been exceeded and that the server has not yet sent a response back to your client.
  • Any other value indicates that the server has sent a response for the requested operation back to your client. The ldap_result() parameter passes back a pointer to an LDAPMessage structure.
    • An LDAP result code that specifies the result of the operation you requested
    • An additional error message sent back from the server
      This information is optional.
    • If the server cannot find the entry specified by a DN, the portion that identifies an existing entry.
    • A set of referrals, if the servers directory does not contain the requested entries
      The server must be configured to return referrals.
    • A set of server response controls that apply to the operation you requested

You can specify a timeout period to wait for results from the server.

Polling Loop

You can set up a loop to poll for results while doing other work. The following example defines a function that does other work while waiting for the server to send a response back to your client.

int global_counter = 0;
void do_other_work()
{
  global_counter++;
}
while Loop

This example sets up a while() loop to call your function when you are not checking for the servers response.

#include <stdio.h>
#include "ldap.h"
...
LDAP              *ld;
LDAPMessage       *res;
LDAPControl       **serverctrls;
char              *matched_msg = NULL, *error_msg = NULL;
char              **referrals;
int               rc, parse_rc, msgid, finished = 0;
struct timeval    zerotime;

zerotime.tv_sec = zerotime.tv_usec = 0L;
...
/* Send an LDAP delete request to the server. */
rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, msgid );
...
/* Poll the server for the results of the LDAP operation. */
while ( !finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );

  /* Check to see if a result was received. */
  switch ( rc ) {
  case -1:
    .../* An error occurred. */...
  case 0:
    /* The timeout period specified by zerotime was exceeded, meaning
       the server has still not yet sent the results of the delete
       operation back to the client. Break out of this switch statement,
       and continue calling ldap_result() to poll for results. */
  default:
    finished = 1;
    .../* Your client received a response from the server. */...
  }

  /* Do other work while waiting. This is called if ldap_result()
     returns 0 (before you continue to top of the loop and call
     ldap_result() again). */
  if ( !finished ) {
    do_other_work();
  }
  ...
}
...
Getting Information From a Server Response

To get information from the server response, call ldap_parse_result() as shown here.

LDAP_API(int) LDAP_CALL
ldap_parse_result( LDAP *ld, LDAPMessage *res, int *errcodep,
  char **matcheddnp, char **errmsgp, char ***referralsp,
  LDAPControl ***serverctrlsp, int freeit );
  • errcodep holds the LDAP result code of the operation that the server finished processing.
  • errmsgp is an additional error message that the server can send to your client.
  • matcheddnp is the portion of the DN that matches an existing entry. The portion of the DN is used when the server is not able to find an entry for the DN that you specified.
  • referralsp is a set of referrals sent back to your client. The set of referrals is sent if you requested an entry that is not part of the DIT managed by the server. The server must be configured to refer clients to other LDAP servers.
  • serverctrlsp is a set of server response controls that apply to the operation.

When processing LDAP search operations, the server can send back individual entries, individual search references, chains of entries, and chains of search references.

The following example retrieves error information from an LDAPMessage structure returned by ldap_result().

#include <stdio.h>
#include "ldap.h"
...
LDAP              *ld;
LDAPMessage       *res;
LDAPControl       **serverctrls;
char              *matched_msg = NULL, *error_msg = NULL;
char              **referrals;
int               rc, parse_rc, msgid, finished = 0;
struct timeval    zerotime;

zerotime.tv_sec = zerotime.tv_usec = 0L;
...
rc = ldap_result( ld, msgid, 0, zerotime, res );

/* Check to see if a result was received. */
switch ( rc ) {
case -1:
  ...
case 0:
  ...
default:
  ...
  /* Call ldap_parse_result() to get information from the results
    received from the server. */
  parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
    error_msg, referrals, serverctrls, 1 );

  /* Make sure the results were parsed successfully. */
  if ( parse_rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_parse_result: %s\n",
      ldap_err2string( parse_rc ) );
    ldap_unbind( ld );
    return( 1 );
  }

  /* Check the results of the LDAP operation. */
  if ( rc != LDAP_SUCCESS ) {
    fprintf(stderr, "Error: %s\n", ldap_err2string(rc));
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    /* If the server returned the portion of the DN
      that identifies an existing entry, print it out. */
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
  } else {
    printf( "Operation completed successfully" );
  }
}
...
Freeing an LDAPMessage Structure

When you are done, call ldap_msgfree() to free the LDAPMessage structure unless the structure is part of a chain of results. The result code returned by this function is not the same as the result code of the operation, errcodep. This operation returns a result code that indicates the type of operation to which the freed LDAPMessage structure is a response.

If you pass a non-zero value for the freeit parameter of ldap_result(), the structure is automatically freed after the information is retrieved.

Canceling an Operation in Progress

If you need to cancel an LDAP operation, call ldap_abandon_ext(). The function returns LDAP_SUCCESS if successful, or an LDAP result code if an error occurs. After you cancel an operation, you cannot retrieve the results of that operation. Thus, calling ldap_result() does not return any results.

Sample Code to Call an Asynchronous Function

The following example calls ldap_delete_ext() to delete an entry in the directory, and ldap_result() within a loop to poll the results of the delete.

#include <stdio.h>
#include "ldap.h"
...
void do_other_work();
int global_counter = 0;
...
/* Change these as needed. */
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
...
LDAP              *ld;
LDAPMessage       *res;
LDAPControl       **serverctrls;
char              *matched_msg = NULL, *error_msg = NULL;
char              **referrals;
int               rc, parse_rc, msgid, finished = 0;
struct timeval    zerotime;

zerotime.tv_sec = zerotime.tv_usec = 0L;
...
/* Send an LDAP delete request to the server. */
rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, msgid );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}

/* Poll the server for the results of the delete operation. */
while ( !finished ) {
  /* Call ldap_result() to get the results of the delete operation.
    ldap_result() blocks for the time specified by the timeout argument
    (set to zerotime here) while waiting for the result from the server. */
  rc = ldap_result( ld, msgid, 0, zerotime, res );

  /* Check to see if a result was received. */
  switch ( rc ) {
  case -1:
    /* If ldap_result() returned -1, an error occurred. */
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );

  case 0:
    /* The timeout period specified by zerotime was exceeded, meaning
       the server has still not yet sent the results of the delete
       operation back to the client. Break out of this switch statement,
       and continue calling ldap_result() to poll for results. */
    break;

  default:
    /* ldap_result() got the results of the delete operation
      from the server. No need to keep polling. */
    finished = 1;

    /* Call ldap_parse_result() to get information from the results
      received from the server. Note the last argument is a non-zero
      value. This means after the function retrieves information from
      the LDAPMessage structure, the structure is freed.
      (You do not need to call ldap_msgfree() to free the structure.)*/
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result: %s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }

    /* Check the results of the LDAP delete operation. */
    if ( rc != LDAP_SUCCESS ) {
      fprintf(stderr, "ldap_delete_ext: %s\n", ldap_err2string(rc));
      if ( error_msg != NULL  *error_msg != '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      /* Print the portion of a specified DN that matches an
         existing entry, if returned by the server. */
      if ( matched_msg != NULL  *matched_msg != '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry: %s\n",
          matched_msg );
      }
    } else {
      printf( "%s deleted successfully.\n"
        "Counted to %d while waiting for the delete operation.\n",
        DELETE_DN, global_counter );
    }
  }

  /* Do other work while waiting for the results of the
    delete operation. */
  if ( !finished ) {
    do_other_work();
  }
}
ldap_unbind( ld );
return 0;
...

/* Perform other work while polling for results. */
void
do_other_work()
{
  global_counter++;
}
...

Retrieving SDK Information

You can get information about the particular version of Directory SDK for C that you are using by calling the ldap_get_option() function:

ldap_get_option(..., LDAP_OPT_API_INFO, ...);

The retrieved information can include the version of the SDK or the highest version of the LDAP that the SDK supports. This example shows how to use this function to retrieve version information.

#include <stdio.h>
#include "ldap.h"

main()
{

LDAPAPIInfo         ldapi;
LDAPAPIFeatureInfo  fi;
int                 i;
int                 rc;
LDAP                *ld;

memset( ldapi, 0, sizeof(ldapi));
ldapi.ldapai_info_version = LDAP_API_INFO_VERSION;

if ((rc = ldap_get_option( ld, LDAP_OPT_API_INFO, ldapi)) != 0) {
        printf("Error: ldap_get_option (rc: %d)\n", rc);
        exit(0);
}

printf("LDAP Library Information -\n"
        "    Highest supported protocol version: %d\n"
        "    LDAP API revision:                  %d\n"
        "    API vendor name:                    %s\n"
        "    Vendor-specific version:            %.2f\n",
        ldapi.ldapai_protocol_version, ldapi.ldapai_api_version,
        ldapi.ldapai_vendor_name,
        (float)ldapi.ldapai_vendor_version / 100.0 );

if ( ldapi.ldapai_extensions != NULL ) {
        printf("    LDAP API Extensions:\n");

        for ( i = 0; ldapi.ldapai_extensions[i] != NULL; i++ )  {
            printf("        %s", ldapi.ldapai_extensions[i] );
            fi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
            fi.ldapaif_name = ldapi.ldapai_extensions[i];
            fi.ldapaif_version = 0;

            if ( ldap_get_option( NULL, LDAP_OPT_API_FEATURE_INFO, fi )
                    != 0 ) {
                printf("Error: ldap_get_option( NULL,"
                       " LDAP_OPT_API_FEATURE_INFO, ... ) for %s failed"
                       " (Feature Info version: %d)\n",
                       fi.ldapaif_name, fi.ldapaif_info_version );
            } else {
                printf(" (revision %d)\n", fi.ldapaif_version);
            }
        }
    }
   printf("\n");
}

Managing Memory

Several of the SDK functions allocate memory when called. When you have finished working with data allocated by these functions, you should free the memory. The following shows some of the functions that allocate memory and the corresponding functions you use to free the memory when done.

Functions to Allocate and Free Memory
Function to Free Memory
Type of Memory Freed
ldap_unbind(), ldap_unbind_s()
Frees LDAP structures allocated by ldap_init() or prldap_init().
ldap_msgfree()
Frees LDAPMessage structures allocated by ldap_result() or ldap_search_ext_s().
ldap_ber_free()
Frees BerElement structures allocated by ldap_first_attribute().
ldap_value_free()
Frees char ** arrays and structures allocated by ldap_get_values().
ldap_value_free_len()
Frees arrays of berval structures allocated by ldap_get_values_len().
ber_bvfree()
Frees berval structures allocated by ldap_extended_operation_s(), ldap_parse_extended_result(), ldap_parse_sasl_bind_result(), and ldap_sasl_bind_s().
ldap_free_friendlymap()
Frees FriendlyMap structures allocated by ldap_friendly_name().
ldap_free_urldesc()
Frees LDAPURLDesc structures allocated by ldap_url_parse().
ldap_getfilter_free()
Frees LDAPFiltDesc structures allocated by ldap_init_getfilter() or ldap_init_getfilter_buf().
ldap_mods_free()
Frees LDAPMod** arrays and structures allocated by functions that you call when you add or modify entries.
ldap_free_sort_keylist()
Frees LDAPsortkey** arrays that you allocate by calling ldap_create_sort_keylist().
ldap_control_free()
Frees LDAPControl structures that you allocate by calling ldap_create_sort_control() or ldap_create_persistentsearch_control().
ldap_controls_free()
Frees LDAPControl** arrays and structures that you allocate by calling ldap_get_entry_controls(), ldap_parse_result(), or ldap_parse_reference().
ldap_memfree()
Frees any other types of memory that you allocate. This function is a general function for freeing memory.

Reporting Errors

In LDAP, the success or failure of an operation is specified by a result code sent back to the client. A result code of zero (0) normally indicates that the operation was successful, whereas a nonzero result code usually indicates that an error occurred.

Setting Error Codes

When an LDAP operation is performed, the error information from the operation is specified in the LDAP structure. If you want to set error codes and error information in the LDAP structure, call the ldap_set_lderrno() function. This example sets the LDAP_PARAM_ERROR error code in an LDAP structure.

#include "ldap.h"
...
LDAP *ld;
char *errmsg = "Invalid parameter";
...
if ( ldap_my_function() != LDAP_SUCCESS ) {
    ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, errmsg );
    return( 1 );
}
...

Getting Information About an Error

When an error occurs in an LDAP operation, the server sends an LDAP result code for the error back to the client. The server also sends a message with any additional information about the error.

  • If you are calling asynchronous functions, you can get the information from the LDAPMessage structure that represents the result the server returns.
  • Sometimes, you do not have an LDAPMessage structure. For example, you might be calling functions that do not interact with the server. When you do not have a message ID, get error information from the LDAP connection handle.
Getting Information From an LDAPMessage Structure

If you have requested the operation through an asynchronous function, get the result by calling the ldap_result() function. This function passes the result as an LDAPMessage structure. You can get information from this structure by calling the ldap_parse_result() function whose prototype is shown here.

LDAP_API(int) LDAP_CALL ldap_parse_result( LDAP *ld,
   LDAPMessage *res, int *errcodep, char **matcheddnp,
   char **errmsgp, char ***referralsp,
   LDAPControl ***serverctrlsp, int freeit );
  • The LDAP result code is the errcodep argument.
  • Additional information from the server is passed back as the errmsgp argument.
  • When the server cannot find an entry from a DN, the portion of the DN that identifies an entry is passed as the matcheddnp argument.

You can also get the error message that describes the LDAP result code by using the ldap_err2string() function.

The following example gets and prints information about an error returned from the server.

#include <stdio.h>
#include "ldap.h"
...
LDAP              *ld;
LDAPMessage       *res;
int               msgid = 0, rc = 0, parse_rc = 0, finished = 0;
char              *matched_msg = NULL, *error_msg = NULL;
char              **referrals;
LDAPControl       **serverctrls;
struct timeval    zerotime;
...
while ( !finished ) {
  /* Check to see if the server returned a result. */
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  ...
  default:
    /* The client has received the result of the LDAP operation. */
    finished = 1;

    /* Parse this result to determine if the operation was successful. */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );

    /* Verify that the result was parsed correctly. */
    if ( parse_rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result error: %s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }

    /* Check the results of the operation. */
    if ( rc != LDAP_SUCCESS ) {

      /* Print the error message corresponding to the result code. */
      fprintf( stderr, "Error: %s\n",
        ldap_err2string( rc ) );

      /* If the server sent an additional message, print it out. */
      if ( error_msg != NULL  *error_msg != '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }

      /* If the server cannot find an entry with the specified DN,
         it may send back the portion of the DN that matches
         an existing entry. */
      if ( matched_msg != NULL  *matched_msg != '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry: %s\n",
          matched_msg );
      }

      /* Disconnect and return. */
      ldap_unbind( ld );
      return( 1 );
    }
...
Getting Information From an LDAP Structure

Sometimes, you do not get an LDAPMessage structure. For example, when you call functions that do not interact with the server, get error information from the connection handle. You can get information about the last error that has occurred by calling the ldap_get_lerrno() function whose prototype is shown here.

LDAP_API(int) LDAP_CALL ldap_get_lderrno(LDAP *ld,
  char **m, char **s);
  • The LDAP result code is returned by this function.
  • Additional information from the server is passed back as the s argument.
  • When the server cannot find an entry from a DN, the portion of the DN that identifies an entry is passed as the m argument.

If you do not need to use the parameters returned by the ldap_get_lerrno function, set the parameters to NULL:

ldap_get_lderrno( ld, NULL, NULL );

The following example gets and prints information about an error from an LDAP structure.

#include <stdio.h>
#include "ldap.h"
...
LDAP     *ld;
char*    *error_msg = NULL, *matched_msg = NULL;
int      rc;
...
rc = ldap_get_lderrno( ld, matched_msg, error_msg );
fprintf( stderr, "ldap_result error: %s\n", ldap_err2string( rc ) );
if ( error_msg != NULL  *error_msg != '\0' ) {
  fprintf( stderr, "%s\n", error_msg );
}

/* If the server cannot find an entry with the specified DN,
   it may send back the portion of the DN that matches
   an existing entry. */
if ( matched_msg != NULL  *matched_msg != '\0' ) {
  fprintf( stderr,
    "Part of the DN that matches an existing entry: %s\n",
    matched_msg );
}
...
Getting the Error Message From an Error Code

If you have an error code, you can retrieve its corresponding error message using the ldap_err2string function. The function returns a pointer to the error message. The pointer returned by this function is a pointer to static data. Do not free this string.

#include <stdio.h>
#include "ldap.h"
...
int      rc;
...
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "Error: %s\n", ldap_err2string( rc ) );
}
...

Receiving the Matching Portion of a DN

If the server cannot find an entry specified by a DN, the server can return the portion of the DN that identifies an existing entry. According to LDAP v3, if a server returns an LDAP_NO_SUCH_OBJECT, LDAP_ALIAS_PROBLEM, LDAP_INVALID_DN_SYNTAX, or LDAP_ALIAS_DEREF_PROBLEM result code, the LDAP server should also send back the portion of the DN that matches an entry that is closest to the requested entry.

For example, suppose that the LDAP server processes a request to modify the entry with the DN uid=bjensen,ou=Contractors,dc=example,dc=com but that entry does not exist in the directory. If ou=Contractors,dc=example,dc=com does exist, the server sends this portion of the DN with the result code LDAP_NO_SUCH_OBJECT. If ou=Contractors,dc=example,dc=com does not exist, but dc=example,dc=com does, the server sends dc=example,dc=com back to the client. The server also returns the result code LDAP_NO_SUCH_OBJECT. Basically, the server removes one DN component at a time, until the server can find a DN that identifies an existing entry.

Printing Error Messages

To print the error message that describes the last error that occurred, call the ldap_get_lerrno() function. The following prints a message if a function fails to delete an entry in the server.

#include "ldap.h"
...
int lderr;
char * errmsg;
LDAP *ld;
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
...
if ( ldap_delete_s( ld, dn ) != LDAP_SUCCESS ) {
  lderr = ldap_get_lderrno (ld, NULL, errmsg);
  if ( errmsg, != NULL ) {
    fprintf(stderr, "ldap_delete_s: %s\n", errmsg );
    ldap_memfree( errmsg );
  }
  return( 1 );
}
...

The client also prints the following message if the client does not have access permissions to delete the entry:

ldap_delete_s: Insufficient access

Handling Referrals With Directory SDK for C

When a server receives a request for a DN, that DN might not be in its directory tree. The server can refer clients to another server that might contain the DN. The reference that the client receives is called a referral.

Consider an LDAP server that has a directory that starts under dc=example,dc=com.

  • If the server is not configured to send a referral, the server sends back an LDAP_NO_SUCH_OBJECT result code.
  • If the server is configured to refer you to another LDAP server, the server sends a referral back to your client. The referral consists of the result code, LDAP_PARTIAL_RESULTS for LDAP v2 clients, or LDAP_REFERRAL for LDAP v3 clients, and one or more LDAP URLs. For LDAP v2 clients, the URLs are included in the error message that the server sends to the client. For LDAP v3 clients, the URLs are included in a separate section of the result.
  • If your client handles referrals automatically, the client connects to the LDAP server specified in the referral. The client then requests the operation from that server. The client binds anonymously to that server.
  • If your client does not handle referrals automatically, your client returns the result code sent from the server, LDAP_PARTIAL_RESULTS or LDAP_REFERRAL. You can get the LDAP URLs from the result by calling the ldap_parse_result() function.

By default, clients built with Directory SDK for C follow referrals automatically.

Searching References and Referrals

A concept that is similar to a referral is a search reference. A search reference is an entry with the object class referral. The ref attribute of this object class contains an LDAP URL that identifies another LDAP server. When your client searches a subtree of a directory that contains search references, the server returns a mix of matching entries and search references.

  • If your client handles referrals automatically, Directory SDK for C retrieves each search reference, binds to the server identified in the reference, and then retrieves the entry.
  • If your client does not handle referrals automatically, Directory SDK for C adds the search reference to the chain of search results. The search reference is a message of the type LDAP_RES_SEARCH_REFERENCE. You can get the search references from a chain of results by calling the ldap_first_reference() and ldap_next_reference() functions. You can also call the ldap_first_message() and ldap_next_message() functions to get each message in the search results, and then call the ldap_msgtype() function to determine if the message is of the type LDAP_RES_SEARCH_REFERENCE.

See the ldap_ssl.h header file for information about specifying a DN and password for binding to a server for a referral.

Enabling or Disabling Referral Handling With Directory SDK for C

By default, clients built with Directory SDK for C automatically follow referrals to other servers. To change the way referrals are handled, call the ldap_set_option() function and pass LDAP_OPT_REFERRALS as the value of the option parameter.

  • To prevent the client from automatically following referrals, set the optdata parameter to LDAP_OPT_OFF.
  • If you want the client to automatically follow referrals again, set the optdata parameter to LDAP_OPT_ON.

Both LDAP_OPT_OFF and LDAP_OPT_ON are cast to (void *). You can pass these parameters directly to the function as shown in the following example. The parameter prevents the client from automatically following referrals to other LDAP servers.

#include <stdio.h>
#include "ldap.h"
...
LDAP    *ld;
int     rc;
char    *host = "localhost";
...
/* Initialize a session with the LDAP server ldap.example.com:389. */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}

/* Never follow referrals. */
if ( ldap_set_option( ld,
                      LDAP_OPT_REFERRALS,
                      LDAP_OPT_OFF) !=
     LDAP_SUCCESS ) {
  rc = ldap_get_lderrno( ld, NULL, NULL );
  fprintf( stderr, "ldap_set_option: %s\n",
    ldap_err2string( rc );
  return( 1 );
}
...

Limiting Referral Hops With Directory SDK for C

You can specify the maximum number of referral hops that should be followed in a sequence of referrals. The maximum setting is called the referral hop limit. You can specify the limit as a preference for the connection. You can also specify the limit as a search constraint for a specific search operation. For example, LDAP server 1 refers your client to server 2, server 2 to server 3, and then server 3 to server 4. Your client is being referred three times. With a limit of two referral hops, your client would not follow the referral to server 4, as the third referral exceeds the limit. If the referral hop limit is exceeded, the client returns the result code LDAP_REFERRAL_LIMIT_EXCEEDED.

To set the referral hop limit, pass LDAP_OPT_REFERRAL_HOP_LIMIT as the value of the option parameter. Also, pass the maximum number of hops as the value of the optdata parameter. By default, the maximum number of hops is 5.

Binding for Referrals

If the session setup specifies that the client always follows referrals, the LDAP server that the client connects to can refer the client to another server. By default, the client binds anonymously when following referrals. No user name or password is specified. The following sections explain how to set up your client to authenticate with a DN and with corresponding credentials.

How Referral Binding Works

To authenticate to the referred LDAP server, define a rebind function of the type LDAP_REBINDPROC_CALLBACK. The rebind function gets the DN and password to be used for authentication. Then, you specify that your function should be used if binding to other servers when following referrals.

  1. The LDAP server sends a referral back to the client.
    The referral contains an LDAP URL that identifies another LDAP server.
  2. The client calls the rebind() function, specified by the LDAP_OPT_REBIND_FN option, passing 0 as the freeit argument.
  3. The rebind() function sets the dnp, passwdp, and authmethodp arguments.
    • The dnp argument points to the DN used to authenticate to the new LDAP server.
    • The passwdp argument points to the credentials for this DN.
    • The authmethodp argument points to the method of authentication that is used, such as LDAP_AUTH_SIMPLE.
  4. If successful, the rebind() function returns LDAP_SUCCESS, and referral processing continues.
    If any other value is returned, referral processing stops, and that value is returned as the result code for the original LDAP request.
  5. The client gets the DN, the credentials, and the authentication method from the arguments of the rebind() function. The client uses this information to authenticate to the new LDAP server.
  6. The client calls the rebind() function again, passing 1 as the freeit argument.
  7. The rebind() function frees any memory that was allocated earlier to specify the DN and credentials.
Defining the Rebind Function
  • If freeit is 0, do the following:
    • Set dnp to point to the DN to be used for authentication.
    • Set passwdp to point to the credentials to be used for authentication.
    • Set authmethodp to point to the method of authentication to be used, such as LDAP_AUTH_SIMPLE.
    • Alternatively, you can also make use of the arg argument, a pointer to the argument specified in the ldap_set_rebind_proc() function. If successful, the function returns LDAP_SUCCESS. Otherwise, the function returns the appropriate LDAP error code.
  • If freeit is 1, free any memory that you allocated to create the DN and credentials.

The following code defines the rebind() function. The list defines the parameters of the rebind() function. LDAP_CALL and LDAP_CALLBACK set up calling conventions. The structures are defined in the lber.h header file.

int LDAP_CALL LDAP_CALLBACK rebindproc( LDAP *ld, char **dnp,
  char **passwdp, int *authmethodp, int freeit, void *arg );
  • ld: Pointer to the connection handle to the LDAP server.
  • dnp: Pointer to the DN of the user or entity who wants to perform the LDAP operations. Your function needs to set this value.
  • passwdp: Pointer to the user password. Your function needs to set this value.
  • authmethodp: Pointer to the method of authentication. Your function needs to set this value.
  • freeit: Specifies whether or not to free the memory allocated by the previous rebindproc() function call in the event that this function is called more than once. If freeit is set to a nonzero value, your function should free the memory allocated by the previous call.
  • arg: Pointer to data that can be passed to your function.
Registering the Rebind Function
  • Call ldap_set_rebind_proc(), specifying your function and any data that you want passed as an argument.
  • Call ldap_set_option() to set the LDAP_OPT_REBIND_FN option to your function. Use the LDAP_OPT_REBIND_ARG option to specify any arguments to pass to your rebind() function.

Creating an In-Memory Cache

Directory SDK for C includes functions that allow you to create an in-memory cache of search results for your client. Then, when sending a search request and receiving results, the results would be cached. The next time your client issues the same search request, the results are read from the cache. To set up a cache for your connection, complete the following procedure.

To Set Up an In-Memory Cache

  1. Call the ldap_memcache_init() function to create a new LDAPMemCache structure.
    The structure is the cache. Pass the pointer to this structure for subsequent operations.
  2. Call the ldap_memcache_set function() to associate the cache with an LDAP structure, which is a connection handle.
    When a search request is cached, the search criteria are used as the key to the item in the cache. If you run the same search again, the results are read from the cache. If you alter the criteria, your client gets the results from the server rather than the cache. For example, you can specify to return all attributes instead of just the uid attribute.
    The cache periodically checks for expired items. The cache mechanism removes expired items from the cache.
  3. When you write a multithreaded application, set up a separate thread to keep the cache up to date.
    To keep the cache updated, call the ldap_memcache_update() function.
  4. If you want to remove items from the cache or flush the cache, call the ldap_memcache_flush() function.
  5. When you are done working with the cache, call the ldap_memcache_destroy() function.
#include "ldap.h"
...
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
...
LDAP          *ld;
LDAPMemCache  *dircache;
char *matched_msg = NULL, *error_msg = NULL;
int rc;
...
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
...
/* Create an in-memory cache. */
rc = ldap_memcache_init( 0, 0, NULL, NULL, dircache );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_memcache_init: %s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}

/* Associate the cache with the connection. */
rc = ldap_memcache_set( ld, dircache );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_memcache_set: %s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
...

Handling Failover

While performing an LDAP operation, if the LDAP client loses the connection with the server, the SDK returns an LDAP_SERVER_DOWN or LDAP_CONNECT_ERROR result code.

  • Free the current connection handle. Then create a new connection handle.
  • Use the reconnect option, LDAP_OPT_RECONNECT, to connect to the server again with the same connection handle.
    You can use this option if you do not want to free the connection handle, for example, if multiple threads are sharing the same connection handle.

Creating a New Connection Handle

Call the ldap_unbind() or ldap_unbind_s() function to free the existing connection handle, which is an LDAP structure. Then call ldap_init() or prldap_init() to initialize a new connection as shown in the following example.

The disadvantage of this approach is the need to free the connection handle, which can make sharing connection handles between threads difficult.

#include "ldap.h"
...
LDAP *ld;
int tries = 0, rc = 0;
...
do {
  /* Call a function that performs an LDAP operation
  (my_ldap_request_function() can be any of these functions,
  such as ldap_search_ext_s()) */
  rc = my_ldap_request_function( ld );

  /* Check to see if the connection was lost. */
  if ( rc != LDAP_SERVER_DOWN  rc != LDAP_CONNECT_ERROR ) {
    return( rc ); /* Return result code. */
  }

  /* If the connection was lost, free the handle. */
  ldap_unbind( ld );

  /* Create a new connection handle and attempt to bind again. */
  /* Use prldap_init() for IPv6 support. */
  if (( ld = ldap_init( hostlist, port )) != NULL ) {
    ldap_simple_bind_s();

    /* Perform any other initialization
    work on the connection handle. */
  }
} while ( ld != NULL  ++tries  2 );
...

Using the Reconnect Option

To reconnect to the server without freeing the connection handle, for example, if multiple threads need to share the same connection handle, call the ldap_set_option() function to set the LDAP_OPT_RECONNECT option to LDAP_OPT_ON. Call this function immediately after calling ldap_init() or prldap_init() as shown in the following example:

#include "ldap.h"
...
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
...
LDAP *ld;
...
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}

/* Set the reconnect option. */
if ( ldap_set_option( ld, LDAP_OPT_RECONNECT, LDAP_OPT_ON ) == 0 ) {
  /* success */
  } else {
  /* failure */
}
...

If after setting this option, the connection to the server has been lost, the SDK returns an LDAP_CONNECT_ERROR or LDAP_SERVER_DOWN result code to your client. When you receive this result code, call the ldap_simple_bind_s() function. This function reestablishes a connection to one of the hosts specified in the ldap_init() or prldap_init() function call. If your client is able to reconnect with the server, ldap_simple_bind_s() issues a bind request to the server and returns the result. The following example attempts to reconnect to the server if the client is disconnected.

#include "ldap.h"
...
LDAP *ld;
int tries = 0, rc = 0;
...
do {
  /* Call a function that performs an LDAP operation
  (my_ldap_request_function() can be any of these functions,
  such as ldap_search_ext_s()) */
  rc = my_ldap_request_function( ld );

  /* Check to see if the connection was lost. */
  if ( rc != LDAP_SERVER_DOWN  rc != LDAP_CONNECT_ERROR ) {
    return( rc ); /* Return the result code. */
  }

  /* If the connection was lost, call
  ldap_simple_bind_s() to reconnect. */
  if ( ldap_simple_bind_s( ld, dn, passwd ) != LDAP_SUCCESS ) {
    /* failure -- could not reconnect */
    /* remember that ld as bad */
    return( rc );
  }
} while ( ++tries  2 );

Searching the Directory With Directory SDK for C

This chapter explains how to use the LDAP C API to search the directory and to retrieve entries.

Directory SDK for C provides functions that allow you to search a directory and to retrieve results from the server. For example, you can send a search request by calling the synchronous ldap_search_ext_s() function or the asynchronous ldap_search_ext() function and the server sends back matching results.

  • Directory entries found by the search
  • Search references found within the scope of the search
    A search reference is a reference to another LDAP server.
  • An LDAP result code that specifies the result of the search operation
    Note: To receive search references from LDAP v3 servers, you must identify your client as LDAP v3 enabled. If you do not, the server returns the LDAP error code LDAP_PARTIAL_RESULTS, and a set of referrals. See Specifying the LDAP Version of Your Client for details.
  • If you are retrieving the results sequentially, call ldap_result(). This function returns each result, an LDAPMessage structure, and determines the type of result. A result can be either an entry or a search reference.
  • If you are retrieving a chain of results, you can call ldap_first_message() and ldap_next_message() to iterate through the results in the chain.
  • If you are just interested in entries, you can call ldap_first_entry() and ldap_next_entry().
  • If you are just interested in search references, you can call ldap_first_reference() and ldap_next_reference().
  • To get an entry from a result, an LDAPMessage structure, call ldap_parse_entry().
  • To get a search reference from a result, an LDAPMessage structure, call ldap_parse_reference().
  • To get the LDAP result code for the search operation from a result, an LDAPMessage structure, call ldap_parse_result().

Tip: To access data from entries found by the search, you need to follow this general process in your code.

  1. Get each entry in the results.
  2. Get the attributes from each entry.
  3. Get the values from each attribute.

Sending a Search Request With Directory SDK for C

To search the directory, call ldap_search_ext_s() or ldap_search_ext. ldap_search_ext_s() is a synchronous function that blocks other work until all results have been received from the server. The function is declared as shown here.

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

ldap_search_ext() is an asynchronous function that sends an LDAP search request to the server. You can do other work while checking to see if the server has returned any results. The function is declared as shown here.

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

Sample code for sending a search request can be found in Sending Search Request Using Directory SDK for C.

Search Parameters for Directory SDK for C

For either of the functions ldap_search_ext_s() or ldap_search_ext(), you specify the search criteria by using the parameters as detailed in the following list.

  • base: Specifies the starting point in the directory, or the base DN, where the search begins. For example, to search entries under dc=example,dc=com, the base DN is dc=example,dc=com. See Specifying the Base DN and the Scope With Directory SDK for C.
  • scope: Specifies which entries to search. The search can address the base DN only, entries one level under the base DN, or all entries under the base DN. See Specifying the Base DN and the Scope With Directory SDK for C.
  • filter: Specifies a search filter by defining what to search for. A search filter can be as simple as find entries with the last name of Jensen or as complex as find entries that belong to Dept. #17 and whose first names start with the letter F. See Specifying a Search Filter With Directory SDK for C.
  • attrsattrsonly: Specify what to return. Options are the type of information to return, and the attributes to retrieve. Also, options include whether to return only attribute types, or both types and values. You can also specify to return the names of attributes only, and not the values, by passing a nonzero value for the attrsonly argument. See Specifying the Attributes to Retrieve With Directory SDK for C.
  • serverctrlsclientctrls: Specify the LDAP v3 controls that are associated with this search operation. For details on LDAP v3 controls, see Chapter16, LDAP Controls With Directory SDK for C.
  • timeoutpsizelimit: Specify search constraints that you want applied to the search. For example, you can specify a different timeout period or maximum number of results from the values already defined for the current session. See Setting Search Preferences With Directory SDK for C.

Specifying the Base DN and the Scope With Directory SDK for C

When sending a search request, you need to specify the base DN and the search scope to identify the entries that you want searched. The base DN, the root argument, is the DN of the entry that serves as the starting point for the search.

  • LDAP_SCOPE_SUBTREE searches the base entry and all entries at all levels under the base entry.
  • LDAP_SCOPE_ONELEVEL searches all entries one level under the base entry. The base entry is not included in the search. Use this setting if you just want to list the entries under a given entry.
  • LDAP_SCOPE_BASE searches only the base entry. Use this setting if you just want to read the attributes of the base entry.

Specifying a Search Filter With Directory SDK for C

When you search the directory, you use a search filter to define the search. The following example illustrates the search filter syntax:

(attribute operator value)

(cn=Barbara Jensen)

Compare the syntax to the example. You see that cn is the attribute, that = is the operator, and that Barbara Jensen is the value. The filter finds entries with the common name Barbara Jensen. For a list of valid attributes for your search filter, see the LDAP schema for the directory server you are using. For a list of valid operators that you can use in your search filter, see the following list.

  • =
    Returns entries whose attribute is equal to the value.
    (cn=Barbara Jensen) finds the entry with RDN cn=Barbara Jensen.
  • >=
    Returns entries whose attribute is greater than or equal to the value.
    (sn >= jensen) finds all entries with surname (SN) from jensen to the end of the alphabetical list.
  • =
    Returns entries whose attribute is less than or equal to the value.
    (sn = jensen) finds all entries with SN from the beginning of the alphabetical list to jensen.
  • =*
    Returns entries that have a value set for that attribute.
    (sn =*) finds all entries that have the sn attribute.
  • ~=
    Returns entries whose attribute value approximately matches the specified value. Typically, the algorithm matches words that sound alike.
    (sn ~= jensen) finds entries with sn = jensen but also sn = jansen.

With boolean operators and with parentheses, you can combine different sets of conditions into one filter. The following shows boolean search filter syntax for combining filters, and a simple example:

(boolean-operator(filter1)(filter2)(...))

(|(sn=Jensen)(sn=Johnson))

The example uses the boolean or operator, |, to signify a search for all entries with the last name Jensen or the last name Johnson. The following list describes the valid boolean operators that you can use in your search filter.

  • &
    Returns entries that match all specified filter criteria.
  • |
    Returns entries that match one or more of the filter criteria.
  • !
    Returns entries for which the filter is not true. You can only apply this operator to a single filter. For example: You can use:
    (!(filter))

    You cannot use:
    (!(filter1)(filter2))

You can also include wildcard characters, *, to search for entries that start with, contain, or end with a given value. For example, you can use this filter to search for all entries whose names begin with the letter F:

(givenName=F*)

When comparing values with letters, the value of the letter a is less than the value z. For example, the following filter finds all entries with last names beginning with a through Jensen:

(sn=jensen)

Specifying the Attributes to Retrieve With Directory SDK for C

With the attrs argument, you can retrieve all attributes in the entries returned by the search. Alternatively, you can specify the attributes from the search results.

  • To return selected attributes, pass an array of the attribute names as the attrs argument.
    For example, to return only email addresses and phone numbers, pass the NULL terminated array {"mail", "telephoneNumber", NULL} as the attrs argument.
  • To return all attributes in an entry, pass NULL as the attrs argument.
  • To return no attributes from an entry, pass LDAP_NO_ATTRS as the attrs argument.
Sorting Attributes

If you plan to sort the results on your client, you need to return the attributes that you plan to use for sorting. For example, if you plan to sort by email address, make sure that the mail attribute is returned in the search results.

Operational Attributes

Some attributes are used by servers for administering the directory. For example, the creatorsName attribute specifies the DN of the user who added the entry. These attributes are called operational attributes.

Servers do not normally return operational attributes in search results unless you specify the attributes by name. For example, you can pass NULL for the attrs argument to retrieve all of the attributes in entries found by the search. When you pass this value, the operational attribute creatorsName is not returned to your client. You need to explicitly specify the creatorsName attribute in the attrs argument. You can retrieve all attributes in an entry, as well as selected operational attributes. Pass a NULL terminated array that contains LDAP_ALL_USER_ATTRS. Also, pass the names of the operational attributes as the attrs argument. The following list shows operational attributes and explains the meaning of their values.

  • createTimestamp: The time that the entry was added to the directory
  • modifyTimestamp: The time that the entry was last modified
  • creatorsName: DN of the user who added the entry to the directory
  • modifiersName: DN of the user who last modified the entry
  • subschemaSubentry: DN of the subschema entry, which controls the schema for this entry

Setting Search Preferences With Directory SDK for C

For a given search, you can specify the maximum number of results to be returned. Alternatively, you can specify the maximum amount of time to wait for a search.

  • To specify an infinite time limit, in other words, no limit, create a timeval structure with tv_sec = tv_usec = 0. Then pass a pointer to the structure as the timeoutp argument.
  • To use the time limit specified by the LDAP_OPT_TIMELIMIT option for this connection, pass NULL as the timeoutp argument.
  • To specify an infinite size limit, in other words, no limit, pass LDAP_NO_LIMIT as the sizelimit argument.
  • To use the size limit specified by the LDAP_OPT_SIZELIMIT option for this connection, pass NULL as the sizelimit argument.
  • To specify preferences for all searches under the current connection, call ldap_set_option and set the LDAP_OPT_SIZELIMIT and LDAP_OPT_TIMELIMIT options.
    If you do not want to specify a limit, in other words, no limit, set the value of each option to LDAP_NO_LIMIT.
    Note: The LDAP server administrator might already have configured time limits and size constraints that you cannot override.

The following example sets these session preferences so that a search returns no more than 100 entries, and takes no more than 30 seconds.

#include <stdio.h>
#include "ldap.h"
...
LDAP *ld;
int max_ret, max_tim;
char *host = "ldap.example.com";
...
/* Initialize a session with the LDAP server ldap.example.com:389. */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}

/* Set the maximum number of entries returned. */
max_ret = 100;
ldap_set_option(ld, LDAP_OPT_SIZELIMIT, (void *)max_ret );


/* Set the maximum number of seconds to wait. */
max_tim = 30;
ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *)max_tim );
...

Getting the Search Results With Directory SDK for C

The directory entries found by the search. In other words, those entries that match the search criteria.

  • Any search references found within the scope of the search. A search reference is a reference to another LDAP server.
  • An LDAP result code that specifies the result of the search operation.
    Note: Because results are represented as a chain, do not free individual LDAPMessage structures within the chain. When you are done working with the results, free the chain, rather than the individual structures. If you free individual LDAPMessage structures from memory, you might lose all of the results.
  • To get each entry and each search reference in the result, call ldap_first_message() and ldap_next_message(). Both of these functions return a pointer to an LDAPMessage structure that represents an entry, search reference, or LDAP result code. You can get the count of the structures in the chain by calling ldap_count_messages().
  • If you want to retrieve just the entries from the chain, call ldap_first_entry() and ldap_next_entry(). Both of these functions return a pointer to an LDAPMessage structure that represents an entry. You can get the count of the entries in the chain by calling ldap_count_entries().
  • If you want to retrieve just the search references from the chain, call ldap_first_reference() and ldap_next_reference(). Both of these functions return a pointer to an LDAPMessage structure that represents a search reference. You can get the count of the search references in the chain by calling ldap_count_references().

Getting Results Synchronously

If you call ldap_search_ext_s() to search the directory synchronously, the function blocks processes until all results have been received. The function then returns a chain of results in the result parameter, a handle to an LDAPMessage structure. The following example prints the values of all attributes in the entries returned by a synchronous search.

#include <stdio.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"
int
main( int argc, char **argv )
{
    LDAP           *ld;
    LDAPMessage    *res, *msg;
  LDAPControl      **serverctrls;
    BerElement     *ber;
    char           *a, *dn, *matched_msg = NULL, *error_msg = NULL;
    char           **vals, **referrals;
    int            version, i, rc, parse_rc, msgtype, num_entries = 0,
                     num_refs = 0;
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
    }
  version = LDAP_VERSION3;
  if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version ) !=
        LDAP_SUCCESS ) {
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_set_option: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
    /* Bind to the server anonymously. */
    rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
          "Part of the DN that matches an existing entry: %s\n",
          matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
    }
    /* Perform the search operation. */
    rc = ldap_search_ext_s( ld, BASEDN, SCOPE, FILTER,
         NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, res );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
               "Part of the DN that matches an existing entry: %s\n",
               matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
    }
    num_entries = ldap_count_entries( ld, res );
  num_refs = ldap_count_references( ld, res );
  /* Iterate through the results. An LDAPMessage structure sent back from
      a search operation can contain either an entry found by the search,
      a search reference, or the final result of the search operation. */
  for ( msg = ldap_first_message( ld, res );
        msg != NULL;
        msg = ldap_next_message( ld, msg ) ) {
    /* Determine what type of message was sent from the server. */
    msgtype = ldap_msgtype( msg );
    switch( msgtype ) {
    /* If the result was an entry found by the search, get and print the
       attributes and values of the entry. */
    case LDAP_RES_SEARCH_ENTRY:
      /* Get and print the DN of the entry. */
      if (( dn = ldap_get_dn( ld, res )) != NULL ) {
        printf( "dn: %s\n", dn );
        ldap_memfree( dn );
      }
      /* Iterate through each attribute in the entry. */
      for ( a = ldap_first_attribute( ld, res, ber );
      a != NULL; a = ldap_next_attribute( ld, res, ber ) ) {
        /* Get and print all values for each attribute. */
        if (( vals = ldap_get_values( ld, res, a )) != NULL ) {
          for ( i = 0; vals[ i ] != NULL; i++ ) {
            printf( "%s: %s\n", a, vals[ i ] );
          }
          ldap_value_free( vals );
        }
        ldap_memfree( a );
      }
      if ( ber != NULL ) {
        ber_free( ber, 0 );
      }
      printf( "\n" );
      break;
    case LDAP_RES_SEARCH_REFERENCE:
      /* The server sent a search reference encountered during the
         search operation. */
      /* Parse the result and print the search references.
         Ideally, rather than print them out, you would follow the
         references. */
      parse_rc = ldap_parse_reference( ld, msg, referrals, NULL, 0 );
      if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr, 
         "ldap_parse_result: %s\n",
         ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      if ( referrals != NULL ) {
        for ( i = 0; referrals[ i ] != NULL; i++ ) {
          printf( "Search reference: %s\n\n", referrals[ i ] );
        }
        ldap_value_free( referrals );
      }
      break;
    case LDAP_RES_SEARCH_RESULT:
      /* Parse the final result received from the server. Note the last
         argument is a non-zero value, which indicates that the
         LDAPMessage structure will be freed when done.  (No need
         to call ldap_msgfree().) */
      parse_rc = ldap_parse_result( ld, msg, rc,
        matched_msg, error_msg, NULL, serverctrls, 0 );
      if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr,
                 "ldap_parse_result: %s\n",
                 ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP search operation. */
      if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext: %s\n", ldap_err2string( rc ) );
        if ( error_msg != NULL  *error_msg != '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg != NULL  *matched_msg != '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry: %s\n",
            matched_msg );
        }
      } else {
        printf( "Search completed successfully.\n"
          "Entries found: %d\n"
          "Search references returned: %d\n",
          num_entries, num_refs );
      }

      break;

    default:
      break;
    }
  }
    /* Disconnect when done. */
    ldap_unbind( ld );
    return( 0 );
}

Getting Results Asynchronously

If you use the asynchronous function ldap_search_ext(), you first need to call ldap_result() to determine if the server sent back any results.

LDAP_API(int) LDAP_CALL ldap_result( LDAP *ld, int msgid, int all,
  struct timeval *timeout, LDAPMessage **result );

You can specify how you want to get asynchronous results.

To get the results individually as the client receives the results from the server, pass LDAP_MSG_ONE as the all argument.

#include <stdio.h>
#include "ldap.h"
...
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"
...
LDAP      *ld;
LDAPMessage    *res;
int        msgid, rc, parse_rc, finished = 0;
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
...
/* Send the LDAP search request. */
rc = ldap_search_ext( ld, BASEDN, SCOPE, FILTER, NULL, 0, NULL, NULL,
  NULL, LDAP_NO_LIMIT, msgid );
...
/* Poll the server for the results of the search operation. */
while ( !finished ) {
  rc = ldap_result( ld, msgid, LDAP_MSG_ONE, zerotime, res );
  switch ( rc ) {
  case -1:
    /* An error occurred. */
    ...
  case 0:
    /* The timeout period specified by zerotime was exceeded. */
    ...
  case LDAP_RES_SEARCH_ENTRY:
    /* The server sent one of the entries found by the search. */
    ...
  case LDAP_RES_SEARCH_REFERENCE:
    /* The server sent a search reference .*/
    ...
  case LDAP_RES_SEARCH_RESULT:
    /* Parse the final result received from the server. */
    ...
  }
...
}
...
  • To get the results all at once, in other words, to block processes until all results are received, pass LDAP_MSG_ALL as the all argument.
  • To get the results received thus far, pass LDAP_MSG_RECEIVED as the all argument.

If you specify either LDAP_MSG_ALL or LDAP_MSG_RECEIVED, the function passes back a chain of search results as the result argument. If you specify LDAP_MSG_ONE, the function passes back a single search result as the result argument. The function normally returns the type of the first search result. When the function returns the type, as only one result is returned, the function returns the type of that result.

The following example prints the values of all attributes in the entries returned by an asynchronous search.

#include <stdio.h>
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"
int
main( int argc, char **argv )
{
    LDAP           *ld;
    LDAPMessage    *res;
    BerElement     *ber;
  LDAPControl      **serverctrls;
    char           *a, *dn, *matched_msg = NULL, *error_msg = NULL;
    char           **vals, **referrals;
    int           version, i, msgid, rc, parse_rc, finished = 0,
                   num_entries = 0, num_refs = 0;
    struct         timeval  zerotime;
    zerotime.tv_sec = zerotime.tv_usec = 0L;
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
    }
  version = LDAP_VERSION3;
  if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version ) !=
       LDAP_SUCCESS ) {
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_set_option: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
    /* Bind to the server anonymously. */
    rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    /* If the server cannot find an entry,
      print the portion of the DN that matches
      an existing entry. */ 
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
    }
    /* Send the LDAP search request. */
    rc = ldap_search_ext( ld, BASEDN, SCOPE, FILTER,
           NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, msgid );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_search_ext: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
    }
    /* Poll the server for the results of the search operation.
     Passing LDAP_MSG_ONE indicates that you want to receive
     the entries one at a time, as they come in.  If the next
     entry that you retrieve is NULL, there are no more entries. */
    while ( !finished ) {
    rc = ldap_result( ld, msgid, LDAP_MSG_ONE, zerotime, res );
    /* The server can return three types of results back to the client,
       and the return value of ldap_result() indicates the result type:
       LDAP_RES_SEARCH_ENTRY identifies an entry found by the search,
       LDAP_RES_SEARCH_REFERENCE identifies a search reference returned
       by the server, and LDAP_RES_SEARCH_RESULT is the last result
       sent from the server to the client after the operation completes.
       You need to check for each of these types of results. */
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
         This means that the server has still not yet sent the
         results of the search operation back to your client.
         Break out of this switch statement, and continue calling
         ldap_result() to poll for results. */
      break;
    case LDAP_RES_SEARCH_ENTRY:
      /* The server sent one of the entries found by the search
         operation. Print the DN, attributes, and values of the entry. */
      /* Keep track of the number of entries found. */
      num_entries++;
      /* Get and print the DN of the entry. */
      if (( dn = ldap_get_dn( ld, res )) != NULL ) {
        printf( "dn: %s\n", dn );
        ldap_memfree( dn );
      }
      /* Iterate through each attribute in the entry. */
      for ( a = ldap_first_attribute( ld, res, ber );
      a != NULL; a = ldap_next_attribute( ld, res, ber ) ) {
        /* Get and print all values for each attribute. */
        if (( vals = ldap_get_values( ld, res, a )) != NULL ) {
          for ( i = 0; vals[ i ] != NULL; i++ ) {
            printf( "%s: %s\n", a, vals[ i ] );
          }
          ldap_value_free( vals );
        }
        ldap_memfree( a );
      }
      if ( ber != NULL ) {
        ber_free( ber, 0 );
      }
      printf( "\n" );
      ldap_msgfree( res );
      break;
    case LDAP_RES_SEARCH_REFERENCE:
      /* The server sent a search reference encountered during the
         search operation. */
      /* Keep track of the number of search references returned from
         the server. */
      num_refs++;
      /* Parse the result and print the search references.
         Ideally, rather than print them out, you would follow the
         references. */
      parse_rc = ldap_parse_reference( ld, res, referrals, NULL, 1 );
      if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr,
                 "ldap_parse_result: %s\n",
                 ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      if ( referrals != NULL ) {
        for ( i = 0; referrals[ i ] != NULL; i++ ) {
          printf( "Search reference: %s\n\n", referrals[ i ] );
        }
        ldap_value_free( referrals );
      }
      break;
    case LDAP_RES_SEARCH_RESULT:
      /* Parse the final result received from the server. Note the last
         argument is a non-zero value, which indicates that the
         LDAPMessage structure will be freed when done.  (No need
         to call ldap_msgfree().) */
      finished = 1;
      parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
                   error_msg, NULL, serverctrls, 1 );
      if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr, 
                 "ldap_parse_result: %s\n",
                 ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP search operation. */
      if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext: %s\n", ldap_err2string(rc) );
        ldap_get_lderrno( ld, matched_msg, error_msg );
        if ( error_msg != NULL  *error_msg != '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg != NULL  *matched_msg != '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry: %s\n",
            matched_msg );
        }
      } else {
        printf( "Search completed successfully.\n"
          "Entries found: %d\n"
          "Search references returned: %d\n"
          "Counted to %d while waiting for the search operation.\n",
          num_entries, num_refs, global_counter );
      }

      break;

    default:
      break;
    }

    /* Do other work here while waiting for the search operation
       to complete. */
    if ( !finished ) {
      do_other_work();
    }
  }
    /* Disconnect when done. */
    ldap_unbind( ld );
    return( 0 );
}
/*
 * Perform other work while polling for results.  This doesn't do 
 * anything useful, but it could.
 */
static void
do_other_work()
{
    global_counter++;
}

Determining Search Result Types

To determine what type of result was returned, call the ldap_msgtype() function.

  • LDAP_RES_SEARCH_ENTRY indicates that the result is an entry that is found in the search. You can pass the LDAPMessage structure that represents the entry to ldap_get_dn() to get the DN of the entry. You can pass the structure to ldap_first_attribute() and ldap_next_attribute() to get the attributes of the entry.
  • LDAP_RES_SEARCH_REFERENCE indicates that the result is a search reference that is found within the scope of the search. You can pass the LDAPMessage structure representing the search reference to the ldap_parse_reference() function to get the referrals, LDAP URLs, to other servers.
    To receive search references from an LDAP v3 server, you must identify your client as LDAP v3 enabled. If not, the server returns the error code LDAP_PARTIAL_RESULTS and a set of referrals.
  • LDAP_RES_SEARCH_RESULT indicates that the result is the final data sent by the server to indicate the end of the LDAP search operation. You can pass the LDAPMessage structure that represents the result to the ldap_parse_result() function to get the LDAP result code for the search operation. For a list of possible result codes for an LDAP search operation, see the ldap_search_ext_s(3ldap) man page.

This example retrieves each result in a chain. The example then determines its type.

#include <stdio.h>
#include "ldap.h"
...
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"
...
LDAP      *ld;
LDAPMessage    *res, *msg;
BerElement    *ber;
char      *matched_msg = NULL, *error_msg = NULL;
int        rc, msgtype, num_entries = 0, num_refs = 0;
...
/* Perform the search operation. */
rc = ldap_search_ext_s( ld, BASEDN, SCOPE, FILTER, NULL, 0, NULL, NULL,
  NULL, LDAP_NO_LIMIT, res );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) );
  if ( error_msg != NULL  *error_msg != '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  /* If the server cannot find an entry and returns the portion of
     the DN that can find an entry, print it out. */
  if ( matched_msg != NULL  *matched_msg != '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry: %s\n",
      matched_msg );
  }
  ldap_unbind_s( ld );
  return( 1 );
}
...
num_entries = ldap_count_entries( ld, res );
num_refs = ldap_count_references( ld, res );
...
/* Iterate through the results. */
for ( msg = ldap_first_message( ld, res ); msg != NULL;
  msg = ldap_next_message( ld, msg ) ) {

  /* Determine what type of message was sent from the server. */
  msgtype = ldap_msgtype( msg );
  switch( msgtype ) {
  case LDAP_RES_SEARCH_ENTRY:
    /* The result is an entry. */
    ...
  case LDAP_RES_SEARCH_REFERENCE:
    /* The result is a search reference. */
    ...
  case LDAP_RES_SEARCH_RESULT:
    /* The result is the final result sent by the server. */
    ...
  }
...
}
...

Getting Distinguished Names for Each Entry

Because the DN of an entry differentiates the entry from other entries, you might want to access the DN in search results. You might also want to parse the name into its individual components. The SDK provides functions for both of these tasks.

Getting the Distinguished Name of an Entry

To get the DN of an entry, call the ldap_get_dn() function. When finished with the DN, free the DN from memory by calling the ldap_memfree() function.

#include stdio.h>
#include "ldap.h"
...
LDAP *ld;
LDAPMessage *result, *e;
char *dn;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
                    my_filter, NULL, 0, result ) !=
     LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}

/* For each matching entry found, print the name of the entry.*/
for ( e = ldap_first_entry( ld, result ); e != NULL;
      e = ldap_next_entry( ld, e ) ) {
  if ( ( dn = ldap_get_dn( ld, e ) ) != NULL ) {
    printf( "dn: %s\n", dn );
    /* Free the memory used for the DN when done */
    ldap_memfree( dn );
  }
}
/* Free the result from memory when done. */
ldap_msgfree( result );
Getting the Components of a Distinguished Name

If you want to access individual components of a DN or relative DN, call the ldap_explode_dn() or ldap_explode_rdn() function, respectively. Both functions return a NULL terminated array that contains the components of the DN. When you are done working with this array, free the array by calling the ldap_value_free() function.

You can also specify whether or not you want the attribute names included in the array, by using the notypes parameter.

Set notypes to 0 if you want to include attribute names, as in this function call:

ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 0 )

This function then returns this array:

{ "uid=bjensen", "ou=People", "dc=example,dc=com", NULL }

Set notypes to 1 if you do not want to include the attribute names in the array, as in this function call:

ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 1 )

This function then returns this array:

{ "bjensen", "People", "example.com", NULL }

Getting Attribute Types From an Entry

To retrieve the type, also called the name, of the first attribute in an entry, call the ldap_first_attribute() function. To get the type of the next attribute, call the ldap_next_attribute() function.

Note: Operational attributes such as creatorsName and modifyTimestamp are not normally returned in search results. You must explicitly specify operational attibutes by type in the search request. For more details, see Operational Attributes.

When you are finished iterating through the attributes, you need to free the BerElement structure allocated by the ldap_first_attribute() function, if the structure is not NULL. To free this structure, call the ldap_ber_free() function. You should also free the attribute type returned by the ldap_first_attribute() function. To free the attribute type, call the ldap_memfree() function. The following example shows how to do this.

#include <stdio.h>
#include "ldap.h"
...
LDAP         *ld;
LDAPMessage  *result, *e;
BerElement   *ber;
char         *a;
char         *my_searchbase = "dc=example,dc=com";
char         *my_filter = "(sn=Jensen)";
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
      NULL, 0, result ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}

/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );

/* Retrieve the attributes of the entry. */
  for (a = ldap_first_attribute(ld, e, ber); a != NULL;
        a = ldap_next_attribute(ld, e, ber)){
    ...
    /* Code to get and manipulate attribute values */
    ...
    }
    ldap_memfree( a );
  }
  /* Free the BerElement structure from memory when done. */
  if ( ber != NULL ) {
    ldap_ber_free( ber, 0 );
  }
...

Getting the Values of an Attribute

The values of an attribute are represented by a NULL terminated array. If the attribute contains string data, such as a name or phone number, the values are a list of strings. If the attribute contains binary data, the values are a list of berval structures, such as JPEG files or audio files. Use the following guidelines to retrieve the values of an attribute:

  • To get the values of an attribute that contains string data, call the ldap_get_values() function. The ldap_get_values function returns a NULL terminated array of strings that represent the value of the attribute.
  • To get the values of an attribute that contains binary data, call the ldap_get_values_len() function. The ldap_get_values_len function returns a NULL terminated array of berval structures that represent the value of the attribute.
  • To get the number of values in an attribute, call either the ldap_count_values() or ldap_count_values_len() function. Both functions return the number of values in the attribute.

When you have finished working with the values of the attribute, you need to free the values from memory. To free the values, call ldap_free_value() or ldap_free_value_len(). The following example gets, then prints the values of an attribute in an entry. The function assumes that all attributes have string values.

#include <stdio.h>
#include "ldap.h"
...
LDAP          *ld;
LDAPMessage   *result, *e;
BerElement    *ber;
char          *a;
char          **vals;
char          *my_searchbase = "dc=example,dc=com";
char          *my_filter = "(sn=Jensen)";
int i;
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
                    my_filter, NULL, 0, result ) !=
     LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}

/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );

/* Get the first matching attribute. */
a = ldap_first_attribute( ld, e, ber );

/* Get the values of the attribute. */
if ( ( vals = ldap_get_values( ld, e, a ) ) != NULL ) {
  for ( i = 0; vals[i] != NULL; i++ ) {
    /* Print the name of the attribute and each value */
    printf( "%s: %s\n", a, vals[i] );
  }
  /* Free the attribute values from memory when done. */
  ldap_value_free( vals );
}
...

The following example gets the first value of the jpegPhoto attribute and saves the JPEG data to a file.

#include <stdio.h>
#include "ldap.h"
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a;
struct berval photo_data;
struct berval **list_of_photos;
FILE *out;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
                    my_filter, NULL, 0, result ) !=
     LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}

/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );

/* Find the jpegPhoto attribute. */
a = ldap_first_attribute( ld, e, ber );
while ( strcasecmp( a, "jpegphoto" ) != 0 ) {
  a = ldap_next_attribute( ld, e, ber );
}

/* Get the value of the attribute. */
if ( ( list_of_photos = ldap_get_values_len( ld, e, a ) ) !=
       NULL ) {
  /* Prepare to write the JPEG data to a file */
  if ( ( out = fopen( "photo.jpg", "wb" ) ) == NULL ) {
    perror( "fopen" );
    return( 1 );
  }
  /* Get the first JPEG. */
  photo_data = *list_of_photos[0];
  /* Write the JPEG data to a file */
  fwrite( photo_data.bv_val, photo_data.bv_len, 1, out );
  fclose( out );
  /* Free the attribute values from memory when done. */
  ldap_value_free_len( list_of_photos );
}
...

Getting Referrals From Search References

A search reference returned from the server contains one or more referrals, which are LDAP URLs that identify other LDAP servers. To retrieve these referrals, you need to call the ldap_parse_reference() function. The following example gets and prints the referrals from a search reference.

#include <stdio.h>
#include "ldap.h"
...
LDAP          *ld;
LDAPMessage   *msg;
char          **referrals;
int           i, rc, parse_rc;
...
parse_rc = ldap_parse_reference( ld, msg, referrals, NULL, 0 );
if ( parse_rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_parse_result: %s\n",
    ldap_err2string( parse_rc ) );
  ldap_unbind( ld );
  return( 1 );
}
if ( referrals != NULL ) {
  for ( i = 0; referrals[ i ] != NULL; i++ ) {
    printf( "Search reference: %s\n\n", referrals[ i ] );
  }
  ldap_value_free( referrals );
}
...

Sorting the Search Results With Directory SDK for C

Directory SDK for C offers functions to sort entries and values in the search results. You can either specify that the server return sorted results or you can sort entries on your client.

Server-Side Sorting

To sort results on the server, you need to send a server-side sorting control with the search request. For details, see Using the Server-Side Sorting Control With Directory SDK for C for details.

Client-Side Sorting

First, you need to retrieve the attributes that you plan to use for sorting. For example, you might plan to sort the results by email address. Make sure that the mail attribute is one of the attributes returned in the search.

Sorting Entries by an Attribute

To sort the search results by a particular attribute, call the ldap_sort_entries() function. If you do not specify an attribute for sorting, that is, if you pass NULL for the attr parameter, the entries are sorted by DN.

This example sorts entries by the roomNumber attribute.

#include <stdio.h>
#include <string.h>
#include "ldap.h"
...
LDAP *ld;
LDAPMessage *result;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
char *sortby = "roomNumber";
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
                    my_filter, NULL, 0, result ) != 
     LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}

/* Sort the results by room number, using strcasecmp. */
if ( ldap_sort_entries(ld, result, sortby, strcasecmp) !=
     LDAP_SUCCESS ){
  ldap_perror( ld, "ldap_sort_entries" );
  return( 1 );
}
...
Sorting Entries by Multiple Attributes

To sort the search results by multiple attributes, call the ldap_multisort_entries() function. If you do not specify a set of attributes for sorting, the entries are sorted by DN. To sort entries by DN, pass NULL for the attr parameter.

This example sorts entries first by the roomNumber attribute, then by the telephoneNumber attribute.

#include <stdio.h>
#include <string.h>
#include "ldap.h"
LDAP *ld;
LDAPMessage *res;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
char *attrs[2];
attrs[0] = "roomNumber";
attrs[1] = "telephoneNumber";
attrs[2] = NULL;
...
/* Search the directory. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
                    my_filter, NULL, 0, res ) !=
     LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}

/* Sort the results, using strcasecmp. */
if ( ldap_multisort_entries(ld,res,attrs, strcasecmp) !=
     LDAP_SUCCESS ){
  ldap_perror( ld, "ldap_sort_entries" );
  return( 1 );
}
Sorting the Values of an Attribute

You can also sort the values of a particular attribute. To sort the values, call the ldap_sort_strcasecmp() function. In this function, the comparison function must pass parameters of the type char **. You should use the ldap_sort_strcasecmp() function, rather than a function like strcasecmp(), which passes parameters of the type char *. The following example sorts the values of attributes before printing the values.

#include stdio.h>
#include string.h>
#include "ldap.h"
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a, *dn;
char **vals;
int i;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
    if ( ( vals = ldap_get_values( ld, e, a ) ) != NULL ) {
      /* Sort the values of the attribute */
      if ( ldap_sort_values(ld, vals, strcasecmp)) !=
           LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_sort_values" );
        return( 1 );
      }
      /* Print the values of the attribute. */
      for ( i = 0; vals[i] != NULL; i++ ) {
        printf( "%s: %s\n", a, vals[i] );
      }
      /* Free the values from memory. */
      ldap_value_free( vals );
    }
...

Freeing the Search Results With Directory SDK for C

The results of the search are returned in an LDAPMessage structure. After you are done working with the search results, you should free this structure from memory. To free the search results, call the ldap_msgfree() function, which returns the type of the last message freed from memory.

Examples of Search Operations With Directory SDK for C

This section contains sample code for various search operations.

Reading an Entry With a Search

You can use the search functions to read a specific entry in the directory. To read an entry, set the starting point of the search to the entry. Also, set the scope of the search to LDAP_SCOPE_BASE, specifying (objectclass=*) as the search filter, as shown in the following example.

#include <stdio.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORT_NUMBER  LDAP_PORT
#define FIND_DN "uid=bjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
    LDAP  *ld;
    LDAPMessage  *result, *e;
    BerElement  *ber;
    char  *a;
    char  **vals;
    int    i, rc;
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( HOSTNAME, PORT_NUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
    }
    /* Bind anonymously to the LDAP server. */
    if ( ( rc = ldap_simple_bind_s( ld, NULL, NULL ) ) !=
         LDAP_SUCCESS ) {
     fprintf( stderr,
              "ldap_simple_bind_s: %s\n",
              ldap_err2string( rc ) );
    return( 1 );
    }
    /* Search for the entry. */
    if ( ( rc = ldap_search_ext_s( ld, FIND_DN, LDAP_SCOPE_BASE, 
                                   "(objectclass=*)", NULL, 0, NULL,
                                   NULL, LDAP_NO_LIMIT,
                                   LDAP_NO_LIMIT, result ) ) !=
           LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) );
    return( 1 );
    }
    /* Since this is a base search, there should be only one
       matching entry.  */
    e = ldap_first_entry( ld, result );
  if ( e != NULL ) {
    printf( "\nFound %s:\n\n", FIND_DN );
    /* Iterate through each attribute in the entry. */
    for ( a = ldap_first_attribute( ld, e, ber );
      a != NULL; a = ldap_next_attribute( ld, e, ber ) ) {
      /* For each attribute, print the attribute name and values. */
      if ((vals = ldap_get_values( ld, e, a)) != NULL ) {
        for ( i = 0; vals[i] != NULL; i++ ) {
          printf( "%s: %s\n", a, vals[i] );
        }
        ldap_value_free( vals );
      }
      ldap_memfree( a );
    }
    if ( ber != NULL ) {
      ber_free( ber, 0 );
    }
  }
  ldap_msgfree( result );
  ldap_unbind( ld );
  return( 0 );
}

Listing Subentries With a Search

You can use the search functions to list the subentries under a specific entry in the directory. To list the subentries, set the starting point of the search to the entry. Also, set the scope of the search to LDAP_SCOPE_ONELEVEL. The following lists all entries one level under the dc=example,dc=com entry in the directory hierarchy.

#include <stdio.h>
#include "ldap.h"

LDAP        *ld;
LDAPMessage *result, *e;
BerElement  *ber;
char        *a, *dn;
char        **vals;
char        *my_searchbase = "dc=example,dc=com";
char        *my_filter = "(objectclass=*)"

/* Search one level under the starting point. */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_ONELEVEL, my_filter,
      NULL, 0, result ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}
/* For each matching entry, print the entry name and its attributes. */
for ( e = ldap_first_entry( ld, result ); e != NULL;
      e = ldap_next_entry( ld, e ) ) {
  if ( ( dn = ldap_get_dn( ld, e ) ) != NULL ) {
    printf( "dn: %s\n", dn );
    ldap_memfree( dn );
  }
  for ( a = ldap_first_attribute( ld, e, ber ); a != NULL;
      a = ldap_next_attribute( ld, e, ber ) ) {
    if ( ( vals = ldap_get_values( ld, e, a ) ) != NULL ) {
      for ( i = 0; vals[i] != NULL; i++ ) {
        printf( "%s: %s\n", a, vals[i] );
      }
      ldap_value_free( vals );
    }
    ldap_memfree( a );
  }
  if ( ber != NULL ) {
    ldap_ber_free( ber, 0 );
  }
  printf( "\n" );
}
ldap_msgfree( result );
...

Sending Search Request Using Directory SDK for C

The following sample code shows how to search for all entries with the last name (surname) Jensen in the example.com organization.

#include <stdio.h>
#include "ldap.h"
...
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(sn=Jensen)"
...
LDAP      *ld;
int      msgid, rc;
...
/* Send the search request. */
rc = ldap_search_ext( ld, BASEDN, SCOPE, FILTER, NULL, 0, NULL,
  NULL, NULL, LDAP_NO_LIMIT, msgid );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_search_ext: %s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
...

Using Filter Configuration Files With Directory SDK for C

This section explains how to use LDAP C API functions to work with filter configuration files.

Understanding Filter Configuration Files for Directory SDK for C

Filter configuration files can help simplify the process of selecting the appropriate filter for a search request. A filter configuration file contains a list of filters that you can load and use in your searches. You might be writing a client that allows users to search the directory. Use different search filters tailored for specific types of search criteria.

For example, if the user wants to search for the email address bjensen@example.com, you might want to use this search filter:

(mail=bjensen@example.com)

Similarly, suppose the search term entered by the user contains numbers, as in 555-1212. In this case, you might want to use this search filter:

(telephoneNumber=555-1212)

Rather than write code to find and select the appropriate filter, you can include the filters in a filter configuration file. For example, the following section of a filter configuration file specifies one filter for telephone numbers and two filters for email addresses. The telephone number filter is used if the search criteria contain one or more numbers. The email filters are used if the search criteria contain an at sign, @.

"people"
  "^[0-9][0-9-]*$"           " "
  "(telephoneNumber=*%v))"   "phone number ends with"
  "@"    " "  "(mail=%v)"    "email address is"
  "(mail=%v*)"               "email address starts with"

You should specify the filters in the order that you want the filters to be used. For example, if you want to apply the (mail=%v) filter before the (mail=%v*) filter, make sure that the filters appear in that order.

Syntax for Filter Configuration Files

A filter configuration file has the following format. The variables are discussed in the following sections.

''tag''
  ''pattern1''    ''delimiters''    ''filter1-1''  ''desc1-1''  [''scope'']
  ''filter1-2''   ''desc1-2''                           [''scope'']
  ''pattern2''    ''delimiters''    ''filter2-1''  ''desc2-1''  [''scope'']
Tag for Filter Groups

A tag identifies a group of filters. You can use different tags to distinguish filters for different types of objects. For example, you can use one tag to represent filters for person entries, another tag to represent filters for organization entries, and so on.

"people"
     (filters for searching "person" entries) 
"organization"
     (filters for "organization" entries)

When you call functions like ldap_getfirstfilter() to retrieve a filter, you can specify a tag, or part of a tag, as a parameter. The tag narrows the list of filters that the function can retrieve.

Patterns to Select Filters

pattern1 and pattern2 are regular expressions used to determine which filter is selected, based on the search criteria. For example, if you specify "^[0-9]" as the pattern for a filter, the filter is selected for all search criteria that begin with a number.

"people"
  "^[0-9]" 
Delimiters for Fields

Delimiters specifies the delimiters used to distinguish one field from another field within the search criteria. For example, if the search criteria consist of a city name and a state abbreviation separated by a comma, specify a comma as the delimiter.

Filter Lists

filter1-1, filter1-2, and filter2-1 are filters. Use %v to represent the search criteria. For example, to search email addresses, use the filter (mail=%v). During runtime, if the search criteria bjensen@example.com is entered, the filter becomes (mail=bjensen@example.com).

The search criteria might consist of a number of delimited fields. For example, the criteria might have a last name, first name format such as Jensen, Barbara. Use %v1, %v2, , %vn to represent the different fields within the search criteria as shown here:

"people"
  "^[A-Z]*,"      ","    ((sn=%v1)(givenName=%v2))

In this example, the delimiter is a comma. The word before the delimiter replaces %v1 in the filter. The word after the delimiter replaces %v2 in the filter. If the user searches for Jensen, Barbara , the resulting filter is as follows:

((sn=Jensen)(givenName=Barbara)) You can also specify ranges of fields. For example, to specify the values in the first three fields, use %v1-3. To specify values from the third field to the last field, use %v3-. To specify the value in the last field, use %v$.

Descriptions of Filters

desc1-1, desc1-2, and desc2-1 are phrases that briefly describe the filters.

Filter Parameters

Filter specifications in the configuration file support the following parameters:

  • %v
    Insert the search criterion as is in place of %v.
    For example, if the filter specification is (mail=%v), entering bjensen results in the filter (mail=bjensen).
  • %v$
    Insert the last word of the search criterion as is in place of %v.
    For example, if the filter specification is (sn=%v$), entering Barbara Jensen results in the filter (sn=Jensen).
  • %vN
    Insert the Nth word of the criteria in place of %v, where N is a single digit between 1 and 9.
    For example, if the filter specification is (sn=%v2), entering Barbara Jensen results in the filter (sn=Jensen).
  • %vM-N
    Insert the sequence of the Mth through Nth words of the criteria in place of %v. Here, M and N are single digits between 1 and 9.
    For example, if the filter specification is (cn=%v1-2), entering Barbara Jensen results in the filter (cn=Barbara Jensen).
  • %vN-
    Insert the sequence of the Nth through last words of the criteria in place of %v. Here, N is a single digit between 1 and 9.
    For example, if the filter specification is (cn=%v2-), entering Ms. Barbara Jensen results in the filter (cn=Barbara Jensen).

Loading Filter Configuration Files With Directory SDK for C

To load a filter configuration file, call the ldap_init_getfilter() function. You can also read the filter configuration file from a buffer in memory by calling the ldap_init_getfilter_buf() function. Both functions return a pointer to an LDAPFiltDesc structure, which contains information about the filter. If an error occurs, both functions return NULL.

Retrieving Filters

After loading a filter configuration file into memory, you can retrieve filters based on the search criteria. For example, the search criteria might be an email address, (bjensen@example.com). Have your client automatically search for this value in the mail attribute of person entries.

To retrieve the first filter that matches the search criteria, call the ldap_getfirstfilter() function. To get the next filter that matches the search criteria, call the ldap_getnextfilter() function. Both functions return a pointer to an LDAPFiltInfo structure, which contains information about the filter, as shown here.

#include <stdio.h>
#include "ldap.h"

LDAP          *ld;
LDAPMessage   *result, *e;
BerElement    *ber;
char          *a, *dn;
char          **vals;
int i;
LDAPFiltDesc *ldfp;
LDAPFiltInfo *ldfi;
char buf[ 80 ]; /* contains the search criteria */
int found;

/* Load the filter configuration file into an LDAPFiltDesc structure. */
if ( ( ldfp = ldap_init_getfilter( "myfilters.conf" ) ) == NULL ) {
  perror( "Cannot open filter configuration file" );
}

/* Select a filter to use when searching for the value in buf.
Use filters under the "people" tag in the filter configuration file. */
found = 0;
for ( ldfi = ldap_getfirstfilter( ldfp, "people", buf ); ldfi != NULL;
  ldfi = ldap_getnextfilter( ldfp ) ) {

  /* Use the selected filter to search the directory. */
  if ( ldap_search_s( ld, "dc=example,dc=com", ldfi->lfi_scope,
   ldfi->lfi_filter, NULL, 0, result ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
  } else {

    /* Once a filter gets results back, stop iterating through
    the different filters. */
    if ( ( found = ldap_count_entries( ld, result ) > 0 ) ) {
      break;
    } else {
      ldap_msgfree( result );
    }
  }
}

if ( found == 0 ) {
  printf( "No matching entries found.\n" );
} else {
  printf( "Found %d match%s where %s \"%s\"\n\n", found,
   found == 1 ? "" : "es", ldfi->lfi_desc, buf );
}

ldap_msgfree( result );
ldap_getfilter_free( ldfp );

Suppose that the search criteria is bjensen@example.com and that the client application finds a single matching entry. Then the application prints the following output:

Found 1 match where email address is bjensen@example.com

Filter Prefixes and Suffixes for Directory SDK for C

If you need to apply a filter to all searches, add a filter prefix and suffix to all filters. Do not add the criteria to all filters. The prefix is automatically added to any filter retrieved through the ldap_getfirstfilter() and ldap_getnextfilter() functions. The required suffix ) needed to balance the number of parentheses is also added. For example, suppose you use this filter in a filter configuration file:

(cn=Babs Jensen)

You can retrieve this filter by using ldap_getfirstfilter() or ldap_getnextfilter(). These functions get a filter that constrains your client searches to person entries for the defined filter:

((objectClass=person)(cn=Babs Jensen))

To add a prefix and suffix automatically to all filters retrieved from the filter configuration file, call the ldap_set_filter_additions() function. The following example adds the prefix ((objectClass=person) and the suffix ) to each filter retrieved.

#include "ldap.h"

LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";
char *prefix = "((objectClass=person)";
char *suffix = ")";

lfdp = ldap_init_getfilter( filter_file );
ldap_setfilteraffixes( lfdp, prefix, suffix );

Freeing Filters From Memory With Directory SDK for C

When you complete your search, free the LDAPFiltDesc structure from memory. To free LDAPFiltDesc, call the ldap_getfilter_free() function as shown here.

#include "ldap.h"

LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";

/* Read the filter configuration file into an LDAPFiltDesc structure. */
lfdp = ldap_init_getfilter( filter_file );

/* Retrieve filters and perform searches. */

/* Free the configuration file (the LDAPFiltDesc structure). */
ldap_getfilter_free( lfdp );

Creating Filters Programmatically With Directory SDK for C

You can build your own filters by calling the ldap_create_filter() function. The following example builds the filter (mail=bjensen@example.com).

char buf[LDAP_FILT_MAXSIZ];
char *pattern = "(%a=%v);
char *attr = "mail";
char *value = "bjensen@example.com";

ldap_create_filter( buf, LDAP_FILT_MAXSIZ, pattern, NULL, NULL, attr,
    value, NULL );

Adding, Updating, and Deleting Entries With Directory SDK for C

This section explains how to use LDAP C API functions to add, update, delete, and rename entries.

Specifying Entry Information With Directory SDK for C

The type of attribute that you are working with. For example, the sn attribute or the telephoneNumber attribute.

  • The values that you are adding, or replacing in the attribute.
  • The operation that you are performing when modifying an existing entry. In other words, determine whether you are adding, modifying, or deleting the attribute in the existing entry.
  • To specify this information, you use an LDAPMod structure as shown here.
typedef struct ldapmod {
  int mod_op;
  char *mod_type;
  union {
    char **modv_strvals;
    struct berval **modv_bvals;
  } mod_vals;
#define mod_values        mod_vals.modv_strvals
#define mod_bvalues       mod_vals.modv_bvals
} LDAPMod;

The following list details the fields in the LDAPMod data structure.

  • mod_op
    • LDAP_MOD_ADD adds a value to the attribute.
    • LDAP_MOD_DELETE removes a value from the attribute.
    • LDAP_MOD_REPLACE replaces all existing values of the attribute.
      Furthermore, if you specify binary values in the mod_bvalues field, use the bitwise or operator, |, to combine LDAP_MOD_BVALUES with the operation type:
      mod->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES
      If you are using the structure to add a new entry, you can specify 0 for the mod_op field, unless you are adding binary values and need to specify LDAP_MOD_BVALUES.
  • mod_type
    Attribute type that you want to add, delete, or replace, such as sn or telephoneNumber.
  • mod_values
    Pointer to a NULL terminated array of string values for the attribute.
  • mod_bvalues
    Pointer to a NULL terminated array of berval structures for the attribute.

The following precautions pertain to entry modifications and the fields detailed in this list.

  • If you specify LDAP_MOD_DELETE in the mod_op field to remove all values in an attribute, the attribute is removed from the entry.
  • If you specify LDAP_MOD_DELETE in the mod_op field and NULL in the mod_values field, the attribute is removed from the entry.
  • If you specify LDAP_MOD_REPLACE in the mod_op field and NULL in the mod_values field, the attribute is removed from the entry.
  • If you specify LDAP_MOD_REPLACE in the mod_op field, but the attribute does not exist in the entry, the attribute is added to the entry.
  • If you specify LDAP_MOD_ADD in the mod_op field, but the attribute does not exist in the entry, the attribute is added to the entry.

If you allocate memory for the structures yourself, free the structures when you finish by calling the ldap_mods_free() function.

Adding an Entry With Directory SDK for C

The following procedure provides the general steps for adding a new entry to the directory.

To Add a New Entry

  1. Use the LDAPMod structure to specify the name and values of each attribute.
  2. Create an array of LDAPMod structures to represent the attributes in the entry.
  3. Call the ldap_add_ext() or ldap_add_ext_s() function, passing in the array of LDAPMod structures and a distinguished name (DN) for the entry.
  4. Call the ldap_mods_free function to free any LDAPMod structures that you allocated.

Specifying Values for Attributes

You can specify a value for an attribute in three ways. You can specify a single value. You can specify multiple values. You can add binary data as the value of an attribute.

Specifying a Single Value in an Attribute

To specify a value in an attribute, set the mod_op, mod_type, and mod_values fields in an LDAPMod structure. This example sets up the structure for the sn attribute.

#include "ldap.h"

LDAPMod attribute1;
char *sn_values[] = { "Jensen", NULL };

attribute1.mod_op = 0;
attribute1.mod_type = "sn";
attribute1.mod_values = sn_values;

Because you are specifying an attribute for a new entry, rather than for an existing entry, you can set the mod_op field to 0. For an existing entry, the mod_op field identifies the type of change you are making to the entry.

Specifying Multiple Values in an Attribute

If an attribute has more than one value, specify the values in the mod_values array. This example specifies two values for the cn attribute.

#include "ldap.h"

LDAPMod attribute2, attribute3;
char *cn_values[] = { "Barbara Jensen", "Babs Jensen", NULL };
char *objectClass_values[] = { "top", "person",
   "organizationalPerson", "inetOrgPerson", NULL };

attribute2.mod_op = 0;
attribute2.mod_type = "cn";
attribute2.mod_values = cn_values;
attribute3.mod_op = 0;
attribute3.mod_type = "objectClass";
attribute3.mod_values = objectClass_values;
Specifying Binary Data as the Value of an Attribute

If the attribute contains binary data rather than string values, specify the data in a berval structure similar to this.

struct berval {
   unsigned long bv_len;
   char *bv_val;
}

The berval structure fields and field descriptions are as follows:

bv_len: The length of the data

bv_val: A pointer to the binary data

After creating the berval structures for the binary data, you may use the structures.

To Use berval Structures

  1. Add the berval structures to the mod_bvalues field in the LDAPMod structure.
  2. Use the bitwise or operator, |, to combine the value of the mod_op field with LDAP_MOD_BVALUES.
    When adding a new entry, you set the mod_op field to LDAP_MOD_BVALUES because the mod_op field is 0 in this case.
    For example, suppose the file my_photo.jpg contains a JPEG photograph of Barbara Jensen. The following example sets the jpegPhoto attribute to the JPEG data of the photograph.
#include <stdio.h>
#include <sys/stat.h>
#include "ldap.h"

char *photo_data;
FILE *fp;
struct stat st;
LDAPMod attribute4;
struct berval photo_berval;
struct berval *jpegPhoto_values[2];
/* Get information about the JPEG file, including its size. */
if ( stat( "my_photo.jpg", st ) != 0 ) {
  perror( "stat" );
  return( 1 );
}

/* Open the JPEG file and read it into memory. */
if ( ( fp = fopen( "my_photo.jpg", "rb" ) ) == NULL ) {
  perror( "fopen" );
  return( 1 );
}
if ( ( ( photo_data = ( char * )malloc( st.st_size ) ) == NULL ) ||
      ( fread ( photo_data, st.st_size, 1, fp ) != 1 ) ) {
  perror( photo_data ? "fread" : "malloc" );
  return( 1 );
}

fclose( fp );

attribute4.mod_op = LDAP_MOD_BVALUES;
attribute4.mod_type = "jpegPhoto";
photo_berval.bv_len = st.st_size;
photo_berval.bv_val = photo_data;
jpegPhoto_values[0] = photo_berval;
jpegPhoto_values[1] = NULL;
attribute4.mod_values = jpegPhoto_values;

Specifying Attributes in the Entry

After specifying values for attributes in LDAPMod structures, as described in Specifying Values for Attributes, you need to construct an array of these structures. You then pass a pointer to this array as a parameter to the function for creating a new entry.

Make sure you create LDAPMod structures for all required attributes in the new entry.

The following example creates an array of LDAPMod structures.


#include "ldap.h"
LDAPMod *list_of_mods[5]
LDAPMod attribute1, attribute2, attribute3, attribute4;

/* Code for filling the LDAPMod structures with values */

list_of_mods[0] = attribute1;
list_of_mods[1] = attribute2;
list_of_mods[2] = attribute3;
list_of_mods[3] = attribute4;
list_of_mods[4] = NULL;

Adding the Entry to the Directory

  • The synchronous ldap_add_ext_s() function
  • The asynchronous ldap_add_ext() function

If you have allocated LDAPMod structures yourself, you should free the structures when you are done. Call the ldap_mods_free() function to free LDAPMod structures.

Synchronous Add Operation

If you want to wait for the results of the add operation to complete before continuing, call the synchronous ldap_add_ext_s() function. This function sends an LDAP add request to the server. The function also blocks other work until the server sends the results of the operation back to your client. The ldap_add_ext_s() function returns LDAP_SUCCESS if the operation completed successfully, or an error code if a problem occurred.

The following example calls the synchronous ldap_add_ext_s() function to add the user William Jensen to the directory.

#include <stdio.h>
#include "ldap.h"

#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"

LDAP         *ld;
LDAPMod      **mods;
char         *matched_msg = NULL, *error_msg = NULL;
int         rc;

/* Perform the add operation. */
rc = ldap_add_ext_s( ld, NEW_DN, mods, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_add_ext_s: %s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg != NULL  *error_msg != '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  if ( matched_msg != NULL  *matched_msg != '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry: %s\n",
      matched_msg );
  }
} else {
  printf( "%s added successfully.\n", NEW_DN );
}

The following sample program calls the synchronous ldap_add_ext_s() function to add a new user to the directory.

#include <stdio.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define  NUM_MODS 5
int
main( int argc, char **argv )
{
  LDAP           *ld;
  LDAPMod        **mods;
  char           *matched_msg = NULL, *error_msg = NULL;
    int          i, rc;
  char *object_vals[] = { "top", "person", "organizationalPerson",
    "inetOrgPerson", NULL };

char *cn_vals[] = { "William B Jensen", "William Jensen", "Bill Jensen",
    NULL };
    char *sn_vals[] = { "Jensen", NULL };
    char *givenname_vals[] = { "William", "Bill", NULL };
    char *telephonenumber_vals[] = { "+1 415 555 1212", NULL };
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
    }
    /* Bind to the server as the Directory Manager. */
    rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
    }
    /* Construct the array of LDAPMod structures representing the attributes
     of the new entry. */
    mods = ( LDAPMod ** ) malloc(( NUM_MODS + 1 ) * sizeof( LDAPMod * ));
    if ( mods == NULL ) {
    fprintf( stderr, "Cannot allocate memory for mods array\n" );
    exit( 1 );
    }
    for ( i = 0; i  NUM_MODS; i++ ) {
    if (( mods[ i ] = ( LDAPMod * ) malloc( sizeof( LDAPMod ))) == NULL ) {
      fprintf( stderr, "Cannot allocate memory for mods element\n" );
      exit( 1 );
    }
    }
    mods[ 0 ]->mod_op = 0;
    mods[ 0 ]->mod_type = "objectclass";
    mods[ 0 ]->mod_values = object_vals;
    mods[ 1 ]->mod_op = 0;
    mods[ 1 ]->mod_type = "cn";
    mods[ 1 ]->mod_values = cn_vals;
    mods[ 2 ]->mod_op = 0;
    mods[ 2 ]->mod_type = "sn";
    mods[ 2 ]->mod_values = sn_vals;
    mods[ 3 ]->mod_op = 0;
    mods[ 3 ]->mod_type = "givenname";
    mods[ 3 ]->mod_values = givenname_vals;
    mods[ 4 ]->mod_op = 0;
    mods[ 4 ]->mod_type = "telephonenumber";
    mods[ 4 ]->mod_values = telephonenumber_vals;
    mods[ 5 ] = NULL;
    /* Perform the add operation. */
    rc = ldap_add_ext_s( ld, NEW_DN, mods, NULL, NULL );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_add_ext_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    } else {
    printf( "%s added successfully.\n", NEW_DN );
  }
  ldap_unbind_s( ld );
  for ( i = 0; i  NUM_MODS; i++ ) {
    free( mods[ i ] );
  }
  free( mods );
  return 0;
}
Asynchronous Add Operation

If you want to perform other work while waiting for the entry to be added, call the asynchronous ldap_add_ext() function. This function sends an LDAP add request to the server and returns an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred.

The ldap_add_ext() function passes back a message ID identifying the add operation. To determine whether the server sent a response for this operation to your client, call the ldap_result() function and pass in this message ID. The ldap_result() function uses the message ID to determine if the server sent the results of the add operation. The ldap_result() function passes back the results in an LDAPMessage structure. You can call the ldap_parse_result() function to parse the LDAPMessage structure to determine if the operation was successful.

The following example calls the asynchronous ldap_add_ext() function to add the user William Jensen to the directory.

#include <stdio.h>
#include "ldap.h"

#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"


LDAP           *ld;
LDAPMessage    *res;
LDAPControl    **serverctrls;
char           *matched_msg = NULL, *error_msg = NULL;
char           **referrals;
int            i, rc, parse_rc, msgid, finished = 0;

/* Timeout period for the ldap_result() function to wait for results. */
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;

/* Send the LDAP add request. */
rc = ldap_add_ext( ld, NEW_DN, mods, NULL, NULL, msgid );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}

/* Poll the server for the results of the add operation. */
while ( !finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  case -1:
    /* An error occurred. */
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  case 0:
    /* The timeout period specified by zerotime was exceeded,
      so call ldap_result() again and continue polling. */
    break;
  default:
    /* The function has retrieved the results of the add operation. */
    finished = 1;

    /* Parse the result to determine the result of
      the add operation. */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result: %s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }

    /* Check the results of the LDAP add operation. */
    if ( rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) );
      if ( error_msg != NULL  *error_msg != '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      if ( matched_msg != NULL  *matched_msg != '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry: %s\n",
          matched_msg );
      }
    } else {
      printf( "%s added successfully.\n", NEW_DN );
    }
  }
}

The following sample program calls the asynchronous ldap_add_ext() function to add a new user to the directory.

#include <stdio.h>
#include "ldap.h"
void do_other_work();
int global_counter = 0;
void free_mods( LDAPMod **mods );
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define  NUM_MODS 5
int
main( int argc, char **argv )
{
    LDAP      *ld;
    LDAPMessage    *res;
    LDAPMod      **mods;
  LDAPControl    **serverctrls;
  char           *matched_msg = NULL, *error_msg = NULL;
  char           **referrals;
    int        i, rc, parse_rc, msgid, finished = 0;
    struct timeval  zerotime;
    char *object_vals[] = { "top", "person", "organizationalPerson", 
                            "inetOrgPerson", NULL };
    char *cn_vals[] = { "William B Jensen", "William Jensen",
                        "Bill Jensen", NULL };
    char *sn_vals[] = { "Jensen", NULL };
    char *givenname_vals[] = { "William", "Bill", NULL };
    char *telephonenumber_vals[] = { "+1 415 555 1212", NULL };
    zerotime.tv_sec = zerotime.tv_usec = 0L;
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
    }
    /* Bind to the server as the Directory Manager. */
    rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
    }
    /* Construct the array of LDAPMod structures representing the attributes
     of the new entry. */
    mods = ( LDAPMod ** ) malloc(( NUM_MODS + 1 ) * sizeof( LDAPMod * ));
    if ( mods == NULL ) {
    fprintf( stderr, "Cannot allocate memory for mods array\n" );
    exit( 1 );
    }
    for ( i = 0; i  NUM_MODS; i++ ) {
    if (( mods[ i ] = ( LDAPMod * ) malloc( sizeof( LDAPMod ))) == NULL ) {
      fprintf( stderr, "Cannot allocate memory for mods element\n" );
      exit( 1 );
    }
    }
    mods[ 0 ]->mod_op = 0;
    mods[ 0 ]->mod_type = "objectclass";
    mods[ 0 ]->mod_values = object_vals;
    mods[ 1 ]->mod_op = 0;
    mods[ 1 ]->mod_type = "cn";
    mods[ 1 ]->mod_values = cn_vals;
    mods[ 2 ]->mod_op = 0;
    mods[ 2 ]->mod_type = "sn";
    mods[ 2 ]->mod_values = sn_vals;
    mods[ 3 ]->mod_op = 0;
    mods[ 3 ]->mod_type = "givenname";
    mods[ 3 ]->mod_values = givenname_vals;
    mods[ 4 ]->mod_op = 0;
    mods[ 4 ]->mod_type = "telephonenumber";
    mods[ 4 ]->mod_values = telephonenumber_vals;
    mods[ 5 ] = NULL;
    /* Send the LDAP add request. */
    rc = ldap_add_ext( ld, NEW_DN, mods, NULL, NULL, msgid );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    free_mods( mods );
    return( 1 );
    }
    /* Poll the server for the results of the add operation. */
    while ( !finished ) {
    rc = ldap_result( ld, msgid, 0, zerotime, res );
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      free_mods( mods );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
         This means that the server has still not yet sent the
         results of the add operation back to your client.
         Break out of this switch statement, and continue calling
         ldap_result() to poll for results. */
      break;
    default:
      /* The function has retrieved the results of the add operation
         from the server. */
      finished = 1;
      /* Parse the results received from the server. Note the last
         argument is a non-zero value, which indicates that the
         LDAPMessage structure will be freed when done.  (No need
         to call ldap_msgfree().) */
      parse_rc =
        ldap_parse_result( ld, res, rc, matched_msg,
                           error_msg, referrals, serverctrls, 1 );
      if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr,
                 "ldap_parse_result: %s\n", 
                 ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        free_mods( mods );
        return( 1 );
      }
      /* Check the results of the LDAP add operation. */
      if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) );
        if ( error_msg != NULL  *error_msg != '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg != NULL  *matched_msg != '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry: %s\n",
            matched_msg );
        }
      } else {
        printf( "%s added successfully.\n"
          "Counted to %d while waiting for the add operation.\n",
          NEW_DN, global_counter );
      }
    }
    /* Do other work while waiting for the results of the add operation. */
    if ( !finished ) {
      do_other_work();
    }
  }
  ldap_unbind( ld );
  free_mods( mods );
  return 0;
}
/*
 * Free a mods array.
 */
void
free_mods( LDAPMod **mods )
{
    int i;
    for ( i = 0; i  NUM_MODS; i++ ) {
  free( mods[ i ] );
    }
    free( mods );
}

/*
 * Perform other work while polling for results.
 * This doesn't do anything useful, but it could.
 */
void
do_other_work()
{
    global_counter++;
}

Modifying an Entry With Directory SDK for C

The following procedure provides the general steps for modifying an entry.

To Modify an Entry

  1. Use the LDAPMod structure to specify a change to an attribute.
  2. Create an array of LDAPMod structures that represent the changes that need to be made.
  3. Call the ldap_modify_ext() or ldap_modify_ext_s() function, passing in the array of LDAPMod structures and the DN of the entry that you want modified.
  4. Call the ldap_mods_free() function to free any LDAPMod structures that you allocated.

Types of Modifications

You can modify an entry in various ways. The following sections explain the types of modifications.

Replacing the Values of an Attribute
  • Set the mod_type field to the attribute type that you want to change, such as telephoneNumber.
  • Set the mod_values field to the new values of the attribute.
  • Set the value of the mod_op field to LDAP_MOD_REPLACE.

The following code specifies a change that replaces the values of the telephoneNumber attribute.

#include "ldap.h"
LDAPMod attribute1;
char *telephoneNumber_values[] = { "+1 800 555 1212", NULL };
attribute1.mod_type = "telephoneNumber";
attribute1.mod_op = LDAP_MOD_REPLACE;
attribute1.mod_values = telephoneNumber_values;
  • Use the mod_bvalues field rather than the mod_values field.
  • Use the bitwise or operator, |, to combine the value LDAP_MOD_BVALUES with the value of the mod_op field.

Note: If you specify an attribute that does not exist in the entry, the attribute is added to the entry.

You can set a NULL value for the attribute either by setting the mod_values field to NULL or by setting the mod_bvalues field to NULL. When the mod_op field also contains LDAP_MOD_BVALUES, the attribute is removed from the entry.

Removing Values From an Attribute
  • Set the mod_type field to the attribute type that contains the values to remove such as facsimileTelephoneNumber.
  • Set the mod_values field to the values that you want removed from the attribute.
  • Set the value of the mod_op field to LDAP_MOD_DELETE.
    The following code specifies the removal of one of the values of the facsimileTelephoneNumber attribute in the entry.
include "ldap.h"
LDAPMod attribute2;
char *fax_values[] = { "+1 800 555 1212", NULL };
attribute2.mod_type = "facsimileTelephoneNumber";
attribute2.mod_op = LDAP_MOD_DELETE;
attribute2.mod_values = fax_values;
  • Use the mod_bvalues field rather than the mod_values field.
  • Use the bitwise or operator, |, to combine the value LDAP_MOD_BVALUES with the value of the mod_op field.

Note: If you remove all values from the attribute, the attribute is removed from the entry.

You can set a NULL value for the attribute either by setting the mod_values field to NULL, or by setting the mod_bvalues field to NULL. When the mod_op field then contains LDAP_MOD_BVALUES, the attribute is removed from the entry.

Adding Values to an Attribute
  • Set the mod_type field to the attribute type that you want to add values to, such as audio.
  • Set the mod_values field to the new values of the attribute.
  • Set the value of the mod_op field to LDAP_MOD_ADD.
  • Use the mod_bvalues field rather than the mod_values field, and put the values in berval structures.
  • Use the bitwise or operator, |, to combine the value LDAP_MOD_BVALUES with the value of the mod_op field.

If the attribute does not already exist in the entry, the attribute is added to the entry.

The following code adds values to the audio attribute of an entry.

#include <stdio.h>
#include <sys/stat.h>
#include "ldap.h"

char *audio_data;
FILE *fp;
struct stat st;
LDAPMod attribute3;
struct berval audio_berval;
struct berval *audio_values[2];

/* Get information about the audio file, including its size. */
if ( stat( "my_sounds.au", st ) != 0 ) {
  perror( "stat" );
  return( 1 );
}

/* Open the audio file and read it into memory. */
if ( ( fp = fopen( "my_sounds.au", "rb" ) ) == NULL ) {
  perror( "fopen" );
  return( 1 );
}

if ( ( ( audio_data = ( char * )malloc( st.st_size ) ) == NULL ) ||
      ( fread ( audio_data, st.st_size, 1, fp ) != 1 ) ) {
  perror( audio_data ? "fread" : "malloc" );
  return( 1 );
}

fclose( fp );
attribute3.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
attribute3.mod_type = "audio";
audio_berval.bv_len = st.st_size;
audio_berval.bv_val = audio_data;
audio_values[0] = audio_berval;
audio_values[1] = NULL;
attribute3.mod_values = audio_values;
Removing an Attribute With Directory SDK for C
  • Remove all values from the attribute.
  • Set the mod_op field to LDAP_MOD_REPLACE or LDAP_MOD_DELETE, and specify NULL for the mod_values field.
Adding an Attribute With Directory SDK for C

If you add or replace values in an attribute that does not yet exist in the entry, the attribute is added to the entry.

Creating an Array of Changes

After specifying the changes to attribute values in LDAPMod structures, you need to construct an array of these structures. You pass a pointer to this array as a parameter to the function for modifying the entry. The following example creates an array of LDAPMod structures.

#include "ldap.h"

LDAPMod *list_of_mods[4]
LDAPMod attribute1, attribute2, attribute3;

/* Code for filling the LDAPMod structures with values */

list_of_mods[0] = attribute1;
list_of_mods[1] = attribute2;
list_of_mods[2] = attribute3;
list_of_mods[3] = NULL;

Modifying an Entry in the Directory With Directory SDK for C

  • The synchronous ldap_modify_ext_s() function
  • The asynchronous ldap_modify_ext() function
Synchronous Modify Operation

If you want to wait for the results of the modify operation to complete before continuing, call the synchronous ldap_modify_ext_s() function. The function sends a modify request to the server. Also, the function blocks all work until the server sends the results of the operation back to your client. The function returns LDAP_SUCCESS if the operation completed successfully, or an error code if a problem occurred.

The following example calls the synchronous ldap_modify_ext_s() function to modify the entry for the user William Jensen in the directory.

#include <stdio.h>
#include "ldap.h"

#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"

LDAP      *ld;
LDAPMod   *mods[ 3 ];
char      *matched_msg = NULL, *error_msg = NULL;
int        rc;

/* Perform the modify operation. */
rc = ldap_modify_ext_s( ld, MODIFY_DN, mods, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_modify_ext_s: %s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg != NULL  *error_msg != '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  if ( matched_msg != NULL  *matched_msg != '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry: %s\n",
      matched_msg );
  }
} else {
  printf( "%s modified successfully.\n", MODIFY_DN );
}
ldap_unbind_s( ld );

The following sample program calls the synchronous ldap_modify_ext_s() function to modify a user entry in the directory. The program replaces the values of the mail attribute and adds a description attribute to the entry.

#include <stdio.h>
#include <time.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
  LDAP         *ld;
  LDAPMod      mod0, mod1;
  LDAPMod      *mods[ 3 ];
  char         *matched_msg = NULL, *error_msg = NULL;
  char         *vals0[ 2 ], *vals1[ 2 ];
  time_t       now;
  char         buf[ 128 ];
  int          rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Construct the array of LDAPMod structures representing the
   changes that you want to make to attributes in the entry. */
/* Specify the first modification, which replaces all values of the
mail attribute with the value "wbj@example.com". */
  mod0.mod_op = LDAP_MOD_REPLACE;
  mod0.mod_type = "mail";
  vals0[0] = "wbj@example.com";
  vals0[1] = NULL;
  mod0.mod_values = vals0;
/* Specify the second modification, which adds a value to the
   description attribute. If this attribute does not yet exist,
   the attribute ia added to the entry. */
  mod1.mod_op = LDAP_MOD_ADD;
  mod1.mod_type = "description";
  time( now );
  sprintf( buf, "This entry was modified with the modattrs program on %s",
  ctime( now ));
/* Get rid of \n which ctime put on the end of the time string */
  if ( buf[ strlen( buf ) - 1 ] == '\n' ) {
    buf[ strlen( buf ) - 1 ] = '\0';
  }
  vals1[ 0 ] = buf;
  vals1[ 1 ] = NULL;
  mod1.mod_values = vals1;
  mods[ 0 ] = mod0;
  mods[ 1 ] = mod1;
  mods[ 2 ] = NULL;
/* Perform the modify operation. */
  rc = ldap_modify_ext_s( ld, MODIFY_DN, mods, NULL, NULL );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_modify_ext_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
  } else {
    printf( "%s modified successfully.\n", MODIFY_DN );
  }
  ldap_unbind_s( ld );
  return 0;
}
Asynchronous Modify Operation

If you want to perform other work in parallel while waiting for the entry to be modified, call the asynchronous ldap_modify_ext() function. This function sends a modify request to the server and returns an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred.

The ldap_modify_ext() function passes back a message ID identifying the modify operation. To determine whether the server sent a response for this operation to your client, call the ldap_result() function and pass in this message ID. The ldap_result() function uses the message ID to determine if the server sent the results of the modify operation. The ldap_result() function passes back the results in an LDAPMessage structure. You can call the ldap_parse_result() function to parse the LDAPMessage structure to determine if the operation was successful.

The following example calls the asynchronous ldap_modify_ext() function to modify the entry for the user William Jensen in the directory.

#include <stdio.h>
#include "ldap.h"

#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"

LDAP      *ld;
LDAPMessage    *res;
LDAPMod      *mods[ 3 ];
LDAPControl    **serverctrls;
char      *matched_msg = NULL, *error_msg = NULL;
char      **referrals;
int        rc, parse_rc, msgid, finished = 0;

/* Timeout period for the ldap_result() function to wait for results. */
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;

/* Send the LDAP modify request. */
rc = ldap_modify_ext( ld, MODIFY_DN, mods, NULL, NULL, msgid );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_modify_ext: %s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}

/* Poll the server for the results of the modify operation. */
while ( !finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  case -1:
    /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
  case 0:
    /* The timeout period specified by zerotime was exceeded,
      so call ldap_result() again and continue polling. */
    break;
  default:
    /* The function has retrieved the results of the
      modify operation. */
    finished = 1;

    /* Parse the results received from the server. */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result: %s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }

    /* Check the results of the LDAP modify operation. */
    if ( rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_modify_ext: %s\n",
        ldap_err2string( rc ) );
      if ( error_msg != NULL  *error_msg != '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      if ( matched_msg != NULL  *matched_msg != '\0' ) {
        fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
      }
    } else {
      printf( "%s modified successfully.\n", MODIFY_DN );
    }
  }
}
ldap_unbind( ld );

The following sample program calls the asynchronous ldap_modify_ext() function to modify a user entry in the directory. The program replaces the values of the mail attribute and adds a description attribute to the entry.

#include <stdio.h>
#include <time.h>
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
  LDAP           *ld;
  LDAPMessage    *res;
  LDAPMod        mod0, mod1;
  LDAPMod        *mods[ 3 ];
  LDAPControl    **serverctrls;
  char           *matched_msg = NULL, *error_msg = NULL;
  char           **referrals;
  char           *vals0[ 2 ], *vals1[ 2 ];
  time_t      now;
  char      buf[ 128 ];
  int        rc, parse_rc, msgid, finished = 0;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Construct the array of LDAPMod structures representing the changes
   that you want to make to attributes in the entry. */
/* Specify the first modification, which replaces all values of the
   mail attribute with the value "wbj@example.com". */
  mod0.mod_op = LDAP_MOD_REPLACE;
  mod0.mod_type = "mail";
  vals0[0] = "wbj@example.com";
  vals0[1] = NULL;
  mod0.mod_values = vals0;
/* Specify the second modification, which adds a value to the description
   attribute.  If this attribute does not yet exist, the attribute ia added
   to the entry. */
  mod1.mod_op = LDAP_MOD_ADD;
  mod1.mod_type = "description";
  time( now );
  sprintf( buf,
           "This entry was modified with the modattrs program on %s",
           ctime( now ));
/* Get rid of \n which ctime put on the end of the time string */
  if ( buf[ strlen( buf ) - 1 ] == '\n' ) {
    buf[ strlen( buf ) - 1 ] = '\0';
  }
  vals1[ 0 ] = buf;
  vals1[ 1 ] = NULL;
  mod1.mod_values = vals1;
  mods[ 0 ] = mod0;
  mods[ 1 ] = mod1;
  mods[ 2 ] = NULL;
/* Send the LDAP modify request. */
  rc = ldap_modify_ext( ld, MODIFY_DN, mods, NULL, NULL, msgid );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_modify_ext: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
/* Poll the server for the results of the modify operation. */
  while ( !finished ) {
    rc = ldap_result( ld, msgid, 0, zerotime, res );
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
         This means that the server has still not yet sent the
         results of the modify operation back to your client.
         Break out of this switch statement, and continue calling
         ldap_result() to poll for results. */
      break;
    default:
      /* The function has retrieved the results of the modify
         operation from the server. */
      finished = 1;
      /* Parse the results received from the server. Note the last
         argument is a non-zero value, which indicates that the
         LDAPMessage structure will be freed when done.  (No need
         to call ldap_msgfree().) */
      parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
                   error_msg, referrals, serverctrls, 1 );
      if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr,
                 "ldap_parse_result: %s\n",
                 ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP add operation. */
      if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_modify_ext: %s\n", ldap_err2string( rc ) );
        if ( error_msg != NULL  *error_msg != '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg != NULL  *matched_msg != '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry: %s\n",
            matched_msg );
        }
      } else {
        printf( "%s modified successfully.\n"
          "Counted to %d while waiting for the modify operation.\n",
          MODIFY_DN, global_counter );
      }
    }
/* Do other work while waiting for the results of the modify operation. */
    if ( !finished ) {
      do_other_work();
    }
  }
  ldap_unbind( ld );
  return 0;
}

/*
 * Perform other work while polling for results.  This doesn't do anything
 * useful, but it could.
 */
void
do_other_work()
{
  global_counter++;
}

Deleting an Entry With Directory SDK for C

  • The synchronous ldap_delete_ext_s() function
  • The asynchronous ldap_delete_ext() function

Synchronous Delete Operation

If you want to wait for the results of the delete operation to complete before continuing, call the synchronous ldap_delete_ext_s() function. This function sends a delete request to the server. The function also blocks all other processes until the server sends the results of the operation back to your client. The ldap_delete_ext_s() function returns LDAP_SUCCESS if the operation completed successfully, or an error code if a problem occurred.

The following example calls the synchronous ldap_delete_ext_s function to remove the entry for user William Jensen from the directory.

#include <stdio.h>
#include "ldap.h"

#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"

LDAP      *ld;
char      *matched_msg = NULL, *error_msg = NULL;
int      rc;

/* Perform the delete operation. */
rc = ldap_delete_ext_s( ld, DELETE_DN, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_delete_ext_s: %s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg != NULL  *error_msg != '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  if ( matched_msg != NULL  *matched_msg != '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry: %s\n",
      matched_msg );
  }
} else {
  printf( "%s deleted successfully.\n", DELETE_DN );
}
ldap_unbind_s( ld );

The following sample program calls the synchronous ldap_delete_ext_s() function to delete a user entry from the directory.

#include <stdio.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  char      *matched_msg = NULL, *error_msg = NULL;
  int        rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Perform the delete operation. */
  rc = ldap_delete_ext_s( ld, DELETE_DN, NULL, NULL );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_delete_ext_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
  } else {
    printf( "%s deleted successfully.\n", DELETE_DN );
  }
  ldap_unbind_s( ld );
  return 0;
}

Asynchronous Delete Operation

If you want to perform other work in parallel while waiting for the entry to be deleted, call the asynchronous ldap_delete_ext() function. This function sends a delete request to the server and returns an LDAP_SUCCESS result code if the request was successfully sent, an LDAP result code if an error occurred.

The ldap_delete_ext() function passes back a message ID identifying the delete operation. To determine whether the server sent a response for this operation to your client, call the ldap_result() function and pass in this message ID. The ldap_result() function uses the message ID to determine if the server sent the results of the delete operation. The ldap_result() function passes back the results in an LDAPMessage structure. You can call the ldap_parse_result() function to parse the LDAPMessage structure to determine if the operation was successful.

The following example calls the asynchronous ldap_delete_ext() function to remove the user William Jensen from the directory.

#include <stdio.h>
#include "ldap.h"

#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"

LDAP      *ld;
LDAPMessage    *res;
LDAPControl    **serverctrls;
char      *matched_msg = NULL, *error_msg = NULL;
char      **referrals;
int        rc, parse_rc, msgid, finished = 0;

/* Timeout period for the ldap_result() function to wait for results. */
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;

/* Send the LDAP delete request. */
rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, msgid );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}

/* Poll the server for the results of the delete operation. */
while ( !finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  case -1:
    /* An error occurred. */
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  case 0:
    /* The timeout period specified by zerotime was exceeded,
      so call ldap_result() again and continue polling. */
      break;
  default:
    /* The function has retrieved the results of the
      delete operation. */
      finished = 1;

    /* Parse the results received from the server. */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result: %s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }
    /* Check the results of the LDAP delete operation. */
    if ( rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_delete_ext: %s\n",
        ldap_err2string( rc ) );
      if ( error_msg != NULL  *error_msg != '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      if ( matched_msg != NULL  *matched_msg != '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry: %s\n",
          matched_msg );
      }
    } else {
      printf( "%s deleted successfully.\n", DELETE_DN );
    }
  }
}
ldap_unbind( ld );

The following sample program calls the asynchronous ldap_delete_ext() function to delete a user entry from the directory.

#include <stdio.h>
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  LDAPMessage    *res;
  LDAPControl    **serverctrls;
  char      *matched_msg = NULL, *error_msg = NULL;
  char      **referrals;
  int        rc, parse_rc, msgid, finished = 0;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Send the LDAP delete request. */
  rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, msgid );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
/* Poll the server for the results of the delete operation. */
  while ( !finished ) {
    rc = ldap_result( ld, msgid, 0, zerotime, res );
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
         This means that the server has still not yet sent the
         results of the delete operation back to your client.
         Break out of this switch statement, and continue calling
         ldap_result() to poll for results. */
      break;
    default:
  /* The function has retrieved the results of the delete operation
     from the server. */
      finished = 1;
      /* Parse the results received from the server. Note the last
         argument is a non-zero value, which indicates that the
         LDAPMessage structure will be freed when done.  (No need
         to call ldap_msgfree().) */
      parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
                   error_msg, referrals, serverctrls, 1 );
      if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr,
                 "ldap_parse_result: %s\n",
                 ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP delete operation. */
      if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) );
        if ( error_msg != NULL  *error_msg != '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg != NULL  *matched_msg != '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry: %s\n",
          matched_msg );
        }
      } else {
        printf( "%s deleted successfully.\n"
          "Counted to %d while waiting for the delete operation.\n",
          DELETE_DN, global_counter );
      }
    }
    /* Do other work while waiting for the results of the
       delete operation. */
    if ( !finished ) {
      do_other_work();
    }
  }
  ldap_unbind( ld );
  return 0;
}
/*
 * Perform other work while polling for results.  This
 * doesn't do anything useful, but it could.
 */
void
do_other_work()
{
    global_counter++;
}

Changing the DN of an Entry With Directory SDK for C

  • The synchronous ldap_rename_s() function
  • The asynchronous ldap_rename() function

For both functions, you can choose to delete the attribute that represents the old relative distinguished name (RDN). You can also change the location of the entry in the directory tree.

Synchronous Renaming Operation

If you want to wait for the results of the modify DN operation to complete before continuing, call the synchronous ldap_rename_s() function. This function sends a modify DN request to the server. The function also blocks other work until the server sends the results of the operation back to your client. The ldap_rename_s() function returns LDAP_SUCCESS if the operation completed successfully, or an error code if a problem occurred.

The following calls the synchronous ldap_rename_s() function to change the RDN of the entry for the user William Jensen in the directory.

#include <stdio.h>
#include "ldap.h"

#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"

LDAP      *ld;
char      *matched_msg = NULL, *error_msg = NULL;
int        rc;

/* Perform the modify DN operation. */
rc = ldap_rename_s( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_rename_s: %s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg != NULL  *error_msg != '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  if ( matched_msg != NULL  *matched_msg != '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry: %s\n",
      matched_msg );
  }
} else {
  printf( "%s renamed successfully.\n", OLD_DN );
}
ldap_unbind_s( ld );

Asynchronous Renaming Operation

If you want to perform other work in parallel while waiting for the entry to be renamed, call the asynchronous ldap_rename() function. This function sends a modify DN request to the server and returns an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred.

The ldap_rename() function passes back a message ID identifying the modify DN operation. To determine whether the server sent a response for this operation to your client, call the ldap_result() function and pass in this message ID. The ldap_result() function uses the message ID to determine if the server sent the results of the modify DN operation. The ldap_result() function passes back the results in an LDAPMessage structure. You can call the ldap_parse_result() function to parse the LDAPMessage structure to determine if the operation was successful.

The following example calls the asynchronous ldap_rename() function to change the RDN of the user William Jensen in the directory.

#include <stdio.h>
#include "ldap.h"

#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"

LDAP      *ld;
LDAPMessage    *res;
LDAPControl    **serverctrls;
char      *matched_msg = NULL, *error_msg = NULL;
char      **referrals;
int        rc, parse_rc, msgid, finished = 0;

/* Timeout period for the ldap_result() function to wait
   for results. */
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;

/* Send the LDAP modify DN request. */
rc = ldap_rename( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL, msgid );
if ( rc != LDAP_SUCCESS ) {
  fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}

/* Poll the server for the results of the modify DN operation. */
while ( !finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {
  case -1:
    /* An error occurred. */
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  case 0:
    /* The timeout period specified by zerotime was exceeded,
      so call ldap_result() again and continue polling. */
    break;
  default:
    /* The function has retrieved the results of the
      modify DN operation. */
    finished = 1;

    /* Parse the results received from the server. */
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result: %s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }

    /* Check the results of the LDAP modify DN operation. */
    if ( rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) );
      if ( error_msg != NULL  *error_msg != '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      if ( matched_msg != NULL  *matched_msg != '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry: %s\n",
          matched_msg );
      }
    } else {
      printf( "%s renamed successfully.\n", OLD_DN );
    }
  }
}
ldap_unbind( ld );

Deleting the Attribute From the Old RDN

Both ldap_rename and ldap_rename_s() have a deleteoldrdn parameter that allows you to remove the old RDN from the entry. For example, suppose an entry has the following values for the cn attribute:

cn: Barbara Jensen
cn: Babs Jensen

Then the following function adds the second name and removes the first:

ldap_modrdn2( "cn=Barbara Jensen", "cn=Barbie Jensen", 1 );

The function adds Barbie Jensen to the list of values. The function removes the Barbara Jensen value. The resulting entry has the following values:

cn: Barbie Jensen
cn: Babs Jensen

Suppose 0 is passed for the deleteoldrdn parameter instead of 1:

ldap_modrdn2( "cn=Barbara Jensen", "cn=Barbie Jensen", 0 );

The Barbara Jensen value is not removed from the entry. The resulting entry has the following values:

cn: Barbie Jensen
cn: Babs Jensen
cn: Barbara Jensen

Changing the Location of the Entry

Both ldap_rename() and ldap_rename_s() have a newparent parameter that allows you to specify a new location for the entry in the directory tree. For example, if you pass ou=Contractors,dc=example,dc=com as the newparent parameter when renaming the entry uid=bjensen,ou=People,dc=example,dc=com, the entry is moved under ou=Contractors,dc=example,dc=com. The new DN for the entry is uid=bjensen,ou=Contractors,dc=example,dc=com.

Note: Some LDAP servers do not support this feature. When you specify this argument, a server might return the LDAP result code LDAP_UNWILLING_TO_PERFORM, with the error message Server does not support moving of entries.

Synchronous Relocation of an Entry

The following example calls the synchronous ldap_rename_s() function to change the RDN of a user entry in the directory.

#include <stdio.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "23skidoo"
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  char      *matched_msg = NULL, *error_msg = NULL;
  int        rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Perform the modify DN operation. */
  rc = ldap_rename_s( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_rename_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
  } else {
    printf( "%s renamed successfully.\n", OLD_DN );
  }
  ldap_unbind_s( ld );
  return 0;
}
Asynchronous Relocation of an Entry

The following example calls the asynchronous ldap_rename() function to change the RDN of a user entry in the directory.

#include <stdio.h>
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "cn=Directory Manager"
#define BIND_PW "dougy4444"
#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com"
#define NEW_RDN "uid=wjensen"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  LDAPMessage    *res;
  LDAPControl    **serverctrls;
  char      *matched_msg = NULL, *error_msg = NULL;
  char      **referrals;
  int        rc, parse_rc, msgid, finished = 0;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind to the server as the Directory Manager. */
  rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Send the LDAP modify DN request. */
  rc = ldap_rename( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL, msgid );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
/* Poll the server for the results of the modify DN operation. */
  while ( !finished ) {
    rc = ldap_result( ld, msgid, 0, zerotime, res );
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
         This means that the server has still not yet sent the
         results of the modify DN operation back to your client.
         Break out of this switch statement, and continue calling
         ldap_result() to poll for results. */
      break;
    default:
  /* The function has retrieved the results of the modify DN operation
         from the server. */
      finished = 1;
      /* Parse the results received from the server. Note the last
         argument is a non-zero value, which indicates that the
         LDAPMessage structure will be freed when done.  (No need
         to call ldap_msgfree().) */
      parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
        error_msg, referrals, serverctrls, 1 );
      if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr,
                 "ldap_parse_result: %s\n",
                 ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP modify DN operation. */
      if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) );
        if ( error_msg != NULL  *error_msg != '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg != NULL  *matched_msg != '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry: %s\n",
            matched_msg );
        }
      } else {
        printf( "%s renamed successfully.\n"
          "Counted to %d while waiting for the modify DN operation.\n",
          OLD_DN, global_counter );
      }
    }
    /* Do other work while waiting for the results of the
       modify DN operation. */
    if ( !finished ) {
      do_other_work();
    }
  }
  ldap_unbind( ld );
  return 0;
}
/*
 * Perform other work while polling for results.  This doesn't do
 * anything useful, but it could.
 */
void
do_other_work()
{
    global_counter++;
}

Comparing Attribute Values With Directory SDK for C

This section describes how to compare the value of an attribute in an entry against a specified value.

Functions for Comparing Attribute Values With Directory SDK for C

Directory SDK for C has functions to determine if an attribute contains a certain string or binary value.

  • The synchronous ldap_compare_s() function
  • The asynchronous ldap_compare() function
  • The synchronous ldap_compare_ext_s() function
  • The asynchronous ldap_compare_ext() function

Performing Synchronous Comparison Operations With Directory SDK for C

You can wait for the results of the compare operation to complete before continuing. Call the synchronous ldap_compare_ext_s() function to compare values in berval structures or the synchronous ldap_compare_s() function to compare string values. These functions send a compare request to the server and block work until the server sends the results of the operation back to your client.

  • LDAP_COMPARE_TRUE indicates that the attribute contains the specified value.
  • LDAP_COMPARE_FALSE indicates that the attribute does not contain the specified value.

An error code indicates that a problem has occurred during the operation.

The following example calls the synchronous ldap_compare_s() function to determine if an entry has the value bjensen@example.com in the mail attribute.

#include <stdio.h>
#include "ldap.h"
...
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define COMPARE_ATTR "mail"
#define COMPARE_VALUE "bjensen@example.com"
...
LDAP      *ld;
char      *matched_msg = NULL, *error_msg = NULL;
int       rc;
...
/* Perform the compare operation. */
rc = ldap_compare_s( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
switch( rc ) {
case LDAP_COMPARE_TRUE:
  printf( "%s has the value %s in the %s attribute.\n", COMPARE_DN,
    COMPARE_VALUE, COMPARE_ATTR );
  break;
case LDAP_COMPARE_FALSE:
  printf( "%s does not have the value %s in the %s attribute.\n",
    COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
  break;
default:
  fprintf( stderr, "ldap_compare_s: %s\n", ldap_err2string( rc ) );
  ldap_get_lderrno( ld, matched_msg, error_msg );
  if ( error_msg != NULL  *error_msg != '\0' ) {
    fprintf( stderr, "%s\n", error_msg );
  }
  if ( matched_msg != NULL  *matched_msg != '\0' ) {
    fprintf( stderr,
      "Part of the DN that matches an existing entry: %s\n",
      matched_msg );
  }
  break;
}
ldap_unbind_s( ld );
...

The following sample program calls the synchronous ldap_compare_s() function. The sample program uses this function to determine if a user entry has the value bjensen@example.com in the mail attribute.

#include <stdio.h>
#include "ldap.h"

/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define COMPARE_ATTR "mail"
#define COMPARE_VALUE "bjensen@example.com"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  char      *matched_msg = NULL, *error_msg = NULL;
  int        rc;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind anonymously to the server. */
  rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
/* Perform the compare operation. */
  rc = ldap_compare_s( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
  switch( rc ) {
  case LDAP_COMPARE_TRUE:
    printf( "%s has the value %s in the %s attribute.\n",
      COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
    break;
  case LDAP_COMPARE_FALSE:
    printf( "%s does not have the value %s in the %s attribute.\n",
      COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
    break;
  default:
    fprintf( stderr, "ldap_compare_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, matched_msg, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    if ( matched_msg != NULL  *matched_msg != '\0' ) {
      fprintf( stderr,
        "Part of the DN that matches an existing entry: %s\n",
        matched_msg );
    }
    break;
  }
  ldap_unbind_s( ld );
  return 0;
}

Performing Asynchronous Comparison Operations With Directory SDK for C

You can perform other work in parallel while waiting for the comparison to complete. Call the asynchronous ldap_compare_ext() function to compare values in berval structures or the asynchronous ldap_compare function to compare string values. These functions send a compare request to the server and return an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred.

Both functions pass back a message ID identifying the compare operation. To determine whether the server sent a response for this operation to your client, call the ldap_result() function and pass in the message ID. The ldap_result() function uses the message ID to determine if the server sent the results of the compare operation. The ldap_result() function passes back the results in an LDAPMessage structure. You can call the ldap_parse_result() function to parse the LDAPMessage structure to determine if the operation was successful.

  • LDAP_COMPARE_TRUE indicates that the attribute contains the specified value.
  • LDAP_COMPARE_FALSE indicates that the attribute does not contain the specified value.

An error code indicates that a problem occurred during the operation.

The following example calls the asynchronous ldap_compare() function to determine if an entry has the value bjensen@example.com in the mail attribute.

#include <stdio.h>
#include "ldap.h"
...
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define COMPARE_ATTR "mail"
#define COMPARE_VALUE "bjensen@example.com"
...
LDAP      *ld;
LDAPMessage    *res;
LDAPControl    **serverctrls;
char      *matched_msg = NULL, *error_msg = NULL;
char      **referrals;
int        rc, parse_rc, msgid, finished = 0;
struct timeval  zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
...
/* Send the LDAP compare request. */
msgid = ldap_compare( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
if ( msgid  0 ) {
  fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) );
  ldap_unbind( ld );
  return( 1 );
}
/* Poll the server for the results of the LDAP compare operation. */
while ( !finished ) {
  rc = ldap_result( ld, msgid, 0, zerotime, res );
  switch ( rc ) {

  case -1:
    /* An error occurred. */
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );

  case 0:
      /* The timeout period specified by zerotime was exceeded, so
         call ldap_result() again and continue to poll for the
        results. */
    break;

  default:
    /* The client has received the results of the
       LDAP compare operation from the server. */
    finished = 1;

    /* Parse the results received from the server.*/
    parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
      error_msg, referrals, serverctrls, 1 );
    if ( parse_rc != LDAP_SUCCESS ) {
      fprintf( stderr, "ldap_parse_result: %s\n",
        ldap_err2string( parse_rc ) );
      ldap_unbind( ld );
      return( 1 );
    }

    /* Check the results of the LDAP compare operation. */
    switch ( rc ) {
    case LDAP_COMPARE_TRUE:
      printf( "%s has the value %s in the %s attribute.\n",
        COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
      break;
    case LDAP_COMPARE_FALSE:
      printf( "%s does not have the value %s in the %s attribute.\n",
        COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR );
      break;
    default:
      fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) );
      if ( error_msg != NULL  *error_msg != '\0' ) {
        fprintf( stderr, "%s\n", error_msg );
      }
      if ( matched_msg != NULL  *matched_msg != '\0' ) {
        fprintf( stderr,
          "Part of the DN that matches an existing entry: %s\n",
          matched_msg );
      }
      break;
    }
  }
}
...

The following sample program calls the asynchronous ldap_compare() function. The sample program uses this function to determine if a user entry has the value bjensen@example.com in the mail attribute.

#include <stdio.h>
#include "ldap.h"
void do_other_work();
int global_counter = 0;
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com"
#define COMPARE_ATTR "mail"
#define COMPARE_VALUE "bjensen@example.com"
int
main( int argc, char **argv )
{
  LDAP      *ld;
  LDAPMessage    *res;
  LDAPControl    **serverctrls;
  char      *matched_msg = NULL, *error_msg = NULL;
  char      **referrals;
  int        rc, parse_rc, msgid, finished = 0;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
/* Bind anonymously to the server. */
  rc = ldap_simple_bind_s( ld, NULL, NULL );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    ldap_get_lderrno( ld, NULL, error_msg );
    if ( error_msg != NULL  *error_msg != '\0' ) {
      fprintf( stderr, "%s\n", error_msg );
    }
    ldap_unbind_s( ld );
    return( 1 );
  }
  /* Send the LDAP compare request. */
  msgid = ldap_compare( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE );
  if ( msgid  0 ) {
    fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
/* Poll the server for the results of the LDAP compare operation. */
  while ( !finished ) {
    rc = ldap_result( ld, msgid, 0, zerotime, res );
    switch ( rc ) {
    case -1:
      /* An error occurred. */
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
      ldap_unbind( ld );
      return( 1 );
    case 0:
      /* The timeout period specified by zerotime was exceeded.
         This means that your client has not yet received the
         results of the LDAP compare operation.
         Break out of this switch statement, and continue calling
         ldap_result() to poll for the results. */
      break;
    default:
      /* The client has received the results of the
         LDAP compare operation from the server. */
      finished = 1;
      /* Parse the results received from the server. Note the last
         argument is a non-zero value, which indicates that the
         LDAPMessage structure will be freed when done.  (No need
         to call ldap_msgfree().) */
      parse_rc = ldap_parse_result( ld, res, rc, matched_msg,
                   error_msg, referrals, serverctrls, 1 );
      if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr,
                 "ldap_parse_result: %s\n", 
                 ldap_err2string( parse_rc ) );
        ldap_unbind( ld );
        return( 1 );
      }
      /* Check the results of the LDAP compare operation. */
      switch ( rc ) {
      case LDAP_COMPARE_TRUE:
        printf( "%s has the value %s in the %s attribute.\n"
          "Counted to %d while waiting for the compare operation.\n",
          COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR, global_counter );
        break;
      case LDAP_COMPARE_FALSE:
        printf( "%s does not have the value %s in the %s attribute.\n"
          "Counted to %d while waiting for the compare operation.\n",
          COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR, global_counter );
        break;
      default:
        fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) );
        if ( error_msg != NULL  *error_msg != '\0' ) {
          fprintf( stderr, "%s\n", error_msg );
        }
        if ( matched_msg != NULL  *matched_msg != '\0' ) {
          fprintf( stderr,
            "Part of the DN that matches an existing entry: %s\n",
            matched_msg );
        }
        break;
      }
    }
    /* Do other work while waiting for the results of the
       compare operation. */
    if ( !finished ) {
      do_other_work();
    }
  }
  ldap_unbind( ld );
  return 0;
}
/*
 * Perform other work while polling for results.  This
 * doesn't do anything useful, but it could.
 */
void
do_other_work()
{
    global_counter++;
}

LDAP URLs With Directory SDK for C

This section describes how to use LDAP URLs to search and retrieve data from the directory.

Checking an LDAP URL With Directory SDK for C

To determine whether a URL is an LDAP URL, call the ldap_is_ldap_url() function. This function returns a nonzero value if the URL is an LDAP URL. If the URL is not an LDAP URL, the function returns 0. The following example determines if a URL is an LDAP URL.

#include <stdio.h>
#include "ldap.h"
...
char *my_url = "ldap://ldap.example.com/dc=example,dc=com";
...
if ( ldap_is_ldap_url( my_url ) != 0 ) {
printf( "%s is an LDAP URL.\n", my_url );
} else {
printf( "%s is not an LDAP URL.\n", my_url );
}
...

ldap_is_ldap_url() determines whether a URL is an LDAP URL. To verify that an LDAP URL complies with the LDAP URL syntax, you should call the ldap_url_parse() function as detailed in Getting the Components of an LDAP URL With Directory SDK for C.

Getting the Components of an LDAP URL With Directory SDK for C

To retrieve the individual components of an LDAP URL, call ldap_url_parse(). This function returns the LDAP URL components in an LDAPURLDesc structure as shown in this example.

typedef struct ldap_url_desc {
   char *lud_host;
   int lud_port;
   char *lud_dn;
   char **lud_attrs;
   int lud_scope;
   char *lud_filter;
   unsigned long lud_options;
} LDAPURLDesc;

The following list describes the structure's fields.

  • lud_host: The name of the host in the URL.
  • lud_port: The number of the port in the URL.
  • lud_dn: The distinguished name in the URL.
  • lud_attrs: A pointer to a NULL terminated array of the attributes specified in the URL.
  • lud_scope:
    LDAP_SCOPE_BASE specifies a search of the base entry.
    LDAP_SCOPE_ONELEVEL specifies a search of all entries one level under the base entry, not including the base entry.
    LDAP_SCOPE_SUBTREE specifies a search of all entries at all levels under the base entry, including the base entry.
  • lud_filter: Search filter included in the URL.
  • lud_options: Options. If LDAP_URL_OPT_SECURE, indicates that the protocol is ldaps:// instead of ldap://.

The following example parses an LDAP URL.

#include <stdio.h>
#include "ldap.h"
...
char *my_url =
  "ldap://ldap.example.com:1389/dc=example,dc=com?
   cn,mail,telephoneNumber?sub?(sn=Jensen)";
LDAPURLDesc *ludpp;
int res, i;
...
if ( ( res = ldap_url_parse( my_url, ludpp ) ) != 0 ) {
  switch( res ){
    case LDAP_URL_ERR_NOTLDAP:
      printf( "URL does not begin with \"ldap://\"\n" );
      break;
    case LDAP_URL_ERR_NODN:
      printf( "URL missing trailing slash after host or port\n" );
      break;
    case LDAP_URL_ERR_BADSCOPE:
      printf( "URL contains an invalid scope\n" );
      break;
    case LDAP_URL_ERR_MEM:
      printf( "Not enough memory\n" );
      break;
    default:
      printf( "Unknown error\n" );
  }
  return( 1 );
}
printf( "Components of the URL:\n" );
printf( "Host name: %s\n", ludpp->lud_host );
printf( "Port number: %d\n", ludpp->lud_port );
if ( ludpp->lud_dn != NULL ) {
  printf( "Base entry: %s\n", ludpp->lud_dn );
} else {
  printf( "Base entry: Root DN\n" );
}
if ( ludpp->lud_attrs != NULL ) {
  printf( "Attributes returned: \n" );
  for ( i=0; ludpp->lud_attrs[i] != NULL; i++ ) {
    printf( "\t%s\n", ludpp->lud_attrs[i] );
  }
} else {
  printf( "No attributes returned.\n" );
}
printf( "Scope of the search: " );
switch( ludpp->lud_scope ) {
  case LDAP_SCOPE_BASE:
    printf( "base\n" );
    break;
  case LDAP_SCOPE_ONELEVEL:
    printf( "one\n" );
    break;
  case LDAP_SCOPE_SUBTREE:
    printf( "sub\n" );
    break;
  default:
    printf( "Unknown scope\n" );
}
printf( "Filter: %s\n", ludpp->lud_filter );
...

This code prints each component of the URL as shown in the following example.

Components of the URL:
Host name: ldap.example.com
Port number: 1389
Base entry: dc=example,dc=com
Attributes returned:
  cn
  mail
  telephoneNumber
Scope of the search: sub
Filter: (sn=Jensen)

Freeing the Components of an LDAP URL With Directory SDK for C

When you have finished working with the components of an LDAP URL, you should free the LDAPURLDesc structure from memory by calling the ldap_free_urldesc() function. The following example parses an LDAP URL. The example then frees the LDAPURLDesc structure from memory, after verifying that the LDAP URL is valid.

#include stdio.h>
#include "ldap.h"
...
char *my_url = "ldap://ldap.example.com:1389/dc=example,dc=com?cn,mail,
                telephoneNumber?sub?(sn=Jensen)";
LDAPURLDesc *ludpp;
int res, i;
...
if ( ( res = ldap_url_parse( my_url, ludpp ) ) != 0 ) {
  switch( res ){
    case LDAP_URL_ERR_NOTLDAP:
      printf( "URL does not begin with \"ldap://\"\n" );
      break;
    case LDAP_URL_ERR_NODN:
      printf( "URL does not contain a distinguished name\n" );
      break;
    case LDAP_URL_ERR_BADSCOPE:
      printf( "URL contains an invalid scope\n" );
      break;
    case LDAP_URL_ERR_MEM:
      printf( "Not enough memory\n" );
      break;
    default:
      printf( "Unknown error\n" );
  }
  return( 1 );
}
printf( "URL is a valid LDAP URL\n" );
ldap_free_urldesc( ludpp );
...

Processing an LDAP URL With Directory SDK for C

To process an LDAP URL search request, call one of the following functions:

  • ldap_url_search_s() is a synchronous function that completes the search operation before returning. Call this function if you need to wait for the operation to finish before continuing other work. The function returns LDAP_SUCCESS if the operation completed successfully. If an error occurred, the function returns an error code.
  • ldap_url_search_st() is a synchronous function that allows a certain amount of time for the completion of the search operation. Call this function to wait for the operation to complete, and to set a timeout period for the operation.
  • ldap_url_search() is an asynchronous function that initiates the search operation but does not wait for the operation to complete. Call this function if you want to perform other work in parallel while waiting for the operation to complete. The function returns a message ID identifying the search operation. To determine whether the operation is completed or still in progress, call the ldap_result() function.

After the operation is completed, call the ldap_result2error() function to determine if the operation was successful. If the operation completed successfully, the ldap_result2error() function returns LDAP_SUCCESS. If an error occurred, the function returns an error code.

The following example processes a search request from an LDAP URL.

#include <stdio.h>
#include "ldap.h"
...
LDAP *ld;
LDAPMessage *result;
char *my_url = "ldap://ldap.example.com/dc=example,dc=com?cn,mail,
                telephoneNumber?sub?(sn=Jensen)";
/* Process the search request in the URL. */
if ( ldap_url_search_s( ld, my_url, 0, result ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_url_search_s" );
  return( 1 );
}

Getting Server Information With Directory SDK for C

This section explains how to access and modify information about your LDAP server over the LDAP protocol.

Reading DSEs With Directory SDK for C

A DSA-specific entry, DSE, contains information specific to the server. In a directory tree, the root of the tree is the root DSE. The root DSE is not part of any naming context. For example, the root DSE is superior to dc=example,dc=com in the directory tree.

The root DSE is specified as part of LDAP v3. Note that LDAP v2 servers do not necessarily have a root DSE.

  • The naming contexts of this server, such as dc=example,dc=com
  • URLs of alternate servers to contact if this server is unavailable
  • The versions of LDAP supported by this server, version 2 or version 3
  • The LDAP v3 controls supported by the server
  • The SASL mechanisms supported by the server
  • The LDAP v3 extended operations supported by the server

The following list describes root DSE attributes and explains the meaning of their values.

  • namingContexts: The naming contexts supported by this server, such dc=example,dc=com.
  • altServer: LDAP URLs that identify other servers to contact if this server is unavailable.
  • supportedExtension: The object identifiers (OIDs) of the LDAP v3 extended operations supported by this server.
    If this attribute is not in the root DSE, the server does not support any extended operations.
  • supportedControl: The OIDs of the LDAP v3 controls supported by this server.
    If this attribute is not in the root DSE, the server does not support any LDAP v3 controls.
  • supportedSASLMechanisms: The names of the SASL mechanisms supported by the server.
    If this attribute is not in the root DSE, the server does not support any SASL mechanisms.
  • supportedLDAPVersion: The value of this attribute is the version of LDAP supported by this server, such as 2 or 3.

To Get the Root DSE

  1. Initialize an LDAP session by calling the ldap_init() or prldap_init() function.
  2. Turn off automatic referral handling by calling the ldap_set_option() function and setting the LDAP_OPT_REFERRALS option to LDAP_OPT_OFF.
  3. Search the directory with the following criteria:
    1. Set the search scope to a base search.
    2. Specify an empty string for the base DN.
    3. Use the search filter (objectclass=*).
  4. Check the results of the search.
    If the server returns a result code, such as LDAP_OPERATIONS_ERROR, LDAP_PROTOCOL_ERROR, LDAP_REFERRAL, or LDAP_NO_SUCH_OBJECT, the LDAP server probably does not support LDAP v3.

The following example gets the root DSE for a server and prints the values of the root DSE attributes. The function assumes that you are passing in a valid connection handle, an LDAP structure, you have created by calling ldap_init() or prldap_init(). The function returns 0 if successful or 1 if an error occurred.

int printdse( LDAP *ld )
{
  int rc, i;
  char *matched_msg = NULL, *error_msg = NULL;
  LDAPMessage  *result, *e;
  BerElement  *ber;
  char    *a;
  char    **vals;
  char    *attrs[3];
  /* Verify that the connection handle is valid. */
  if ( ld == NULL ) {
    fprintf( stderr, "Invalid connection handle.\n" );
    return( 1 );
  }
  /* Set automatic referral processing off. */
  if ( ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ) != 0 ) {
    rc = ldap_get_lderrno( ld, NULL, NULL );
    fprintf( stderr, "ldap_set_option: %s\n", ldap_err2string( rc ) );
    return( 1 );
  }
  /* Search for the root DSE. */
  attrs[0] = "supportedControl";
  attrs[1] = "supportedExtension";
  attrs[2] = NULL;
  rc = ldap_search_ext_s( ld, "", LDAP_SCOPE_BASE, "(objectclass=*)",
                          attrs, 0, NULL, NULL, NULL, 0, result );
  /* Check the search results. */
  switch( rc ) {
  /* If successful, the root DSE was found. */
  case LDAP_SUCCESS:
    break;
  /* If the root DSE was not found, the server does not comply
     with the LDAPv3 protocol. */
  case LDAP_PARTIAL_RESULTS:
  case LDAP_NO_SUCH_OBJECT:
  case LDAP_OPERATIONS_ERROR:
  case LDAP_PROTOCOL_ERROR:
    printf( "LDAP server returned result code %d (%s).\n"
      "This server does not support the LDAPv3 protocol.\n",
      rc, ldap_err2string( rc ) );
    return( 1 );
  /* If any other value is returned, an error must have occurred. */
  default:
    fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) );
    return( 1 );
  }
  /* Since only one entry should have matched, get that entry. */
  e = ldap_first_entry( ld, result );
  if ( e == NULL ) {
    fprintf( stderr, "ldap_search_ext_s: Unable to get root DSE.\n");
    ldap_memfree( result );
    return( 1 );
  }

  /* Iterate through each attribute in the entry. */
  for ( a = ldap_first_attribute( ld, e, ber );
    a != NULL; a = ldap_next_attribute( ld, e, ber ) ) {

    /* Print each value of the attribute. */
    if ((vals = ldap_get_values( ld, e, a)) != NULL ) {
      for ( i = 0; vals[i] != NULL; i++ ) {
        printf( "%s: %s\n", a, vals[i] );
      }

      /* Free memory allocated by ldap_get_values(). */
      ldap_value_free( vals );
    }

    /* Free memory allocated by ldap_first_attribute(). */
    ldap_memfree( a );
  }

  /* Free memory allocated by ldap_first_attribute(). */
  if ( ber != NULL ) {
    ber_free( ber, 0 );
  }

  printf( "\n" );
  /* Free memory allocated by ldap_search_ext_s(). */
  ldap_msgfree( result );
  ldap_unbind( ld );
  return( 0 );
}

Determining LDAP v3 Support With Directory SDK for C

You can determine what version an LDAP server supports by getting the supportedLDAPVersion attribute from the root DSE. This attribute could contain the value 2 or 3.

You do not need to authenticate or bind before searching the directory. Unlike LDAP v2, LDAP v3 states that clients do not need to bind to the server before performing LDAP operations.

The following example connects to an LDAP server. The example code then determines whether the server supports LDAP v3.

/* Function for determining if the LDAP server supports LDAPv3.
  This function returns 1 if the server supports LDAPv3 or
  0 if the server does not support LDAPv3.
 */
int
check_version( char *hostname, int portnum )
{
  LDAP    *ld;
  int    i, rc, v3supported = 0;
  LDAPMessage  *result, *e;
  BerElement  *ber;
  LDAPControl  **serverctrls = NULL, **clntctrls = NULL;
  char    *a, *dn;
  char    **vals;
  char    *attrs[2];
  char    *filter = "(objectClass=*)";
  /* Check arguments */
  if ( !hostname || !hostname[0] || !portnum ) {
    printf( "Error: hostname or port number not specified\n" );
    return( -1 );
  }
  /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( hostname, portnum )) == NULL ) {
    perror( "ldap_init" );
    return( -1 );
  }
  /* Set automatic referral processing off. */
  if ( ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF) !=
       LDAP_SUCCESS) {
    ldap_perror( ld, "ldap_set_option" );
    return( -1 );
  }
  /* Search for the root DSE and get the supportedLDAPVersion attribute. */
  attrs[0] = "supportedLDAPVersion";
  attrs[1] = NULL;
  rc = ldap_search_ext_s( ld, "", LDAP_SCOPE_BASE, filter, attrs, 0,
    serverctrls, clntctrls, NULL, 0, result );
  /* Check the search results. */
  switch( rc ) {
  /* If successful, the root DSE was found. */
  case LDAP_SUCCESS:
    break;
  /* If the root DSE was not found, the server does not comply
     with the LDAPv3 protocol. */
  case LDAP_PARTIAL_RESULTS:
  case LDAP_NO_SUCH_OBJECT:
  case LDAP_OPERATIONS_ERROR:
  case LDAP_PROTOCOL_ERROR:
    ldap_perror( ld, "ldap_search_ext_s" );
    return( 0 );
    break;
  /* If an different result code is returned, an error may have
     occurred (for example, the server may be down. */
  default:
    ldap_perror( ld, "ldap_search_ext_s" );
    return( -1 );
    break;
  }
  /* Get the values of the supportedLDAPVersion attribute in the entry. */
  if (( e = ldap_first_entry( ld, result )) != NULL  
      ( a = ldap_first_attribute( ld, e, ber )) != NULL  
      (vals = ldap_get_values( ld, e, a)) != NULL ) {
    for ( i = 0; vals[i] != NULL; i++ ) {
      if ( !strcmp( "3", vals[i] ) ) {
        v3supported = 1;
        break;
      }
    }
    /* Free any memory allocated. */
    ldap_value_free( vals );
    ldap_memfree( a );
    if ( ber != NULL ) {
      ber_free( ber, 0 );
    }
  }
  /* Free memory allocated by ldap_search_ext_s(). */
  ldap_msgfree( result );
  /* Free the ld structure. */
  ldap_unbind_s( ld );
  /* Return a value indicating whether or not LDAPv3 is supported. */
  return( v3supported );
}
...

Getting Schema Information With Directory SDK for C

In LDAP v3, an entry can specify the schema that defines the object classes, attributes, and matching rules used by the directory. This entry is called the subschema entry. To find the DN of the subschema entry, get the subschemaSubentry operational attribute from the root DSE or any entry.

  • objectClasses specifies the object class definitions in the schema. Each value of this attribute is an object class that is known to the server.
  • attributeTypes specifies the attribute type definitions in the schema. Each value of this attribute is an attribute type that is known to the server.
  • matchingRules specifies the matching rule definitions in the schema. Each value of this attribute is a matching rule that is known to the server.
  • matchingRuleUse specifies the use of a matching rule in the schema. This rule specifies the attributes that can be used with this extensible matching rule. Each value of this attribute is a matching rule use description.

For information about the format of the attribute values, see RFC 4517, Lightweight Directory Access Protocol (v3): Attribute Syntax Definitions.

SSL Connections With Directory SDK for C

This chapter describes the process of enabling an LDAP client to connect to an LDAP server over the Secure Sockets Layer (SSL) protocol.

How SSL Works With Directory SDK for C

The primary goal of the SSL protocol is to provide privacy and reliability between two communicating applications.

Note: SSL is not supported on all LDAP servers.
SSL communication must take place on a separate TCP port unless the server supports Start TLS.

When an LDAP client connects to an LDAP server over SSL, the server identifies itself by sending a certificate to the client. The client needs to determine whether or not the certificate authority (CA) that issued the certificate is trusted. The client therefore searches a certificate database for the certificate of the CA. If the client cannot find the certificate, the client refuses to connect to the server. If the certificate is marked not trusted, the client also refuses to connect to the server.

The LDAP server can also request that the client send a certificate to authenticate itself. This part of the process is called certificate-based client authentication. If the client receives a request for a certificate from the server, the client retrieves its certificate from the certificate database. The client sends the certificate to the server for authentication. After receiving the clients certificate, the LDAP server determines whether or not the CA that issued the certificate is trusted. If the server cannot find the CA certificate in the certificate database, the server refuses to authenticate the client. If the CA certificate is marked as not trusted, the server also refuses to authenticate the client. If the CA is trusted, the server uses the certificate subject name to determine whether the client has access to perform the requested operation.

  • Your client has access to a certificate database. The function call uses this certificate database to determine if the client can trust the certificate sent from the server.
    Different certificate database versions can be incompatible, which might result in database errors.
    • The certificate of the CA that issued the servers certificate
    • If the CAs are organized in a hierarchy, the certificate of any of the CAs in the hierarchy
    • The certificate of the LDAP server
  • The CA certificate is marked as trusted in the certificate database.
    • A client certificate in the certificate database issued by a CA that is trusted by the LDAP server
    • A public-private key pair in a key file
  • Set the session option for communicating with the server over SSL.
  • Start transport layer security by using the Start TLS extended operation.
  • Replace the default I/O functions with your own I/O functions for communicating over SSL.
  • Enable your client to send certificates to authenticate itself.

Connecting to a Server Over SSL With Directory SDK for C

To enable your LDAP client to connect to an LDAP server with SSL, you need to perform the following procedure.

To Initialize a Client SSL Connection by Using ldapssl_init()

  1. Initialize your client by calling one of the following functions:
    • Call ldapssl_client_init() if you do not plan to use certificate-based client authentication.
    • Call ldapssl_clientauth_init() if you plan to use certificate-based client authentication.
    • Call ldapssl_advclientauth_init().
      If you use certificate-based client authentication, you need to specify the path of the security module database, or to specify the method to verify the server certificate.
      You must initialize your client before initializing the LDAP session. The process of initializing the client opens the certificate database.
  2. Initialize an LDAP session with the secure server by calling the ldapssl_init() function.
    For an alternative way to accomplish this step, see Alternative to ldapssl_init().

This example initializes a client to connect to a secure LDAP server over SSL.

if ( ldapssl_client_init( "/local/examples/alias/", NULL )  0) {
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}
/* get a handle to an LDAP connection */
if ( (ld = ldapssl_init( "cert.example.com", LDAPS_PORT, 1 )) == NULL {
  perror( "ldapssl_init" );
  return( 1 );
}
...
/* Client can now perform LDAP operations on the secure LDAP server. */
...

Alternative to ldapssl_init()

As an alternative to calling the ldapssl_init() function, you can use the following procedure.

To Initialize a Client SSL Connection (Alternative Method Using ldap_init())

  1. After initializing your client, initialize an LDAP session with the server by calling the standard initialization function ldap_init().
  2. Install the standard SSL I/O functions by calling ldapssl_install_routines().
  3. Set the SSL option in the LDAP structure by calling ldap_set_option().

This example prepares a client to connect to a secure LDAP server over SSL using ldap_init().

if ( ldapssl_client_init( "/local/examples/alias/", NULL )  0) {
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}
/* Initialize LDAP session. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( MY_HOST, LDAPS_PORT )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}

/* Load SSL routines */
if ( ldapssl_install_routines( ld ) != 0 ) {
  ldap_perror( ld, "ldapssl_install_routines" );
  return( 1 );
}
/* Set up option in LDAP struct for using SSL */
if ( ldap_set_option( ld, LDAP_OPT_SSL, LDAP_OPT_ON ) != 0 ) {
  ldap_perror( ld, "ldap_set_option" );
  return( 1 );
}
/* Client can now perform LDAP operations on the secure LDAP server. */
...

Handling Errors With Directory SDK for C

After calling any of the SSL initialization functions, you can convert SSL-specific error codes to text strings by calling ldapssl_err2string(). The ldapssl_err2string() function provides support for special SSL error messages that are not handled by the normal error conversion routine ldap_err2string().

Starting Transport Layer Security With Directory SDK for C

RFC 4513, Lightweight Directory Access Protocol (LDAP): Authentication Methods and Security Mechanisms, describes the extended operation. Start TLS allows you to connect to a nonsecure port, and then request transport layer security.

To Use Start TLS

Initialize your client with ldapssl_client_init().

  1. The process of initializing the client opens the certificate database.
  2. Get a handle to an LDAP connection.
  3. Request Start TLS with ldap_start_tls_s().
  4. Authenticate to the directory to perform additional operations.

This example connects and uses Start TLS, then requests the Who am I? extended operation. The example relies on a certificate database directory, /local/examples/alias/.

/*
 * Use the Start TLS extended operation.
 */

#include "examples.h"
#include <ldap_ssl.h>

/*
 * Path to certificate database for SSL
 */
#define CERT_DB_PATH    "/local/examples/alias/"

int
main( int argc, char **argv )
{
    int             version;
    LDAP            *ld;
    int             rc;
    char            *authzid;

    /* Initialize access to the certificate database. */
    if ( ldapssl_client_init( CERT_DB_PATH, NULL ) != 0 ) {
        fprintf( stderr, "ldapssl_client_init failed\n" );
        fprintf( stderr, "certificate database path: %s\n", CERT_DB_PATH );
        return( 1 );
    }

    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
         != 0 ) {
        fprintf( stderr,
                 "ldap_set_option protocol version to %d failed\n",
                 version );
        return( 1 );
    }

    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }

    /* Request Start TLS. */
    if ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_start_tls_s" );
        return( 1 );
    }
    printf( "Start TLS operation successful.\n" );

    /* Authenticate to the directory. */
    if ( ldap_simple_bind_s( ld, ENTRYDN, ENTRYPW ) != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }

    /* Examine my authorization ID. */
    if ( (rc = ldap_whoami_s( ld, NULL, NULL, authzid ) )
         != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_whoami_s: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    printf( "Authorization ID: %s\n", authzid );

    ldap_unbind( ld );
    return( 0 );
}

To troubleshoot Start TLS problems, call the PR_GetError() function. This function gives you access to many Network Security Services (NSS) errors further documented in the Mozilla.org SSL Reference.

Installing Your Own SSL I/O Functions With Directory SDK for C

The ldapssl_init() and ldapssl_install_routines() functions both set up the session to use the standard SSL I/O functions provided with Directory SDK for C. If you want to use your own SSL I/O functions, use the ldap_x_ext_io_fns() structure.

To Install Your Own SSL I/O Functions

  1. Create an ldap_x_ext_io_fns structure, and set the fields to point to your I/O functions.
  2. Call ldap_set_option to point to that structure.
if (ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, my_io_struct) != 0 ) {
      ldap_perror( ld, "ldap_set_option" );
      return( 1 );
}

Using Certificate-Based Client Authentication With Directory SDK for C

Some LDAP servers can be configured to use certificate-based client authentication. The server requests that your client send a certificate to identify itself. Use the following procedure to configure your client to use certificates for authentication.

To Use Certificate-Based Client Authentication

  1. Initialize your LDAP client by calling either ldapssl_clientauth_init() or ldapssl_advclientauth_init(), not ldapssl_client_init().
    Use ldapssl_advclientauth_init() if you want to specify the path of a security module database, or to specify the method used to verify the server certificate.
    You can use one of these functions to initialize your client even if you do not plan to use certificate-based client authentication. The functions are equivalent to ldapssl_client_init().
  2. Initialize an LDAP session with the secure server by calling ldapssl_init().
  3. Enable your client to authenticate with the secure server by calling ldapssl_enable_clientauth().
  4. Perform a Simple Authentication and Security Layer (SASL) bind operation by using the mechanism EXTERNAL. This mechanism indicates to the directory server that certificates should be used to authenticate clients.
    With Directory Server, if you perform a SASL bind operation, but the server cannot find the corresponding directory entry for a client certificate, the server returns an LDAP_INVALID_CREDENTIALS result code with the error message Client Certificate Mapping Failed.

LDAP Controls With Directory SDK for C

This section explains how LDAP controls work and how to use them.

How LDAP Controls Work With Directory SDK for C

LDAP v3, as documented in RFC 4511, allows clients and servers to use controls as a mechanism for extending an LDAP operation. A control is a way to specify additional information as part of a request and a response. For example, a client can send a control to a server as part of a search request. The control indicates that the server should sort the search results before sending the results back to the client.

Servers can also send controls back to clients. For example, Directory Server can send a control back to a client to indicate that the client password has expired, or that the password is going to expire.

  • A unique object identifier (OID) as defined by the creator of the control
    The OID identifies the control.
  • An indication of whether or not the control is critical to the operation
  • Optional data related to the control
    For example, the server-side sort control needs the attributes that would be used for sorting search results.
  • If the server supports the control, and if the control is appropriate, the server should make use of the control when performing the operation.
    • If the control is marked as critical to the operation, the server should not perform the operation. Instead, the server should return the result code LDAP_UNAVAILABLE_CRITICAL_EXTENSION.
    • If the control is not marked as critical to the operation, the server should ignore the control and perform the operation.

If you plan to use a control, make sure that the server supports the control.

Using Controls in the LDAP API

Server controls can be included in requests sent by clients and in responses sent by servers.

Client controls affect the behavior of the SDK only and are never sent to the server.

In the SDK, a control is represented by an LDAPControl structure.

  • ldctl_oid specifies the OID of the control.
  • ldctl_value contains a berval structure that contains data that is associated with the control.
  • ldctl_iscritical specifies whether or not the control is critical to the operation. LDAP_OPT_ON indicates that the control is critical. LDAP_OPT_OFF indicates that the control is not critical.

The following shows the LDAPControl structure definition.

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

You can allocate space for the control, then create the control yourself. You can also call a function to create the control. For example, you can call the ldap_create_sort_control() function to create a server-side sorting control. To include a control in a request, call one of the LDAP v3 API functions, which are functions with names that end with _ext() and _ext_s(). These functions allow you to pass in an array of server controls and an array of client controls.

You can also include controls in a request by specifying the array of controls in the LDAP_OPT_SERVER_CONTROLS option. However, these controls are sent to the server with every request. If the control is specific to a certain type of operation, you should use functions with names that end with _ext() and _ext_s() instead.

To retrieve any controls included in a servers response, call the ldap_parse_result() function. You can then retrieve data from the returned controls yourself by checking the fields of the LDAPControl structure or by calling additional functions such as ldap_parse_sort_control().

After working with a control, or with an array of controls, free the controls from memory. Call ldap_control_free() or ldap_controls_free() function.

Determining the Controls Supported by the Server With Directory SDK for C

According to LDAP v3, servers should list any controls that the server supports in the supportedControl attribute in the root DSE.

The following list shows OIDs for server controls that might be referenced in the supportedControl attribute.

  • 1.2.840.113556.1.4.473, 1.2.840.113556.1.4.474: Server-Side Sort (LDAP_CONTROL_SORTREQUEST, LDAP_CONTROL_SORTRESPONSE)
  • 1.3.6.1.4.1.42.2.27.8.5.1: Password Policy (LDAP_CONTROL_PASSWD_POLICY)
  • 1.3.6.1.4.1.42.2.27.9.5.2: Get Effective Rights Request (LDAP_CONTROL_GETEFFECTIVERIGHTS_REQUEST)
  • 1.3.6.1.4.1.42.2.27.9.5.8: Account Availability (LDAP_CONTROL_ACCOUNT_USABLE)
  • 2.16.840.1.113730.3.4.2: Manage DSA IT (LDAP_CONTROL_MANAGEDSAIT)
  • 2.16.840.1.113730.3.4.3: Persistent Search (LDAP_CONTROL_PERSISTENTSEARCH)
  • 2.16.840.1.113730.3.4.7: Entry Change Notification (LDAP_CONTROL_ENTRYCHANGE)
  • 2.16.840.1.113730.3.4.4: Password Expired (LDAP_CONTROL_PWEXPIRED)
  • 2.16.840.1.113730.3.4.5: Password Expiring (LDAP_CONTROL_PWEXPIRING)
  • 2.16.840.1.113730.3.4.9, 2.16.840.1.113730.3.4.10: Virtual List View (LDAP_CONTROL_VLVREQUEST, LDAP_CONTROL_VLVRESPONSE)
  • 2.16.840.1.113730.3.4.12, 2.16.840.1.113730.3.4.18: Proxied Authorization (LDAP_CONTROL_PROXYAUTH, LDAP_CONTROL_PROXIEDAUTH)
  • 2.16.840.1.113730.3.4.15, 2.16.840.1.113730.3.4.16: Authorization Identity Bind Request (LDAP_CONTROL_AUTHZID_RES, LDAP_CONTROL_AUTHZID_REQ)
    Also known as LDAP_CONTROL_AUTH_RESPONSE, LDAP_CONTROL_AUTH_REQUEST.
  • 2.16.840.1.113730.3.4.17: Real Attributes Only Request (LDAP_CONTROL_REAL_ATTRS_ONLY)
  • 2.16.840.1.113730.3.4.19: Virtual Attributes Only Request (LDAP_CONTROL_VIRTUAL_ATTRS_ONLY)

The following sample command-line program searches for the root DSE. The program then prints the values of the supportedControl attribute.

#include "ldap.h"
static char *usage = "Usage: listctrl -h hostname -p portnumber\n";

/* Associate OIDs of known controls with descriptions. */
struct oid2desc {
  char  *oid;
  char  *desc;
};
static struct oid2desc oidmap[] = {
  {LDAP_CONTROL_ACCOUNT_USABLE, "Account availability control"}
  {LDAP_CONTROL_AUTH_REQUEST, "Authorization bind identity request"}
  {LDAP_CONTROL_AUTH_RESPONSE, "Authorization bind identity response"}
  {LDAP_CONTROL_ENTRYCHANGE, "Entry change notification control"}
  {LDAP_CONTROL_GETEFFECTIVERIGHTS_REQUEST, "Get effective rights control"}
  {LDAP_CONTROL_MANAGEDSAIT, "Manage DSA IT control"}
  {LDAP_CONTROL_PASSWD_POLICY, "Password policy control"}
  {LDAP_CONTROL_PERSISTENTSEARCH, "Persistent search control"}
  {LDAP_CONTROL_PROXIEDAUTH, "Proxied authorization (version 2) control"}
  {LDAP_CONTROL_PROXYAUTH, "Proxied authorization (version 1) control"}
  {LDAP_CONTROL_PWEXPIRED, "Password expired control"}
  {LDAP_CONTROL_PWEXPIRING, "Password expiring control"}
  {LDAP_CONTROL_REAL_ATTRS_ONLY, "Real attributes only control"}
  {LDAP_CONTROL_SORTREQUEST, "Server-side sort request control"}
  {LDAP_CONTROL_SORTRESPONSE, "Server-side sort response control"}
  {LDAP_CONTROL_VIRTUAL_ATTRS_ONLY, "Virtual attributes only control"}
  {LDAP_CONTROL_VLVREQUEST, "Virtual list view request control"}
  {LDAP_CONTROL_VLVRESPONSE, "Virtual list view response control"}
  {NULL, NULL}
};

int
main( int argc, char **argv )
{
  LDAP          *ld;
  LDAPMessage   *result, *e;
  char          *hostname = NULL;
  char          **vals;
  char          *attrs[2];
  int           i, j, c, portnumber = LDAP_PORT, rc;
  LDAPControl   **serverctrls = NULL, **clntctrls = NULL;
  /* Parse the command line arguments. */
  while ( ( c = getopt( argc, argv, "h:p:" ) ) != -1 ) {
    switch ( c ) {
    case 'h':
      hostname = strdup( optarg );
      break;
    case 'p':
      portnumber = atoi( optarg );
      break;
    default:
      printf( "Unsupported option: %c\n", c );
      printf( usage );
      exit( 1 );
    }
  }
  /* By default, connect to localhost at port 389. */
  if ( hostname == NULL || hostname[0] == NULL ) {
      hostname = "localhost";
  }
  /* Initialize the connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( hostname, portnumber )) == NULL ) {
      perror( "ldap_init" );
      return( 1 );
  }
  /* Set automatic referral processing off. */
  if ( ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF )
    != LDAP_SUCCESS ) {
      ldap_perror( ld, "ldap_set_option" );
      return( 1 );
  }
  /* Search for the root DSE and retrieve only the
    supportedControl attribute. */
  attrs[ 0 ] = "supportedControl";
  attrs[ 1 ] = NULL;
  rc = ldap_search_ext_s( ld, "", LDAP_SCOPE_BASE, "(objectclass=*)",
    attrs, 0, serverctrls, clntctrls, NULL, NULL, result );
  /* Check the search results. */
  switch( rc ) {
  /* If successful, the root DSE was found. */
  case LDAP_SUCCESS:
    break;
  /* If the root DSE was not found, the server does not comply
    with the LDAPv3 protocol. */
  case LDAP_PARTIAL_RESULTS:
  case LDAP_NO_SUCH_OBJECT:
  case LDAP_OPERATIONS_ERROR:
  case LDAP_PROTOCOL_ERROR:
    printf( "LDAP server %s:%d returned result code %d (%s).\n"
    "This server does not support the LDAPv3 protocol.\n",
    hostname, portnumber, rc, ldap_err2string( rc ) );
    return( 1 );
    break;
  /* If any other value is returned, an error must have occurred. */
  default:
    ldap_perror( ld, "ldap_search_ext_s" );
    return( 1 );
    break;
  }
  /* Get the root DSE from the results.
    Since there is only one root DSE, there
    should be only one entry in the results. */
  e = ldap_first_entry( ld, result );
  /* Get and print the values of the supportedControl attribute. */
  if (e != NULL 
    (vals = ldap_get_values(ld, e, "supportedControl")) != NULL ) {
    printf( "\nControls Supported by %s:%d\n", hostname, portnumber );
    printf( "==================================================\n" );
    for ( i = 0; vals[i] != NULL; i++ ) {
      printf( "%s\n", vals[i] );
      for ( j = 0; oidmap[j].oid != NULL; j++ ) {
        if ( !strcmp( vals[i], oidmap[j].oid )) {
          printf( "\t%s\n", oidmap[j].desc );
        }
      }
    }
    /* Free the values allocated by ldap_get_values(). */
    ldap_value_free( vals );
    printf( "\n" );
  }
  /* Free memory allocated by ldap_search_ext_s(). */
  ldap_msgfree( result );
  ldap_unbind( ld );
  return( 0 );
}

Using the Server-Side Sorting Control With Directory SDK for C

The control with OID 1.2.840.113556.1.4.473, or LDAP_CONTROL_SORTREQUEST as defined in the ldap.h header file, is a server-side sorting control. When you send a search request with this control to the server, the server should sort the results before sending the results back to you.

The server-side sorting control is described in RFC 2891.

Specifying the Sort Order With Directory SDK for C

To specify the sort order of the results, call the ldap_create_sort_keylist function to create a sort key list from a string in the following format:

[-]''attr-name''[:''matching-rule-oid'']
  • attr-name is the name of the attribute to sort by.
    You can specify a space-delimited list of attribute names.
  • matching-rule-oid is the optional OID of a matching rule that you want to use for sorting.
sn -givenname
  • The minus sign indicates that the results should be sorted in reverse order for that attribute. For example, the following string specifies that results should be sorted by last name, sn, first in ascending order. If multiple entries have the same last name, these entries are sorted by first name, givenname, in descending order.

Pass this string to ldap_create_sort_keylist() to create a sort key list, which is an array of LDAPsortkey structures. You can use this technique to create the server-side sorting control.

Creating the Server-Side Sorting Control With Directory SDK for C

Next, to create the server-side sorting control, you pass the sort key list, the array of LDAPsortkey structures, to the ldap_create_sort_control() function. The function passes back a newly created sort control, an LDAPControl structure that you can include in a search request.

You can specify whether or not the control is critical to the search operation. If the control is marked as critical, but the server cannot sort the results, the server should not send back any entries. See Interpreting the Results of Sorting With Directory SDK for C for more information about the ramifications of marking the control as critical.

After you call the ldap_create_sort_control() function and create the control, free the array of LDAPsortkey structures by calling ldap_free_sort_keylist(). When you are done receiving sorted results from the server, free the LDAPControl structure by calling ldap_control_free().

Performing a Search With Directory SDK for C

For the server to sort the results, add the newly created server-side sorting control to a NULL terminated array of LDAPControl structures. Pass this array to the ldap_search_ext() function or the ldap_search_ext_s() function. The server returns a result for the search operation. The server also returns a response control. The response control indicates the success or failure of the sort. To determine if sort was successful, use the following procedure.

To Search With a Sort Request for Directory SDK for C

  1. Call ldap_parse_result() to parse the result of the search operation.
    The function retrieves any response controls sent back from the server.
    Response controls are passed back in a NULL terminated array of LDAPControl structures.
  2. Pass this array of structures as an argument to ldap_parse_sort_control() to retrieve the LDAP result code for the sorting operation.
    If the sorting operation fails, the server can also return the name of the attribute that caused the failure. The ldap_parse_sort_control() function also retrieves this name, if available.
  3. Free the array by calling the ldap_controls_free() function when you are done parsing the array of response controls.
  4. The server can return the following result codes.
    • LDAP_SUCCESS: The results were sorted successfully.
    • LDAP_OPERATION_ERROR: An internal server error occurred.
    • LDAP_TIMELIMIT_EXCEEDED: The maximum time allowed for a search was exceeded before the server finished sorting the results.
    • LDAP_STRONG_AUTH_REQUIRED: The server refused to send back the sorted search results because the server requires you to use a stronger authentication method.
    • LDAP_ADMINLIMIT_EXCEEDED: The server retrieved too many entries to sort.
    • LDAP_NO_SUCH_ATTRIBUTE: The sort key list specifies an attribute that does not exist.
    • LDAP_INAPPROPRIATE_MATCHING: The sort key list specifies a matching rule that is not recognized or appropriate.
    • LDAP_INSUFFICIENT_ACCESS: The server did not send the sorted results because the client has insufficient access rights.
    • LDAP_BUSY: The server is too busy to sort the results.
    • LDAP_UNWILLING_TO_PERFORM: The server is unable to sort the results.
    • LDAP_OTHER: This general result code indicates that the server failed to sort the results for a reason other than the ones listed previously.

Interpreting the Results of Sorting With Directory SDK for C

The following table shows the kinds of results to expect from the LDAP server under different situations.

Server Responses to Sorting Controls
Does the server support the sort control? Is the sort control marked as critical? Other Conditions Results From LDAP Server
Server does not support the sort control. Control is marked as critical. Not applicable The server does not send back any entries.
  Control is not marked as critical.   The server ignores the sorting control. Instead, the server returns the entries unsorted.
Server does support the sort control. Control is marked as critical. The server cannot sort the results by using the specified sort key list. The server does not send back any entries. The server sends back the sorting response control. The response control specifies the result code of the sort attempt and optionally the attribute type that caused the error.
  Control is not marked as critical.   The server returns the entries unsorted. The server sends back the sorting response control. The response control specifies the result code of the sort attempt and optionally the attribute type that caused the error.
  Not applicable, might or might not be marked as critical. The server successfully sorted the entries. The server sends back the sorted entries. The server sends back the sorting response control. The response control specifies the result code of the sort attempt, LDAP_SUCCESS.
    The search failed for any reason. The server sends back a result code for the search operation. The server does not send back the sorting response control.

Server-Side Sorting Control Sample Program for Directory SDK for C

The following sample program uses the server-side sorting control to get a list of all users in the directory. The list is sorted in ascending order by last name, then in descending order by first name.

#include <stdio.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER 389
int
main( int argc, char **argv )
{
  LDAP         *ld;
  LDAPMessage  *result, *e;
  char         *attrfail, *matched = NULL, *errmsg = NULL;
  char         **vals, **referrals;
  int          rc, parse_rc, version;
  unsigned long     rcode;
  LDAPControl       *sortctrl = NULL;
  LDAPControl       *requestctrls[ 2 ];
  LDAPControl       **resultctrls = NULL;
  LDAPsortkey       **sortkeylist;
  /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( HOSTNAME, PORTNUMBER ) ) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
  version = LDAP_VERSION3;
  ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );
  /* Create a sort key list that specifies the sort order of the results.
     Sort the results by last name first, then by first name. */
  ldap_create_sort_keylist( sortkeylist, "sn -givenname" );
  /* Create the sort control. */
  rc = ldap_create_sort_control( ld, sortkeylist, 1, sortctrl );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr,
             "ldap_create_sort_control: %s\n",
             ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
  requestctrls[ 0 ] = sortctrl;
  requestctrls[ 1 ] = NULL;
  /* Search for all entries in Sunnyvale */
  rc = ldap_search_ext_s( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE,
    "(mail=*example.com*)", NULL, 0, requestctrls,
    NULL, NULL, 0, result );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
  parse_rc = ldap_parse_result( ld, result, rc, matched, 
               errmsg, referrals, resultctrls, 0 );
  if ( parse_rc != LDAP_SUCCESS ) {
    fprintf( stderr,
             "ldap_parse_result: %s\n",
             ldap_err2string( parse_rc ) );
    ldap_unbind( ld );
    return( 1 );
  }
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) );
    if ( errmsg != NULL  *errmsg != '\0' ) {
      fprintf( stderr, "%s\n", errmsg );
    }
    ldap_unbind( ld );
    return( 1 );
  }
  parse_rc =
    ldap_parse_sort_control( ld, resultctrls, rcode, attrfail );
  if ( parse_rc != LDAP_SUCCESS ) {
    fprintf( stderr,
             "ldap_parse_sort_control: %s\n", 
             ldap_err2string( parse_rc ) );
    ldap_unbind( ld );
    return( 1 );
  }

  if ( rcode != LDAP_SUCCESS ) {
    fprintf( stderr, "Sort error: %s\n", ldap_err2string( rcode ) );
    if ( attrfail != NULL  *attrfail != '\0' ) {
      fprintf( stderr, "Bad attribute: %s\n", attrfail );
    }
    ldap_unbind( ld );
    return( 1 );
  }
  /* for each entry print out name + all attrs and values */
  for ( e = ldap_first_entry( ld, result ); e != NULL;
      e = ldap_next_entry( ld, e ) ) {
    if ((vals = ldap_get_values( ld, e, "sn")) != NULL ) {
      if ( vals[0] != NULL ) {
        printf( "%s", vals[0] );
      }
      ldap_value_free( vals );
    }
    if ((vals = ldap_get_values( ld, e, "givenname")) != NULL ) {
      if ( vals[0] != NULL ) {
        printf( "\t%s", vals[0] );
      }
      ldap_value_free( vals );
    }
    printf( "\n" );
  }
  ldap_msgfree( result );
  ldap_free_sort_keylist( sortkeylist );
  ldap_control_free( sortctrl );
  ldap_controls_free( resultctrls );
  ldap_unbind( ld );
  return( 0 );
}

Using the Persistent Search Control With Directory SDK for C

The control OID 2.16.840.1.113730.3.4.3, LDAP_CONTROL_PERSISTENTSEARCH as defined in the ldap.h header file, is the persistent search control. A persistent search is an ongoing search operation that allows your LDAP client to get notification of changes to the directory.

The persistent search control is described in the Internet Draft Persistent Search: A Simple LDAP Change Notification Mechanism.

To use persistent searching for change notification, you create a persistent search control that specifies the types of changes that you want to track. You include the control in a search request. When an entry in the directory changes, the server determines if the entry matches the search criteria in your request. The server also determines if the change is the type of change that you are tracking. If both of these conditions are true, the server sends the entry to your client.

To create a persistent search control, call ldap_create_persistentsearch_control() as shown here.

int ldap_create_persistentsearch_control( LDAP *ld,
   int changetypes, int changesonly, int return_echg_ctls,
   char ctl_iscritical, LDAPControl **ctrlp );
  • changetypes specifies the type of change you want to track.
    • LDAP_CHANGETYPE_ADD indicates that you want to track added entries.
    • LDAP_CHANGETYPE_DELETE indicates that you want to track deleted entries.
    • LDAP_CHANGETYPE_MODIFY indicates that you want to track modified entries.
    • LDAP_CHANGETYPE_MODDN indicates that you want to track renamed entries.
    • LDAP_CHANGETYPE_ANY indicates that you want to track all changes to entries.
  • changesonly indicates whether or not you want the server to return all entries that initially matched the search criteria. Use 0 to return all entries, or non zero to return only the entries that change.
  • return_echg_ctls indicates whether or not you want entry change notification controls included with every modified entry returned by the server. Use a non zero value to return entry change notification controls.

You can use this control in conjunction with an entry change notification control.

The ldap_create_persistentsearch_control() function passes back an LDAPControl structure that represents the control in the ctrlp parameter. You can add the newly created control to a NULL terminated array of LDAPControl structures. Pass this array to the ldap_search_ext() function.

To end the persistent search, call the ldap_abandon_ext() function. Alternatively, call the ldap_unbind() function to disconnect from the server.

The example provided in examples/psearch.c shows how to perform a persistent search.

Using the Entry Change Notification Control With Directory SDK for C

The control with OID 2.16.840.1.113730.3.4.7, LDAP_CONTROL_ENTRYCHANGE as defined in the ldap.h header file, is the entry change notification control. This control contains additional information about the change to the entry. The information includes the type of change, and the change number, which corresponds to an item in the servers change log. If the entry was renamed, the control also contains the old DN of the entry in the change log.

You use this control in conjunction with a persistent search control. You can specify the preference for returning entry change notification controls. The server then includes an entry change notification control with each entry found by the search. To retrieve and parse an entry change notification control included with an entry, follow this procedure.

To Use Entry Change Notification With Directory SDK for C

  1. Pass the LDAPMessage structure that represents an entry to the ldap_get_entry_controls() function.
  2. Pass the entry change notification control to the ldap_parse_entrychange_control() function.

Using the Virtual List View Control With Directory SDK for C

The control with OID 2.16.840.1.113730.3.4.9, LDAP_CONTROL_VLVREQUEST as defined in the ldap.h header file, is a virtual list view control. When you send a search request with this control and a server-side sorting control, the server should sort the results. The server should then return the specified subset of entries back to your client.

The virtual list view control is described in the Internet Draft, LDAP Extensions for Scrolling View Browsing of Search Results.

Using the Manage DSA IT Control With Directory SDK for C

The control with OID 2.16.840.1.113730.3.4.2, LDAP_CONTROL_MANAGEDSAIT as defined in the ldap.h header file, is the manage DSA IT control. You can use this control to manage search references in the directory. To create this control, create an LDAPControl structure and set the ldctl_oid field to 2.16.840.1.113730.3.4.2.

When you add this control to the array of LDAPControl structures for ldap_search_ext() or ldap_modify_ext(), the server treats search references as ordinary entries. Rather than returning a reference to you, the server returns the entry that contains the reference. This mechanism allows your client application to manage search references in the directory.

The manage DSA IT control is described in RFC 2891.

Using Password Policy Controls With Directory SDK for C

Directory Server offers three password policy response controls sent back to a client that performs a bind operation. The server also offers an account availability control that does not require a bind to return status about a client account.

Using Password Policy Expiration Controls With Directory SDK for C

  • The control with OID 2.16.840.1.113730.3.4.4, LDAP_CONTROL_PWEXPIRED, is the expired password control.
    This control serves when the server requires users to change passwords when first logging in, and after password reset. After the first login, and after password reset, the server sends this control to indicate that the client needs to change the password immediately. At this point, the only operation that the client can perform is to change the users password. If the client requests any other operation, the server sends back an LDAP_UNWILLING_TO_PERFORM result code with an expired password control.
  • The control with OID 2.16.840.1.113730.3.4.5, LDAP_CONTROL_PWEXPIRING, is the password expiration warning control.
    This control is used if the server is configured to expire user passwords after a certain amount of time. The server sends this control back to the client if the client binds with a password that is to expire soon . The ldctl_value field of the LDAPControl structure specifies the number of seconds before the password expires.

To Use Password Policy Expiration Controls With Directory SDK for C

  1. Call ldap_simple_bind() to send a request for an asynchronous bind operation.
  2. Call ldap_result() to get the results of the operation.
  3. Call ldap_parse_result() to parse the result.
    The function retrieves the server response controls from the result as an array of LDAPControl structures.
  4. Check the ldctl_oid field to determine the OID of the control and the ldctl_value field for any data that is included in the control.

Using the Account Availability Control With Directory SDK for C

Directory Server offers an account availability control that does not require a bind to return status about a client account. The account availability control is assigned OID 1.3.6.1.4.1.42.2.27.9.5.8, LDAP_CONTROL_ACCOUNT_USABLE. This control allows the client to read information about an account without having to bind as the user having that account.

To Use the Account Availability Control With Directory SDK for C

  1. Allocate an LDAPuserstatus structure to hold the values for the account status.
  2. Create an account status control with ldap_create_userstatus_control().
  3. Read the entry for which you want account status, passing in the control as part of the search.
  4. Get the controls on the entry that the search returns.
  5. Pass the LDAPuserstatus structure to ldap_parse_userstatus_control() to fill the structure.
  6. Read account status information from the LDAPuserstatus structure.

This example displays status for Barbara Jensen's account.

/*
 * Get account status using the account status control.
 */

#include "examples.h"

int
main( int argc, char **argv )
{
    LDAPuserstatus  *status;
    int             version;
    LDAP            *ld;
    int             rc;
    LDAPControl     *status_ctrl = NULL;
    LDAPControl     *requestctrls[ 2 ];
    LDAPMessage     *result;
    char            *matched = NULL;
    char            *errmsg = NULL;
    char            **referrals;
    LDAPControl     **resultctrls = NULL;
    LDAPMessage     *msg;
    LDAPControl     **ectrls = NULL;

    /* Allocate the LDAPuserstatus structure. */
    if ( !( status = (LDAPuserstatus*)malloc(sizeof(LDAPuserstatus)) ) ) {
        perror("malloc");
        return ( 1 );
    }

    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
         != 0 ) {
            fprintf( stderr,
                "ldap_set_option protocol version to %d failed\n",
                version );
            return ( 1 );
    }

    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }

    /* Create an account status control. */
    rc = ldap_create_userstatus_control( ld, 1, status_ctrl );
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_create_userstatus_control: %s\n",
                 ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    requestctrls[ 0 ] = status_ctrl;
    requestctrls[ 1 ] = NULL;

    /* Authenticate to the directory as a user. */
    if ( ldap_simple_bind_s( ld, USER_DN, USER_PW ) != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }

    /* Read the account entry using the control. */
    rc = ldap_search_ext_s( ld, ENTRYDN, LDAP_SCOPE_BASE,
        "(objectclass=*)", NULL, 0, requestctrls, NULL, NULL, 0, result );
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }

    /* Show the account status. */
    rc = ldap_parse_result( ld, result, rc, matched, errmsg,
        referrals, resultctrls, 0 );
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_parse_result: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }

    for ( msg = ldap_first_message( ld, result );
          msg != NULL;
          msg = ldap_next_message ( ld, msg) ) {
        if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) continue;
        if ( ldap_get_entry_controls( ld, msg, ectrls ) != LDAP_SUCCESS ) {
            ldap_perror ( ld, "ldap_get_entry_controls" );
        } else {
            rc = ldap_parse_userstatus_control( ld, ectrls, status );
            if ( rc != LDAP_SUCCESS ) {
                fprintf( stderr,
                    "ldap_parse_userstatus_control: %s\n",
                    ldap_err2string( rc ) );
            } else {
                printf( "DN: %s\n", ENTRYDN );
                if ( LDAP_US_ACCOUNT_USABLE == status->us_available ) {
                    printf( " Account is usable:\tY\n" );
                } else {
                    printf( " Account is usable:\tN\n" );
                }
                printf( " Password expires in:\t%ld s\n",
                    status->us_expire );
                if ( LDAP_US_ACCOUNT_INACTIVE == status->us_inactive ) {
                    printf( " Account is locked:\tY\n" );
                } else {
                    printf( " Account is locked:\tN\n" );
                }
                if ( LDAP_US_ACCOUNT_RESET == status->us_reset ) {
                    printf( " Password was reset:\tY\n" );
                } else {
                    printf( " Password was reset:\tN\n" );
                }
                if ( LDAP_US_ACCOUNT_EXPIRED == status->us_expired ) {
                    printf( " Password has expired:\tY\n" );
                } else {
                    printf( " Password has expired:\tN\n" );
                }
                printf( " Grace logins left:\t%d\n",
                    status->us_remaining );
                printf( " Account unlocks in:\t%d s\n",
                    status->us_seconds );
            }
        }
    }
    
    ldap_msgfree( result );
    ldap_control_free( status_ctrl );
    ldap_controls_free( resultctrls );
    ldap_unbind( ld );
    return( 0 );
}

Using the Password Policy Control With Directory SDK for C

Directory Server offers a password policy control to retrieve information about the password policy that applies to the account used to bind to the server. The password policy control is assigned OID 1.3.6.1.4.1.42.2.27.8.5.1, LDAP_CONTROL_PASSWD_POLICY.

To Use the Password Policy Control With Directory SDK for C

  1. Allocate an LDAPpwdpolicy structure to hold the values for the account status.
  2. Create a password policy control with ldap_create_pwdpolicy_control().
  3. Bind sending the password policy control.
  4. Perform a bind, a modify, an add, a compare, or an extended operation, getting the result controls.
  5. Pass the LDAPpwdpolicy structure to ldap_parse_pwdpolicy_control() to fill the structure.
  6. Read password policy information from the LDAPpwdpolicy structure.

This example displays the password policy that governs Barbara Jensen's account retrieved during the bind operation.

/*
 * Get password policy information using the password policy control.
 */

#include "examples.h"

int
main( int argc, char **argv )
{
    LDAPpwdpolicy   *policy;
    int             version;
    LDAP            *ld;
    int             rc;
    LDAPControl     *pwpctrl = NULL;
    LDAPControl     *requestctrls[ 2 ];
    int             msgid;
    LDAPMessage     *result;
    int             parse_rc;
    char            *matched = NULL;
    char            *errmsg = NULL;
    char            **referrals;
    LDAPControl     **resultctrls = NULL;

    /* Allocate the LDAPpwdpolicy structure. */
    if ( !( policy = (LDAPpwdpolicy*)malloc(sizeof(LDAPpwdpolicy) ) ) ) {
        perror("malloc");
        return ( 1 );
    }

    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
         != 0 ) {
            fprintf( stderr,
                "ldap_set_option protocol version to %d failed\n",
                version );
            return ( 1 );
    }

    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }

    /* Create a password policy control. */
    rc = ldap_create_pwdpolicy_control( ld, 1, pwpctrl);
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_create_pwdpolicy_control: %s\n",
                 ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    requestctrls[ 0 ] = pwpctrl;
    requestctrls[ 1 ] = NULL;

    /* Use the password policy control for the bind. */
    rc = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, pwpctrl );
    if ( rc != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_set_option" );
        return ( 1 );
    }

    /* Authenticate to the directory, checking for result controls. */
    msgid = ldap_simple_bind( ld, ENTRYDN, ENTRYPW );
    if ( msgid  0 ) {
        fprintf( stderr, "ldap_simple_bind: %s\n", ldap_err2string( rc ) );
        if ( errmsg != NULL  errmsg != '\0' ) {
            fprintf( stderr, "%s\n", errmsg );
        }
        ldap_unbind( ld );
        return ( 1 );
    }

    rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, result );
    if ( rc  0 ) {
        rc = ldap_get_lderrno( ld, NULL, NULL );
        fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }

    parse_rc = ldap_parse_result( ld, result, rc, matched, errmsg,
        referrals, resultctrls, 0 );
    if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_parse_result: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_simple_bind: %s\n", ldap_err2string( rc ) );
        if ( errmsg != NULL  errmsg != '\0' ) {
            fprintf( stderr, "%s\n", errmsg );
        }
    }
    if ( resultctrls == NULL ) {
        fprintf( stderr, "No pwp result control from server.\n" );
        ldap_unbind( ld );
        return ( 1 );
    }

    /* Show the password policy information. */
    parse_rc = ldap_parse_pwdpolicy_control( ld, resultctrls, policy );
    if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_parse_pwdpolicy_control: %s\n",
            ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }

    printf( "DN: %s\n", ENTRYDN );
    switch ( policy->pp_warning ) {
    case LDAP_PP_WARNING_NONE:
        printf( " No warnings\n" );
        break;
    case LDAP_PP_WARNING_EXP:
        printf( " Password expires in: %d s\n", policy->pp_warning_info );
        break;
    case LDAP_PP_WARNING_GRACE:
        printf( " Grace logins left: %d", policy->pp_warning_info );
        break;
    default: printf( " Unrecognized password policy warning\n" ); break;
    }
    switch ( policy->pp_error ) {
    case LDAP_PP_ERROR_NONE:
        printf( " No errors\n" );
        break;
    case LDAP_PP_ERROR_EXPIRED:
        printf( " Password has expired, and must be reset.\n" );
        break;
    case LDAP_PP_ERROR_LOCKED:
        printf( " Account is locked.\n" );
        break;
    case LDAP_PP_ERROR_MUSTCHANGE:
        printf( " Password has been reset, and must be changed.\n" );
        break;
    case LDAP_PP_ERROR_NOTMOD:
        printf( " This user may not change the password.\n" );
        break;
    case LDAP_PP_ERROR_OLDPASSWD:
        printf( " Old password must be supplied for this operation.\n" );
        break;
    case LDAP_PP_ERROR_NOQUALITY:
        printf( " Password does not pass quality check.\n" );
        break;
    case LDAP_PP_ERROR_TOOSHORT:
        printf( " Password is too short.\n" );
        break;
    case LDAP_PP_ERROR_MINAGE:
        printf( " Password is too new to be modified already.\n" );
        break;
    case LDAP_PP_ERROR_INHISTORY:
        printf( " Password has already been used.\n" );
        break;
    default: printf( " Unrecognized password policy error\n" ); break;
    }

    ldap_msgfree( result );
    ldap_control_free( pwpctrl );
    ldap_controls_free( resultctrls );
    ldap_unbind( ld );
    return( 0 );
}

Using the Proxied Authorization Control With Directory SDK for C

Proxied authorization is an extension to LDAP v3 that allows a bound client to assume the identity of another directory entity without rebinding. The rebind allows the client to perform operations as if it were bound as the proxied directory entity. All directory access, including read, write, search, compare, delete, and add operations, is supported by proxied authorization. For example, suppose a client is bound as uid=bjensen,ou=Engineering,dc=example,dc=com. The user bjensen does not have the right to search the ou=Marketing,dc=example,dc=com tree. However, uid=lboyd,ou=Marketing,dc=example,dc=com does have rights to search the Marketing tree, and lboyd grants proxy rights to bjensen. In this case, bjensen can bind as herself, assume the identity of lboyd, and then search the Marketing tree.

This feature is intended as a performance and administrative benefit for certain types of directory usage. Specifically, applications that allow many clients to access directory data without rebinding as another directory entity might use this feature.

Proxy Right for Directory SDK for C

Proxied authorization adds an additional access right: proxy. If an entry grants the proxy right, then the entity to which that right is granted can assume the identity of the granting entity. For example, to allow uid=bjensen the right to proxy as uid=lboyd, add the Proxy Right access control instruction (ACI) as shown in the following example. This ACI allows bjensen to assume the identity of lboyd for all directory operations. The ACI gives bjensen permission to do to the directory whatever lboyd has permission to do.

aci: (target = "ldap:///uid=lboyd,ou=Marketing,dc=example,dc=com")
 (targetattr=*)
 (version 3.0; aci "grant bjensen the right to proxy as lboyd";
  allow(proxy)
  userdn="ldap:///uid=bjensen,ou=Engineering,dc=example,dc=com";)

Proxy Authorization Control With Directory SDK for C

To support proxy authorization, an extension to LDAP v3, the proxy authorization control has been added to Directory SDK for C in the form of the ldap_create_proxyauth_control() function. You use this function to create the control that allows a bound entity to assume the identity of another directory entry.

Proxy authorization is an optional LDAP server feature. Proxy authorization might not be supported on all LDAP servers. You should call the proxy authorization control function only when interacting with LDAP servers that support this LDAP v3 extension. You can check on the support of this control by looking at the root DSE supportedControl attribute. For example, the following command uses the ldapsearch utility to display the root DSE:

$ ldapsearch -h localhost -p 389 -b "" -s base "(objectclass=*)"

For the control to work, the server to connect to must support the server control for Proxy Authorization, OID 2.16.840.1.113730.3.4.12. This control is LDAP_CONTROL_PROXYAUTH as defined in the ldap.h header file.

Proxy Authorization Sample Program for Directory SDK for C

The following sample program creates an LDAP connection, sets the Proxy Authorization control, binds to the directory, and then performs a search operation using the Proxy Authorization control.

#include "ldap.h"

int            version;
LDAP           *ld;
LDAPControl    *requestctrls[ 2 ];
LDAPControl    *pactrl = NULL;

/* Customize the following host and bind information for your site. */
int        port=389;
char       *host="directory.example.com";
char       *baseDN="dc=example,dc=com";

/* Proxied auth specific information.
   proxyDN is the entity that will be proxied.
   bindDN and bindpw is for the bind entity that will use the proxyDN. */
char            *proxyDN = "uid=lboyd,ou=marketing,dc=example,dc=com";
char            *bindDN = "uid=bjensen,ou=engineering,dc=example,dc=com";
char            *bindpw = "password";

/* Do general LDAP init stuff */
/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( host, port ) ) == NULL ) {
        printf("ldap_init did not return a conn handle.\n");
        return;
        }
/* set version to ldap version 3 */
version = LDAP_VERSION3;
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );

/* authenticate to the directory */
if ( ldap_simple_bind_s( ld, bindDN, bindpw ) != LDAP_SUCCESS ) {
        printf("ldap_simple_bind_s failed");
        return (-1);
}

/* create the Proxy Authorization control */
if ( ldap_create_proxyauth_control( ld, proxyDN, 1, pactrl ) ) {
   printf("ldap_create_proxyauth_control failed.\n");
   if ( ldap_unbind( ld ) != LDAP_SUCCESS ) {
        printf("ldap_unbind failed\n");
   }
   return(-1);
}

requestctrls[ 0 ] = pactrl;
requestctrls[ 1 ] = NULL;

/* Perform the search using the control */
printf("Searching for %s with the proxy auth control.\n", proxyDN);
if ( ldap_search_ext_s( ld, proxyDN, LDAP_SCOPE_SUBTREE, "(objectclass=*)",
        NULL, 0, requestctrls, NULL, NULL, LDAP_NO_LIMIT, results ) !=
        LDAP_SUCCESS ) {
                printf("ldap_search_ext failed.\n");
                printf("Something is wrong with proxied auth.\n");
} else {
         print_search_results(ld, results);
}

Using the Authorization Identity Bind Request Control With Directory SDK for C

The control with OID 2.16.840.1.113730.3.4.16, LDAP_CONTROL_AUTHZID_REQ, is the authorization identity bind request control. This control lets you request the authorization ID when binding to the server.

To Retrieve the Authorization ID

Directory Server supports the authorization identity bind request and response controls defined in RFC 3829. The server also allows you to retrieve the authorization identity value as a string.

  1. Create an authorization identity request control using the ldap_create_authzid_control() function.
  2. Bind sending the authorization identity request control.
  3. Read the authorization identity from the response control using the ldap_parse_authzid_control() function.

This example gets the authorization ID for Barbara Jensen.

/*
 * Get the authorization ID for an operation.
 */

#include "examples.h"

int
main( int argc, char **argv )
{
    int             version;
    LDAP            *ld;
    int             rc;
    LDAPControl     *authzidctrl = NULL;
    LDAPControl     *requestctrls[ 2 ];
    int             msgid;
    LDAPMessage     *result;
    int             parse_rc;
    char            *matched = NULL;
    char            *errmsg = NULL;
    char            **referrals;
    LDAPControl     **resultctrls = NULL;
    char            *authzid;

    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
         != 0 ) {
            fprintf( stderr,
                "ldap_set_option protocol version to %d failed\n",
                version );
            return ( 1 );
    }

    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }

    /* Create a authorization ID control. */
    rc = ldap_create_authzid_control( ld, 1, authzidctrl );
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_create_authzid_control: %s\n",
                 ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    requestctrls[ 0 ] = authzidctrl;
    requestctrls[ 1 ] = NULL;

    /* Use the authorization ID control for the bind. */
    rc = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, authzidctrl );
    if ( rc != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_set_option" );
        return ( 1 );
    }

    /* Authenticate to the directory, checking for result controls. */
    msgid = ldap_simple_bind( ld, ENTRYDN, ENTRYPW );
    if ( msgid  0 ) {
        fprintf( stderr, "ldap_simple_bind: %s\n", ldap_err2string( rc ) );
        if ( errmsg != NULL  errmsg != '\0' ) {
            fprintf( stderr, "%s\n", errmsg );
        }
        ldap_unbind( ld );
        return ( 1 );
    }

    rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, result );
    if ( rc  0 ) {
        rc = ldap_get_lderrno( ld, NULL, NULL );
        fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }

    parse_rc = ldap_parse_result( ld, result, rc, matched, errmsg,
        referrals, resultctrls, 0 );
    if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_parse_result: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_simple_bind: %s\n", ldap_err2string( rc ) );
        if ( errmsg != NULL  errmsg != '\0' ) {
            fprintf( stderr, "%s\n", errmsg );
        }
    }
    if ( resultctrls == NULL ) {
        fprintf( stderr, "No result control from server.\n" );
        ldap_unbind( ld );
        return ( 1 );
    }

    /* Show the authorization ID. */
    parse_rc = ldap_parse_authzid_control( ld, resultctrls, authzid );
    if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_parse_authzid_control: %s\n",
            ldap_err2string( rc ) );
        ldap_unbind( ld );
        return ( 1 );
    }

    printf( "DN:       %s\n", ENTRYDN );
    printf( "Authz ID: %s\n", authzid );

    ldap_msgfree( result );
    ldap_control_free( authzidctrl );
    ldap_controls_free( resultctrls );
    ldap_unbind( ld );
    return( 0 );
}

Using the Get Effective Rights Request Control With Directory SDK for C

The control with OID 1.3.6.1.4.1.42.2.27.9.5.2, LDAP_CONTROL_GETEFFECTIVERIGHTS_REQUEST, is the get effective rights request control. This control lets you request information about the effective access rights a user has, by performing a search for the aclRights and aclRightsInfo attributes.

To Get Effective Rights

  1. Create a get effective rights request control using the ldap_create_geteffectiveRights_control function.
  2. Perform a search with the control, requesting the aclRights and aclRightsInfo attributes.
  3. Read the values of the attributes for the effective rights information.

This example gets effective rights for Kirsten Vaughan.

/*
 * Get effective rights for another user.
 */

#include "examples.h"

int
main( int argc, char **argv )
{
    int             version;
    LDAP            *ld;
    int             rc;
    LDAPControl     *gerctrl = NULL;
    LDAPControl     *requestctrls[ 2 ];
    char            *authzid;
    char            **attrlist;
    LDAPMessage     *result;
    LDAPMessage     *entry;
    char            *attr;
    BerElement      *ber;
    char            **vals;
    int             i;

    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
         != 0 ) {
            fprintf( stderr,
                "ldap_set_option protocol version to %d failed\n",
                version );
            return ( 1 );
    }

    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }

    /* Authenticate to the directory as a user. */
    if ( ldap_simple_bind_s( ld, USER_DN, USER_PW ) != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }

    /* Create a get effective rights control. */
    authzid = "dn: uid=kvaughan,ou=people,dc=example,dc=com";
    if ( !( attrlist = (char**)malloc(sizeof(char * [ 2 ]) ) ) ) {
        perror( "malloc" );
        ldap_unbind( ld );
        return ( 1 );
    }
    attrlist[ 0 ] = "aclRights";
    attrlist[ 1 ] = NULL;
    rc = ldap_create_geteffectiveRights_control( ld, authzid,
        (const char **)attrlist, 1, gerctrl );
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_create_geteffectiveRights_control: %s\n",
                 ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    requestctrls[ 0 ] = gerctrl;
    requestctrls[ 1 ] = NULL;

    /* Read an entry using the control. */
    rc = ldap_search_ext_s( ld, ENTRYDN, LDAP_SCOPE_BASE,
        "(objectclass=*)", attrlist, 0, requestctrls,
        NULL, NULL, 0, result );
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }

    /* Examine the entry for effective rights. */
    printf( "Bind DN:  %s\n", ENTRYDN );
    printf( "Authz ID: %s\n", authzid );
    printf( "***Rights***\n" );
    for ( entry = ldap_first_entry( ld, result );
          entry != NULL;
          entry = ldap_next_entry( ld, entry ) ) {
        for ( attr = ldap_first_attribute( ld, entry, ber );
              attr != NULL;
              attr = ldap_next_attribute ( ld, entry, ber) ) {
            if ( (vals = ldap_get_values( ld, entry, attr ) ) != NULL) {
                for ( i = 0; vals[i] != NULL; ++i ) {
                    printf( "%s: %s\n", attr, vals[i] );
                }
                ldap_value_free( vals );
            }
            ldap_memfree( attr );
        }
        if ( ber != NULL ) {
            ber_free( ber, 0 );
        }
    }
    printf( "\n" );

    ldap_msgfree( result );
    ldap_control_free( gerctrl );
    ldap_unbind( ld );
    return( 0 );
}

When you compile and run this sample program against Directory Server with a suffix that contains data from Example.ldif, the server produces output similar to the following. Lines are wrapped for readability.

Bind DN:  uid=bjensen, ou=People, dc=example,dc=com
Authz ID: dn: uid=kvaughan,ou=people,dc=example,dc=com
***Rights***
aclRights;entryLevel: add:1,delete:1,read:1,write:1,proxy:0
aclRights;attributeLevel;: search:1,read:1,compare:1,write:1,
 selfwrite_add:1,selfwrite_delete:1,proxy:0
aclRights;attributeLevel;dn: uid=kvaughan,ou=people,dc=example,dc=com:
 search:1,read:1,compare:1,write:1,selfwrite_add:1,selfwrite_delete:1,
 proxy:0
aclRights;attributeLevel;@c : search:1,read:1,compare:1,write:1,
 selfwrite_add:1,selfwrite_delete:1,proxy:0

See your server documentation for information about aclRights and aclRightsInfo values.

Using the Real Attributes Only Request Control With Directory SDK for C

The control with OID 2.16.840.1.113730.3.4.17, LDAP_CONTROL_REAL_ATTRS_ONLY, is the real attributes only request control. This control lets you convey to the server to return only real attributes, attributes that are stored by the directory, during a search.

To Retrieve Only Real Attributes

  1. Create an LDAPControl structure with the OID defined using LDAP_CONTROL_REAL_ATTRS_ONLY.
  2. Pass the control in to the server with the search request.
  3. Free the control when finished.

This example relies on sample data from Example-roles.ldif.

/*
 * Use the control to get only real attributes.
 * First load suffix data from Example-roles.ldif.
 */

#include "examples.h"

int
main( int argc, char **argv )
{
    LDAPControl     *ctrl = NULL;
    LDAPControl     *requestctrls[ 2 ];
    char            **attrlist;
    int             version;
    LDAP            *ld;
    char            *target;
    int             rc;
    LDAPMessage     *result;
    LDAPMessage     *entry;
    char            *dn;
    char            *attr;
    BerElement      *ber;
    char            **vals;
    int             i;

    /* Prepare a real attributes only request control. */
    if ( !(ctrl = (LDAPControl *)malloc(sizeof(LDAPControl))) ) {
        perror( "malloc" );
        return( 1 );
    }
    ctrl->ldctl_oid = strdup( LDAP_CONTROL_REAL_ATTRS_ONLY );
    ctrl->ldctl_iscritical = 1;
    requestctrls[ 0 ] = ctrl;
    requestctrls[ 1 ] = NULL;

    /* Create a list of attributes to retrieve. */
    if ( !( attrlist = (char**)malloc(sizeof(char * [ 3 ]) ) ) ) {
        perror( "malloc" );
        return ( 1 );
    }
    attrlist[ 0 ] = "cn";               /* Real attribute */
    attrlist[ 1 ] = "nsrole";           /* Virtual attribute */
    attrlist[ 2 ] = NULL;

    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
         != 0 ) {
        fprintf( stderr,
                 "ldap_set_option protocol version to %d failed\n",
                 version );
        return ( 1 );
    }

    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }

    /* Authenticate to the directory to read an entry. */
    if ( ldap_simple_bind_s( ld, USER_DN, USER_PW ) != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }

    /* Read an entry using the control. */
    target = "uid=kvaughan,ou=people,dc=example,dc=com";
    rc = ldap_search_ext_s( ld, target, LDAP_SCOPE_BASE, "(objectclass=*)",
        attrlist, 0, requestctrls, NULL, NULL, 0, result );
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }

    /* Examine the results. */
    for ( entry = ldap_first_entry( ld, result );
          entry != NULL;
          entry = ldap_next_entry( ld, entry ) ) {
        if ( (dn = ldap_get_dn( ld, entry )) != NULL ) {
            printf( "dn: %s\n", dn );
            ldap_memfree( dn );
        }
        for ( attr = ldap_first_attribute( ld, entry, ber );
              attr != NULL;
              attr = ldap_next_attribute ( ld, entry, ber) ) {
            if ( (vals = ldap_get_values( ld, entry, attr ) ) != NULL) {
                for ( i = 0; vals[i] != NULL; ++i ) {
                    printf( "%s: %s\n", attr, vals[i] );
                }
                ldap_value_free( vals );
            }
            ldap_memfree( attr );
        }
        if ( ber != NULL ) {
            ber_free( ber, 0 );
        }
    }
    printf( "\n" );

    ldap_msgfree( result );
    ldap_control_free( ctrl );
    ldap_unbind( ld );
    return( 0 );
}

When you compile and run this sample program against Directory Server with a suffix that contains data from Example-roles.ldif, the server produces output similar to this:

dn: uid=kvaughan, ou=People, dc=example,dc=com
cn: Kirsten Vaughan

Using the Virtual Attributes Only Request Control With Directory SDK for C

The control with OID 2.16.840.1.113730.3.4.19, LDAP_CONTROL_VIRTUAL_ATTRS_ONLY, is the virtual attributes only request control. This control lets you convey to the server to return only virtual attributes during a search. Virtual attribute values are not stored by the directory, but instead are generated on request.

To Retrieve Only Virtual Attributes

  1. Create an LDAPControl structure with the OID defined using LDAP_CONTROL_VIRTUAL_ATTRS_ONLY.
  2. Pass the control in to the server with the search request.
  3. Free the control when finished.

This example relies on sample data from Example-roles.ldif.

/*
 * Use the control to get only virtual attributes.
 * First load suffix data from Example-roles.ldif.
 */

#include "examples.h"

int
main( int argc, char **argv )
{
    LDAPControl     *ctrl = NULL;
    LDAPControl     *requestctrls[ 2 ];
    char            **attrlist;
    int             version;
    LDAP            *ld;
    char            *target;
    int             rc;
    LDAPMessage     *result;
    LDAPMessage     *entry;
    char            *dn;
    char            *attr;
    BerElement      *ber;
    char            **vals;
    int             i;

    /* Prepare a virtual attributes only request control. */
    if ( !(ctrl = (LDAPControl *)malloc(sizeof(LDAPControl))) ) {
        perror( "malloc" );
        return( 1 );
    }
    ctrl->ldctl_oid = strdup( LDAP_CONTROL_VIRTUAL_ATTRS_ONLY );
    ctrl->ldctl_iscritical = 1;
    requestctrls[ 0 ] = ctrl;
    requestctrls[ 1 ] = NULL;

    /* Create a list of attributes to retrieve. */
    if ( !( attrlist = (char**)malloc(sizeof(char * [ 3 ]) ) ) ) {
        perror( "malloc" );
        return ( 1 );
    }
    attrlist[ 0 ] = "cn";               /* Real attribute */
    attrlist[ 1 ] = "nsrole";           /* Virtual attribute */
    attrlist[ 2 ] = NULL;

    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
         != 0 ) {
        fprintf( stderr,
                 "ldap_set_option protocol version to %d failed\n",
                 version );
        return ( 1 );
    }

    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }

    /* Authenticate to the directory to read an entry. */
    if ( ldap_simple_bind_s( ld, USER_DN, USER_PW ) != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }

    /* Read an entry using the control. */
    target = "uid=kvaughan,ou=people,dc=example,dc=com";
    rc = ldap_search_ext_s( ld, target, LDAP_SCOPE_BASE, "(objectclass=*)",
        attrlist, 0, requestctrls, NULL, NULL, 0, result );
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }

    /* Examine the results. */
    for ( entry = ldap_first_entry( ld, result );
          entry != NULL;
          entry = ldap_next_entry( ld, entry ) ) {
        if ( (dn = ldap_get_dn( ld, entry )) != NULL ) {
            printf( "dn: %s\n", dn );
            ldap_memfree( dn );
        }
        for ( attr = ldap_first_attribute( ld, entry, ber );
              attr != NULL;
              attr = ldap_next_attribute ( ld, entry, ber) ) {
            if ( (vals = ldap_get_values( ld, entry, attr ) ) != NULL) {
                for ( i = 0; vals[i] != NULL; ++i ) {
                    printf( "%s: %s\n", attr, vals[i] );
                }
                ldap_value_free( vals );
            }
            ldap_memfree( attr );
        }
        if ( ber != NULL ) {
            ber_free( ber, 0 );
        }
    }
    printf( "\n" );

    ldap_msgfree( result );
    ldap_control_free( ctrl );
    ldap_unbind( ld );
    return( 0 );
}

When you compile and run this sample program against Directory Server with a suffix that contains data from Example-roles.ldif, the server produces output similar to this:

dn: uid=kvaughan, ou=People, dc=example,dc=com
nsrole: cn=directory administrators,dc=example,dc=com
nsrole: cn=hr managers,dc=example,dc=com

SASL Authentication With Directory SDK for C

This section describes the process of using a Simple Authentication and Security Layer (SASL) mechanism to authenticate an LDAP client to an LDAP server.

Understanding SASL and Directory SDK for C

The ability to authenticate to an LDAP server with a SASL mechanism is a feature that is new to LDAP v3. LDAP v2 servers do not support this method of authentication.

SASL is described in RFC 4422, Simple Authentication and Security Layer (SASL).

Determining Supported SASL Mechanisms With Directory SDK for C

To determine the SASL mechanisms supported by an LDAP v3 server, get the root DSE of the server, and check the supportedSASLMechanisms attribute. The values of this attribute are the names of the SASL mechanisms supported by the server.

If the root DSE does not have a supportedSASLMechanisms attribute, the server does not support any SASL mechanisms.

Authenticating Using SASL With Directory SDK for C

  • The synchronous ldap_sasl_bind_s() function
  • The asynchronous ldap_sasl_bind() function
    If you call the asynchronous function ldap_sasl_bind(), you need to call the ldap_result() and ldap_parse_sasl_bind_result() functions to get the result of the SASL bind operation.

Authentication with a SASL mechanism can take one or more roundtrips between your client and the server. The server might send a number of challenges to the client. You might need to call ldap_sasl_bind_s() several times, or ldap_sasl_bind(), ldap_result(), and ldap_parse_sasl_bind_result() several times in order to respond to each server challenge.

Before calling the function to perform a SASL bind operation, make sure to specify that your client is LDAP v3 compliant. If you do not, an LDAP_NOT_SUPPORTED result code is returned.

Synchronous SASL Bind Operation

If you want to wait for the results of the SASL bind operation to complete before continuing, call the synchronous ldap_sasl_bind_s() function. This function sends a SASL bind request to the server. This function blocks other work until the server sends the results of the operation back to your client.

  • LDAP_SUCCESS if your client has successfully authenticated.
  • LDAP_SASL_BIND_IN_PROGRESS if the server sends a challenge to your client. If you receive this result code, check the servercredp argument for the berval structure that contains the servers challenge. Call the ldap_sasl_bind function again to send a response to that challenge.
  • An LDAP error code if a problem occurred or if authentication failed. See the ldap_sasl_bind_s() function documentation for a list of the possible result codes.

Asynchronous SASL Bind Operation

If you want to perform other work in parallel while waiting for the SASL bind operation to complete, use the following procedure.

To Bind Asynchronously Over SASL

  1. Call the asynchronous ldap_sasl_bind() function to send an LDAP SASL bind request.
    This function returns an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred while sending the request. The function also sets the msgidp argument to point to a message ID identifying the SASL bind operation.
  2. Call the ldap_result() function, passing in this message ID to determine whether the server sent a response for this operation to your client.
    The ldap_result() function uses the message ID to determine if the server sent a SASL bind response. The function passes back the response in an LDAPMessage structure.
  3. Call the ldap_parse_sasl_bind_result() function to parse the LDAPMessage structure and retrieve information from the servers response.
    If the server sent a challenge to your client, the challenge is specified in the berval structure passed back as the servercredp argument.
  4. Call the ldap_get_lderrno function to get the LDAP result code for the operation.
    • LDAP_SUCCESS if your client successfully authenticated to the server.
    • LDAP_SASL_BIND_IN_PROGRESS if the server sent a challenge to your client.
      If the server returned an LDAP_SASL_BIND_IN_PROGRESS result code, check the servercredp argument for the berval structure that contains the servers challenge.
    • An LDAP error code if a problem occurred or if authentication failed.
      See the ldap_sasl_bind() function documentation for a list of result codes that the server can return for this operation.
  5. If the result code is LDAP_SASL_BIND_IN_PROGRESS and if the server passed back another challenge, determine the response to that challenge by calling the ldap_sasl_bind() function again to send that response to the server.
    You can call ldap_result() and ldap_parse_sasl_bind_result() again to get the next challenge sent from the server, if the result is again LDAP_SASL_BIND_IN_PROGRESS.

This example shows an LDAP client that authenticates using the SASL mechanism that is named babsmechanism.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ldap.h"

int
main( int argc, char **argv )
{
    LDAP        *ld;
    LDAPMod     mod0;
    LDAPMod     mod1;
    LDAPMod     *mods[ 3 ];
    char        *vals0[ 2 ];
    char        *vals1[ 2 ];
    time_t      now;
    char        buf[ 128 ];
    struct berval   cred;
    struct berval   *servcred;
    int         version;
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( "localhost", 389 )) == NULL ) {
      perror( "ldap_init" );
      return( 1 );
    }
    /* Set the LDAP protocol version supported by the client
       to 3. (By default, this is set to 2. SASL authentication
       is part of version 3 of the LDAP protocol.) */
    version = LDAP_VERSION3;
    ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );
    /* authenticate */
    cred.bv_val = "magic";
    cred.bv_len = sizeof( "magic" ) - 1;
    if ( ldap_sasl_bind_s( ld, "uid=bjensen,ou=people,dc=example,dc=com",
                           "babsmechanism", cred, NULL, NULL,
                           servcred ) != LDAP_SUCCESS ) {
      ldap_perror( ld, "ldap_sasl_bind_s" );
      return( 1 );
    }
    /* get and print the credentials returned by the server */
    printf( "Server credentials: %s\n", servcred->bv_val );
    /* construct the list of modifications to make */
    mod0.mod_op = LDAP_MOD_REPLACE;
    mod0.mod_type = "mail";
    vals0[0] = "babs@example.com";
    vals0[1] = NULL;
    mod0.mod_values = vals0;
    mod1.mod_op = LDAP_MOD_ADD;
    mod1.mod_type = "description";
    time( now );
    sprintf( buf, "This entry was modified with the modattrs program on %s",
      ctime( now ));
    /* Get rid of \n which ctime put on the end of the time string */
    if ( buf[ strlen( buf ) - 1 ] == '\n' ) {
      buf[ strlen( buf ) - 1 ] = '\0';
    }
    vals1[ 0 ] = buf;
    vals1[ 1 ] = NULL;
    mod1.mod_values = vals1;
    mods[ 0 ] = mod0;
    mods[ 1 ] = mod1;
    mods[ 2 ] = NULL;
    /* make the change */
    if ( ldap_modify_s(ld, "uid=bjensen,ou=people,dc=example,dc=com", mods)
      != LDAP_SUCCESS ) {
      ldap_perror( ld, "ldap_modify_s" );
      return( 1 );
    }
    ldap_unbind( ld );
    printf( "modification was successful\n" );
    return( 0 );
}

Extended Operations With Directory SDK for C

This section explains LDAP v3 extended operations. It also explains how to use the extended operations supported by your LDAP server.

How Extended Operations Work With Directory SDK for C

Extended operations are part of LDAP v3. Each extended operation is identified by an object identifier (OID). LDAP clients can request the operation by sending an extended operation request.

  • The OID of the extended operation that should be performed
  • Data specific to the extended operation

The server receives the request, then performs the extended operation. The server sends back a response to the client that contains an OID, and any additional data.

To use extended operations, both the server and the client must understand the specific extended operation to be performed. From the LDAP server perspective, Directory Server supports a server plug-in interface that you can use to add support for extended operations.

Determining the Extended Operations Supported With Directory SDK for C

To determine the extended operations supported by the server, get the root DSE of the server, and check the supportedExtension attribute. The values of this attribute are the OIDs of the extended operations supported by this server. If the root DSE does not have a supportedExtension attribute, the server does not support any extended operations.

Performing an Extended Operation With Directory SDK for C

  • The synchronous ldap_extended_operation_s() function
  • The asynchronous ldap_extended_operation() function

Both of these functions allow you to specify the OID of the extended operation and the data that you want applied to the operation.

Before calling the function to perform an LDAP extended operation, make sure to specify that your client is using version 3 of LDAP. If you do not, an LDAP_NOT_SUPPORTED result code is returned.

Synchronous Extended Operation

If you want to wait for the results of an LDAP extended operation to complete before continuing, call the synchronous ldap_extended_operation_s() function. This function sends a SASL bind request to the server. The server blocks other work until the server sends the results of the operation back to your client.

ldap_extended_operation_s() returns LDAP_SUCCESS if the operation completed successfully, or an error code if a problem occurred. See the documentation for the ldap_extended_operation_s() function for a list of the possible result codes.

Asynchronous Extended Operation

If you want to perform other work in parallel while waiting for an LDAP extended operation to complete, perform the following procedure.

To Perform an Asynchronous Extended Operation

  1. Call the asynchronous ldap_extended_operation() function to send an LDAP extended operation request.
    This function returns an LDAP_SUCCESS result code if the request was successfully sent, or an LDAP result code if an error occurred while sending the request. The function also sets the msgidp argument to point to a message ID identifying the extended operation. To determine whether the server sent a response to your client for this operation, call the ldap_result() function and pass in this message ID. The function passes back the response in an LDAPMessage structure.
  2. Call the ldap_parse_extended_result() function to parse the LDAPMessage structure and retrieve information from the servers response.
    If the server sent an OID of an extended operation to your client, the OID is passed back as the retoidp argument. If the server sent data to your client, the data is specified in the berval structure passed back as the retdatap argument.
  3. Call the ldap_get_lderrno() function to get the LDAP result code for the operation.
    The function returns an LDAP_SUCCESS result code if the extended operation was performed successfully, or an LDAP error code if a problem occurred. See the documentation for the ldap_extended_operation() function for a list of result codes that the server can return for this operation.

This example client requests an asynchronous extended operation from the server with OID 1.2.3.4.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ldap.h"

/* Name and port of the LDAP server you want to connect to. */
#define MY_HOST "localhost"
#define MY_PORT  389
/* DN of user (and password of user) who you want to authenticate as */
#define MGR_DN  "cn=Directory Manager"
#define MGR_PW  "23skidoo"
int
main( int argc, char **argv )
{
    /* OID of the extended operation that you are requesting */
    const char     *oidrequest = "1.2.3.4";
    char           *oidresult;
    struct berval  valrequest;
    struct berval  *valresult;
    LDAP           *ld;
    int rc, version;
    /* Set up the value that you want to pass to the server */
    printf( "Setting up value to pass to server...\n" );
    valrequest.bv_val = "My Value";
    valrequest.bv_len = strlen( "My Value" );
    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    printf( "Getting the handle to the LDAP connection...\n" );
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
  perror( "ldap_init" );
  ldap_unbind( ld );
  return( 1 );
    }
    /* Set the LDAP protocol version supported by the client
       to 3. (By default, this is set to 2. Extended operations
       are part of version 3 of the LDAP protocol.) */
    ldap_get_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );
    printf( "Resetting version %d to 3.0...\n", version );
    version = LDAP_VERSION3;
    ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, version );
    /* Authenticate to the directory as the Directory Manager */
    printf( "Binding to the directory...\n" );
    if ( ldap_simple_bind_s( ld, MGR_DN, MGR_PW ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_simple_bind_s" );
  ldap_unbind( ld );
  return( 1 );
    }
    /* Initiate the extended operation */
    printf( "Initiating the extended operation...\n" );
    if ( ( rc = ldap_extended_operation_s( ld, oidrequest, valrequest,
                  NULL, NULL, oidresult, valresult ) ) !=
         LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_extended_operation failed: " );
  ldap_unbind( ld );
  return( 1 );
    }
    /* Get the OID and the value from the result returned by the server. */
    printf( "Operation successful.\n" );
    printf( "\tReturned OID: %s\n", oidresult );
    printf( "\tReturned value: %s\n", valresult->bv_val );
    /* Disconnect from the server. */
    ldap_unbind( ld );
    return 0;
}

Performing an LDAP Password Modify Extended Operation With Directory SDK for C

RFC 3062, LDAP Password Modify Extended Operation, describes the extended operation, which is particularly useful for changing expired passwords.

To Perform an LDAP Password Modify Extended Operation

  1. Get a connection to the directory that uses LDAP version 3.
  2. Authenticate to the directory.
    • As an administrator, to be able to reset an expired user password if you do not have the old password
    • Anonymously to reset an expired password if you have the old password
    • As the user herself to change the password that has not yet expired
  3. Modify the password with the synchronous function ldap_passwd_s() or the asynchronous function ldap_passwd() and use ldap_parse_passwd() or ldap_parse_passwd_result() to examine the results.

This example changes a password using ldap_passwd_s().

/*
 * Use the password modify extended operation to change a password.
 */

#include "examples.h"

int
main( int argc, char **argv )
{
    int             version;
    LDAP            *ld;
    char            *target;
    int             rc;
    struct berval   userid;
    struct berval   oldpasswd;
    struct berval   newpasswd;
    struct berval   genpasswd;

    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
         != 0 ) {
        fprintf( stderr,
                 "ldap_set_option protocol version to %d failed\n",
                 version );
        return ( 1 );
    }

    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }

    /* Authenticate to the directory. */
    if ( ldap_simple_bind_s( ld, ENTRYDN, ENTRYPW ) != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }

    /* Change the password using the extended operation. */
    userid.bv_val = ENTRYDN;
    userid.bv_len = strlen(userid.bv_val);

    oldpasswd.bv_val = ENTRYPW;
    oldpasswd.bv_len = strlen(oldpasswd.bv_val);

    newpasswd.bv_val = "ChangeMe!";
    newpasswd.bv_len = strlen(newpasswd.bv_val);

    rc = ldap_passwd_s(
        ld, userid, oldpasswd, newpasswd, genpasswd, NULL, NULL );
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_passwd_s: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    } else {
        printf( "Successfully changed password for %s\n", userid.bv_val );
    }

    ldap_unbind( ld );
    return( 0 );

When you compile and run this sample program against Directory Server with a suffix that contains data from Example.ldif, the server produces output similar to this:

Successfully changed password for uid=bjensen, ou=People, dc=example,dc=com

Using Start TLS With Directory SDK for C

RFC 4513, Lightweight Directory Access Protocol (LDAP): Authentication Methods and Security Mechanisms, describes the extended operation. Start TLS allows you to connect on a non secure port, and then request transport layer security.

See Starting Transport Layer Security With Directory SDK for C for an example of how to use Start TLS.

Performing a Who Am I? Extended Operation With Directory SDK for C

The Who am I? extended operation allows you to retrieve the authorization identity that is associated with a connection.

This method can involve less code than the standard authorization identity controls that are described in Using the Authorization Identity Bind Request Control With Directory SDK for C.

To Perform a Who Am I? Extended Operation

  1. Get a connection to the directory that uses LDAP version 3.
  2. Use ldap_whoami() and ldap_parse_whoami_result(), or use ldap_whoami_s(), to retrieve the authorization identity.

This example retrieves authorization identity by using ldap_whoami_s().

/*
 * Use the Who Am I? extended operation.
 */

#include "examples.h"

int
main( int argc, char **argv )
{
    int             version;
    LDAP            *ld;
    int             rc;
    char            *authzid;

    /* Use LDAPv3. */
    version = LDAP_VERSION3;
    if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, version )
         != 0 ) {
        fprintf( stderr,
                 "ldap_set_option protocol version to %d failed\n",
                 version );
        return ( 1 );
    }

    /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
    if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
        perror( "ldap_init" );
        return( 1 );
    }

    /* Authenticate to the directory. */
    if ( ldap_simple_bind_s( ld, ENTRYDN, ENTRYPW ) != LDAP_SUCCESS ) {
        ldap_perror( ld, "ldap_simple_bind_s" );
        return( 1 );
    }

    /* Examine my authorization ID. */
    rc = ldap_whoami_s( ld, NULL, NULL, authzid );
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_whoami_s: %s\n", ldap_err2string( rc ) );
        ldap_unbind( ld );
        return( 1 );
    }
    printf( "Authorization ID: %s\n", authzid );

    ldap_unbind( ld );
    return( 0 );
}

When you compile and run this sample program against Directory Server with a suffix that contains data from Example.ldif, the server produces output similar to this:

Authorization ID: dn:uid=bjensen,ou=people,dc=example,dc=com

Writing Multithreaded Clients With Directory SDK for C

This section shows how to write multithreaded LDAP client applications.

The Directory SDK for C APIs are thread-safe. By default, the APIs use POSIX thread-safe primitives. Therefore, unless you specify your own thread functions, standard best practices for POSIX threading apply.

Specifying Thread Functions With Directory SDK for C

You can write a multithreaded client with different threads accessing the same LDAP structure. Use the POSIX thread API. Alternatively, set up the session defining your own structures such that threads do not interfere with data of other threads.

The LDAP_OPT_THREAD_FN_PTRS session option lets you set up an ldap_thread_fns structure. The structure identifies the functions that are called in multithreaded environments. For example, the structure can define functions to lock critical sections of code and to handle errors. As this structure lets you specify these functions, you can use Directory SDK for C in different types of threading environments.

Setting Up the ldap_thread_fns Structure

You can write a multithreaded client in which different threads use the same LDAP connection. Set up the ldap_thread_fns structure. Then identify the functions that you want to use in the ldap_thread_fns structure.

struct ldap_thread_fns {
  LDAP_TF_MUTEX_ALLOC_CALLBACK   *ltf_mutex_alloc;
  LDAP_TF_MUTEX_FREE_CALLBACK    *ltf_mutex_free;
  LDAP_TF_MUTEX_LOCK_CALLBACK    *ltf_mutex_lock;
  LDAP_TF_MUTEX_UNLOCK_CALLBACK  *ltf_mutex_unlock;
  LDAP_TF_GET_ERRNO_CALLBACK     *ltf_get_errno;
  LDAP_TF_SET_ERRNO_CALLBACK     *ltf_set_errno;
  LDAP_TF_GET_LDERRNO_CALLBACK   *ltf_get_lderrno;
  LDAP_TF_SET_LDERRNO_CALLBACK   *ltf_set_lderrno;
  void    *ltf_lderrno_arg;
};

The fields of the ldap_thread_fns structure are described in the following list.

  • *ltf_mutex_alloc: Function pointer for allocating a mutex. This function is called by the client when needed if the function pointer is not NULL.
  • *ltf_mutex_free: Function pointer for freeing a mutex. This function is called by the client when needed if the function pointer is not NULL.
  • *ltf_mutex_lock: Function pointer for locking critical sections of code. This function is called by the client when needed if the function pointer is not NULL.
  • *ltf_mutex_unlock: Function pointer for unlocking critical sections of code. This function is called by the client when needed if the function pointer is not NULL.
  • *ltf_get_errno: Function pointer for getting the value of the errno variable. This function is called by the client when needed if the function pointer is not NULL. In a threaded environment, errno is typically redefined. The error structure has a value for each thread, rather than a global value for the entire process. This redefinition is done at compile time. The libldap library does not know what method your code and your threading environment use to get the value of errno for each thread. The library therefore calls this function to return the value of errno.
  • *ltf_set_errno: Function pointer for setting the value of the errno variable. This function is called by the client when needed if the function pointer is not NULL. In a threaded environment, errno is typically redefined. The error structure has a value for each thread, rather than a global value for the entire process. This redefinition is done at compile time. The libldap library does not know what method your code and your threading environment use to get the value of errno for each thread. The library therefore calls this function to set the value of errno.
  • *ltf_get_lderrno: Function pointer for getting error values from calls to functions in the libldap library. This function is called by the client when needed if the function pointer is not NULL. If this function pointer is not set, the libldap library records these errors in fields in the LDAP structure.
  • *ltf_set_lderrno: Function pointer for setting error values from calls to functions in the libldap library. This function is called by the client when needed if the function pointer is not NULL. If this function pointer is not set, the libldap library records these errors in fields in the LDAP structure.
  • *ltf_lderrno_arg: Additional parameter passed to the functions for getting and setting error values from calls to functions in the libldap library. *ltf_get_lderrno and *ltf_set_lderrno identify these functions.

Setting Up the ldap_extra_thread_fns Structure

Directory SDK for C provides a structure, ldap_extra_thread_fns, that specifies additional thread functions for locking. The structure also specifies thread functions for semaphores, which are protected variables. The ldap_extra_thread_fns structure is defined as follows.

struct ldap_extra_thread_fns {
  LDAP_TF_MUTEX_TRYLOCK_CALLBACK  *ltf_mutex_trylock;
  LDAP_TF_SEMA_ALLOC_CALLBACK     *ltf_sema_alloc;
  LDAP_TF_SEMA_FREE_CALLBACK      *ltf_sema_free;
  LDAP_TF_SEMA_WAIT_CALLBACK      *ltf_sema_wait;
  LDAP_TF_SEMA_POST_CALLBACK      *ltf_sema_post;
  LDAP_TF_THREADID_CALLBACK       *ltf_threadid_fn;
};

Directory SDK for C supports only the LDAP_TF_TREADID_CALLBACK *ltf_threadid_fn function. You use this function callback in a multithreaded application to improve the performance of thread locking. The supported function must return an identifier that is unique to the calling thread, like pthread_self() does. If any of the other extra thread callback functions are set, the extra functions are ignored.

Setting Session Options

After you set up the ldap_thread_fns structure, associate the structure with the current session. Call the ldap_set_option() function and pass LDAP_OPT_THREAD_FN_PTRS as the value of the option parameter. Pass a pointer to the ldap_thread_fns structure as the value of the optdata parameter.

#include <stdio.h>
#include <malloc.h>
#include <errno.h>
#include <pthread.h>
#include "ldap.h"

struct ldap_thread_fns tfns;
...
  /* Set up the ldap_thread_fns structure with pointers
    to the functions that you want called */
  memset( tfns, '\0', sizeof(struct ldap_thread_fns) );

  /* Specify the functions that you want called */

  /* Call the my_mutex_alloc() function whenever mutexes
    need to be allocated */
  tfns.ltf_mutex_alloc = (void *(*)(void)) my_mutex_alloc;

  /* Call the my_mutex_free() function whenever mutexes
    need to be destroyed */
  tfns.ltf_mutex_free = (void (*)(void *)) my_mutex_free;

  /* Call the pthread_mutex_lock() function whenever a
    thread needs to lock a mutex. */
  tfns.ltf_mutex_lock = (int (*)(void *)) pthread_mutex_lock;

  /* Call the pthread_mutex_unlock() function whenever a
    thread needs to unlock a mutex. */
  tfns.ltf_mutex_unlock = (int (*)(void *)) pthread_mutex_unlock;

  /* Call the get_errno() function to get the value of errno */
  tfns.ltf_get_errno = get_errno;

  /* Call the set_errno() function to set the value of errno */
  tfns.ltf_set_errno = set_errno;

  /* Call the get_ld_error() function to get error values from
    calls to functions in the libldap library */
  tfns.ltf_get_lderrno = get_ld_error;

  /* Call the set_ld_error() function to set error values for
    calls to functions in the libldap library */
  tfns.ltf_set_lderrno = set_ld_error;

  /* Dont pass any extra parameter to the functions for
    getting and setting libldap function call errors */
  tfns.ltf_lderrno_arg = NULL;
...
/* Set the session option that specifies the functions to call for
    multi-threaded clients */
if (ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) tfns) != 0) {
  ldap_perror( ld, "ldap_set_option: thread pointers" );
}
...

If you also set up the ldap_extra_thread_fns structure, associate the structure with the current session. Call the ldap_set_option() function, passing LDAP_OPT_EXTRA_THREAD_FN_PTRS as the value of the option parameter. Also pass a pointer to the ldap_extra_thread_fns structure as the value of the optdata parameter.

POSIX Thread Client Application With Directory SDK for C

The following example which uses pthreads (POSIX threads) on Solaris systems, is the source code for a multithreaded client. The client connects to a specified LDAP server. The client then creates several threads to perform multiple search and update operations simultaneously on the directory.

#include <stdio.h>
#include <malloc.h>
#include <errno.h>
#include <pthread.h>
#include <synch.h>
#include "ldap.h"

/* Authentication and search information. */
#define NAME         "cn=Directory Manager"
#define PASSWORD     "rtfm11111"
#define BASE         "dc=example,dc=com"
#define SCOPE        LDAP_SCOPE_SUBTREE

/* Function declarations */
static void *search_thread();
static void *modify_thread();
static void *add_thread();
static void *delete_thread();
static void set_ld_error();
static int  get_ld_error();
static void set_errno();
static int  get_errno();
static void tsd_setup();

/* Linked list of LDAPMessage structs for search results. */
typedef struct ldapmsgwrapper {
    LDAPMessage      *lmw_messagep;
    struct ldapmsgwrapper  *lmw_next;
} ldapmsgwrapper;

LDAP    *ld;
pthread_key_t  key;

main( int argc, char **argv )
{
  pthread_attr_t  attr;
  pthread_t  search_tid, search_tid2, search_tid3, search_tid4;
  pthread_t  modify_tid, add_tid, delete_tid;
  void    *status;
  struct ldap_thread_fns  tfns;
  struct ldap_extra_thread_fns extrafns;
  int rc;

  /* Check command-line syntax. */
  if ( argc != 3 ) {
    fprintf( stderr, "usage: %s host> port>\n", argv[0] );
    exit( 1 );
  }

  /* Create a key. */
  if ( pthread_key_create( key, free ) != 0 ) {
    perror( "pthread_key_create" );
  }
  tsd_setup();

  /* Initialize the LDAP session. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( argv[1], atoi( argv[2] ) )) == NULL ) {
    perror( "ldap_init" );
    exit( 1 );
  }

  /* Set the function pointers for dealing with mutexes
     and error information. */
  memset( tfns, '\0', sizeof(struct ldap_thread_fns) );
  tfns.ltf_mutex_alloc = (void *(*)(void)) my_mutex_alloc;
  tfns.ltf_mutex_free = (void (*)(void *)) my_mutex_free;
  tfns.ltf_mutex_lock = (int (*)(void *)) pthread_mutex_lock;
  tfns.ltf_mutex_unlock = (int (*)(void *)) pthread_mutex_unlock;
  tfns.ltf_get_errno = get_errno;
  tfns.ltf_set_errno = set_errno;
  tfns.ltf_get_lderrno = get_ld_error;
  tfns.ltf_set_lderrno = set_ld_error;
  tfns.ltf_lderrno_arg = NULL;

  /* Set up this session to use those function pointers. */
  rc = ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) tfns );
  if ( rc  0 ) {
    fprintf( stderr, 
             "ldap_set_option (LDAP_OPT_THREAD_FN_PTRS): %s\n",
             ldap_err2string( rc ) );
    exit( 1 );
  }

  /* Set the function pointers for working with semaphores. */
  memset( extrafns, '\0', sizeof(struct ldap_extra_thread_fns) );
  extrafns.ltf_mutex_trylock = (int (*)(void *)) = null;
  extrafns.ltf_sema_alloc = (void *(*)(void)) = null;
  extrafns.ltf_sema_free = (void (*)(void *)) = null;
  extrafns.ltf_sema_wait = (int (*)(void *)) = null;
  extrafns.ltf_sema_post = (int (*)(void *)) = null;
  extrafns.ltf_threadid_fn = (void * (*)(void) )pthread_self;
  /* Set up this session to use those function pointers. */
  rc = ldap_set_option( ld,
                        LDAP_OPT_EXTRA_THREAD_FN_PTRS,
                        (void *) extrafns );
  if ( rc  0 ) {
    fprintf( stderr, 
             "ldap_set_option (LDAP_OPT_EXTRA_THREAD_FN_PTRS): %s\n", 
             ldap_err2string( rc ) );
    exit( 1 );
  }

  /* Attempt to bind to the server. */
  rc = ldap_simple_bind_s( ld, NAME, PASSWORD );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
    exit( 1 );
  }

  /* Initialize the attribute. */
  if ( pthread_attr_init( attr ) != 0 ) {
    perror( "pthread_attr_init" );
    exit( 1 );
  }

  /* Specify that the threads are joinable. */
  pthread_attr_setdetachstate( attr, PTHREAD_CREATE_JOINABLE );

  /* Create seven threads: one for adding, one for modifying,
     one for deleting, and four for searching. */
  if (pthread_create(search_tid, attr, search_thread, "1") != 0) {
    perror( "pthread_create search_thread" );
    exit( 1 );
  }
  if (pthread_create(modify_tid, attr, modify_thread, "2") != 0) {
    perror( "pthread_create modify_thread" );
    exit( 1 );
  }
  if (pthread_create(search_tid2, attr, search_thread, "3") != 0) {
    perror( "pthread_create search_thread2" );
    exit( 1 );
  }
  if (pthread_create(add_tid, attr, add_thread, "4" ) != 0) {
    perror( "pthread_create add_thread" );
    exit( 1 );
  }
  if (pthread_create(search_tid3, attr, search_thread, "5") != 0) {
    perror( "phread_create search_thread3" );
    exit( 1 );
  }
  if (pthread_create(delete_tid, attr, delete_thread, "6") != 0) {
    perror( "pthread_create delete_thread" );
    exit( 1 );
  }
  if (pthread_create(search_tid4, attr, search_thread, "7") != 0) {
    perror( "pthread_create search_thread4" );
    exit( 1 );
  }

  /* Wait until these threads exit. */
  pthread_join( modify_tid, status );
  pthread_join( add_tid, status );
  pthread_join( delete_tid, status );
  pthread_join( search_tid, status );
  pthread_join( search_tid2, status );
  pthread_join( search_tid3, status );
  pthread_join( search_tid4, status );
}

/* Thread for searching the directory.
   The results are not printed out. */
static void *
search_thread( char *id )
{
  LDAPMessage  *res;
  LDAPMessage  *e;
  char    *a;
  char    **v;
  char    *dn;
  BerElement  *ber;
  int    i, rc, parse_rc, msgid, finished;
  int    num_entries, num_refs;
  void    *tsd;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;

  printf( "Starting search_thread %s.\n", id );
  tsd_setup();
  /* Continually search the directory. */
  for ( ;; ) {
    printf( "Thread %s: Searching...\n", id );
    finished = 0;
    num_entries = 0;
    num_refs = 0;
    rc = ldap_search_ext( ld, BASE, SCOPE, "(objectclass=*)",
      NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, msgid );
    if ( rc != LDAP_SUCCESS ) {
      fprintf( stderr, "Thread %s error: ldap_search: %s\n",
        id, ldap_err2string( rc ) );
      continue;
    }

    /* Iterate through the results.  In this example,
       don't print out all the results.  (It's easier
       to see the output from the other threads this way.) */
    while ( !finished ) {
      rc = ldap_result( ld, msgid, LDAP_MSG_ONE, zerotime, res );
      switch ( rc ) {
      case -1:
        rc = ldap_get_lderrno( ld, NULL, NULL );
        fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
        finished = 1;
        break;
      case 0:
        break;
      /* Keep track of the number of entries found. */
      case LDAP_RES_SEARCH_ENTRY:
        num_entries++;
        break;
      /* Keep track of the number of search references. */
      case LDAP_RES_SEARCH_REFERENCE:
        num_refs++;
        break;
      case LDAP_RES_SEARCH_RESULT:
        finished = 1;
        parse_rc = ldap_parse_result( ld, res, rc,
                     NULL, NULL, NULL, NULL, 1 );
        if ( parse_rc != LDAP_SUCCESS ) {
          fprintf( stderr,
                   "Thread %s error: can't parse result code.\n",
                   id );
          break;
        } else {
          if ( rc != LDAP_SUCCESS ) {
            fprintf( stderr, 
                     "Thread %s error: ldap_search: %s\n", 
                     id, ldap_err2string( rc ) );
          } else {
            printf( "Thread %s: Got %d results and %d references.\n", 
                    id, num_entries, num_refs );
          }
        }
        break;
      default:
        break;
      }
    }
  }
}

/* Thread for modifying directory entries.
This thread searches for entries and randomly selects entries from
the search results for modification. */
static void *
modify_thread( char *id )
{
  LDAPMessage      *res;
  LDAPMessage      *e;
  int              i, modentry, num_entries, msgid, rc, parse_rc, finished;
  LDAPMod          mod;
  LDAPMod          *mods[2];
  char             *vals[2];
  char            *dn;
  ldapmsgwrapper  *list, *lmwp, *lastlmwp;
  struct timeval  zerotime;
  zerotime.tv_sec = zerotime.tv_usec = 0L;

  printf( "Starting modify_thread %s.\n", id );
  tsd_setup();
  rc = ldap_search_ext( ld, BASE, SCOPE, "(objectclass=*)",
    NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, msgid );
  if ( rc != LDAP_SUCCESS ) {
    fprintf( stderr, "Thread %s error: Modify thread: "
    "ldap_search_ext: %s\n", id, ldap_err2string( rc ) );
    exit( 1 );
  }
  list = lastlmwp = NULL;
  finished = 0;
  num_entries = 0;
  while ( !finished ) {
    rc = ldap_result( ld, msgid, LDAP_MSG_ONE, zerotime, res );
    switch ( rc ) {
    case -1:
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) );
      exit( 1 );
      break;
    case 0:
      break;

    /* Keep track of the number of entries found. */
    case LDAP_RES_SEARCH_ENTRY:
      num_entries++;
      if (( lmwp = (ldapmsgwrapper *)
        malloc( sizeof( ldapmsgwrapper ))) == NULL ) {
        fprintf( stderr, "Thread %s: Modify thread: Cannot malloc\n", id );
        exit( 1 );
      }
      lmwp->lmw_messagep = res;
      lmwp->lmw_next = NULL;
      if ( lastlmwp == NULL ) {
        list = lastlmwp = lmwp;
      } else {
        lastlmwp->lmw_next = lmwp;
      }
      lastlmwp = lmwp;
      break;
    case LDAP_RES_SEARCH_REFERENCE:
      break;
    case LDAP_RES_SEARCH_RESULT:
      finished = 1;
      parse_rc = ldap_parse_result( ld, res, rc, NULL, NULL,
                                    NULL, NULL, 1 );
      if ( parse_rc != LDAP_SUCCESS ) {
        fprintf( stderr,
                 "Thread %s error: can't parse result code.\n",
                 id );
        exit( 1 );
      } else {
        if ( rc != LDAP_SUCCESS ) {
          fprintf( stderr, 
                   "Thread %s error: ldap_search: %s\n", 
                   id, ldap_err2string( rc ) );
        } else {
          printf( "Thread %s: Got %d results.\n", id, num_entries );
        }
      }
      break;
    default:
      break;
    }
  }

  /* Set up the modifications to be made. */
  mods[0] = mod;
  mods[1] = NULL;
  vals[0] = "bar";
  vals[1] = NULL;

  /* Modify randomly selected entries. */
  for ( ;; ) {

    /* Randomly select the entries. */
    modentry = rand() % num_entries;
    for ( i = 0, lmwp = list; lmwp != NULL  i  modentry;
        i++, lmwp = lmwp->lmw_next ) {
      /* Keep iterating. */
    }
    if ( lmwp == NULL ) {
      fprintf( stderr,
          "Thread %s: Modify thread could not find entry %d of %d\n",
          id, modentry, num_entries );
      continue;
    }
    e = lmwp->lmw_messagep;
    printf( "Thread %s: Modify thread picked entry %d of %d\n",
            id, i, num_entries );

    /* Perform the modification. */
    dn = ldap_get_dn( ld, e );
    mod.mod_op = LDAP_MOD_REPLACE;
    mod.mod_type = "description";
    mod.mod_values = vals;
    printf( "Thread %s: Modifying (%s)\n", id, dn );
    rc = ldap_modify_ext_s( ld, dn, mods, NULL, NULL );
            if ( rc != LDAP_SUCCESS ) {
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_modify_ext_s: %s\n", ldap_err2string( rc ) );
    }
    free( dn );
  }
}

/* Thread for adding directory entries.
   This thread randomly generates DNs for entries and attempts to
   add them to the directory. */
static void *
add_thread( char *id )
{
  LDAPMod  mod[5];
  LDAPMod  *mods[6];
  char  dn[BUFSIZ], name[40];
  char  *cnvals[2], *snvals[2], *ocvals[3];
  int  i, rc;

  printf( "Starting add_thread %s.\n", id );
  tsd_setup();

  /* Set up the entry to be added. */
  for ( i = 0; i  5; i++ ) {
    mods[i] = mod[i];
  }
  mods[5] = NULL;
  mod[0].mod_op = 0;
  mod[0].mod_type = "cn";
  mod[0].mod_values = cnvals;
  cnvals[1] = NULL;
  mod[1].mod_op = 0;
  mod[1].mod_type = "sn";
  mod[1].mod_values = snvals;
  snvals[1] = NULL;
  mod[2].mod_op = 0;
  mod[2].mod_type = "objectclass";
  mod[2].mod_values = ocvals;
  ocvals[0] = "top";
  ocvals[1] = "person";
  ocvals[2] = NULL;
  mods[3] = NULL;

  /* Randomly generate DNs and add entries. */
  for ( ;; ) {
    sprintf( name, "%d", rand() );
    sprintf( dn, "cn=%s, " BASE, name );
    cnvals[0] = name;
    snvals[0] = name;
    printf( "Thread %s: Adding entry (%s)\n", id, dn );
    rc = ldap_add_ext_s( ld, dn, mods, NULL, NULL );
            if ( rc != LDAP_SUCCESS ) {
      rc = ldap_get_lderrno( ld, NULL, NULL );
      fprintf( stderr, "ldap_add_ext_s: %s\n", ldap_err2string( rc ) );
    }
  }
}

/* Thread for deleting directory entries.
This thread randomly selects entries for deletion. */
static void *
delete_thread( char *id )
{
  LDAPMessage  *res;
  char    dn[BUFSIZ], name[40];

  printf( "Starting delete_thread %s.\n", id );
  tsd_setup();

  /* Randomly select entries for deletion. */
  for ( ;; ) {
    sprintf( name, "%d", rand() );
    sprintf( dn, "cn=%s, " BASE, name );
    printf( "Thread %s: Deleting entry (%s)\n", id, dn );
    if ( ldap_delete_ext_s( ld, dn, NULL, NULL ) != LDAP_SUCCESS ) {
      ldap_perror( ld, "ldap_delete_ext_s" );
    }
  }
}

/* Function for allocating a mutex. */
static void *
my_mutex_alloc( void )
{
  pthread_mutex_t  *mutexp;
  if ( (mutexp = malloc( sizeof(pthread_mutex_t) )) != NULL ) {
    pthread_mutex_init( mutexp, NULL );
  }
  return( mutexp );
}

/* Function for freeing a mutex. */
static void
my_mutex_free( void *mutexp )
{
  pthread_mutex_destroy( (pthread_mutex_t *) mutexp );
  free( mutexp );
}

/* Error structure. */
struct ldap_error {
  int  le_errno;
  char  *le_matched;
  char  *le_errmsg;
};

/* Function to set up thread-specific data. */
static void
tsd_setup()
{
  void  *tsd;
  tsd = pthread_getspecific( key );
  if ( tsd != NULL ) {
    fprintf( stderr, "tsd non-null!\n" );
    pthread_exit( NULL );
  }
  tsd = (void *) calloc( 1, sizeof(struct ldap_error) );
  pthread_setspecific( key, tsd );
}

/* Function for setting an LDAP error. */
static void
set_ld_error( int err, char *matched, char *errmsg, void *dummy )
{
  struct ldap_error *le;
  le = pthread_getspecific( key );
  le->le_errno = err;
  if ( le->le_matched != NULL ) {
    ldap_memfree( le->le_matched );
  }
  le->le_matched = matched;
  if ( le->le_errmsg != NULL ) {
    ldap_memfree( le->le_errmsg );
  }
  le->le_errmsg = errmsg;
}

/* Function for getting an LDAP error. */
static int
get_ld_error( char **matched, char **errmsg, void *dummy )
{
  struct ldap_error *le;
  le = pthread_getspecific( key );
  if ( matched != NULL ) {
    *matched = le->le_matched;
  }
  if ( errmsg != NULL ) {
    *errmsg = le->le_errmsg;
  }
  return( le->le_errno );
}

/* Function for setting errno. */
static void
set_errno( int err )
{
  errno = err;
}

/* Function for getting errno. */
static int
get_errno( void )
{
  return( errno );
}

Directory SDK for C Data Type Reference

This section contains reference material for the public data types and structures of Directory SDK for C. The first subsections detail the data types of the grouped into task categories. The last subsection is an alphabetical listing of the same information.

Conventions

The following sections detail certain conventions and concepts used in Directory SDK for C.

Typographical Conventions

The following table lists the typographical conventions used in the names of data types and structures.

Typographical Conventions in Data Types and Structures
Convention Description of Use
LeadingCaps Data structures needed to pass values to and from functions of Directory SDK For C. For consistency, use this typedef name for these structures, not their literal struct name.
ALL_CAPS Names of callback function prototypes which you can implement for extended functionality in your client application.
fns suffix Structures which hold the function pointers for callback functions, grouped by task.

Deprecated Structures

A deprecated API is one you should no longer use for new development, and should begin to phase out for applications you maintain. Deprecated interfaces may disappear in the major version following their deprecation.

Structure Summary by Task

In the following sections the structures defined by Directory SDK For C are grouped into task categories.

BER Structures

The structures listed in the following table represent data encoded using the Basic Encoding Rules (BER). The lber.h header file contains many other type definitions; the ones listed here are those likely to be handled directly. All others are used internally by the various functions of Directory SDK For C.

BER Structures
Structure Description
berval berval represents binary data encoded using BER.
BerElement BerElement indicates the current position during a traversal of an attribute list.

Structures for the Core API

The structures listed in the following table are used by the core functions of Directory SDK For C. These structures are used directly as argument or return types by functions that provide the core functionality.

Core API Structures
Structure Description
LDAP LDAP represents a connection handle to the LDAP server.
LDAPMessage LDAPMessage represents the results of an LDAP operation, a chain of search results, an entry in the search results, or a search reference in the search results.
LDAPMod LDAPMod specifies changes to an attribute in an directory entry.
LDAPControl LDAPControl represents a client or server control associated with an LDAP operation.
LDAPAPIInfo LDAPAPIInfo represents information about the version of Directory SDK For C being implemented
LDAPAPIFeatureInfo LDAPAPIFeatureInfo represents information about the extended features.

Structures for API Extensions

The structures listed in the following table are needed for extensions to the standard API within Directory SDK For C. These structures are used directly as arguments or return types by the functions that provide the extended functionality.

API Extension Structures
Structure Description
LDAPsortkey LDAPsortkey represents a server control used to specify that the server should sort the search results before sending them back to the client.
LDAPVirtualList LDAPVirtualList specifies the information that can be used to create a virtual list view control.
LDAPURLDesc LDAPURLDesc represents the components of an LDAP URL.
LDAPFiltInfo LDAPFiltInfo represents information about a filter in a filter configuration file.
LDAPFiltDesc LDAPFiltDesc is a type of structure returned when you call ldap_init_getfilter to load a filter configuration file.
FriendlyMap FriendlyMap represents the mapping between a list of standard attribute names and their user friendly counterparts.
LDAPMemCache LDAPMemCache represents an in-memory, client-side cache.
LDAPpwdpolicy LDAPpwdpolicy represents password policy information concerning an entry.
LDAPuserstatus LDAPuserstatus represents account availability information.

Note: This prototype for a callback function retrieves authentication information when automatically following referrals to other servers.

Referral Binding Data Type
Data Type Description
LDAP_REBINDPROC_CALLBACK Retrieves authentication information when following referrals to other servers.

Client-Side Sorting Callbacks

The prototype structures listed in the following table are extensions to Directory SDK For C that implement client side sorting of entries.

Client-side Sorting Structures
Data Type Description
LDAP_KEYGEN_CALLBACK Function prototype that generates the sorting key for each entry to be sorted, usually by extracting a value out of an entry.
LDAP_KEYCMP_CALLBACK Function prototype to compare 2 keys (for ordering).
LDAP_KEYFREE_CALLBACK Function prototype that frees the memory allocated during the KEYGEN callback.
LDAP_CMP_CALLBACK Function prototype to sort a specified set of entries.
LDAP_VALCMP_CALLBACK Function prototype to sort a specified set of values.

Extended I/O Control

The following table lists the prototypes and structures used in the extended I/O control, an extension to the standard API.

Structures and Prototypes for Extended I/O Functionality
Data Type Description
ldap_x_ext_io_fns This structure holds extended I/O function pointers.
LDAP_X_PollFD An LDAP file descriptor similar to that of poll().
LDAP_X_EXTIOF_CONNECT_CALLBACK Function prototype for a callback that opens a socket connection.
LDAP_X_EXTIOF_CLOSE_CALLBACK Function prototype for a callback that closes a socket connection.
LDAP_X_EXTIOF_POLL_CALLBACK Function prototype for a callback that surveys a server about a particular event.
LDAP_X_EXTIOF_NEWHANDLE_CALLBACK Function prototype for a callback that defines a new session handle.
LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK Function prototype for a callback that disposes of a session handle.
ldap_x_hostlist_status This structure holds utility functions for parsing space-separated host lists.

Memory Management Control

The prototypes and structures listed in theh following table are used in memory management control, an extension to the standard API. They allow you to specify your own memory allocation mechanisms and functions.

Memory Management Data Types
Data Type Description
ldap_memalloc_fns This structure holds the memory allocation callback functions.
LDAP_MALLOC_CALLBACK LDAP_CALLOC_CALLBACKLDAP_REALLOC_CALLBACK LDAP_FREE_CALLBACK These callbacks allow developers to specify their own memory allocation mechanisms.

Thread Signaling Controls

The prototypes and structures listed in the following table are used in the thread signaling control, an extension to the standard API.

Thread Signaling Control Data Types
Data Type Description
ldap_thread_fns Structure that contains a set of pointers to functions you want to use when writing a multithreaded client.
LDAP_TF_MUTEX_ALLOC_CALLBACK Function prototype for allocating a mutex.
LDAP_TF_MUTEX_FREE_CALLBACK Function prototype freeing a mutex.
LDAP_TF_MUTEX_LOCK_CALLBACK Function prototype for locking critical sections of code.
LDAP_TF_MUTEX_UNLOCK_CALLBACK Function prototype for unlocking critical sections of code.
LDAP_TF_GET_ERRNO_CALLBACK Function prototype for getting the value of the errno variable.
LDAP_TF_SET_ERRNO_CALLBACK Function prototype for setting the value of the errno variable.
LDAP_TF_GET_LDERRNO_CALLBACK Function prototype for getting error values from calls to functions in the libldap library.
LDAP_TF_SET_LDERRNO_CALLBACK Function prototype for setting error values from calls to functions in the libldap library.
ldap_extra_thread_fns Structure that contains a set of pointers to additional functions you want to use when writing a multithreaded client.
LDAP_TF_MUTEX_TRYLOCK_CALLBACK Function prototype for attempting to lock a mutex.
LDAP_TF_SEMA_ALLOC_CALLBACK Function prototype for allocating a semaphore.
LDAP_TF_SEMA_FREE_CALLBACK Function prototype for freeing a semaphore.
LDAP_TF_SEMA_WAIT_CALLBACK Function prototype for waiting for the value of a semaphore to be greater than 0.
LDAP_TF_SEMA_POST_CALLBACK Function prototype for incrementing the value of a semaphore.
LDAP_TF_THREADID_CALLBACK Function prototype to return an identifier that is unique to the calling thread.

Deprecated and Outdated Types

Deprecated types are those being dropped from the standard or from the extensions to Directory SDK For C. They are not guaranteed to be defined in future versions of the API. However, all of these types are still defined in this version for backwards compatibility. The following table lists the deprecated prototypes.

Deprecated Data Types and Their Replacements
Data Type Replacement
LDAP_CANCELPROC_CALLBACK Provides a way to be cancel a process, for example, by a user or because some other condition occurs.
ldap_cache_fns
LDAP_CF_BIND_CALLBACK
LDAP_CF_UNBIND_CALLBACK
LDAP_CF_SEARCH_CALLBACK
LDAP_CF_COMPARE_CALLBACK
LDAP_CF_ADD_CALLBACK
LDAP_CF_DELETE_CALLBACK
LDAP_CF_MODIFY_CALLBACK
LDAP_CF_MODRDN_CALLBACK
LDAP_CF_RESULT_CALLBACK
LDAP_CF_FLUSH_CALLBACK
ldap_cache_fns is a deprecated structure and the typedef declarations associated with it have also been deprecated.
LDAPVersion Replaced by the LDAPAPIInfo type which is returned by the ldap_get_option function using the LDAP_OPT_API_INFO option.

While not officially deprecated, other data types are outdated because they have superseded by new types. Outdated types may become deprecated in future releases of Directory SDK For C. The following table lists the outdated types and the newer types which implement the same functionality.

Outdated Types and Their New Equivalents
Old Data Type New, Equivalent Data Type
LDAPHostEnt
LDAP_DNSFN_GETHOSTBYNAME
LDAP_DNSFN_GETHOSTBYADDR
ldap_dns_fns
The DNS resolver callbacks are an outdated extension to the API. The new way of specifying host information is through the LDAP_X_EXTIOF_CONNECT_CALLBACK prototype.
LDAP_IOF_CLOSE_CALLBACK
LDAP_IOF_CONNECT_CALLBACK
LDAP_IOF_IOCTL_CALLBACK
LDAP_IOF_READ_CALLBACK
LDAP_IOF_SELECT_CALLBACK
LDAP_IOF_SOCKET_CALLBACK
LDAP_IOF_SSL_ENABLE_CALLBACK
LDAP_IOF_WRITE_CALLBACK
ldap_io_fns
Replaced by the types for extended I/O functionality detailed in the section on Extended I/O Control.

Structures Alphabetically

The following sections detail the structures and controls of Directory SDK For C in alphabetical order.

berval

berval is a structure that represents binary data encoded using simplified Basic Encoding Rules (BER).

Description

Use a berval structure when working with attributes that contain binary data (such as a graphic or audio file). The data and the size of the data are both included in a berval structure.

typedef struct berval {
  unsigned long bv_len;
  char *bv_val;
};
berval Field Descriptions
Field What It Contains
bv_len The length of the data in bytes.
bv_val A pointer to the binary data itself.

BerElement

The BerElement structure represents data encoded using the Basic Encoding Rules (BER).

Description

You use this opaque data type to keep track of the current attribute during the traversal of an attribute list. Calling the ldap_first_attribute() function allocates memory for a BerElement structure and initializes it to select the values of the first attribute in the entry.

Subsequently, ldap_next_attribute() is called to obtain the name of each remaining attribute and set BerElement to select their values. Once BerElement has been set to select an attribute's values, ldap_get_values() can be used to obtain all of them from the buffer.

When you are done reading the attributes, you need to free the BerElement structure from memory by calling the ldap_ber_free() function. (A BerElement structure can also be allocated by calling the ber_alloc_t or the ber_init function. In these cases, free the memory allocated to the BerElement structure by using the ber_free() function.)

Note: The BerElement definition is not completely exposed in lber.h because the fields within the structure are not intended to be accessible to clients.

FriendlyMap

FriendlyMap represents the mapping between a list of standard attribute names and their user-friendly counterparts. For example, you can represent the list of two-letter state codes (CA, IA) with their corresponding state names (California, Iowa), or map Country ISO codes to the full country names, in a FriendlyMap structure.

Note:

  • ldap_friendly_name allocates() a FriendlyMap structure and reads a list of standard attribute names and their user friendly counterparts from a file.
  • ldap_free_friendlymap() frees the memory allocated for a FriendlyMap structure.

LDAP

LDAP is an opaque data type representing a connection with the LDAP server. It is initialized through a call to either the ldap_init() or ldapssl_init() function.

LDAP maintains the state of an LDAP session for the duration of the connection. When you call functions that perform LDAP operations on an LDAP server (for example, ldap_search_ext() to search the directory or ldap_modify_ext() to update an entry), you need to pass a pointer to this connection handle.

With the LDAP structure, you can also:

  • Call the ldap_get_option() and ldap_set_option() functions to view or modify the properties of the connection.
  • Call the ldap_unbind() or ldap_unbind_s() function to close the connection and free the LDAP structure.

Note: LDAP is not completely defined in ldap-standard.h because the fields within the structure are not intended to be accessible to clients.

LDAPAPIFeatureInfo

LDAPAPIFeatureInfo is a structure that represents information about the extended features of Directory SDK For C. <title>LDAPAPIFeatureInfo Definition

#define LDAP_FEATURE_INFO_VERSION
typedef struct ldap_apifeature_info {
  int   ldapaif_info_version;       /* version of this struct (1) */
  char  *ldapaif_name;              /* name of supported feature */
  int   ldapaif_version;            /* revision of supported feature */
} LDAPAPIFeatureInfo;

The LDAPAPIFeatureInfo structure can be retrieved by using a sequence like the one displayed below.

LDAPAPIFeatureInfo ldfi;
ldfi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
ldfi.ldapaif_name = "VIRTUAL_LIST_VIEW";
if ( ldap_get_option( NULL, LDAP_OPT_API_FEATURE_INFO, &ldfi ) == 0 )
Parameters
LDAPAPIFeatureInfo Structure Parameters
Parameter Description
ldapaif_info_version Specifies the version number of the LDAPAPIFeatureInfo structure. This must be set to LDAP_FEATURE_INFO_VERSION before call to ldap_get_option() is performed.
ldapaif_name Pointer to NULL terminated string that specifies the name of the supported feature.
ldapaif_version Specifies the version number of the supported feature.

LDAPAPIInfo

LDAPAPIInfo is a structure that represents information about the API and supported extensions.

#define LDAP_API_INFO_VERSION
typedef struct ldapapiinfo {
  int  ldapai_info_version;     /* version of LDAPAPIInfo (1) */
  int  ldapai_api_version;      /* revision of API supported */
  int  ldapai_protocol_version; /* highest LDAP version supported */
  char **ldapai_extensions;     /* names of API extensions */
  char *ldapi_vendor_name;      /* name of supplier */
  int  ldapai_vendor_version;   /* supplier-specific version x 100 */
} LDAPAPIInfo;

The LDAPAPIInfo structure can be retrieved by using a sequence like the one displayed in the following example.

LDAPAPIInfo ldai;
ldai.ldapai_info_version = LDAP_API_INFO_VERSION;
if ( ldap_get_option( NULL, LDAP_OPT_API_INFO, &ldia ) == 0 ) ...
Parameters
LDAPAPIInfo Structure Parameters
Parameter Description
ldapai_info_version Specifies the version number of the LDAPAPIInfo structure. This must be set to LDAP_API_INFO_VERSION before a call to ldap_get_option is performed.
ldapai_api_version Specifies the version number of the API that is supported.
ldapai_protocol_version Specifies the latest LDAP version supported by the LDAP library.
ldapai_extensions Points to a NULL terminated array of character strings that names the supported LDAP extensions. If none are supported, this field is set to NULL. The application is responsible for freeing this memory by calling the ldap_value_free function.
ldapai_vendor_name Pointer to a NULL-terminated string that contains the vendor's name. Call the ldap_memfree function to free the memory.
ldapai_vendor_version Specifies the vendor’s version of the LDAP libraries.

ldap_cache_fns

ldap_cache_fns is a deprecated structure. The following are also deprecated:

  • LDAP_CF_ADD_CALLBACK
  • LDAP_CF_BIND_CALLBACK
  • LDAP_CF_COMPARE_CALLBACK
  • LDAP_CF_DELETE_CALLBACK
  • LDAP_CF_FLUSH_CALLBACK
  • LDAP_CF_MODIFY_CALLBACK
  • LDAP_CF_MODRDN_CALLBACK
  • LDAP_CF_RESULT_CALLBACK
  • LDAP_CF_SEARCH_CALLBACK
  • LDAP_CF_UNBIND_CALLBACK
See Also

See the ldap_memcache_*() functions for current usage.

LDAP_CALLOC_CALLBACK

This callback function prototype of ldap_memalloc_fns() represents memory allocation.

See Also

ldap_memalloc_fns

LDAP_CANCELPROC_CALLBACK

This callback function prototype is deprecated.

See Also

ldap_ufn_search_c, ldap_ufn_search_ct

LDAP_CF_ADD_CALLBACK

This callback function prototype of ldap_cache_fns is deprecated.

LDAP_CF_BIND_CALLBACK

This callback function prototype of ldap_cache_fns is deprecated.

LDAP_CF_COMPARE_CALLBACK

This callback function prototype of ldap_cache_fns is deprecated.

LDAP_CF_DELETE_CALLBACK

This callback function prototype of ldap_cache_fns is deprecated.

LDAP_CF_FLUSH_CALLBACK

This callback function prototype of ldap_cache_fns is deprecated.

LDAP_CF_MODIFY_CALLBACK

This callback function prototype of ldap_cache_fns is deprecated.

LDAP_CF_MODRDN_CALLBACK

This callback function prototype of ldap_cache_fns is deprecated.

LDAP_CF_RESULT_CALLBACK

This callback function prototype of ldap_cache_fns is deprecated.

LDAP_CF_SEARCH_CALLBACK

This callback function prototype of ldap_cache_fns is deprecated.

LDAP_CF_UNBIND_CALLBACK

This callback function prototype of ldap_cache_fns is deprecated.

LDAP_CMP_CALLBACK

LDAP_CMP_CALLBACK specifies the prototype for a comparison callback function used when sorting values. If you define a function with this prototype and specify it when calling ldap_sort_entries() or ldap_multisort_entries(), it will be called by your LDAP client to sort a specified set of entries.

typedef int (LDAP_C LDAP_CALLBACK
  LDAP_CMP_CALLBACK)(const char*, const char*);
See Also

ldap_sort_entries(), ldap_multisort_entries()

LDAPControl

LDAPControl represents a client or server control associated with an LDAP operation. If set as a server control, it is sent to the server along with operation requests; if set as a client control, it is interpreted locally by the client.

Controls are part of the LDAP v3. You can use a control to extend the functionality of an LDAP operation. There are two basic types of controls described in the LDAP v3:

  • Server controls are controls that are sent from the client to the server along with an LDAP request. (In some cases, a server can include a control in the response it sends back to the client.) For example, you can include a server control in a search request to specify that you want the server to sort the search results before sending them back.
  • Client controls are controls that can extend the client but are never sent to the server. As a general example, you might be able to pass a client control to an LDAP API function, which might parse the control and use the data that you’ve specified in the control.

Directory SDK For C does not currently support any client controls.

typedef struct ldapcontrol {
  char *ldctl_oid;
  struct berval ldctl_value;
  char ldctl_iscritical;
} LDAPControl;
LDAPControl Field Descriptions
Field What It Contains
ldctl_oid Object identifier (OID) of the control.
ldctl_value berval structure containing data associated with the control. If you want to specify a zero-length value, set ldctl_value.bv_len to 0 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 Specifies whether or not the control is critical to the operation. This field can have one of the following values:
  • A non-zero value specifies that the control is critical to the operation.
  • 0 specifies that the control is not critical to the operation.

LDAP_DNSFN_GETHOSTBYADDR

LDAP_DNSFN_GETHOSTBYADDR specifies the prototype for a callback function equivalent to the gethostbyaddr_r() function available on some UNIX platforms.

Note: If you define a function with this prototype and set it in the ldap_dns_fns structure, your function will be called by the SDK on behalf of your LDAP client if it needs to get the host name of the LDAP server to which it is connected.

In this version of Directory SDK For C, the functions of the API never call this function, and your implementation will never be executed. Therefore, its implementation is optional.

typedef LDAPHostEnt * (LDAP_C LDAP_CALLBACK
  LDAP_DNSFN_GETHOSTBYADDR)( const char *addr, int length, int type,
  LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
  void *extradata );

LDAP_DNSFN_GETHOSTBYNAME

LDAP_DNSFN_GETHOSTBYNAME specifies the prototype for a callback function equivalent to the gethostbyname_r() function available on some UNIX platforms.

Note: If you define a function with this prototype and set it in the ldap_dns_fns structure, your function will be called by Directory SDK For C on behalf of your LDAP client to get the host entry for the LDAP server when connecting to the server.

typedef LDAPHostEnt * (LDAP_C LDAP_CALLBACK
  LDAP_DNSFN_GETHOSTBYADDR)( const char *addr, int length, int type,
  LDAPHostEnt *result, char *buffer, int buflen, int *statusp,
  void *extradata );

ldap_dns_fns

ldap_dns_fns contains a set of pointers to DNS functions and is equivalent to the gethostbyname_r() and gethostbyaddr_r() functions available on some UNIX platforms.

Note: While not officially deprecated, the functionality of this structure is superseded by the extended I/O functions. The new way of specifying host information is through the LDAP_X_EXTIOF_CONNECT_CALLBACK prototype.

Description

You can use this structure if you want Directory SDK For C to call these functions when looking up the host name or IP address for the LDAP server. For example, you could use this to call versions of the DNS functions that are safe for use in a multithreaded application. The function must have the prototype specified by LDAP_DNSFN_GETHOSTBYADDR.

If NULL, the standard built-in OS routine is used. After you set the fields in this structure, you can register the functions for use by calling the ldap_set_option function and setting the LDAP_OPT_DNS_FN_PTRS option to this structure.

struct ldap_dns_fns {
  void *lddnsfn_extradata;
  int lddnsfn_bufsize;
  LDAP_DNSFN_GETHOSTBYNAME *lddnsfn_gethostbyname;
  LDAP_DNSFN_GETHOSTBYADDR *lddnsfn_gethostbyaddr;
};
ldap_dns_fns Field Descriptions
Field What It Contains
lddnsfn_extradata Value passed in the extradata argument of the LDAP_DNSFN_GETHOSTBYADDR and LDAP_DNSFN_GETHOSTBYNAME function calls.
lddnsfn_bufsize Specifies the size of the buffer that you want passed to your DNS callback function. Your LDAP client passes this value as the buflen argument of the LDAP_DNSFN_GETHOSTBYADDR and LDAP_DNSFN_GETHOSTBYNAME function calls.
lddnsfn_gethostbyname Function pointer for getting the host entry for the LDAP server. This function is called by the client when connecting to the server if the function pointer is not NULL. The function must have the prototype specified by LDAP_DNSFN_GETHOSTBYNAME. If NULL, the standard built-in OS routine is used.
lddnsfn_gethostbyaddr Function pointer for getting the host name of the LDAP server. This function is called by the client when needed if the function pointer is not NULL.

ldap_extra_thread_fns

The ldap_extra_thread_fns structure contains a set of pointers to additional functions that you can use when writing a multithreaded client. Your client calls these functions when getting results from the LDAP structure.

struct ldap_extra_thread_fns {
  LDAP_TF_MUTEX_TRYLOCK_CALLBACK  *ltf_mutex_trylock;
  LDAP_TF_SEMA_ALLOC_CALLBACK     *ltf_sema_alloc;
  LDAP_TF_SEMA_FREE_CALLBACK      *ltf_sema_free;
  LDAP_TF_SEMA_WAIT_CALLBACK      *ltf_sema_wait;
  LDAP_TF_SEMA_POST_CALLBACK      *ltf_sema_post;
  LDAP_TF_THREADID_CALLBACK       *ltf_threadid_fn;
};
ldap_extra_thread_fns Field Descriptions
Field What It Contains
ltf_mutex_trylock Function pointer for attempting to lock a mutex. This function is called by the client when needed if the function pointer is not NULL. The function must have the prototype specified by LDAP_TF_MUTEX_TRYLOCK_CALLBACK.
ltf_sema_alloc Function pointer for allocating a semaphore. This finction is called by the client if needed when the function pointer is not NULL. The function must have the prototype specified by LDAP_TF_SEMA_ALLOC_CALLBACK.
ltf_sema_free Function pointer for freeing a semaphore. This function is called by the client when needed if the function pointer is not NULL. The function must have the prototype specified by LDAP_TF_SEMA_FREE_CALLBACK.
ltf_sema_wait Function pointer for waiting for the value of a semaphore to be greater than 0. This function is called by the client when needed if the function pointer is not NULL. The function must have the prototype specified by LDAP_TF_SEMA_WAIT_CALLBACK.
ltf_sema_post Function pointer for incrementing the value of a semaphore. This function is called by the client when needed if the function pointer is not NULL. The function must have the prototype specified by LDAP_TF_SEMA_POST_CALLBACK.
ltf_threadid_fn Function pointer that is called to retrieve the unique identifier for the calling thread. If this is NULL, it is not used. An example of a similar function in the POSIX threads standard is pthread_self(). The function must have the prototype specified by LDAP_TF_THREADID_CALLBACK.

LDAPFiltDesc

LDAPFiltDesc is a structure that is returned when you call ldap_init_getfilter() to load a filter configuration file.

Note: The LDAPFiltDesc definition is not completely exposed in ldap-extension.h because the fields within the structure are not intended to be accessible to clients.

Description

After calling the ldap_init_getfilter() function, use the pointer to the returned LDAPFiltDesc structure in subsequent calls to get information about filters in the filter configuration file.

LDAPFiltInfo

LDAPFiltInfo represents information about a filter in the filter configuration file.

Description

When you call the ldap_getfirstfilter() or ldap_getnextfilter() functions to get a filter from the filter configuration file, they return a pointer to an LDAPFiltInfo structure containing the information about the filter.

typedef struct ldap_filt_info {
  char *lfi_filter;
  char *lfi_desc;
  int lfi_scope;
  int lfi_isexact;
  struct ldap_filt_info *lfi_next;
} LDAPFiltInfo;
LDAPFilterInfo Field Descriptions
Field What It Contains
lfi_filter The filter, for example (cn=d*).
lfi_desc Description of the filter, also the fifth field in the filter configuration file.
lfi_scope The scope of the filter, also the sixth field in the filter configuration file, which can be one of the following values:
  • LDAP_SCOPE_BASE specifies that the search will be restricted to the current DN.
  • LDAP_SCOPE_ONELEVEL specifies that the search will be restricted to the entries at the level beneath the current DN.
  • LDAP_SCOPE_SUBTREE specifies that the search will encompass entries at all levels beneath the current DN. If the scope of the filter is not specified in the filter configuration file, the scope is LDAP_SCOPE_SUBTREE by default.
lfi_isexact Specifies whether or not the filter is an exact filter, where an exact filter contains no wildcard characters and does not match words that sound alike:
  • 0 specifies that the filter is not an exact filter.
  • 1 specifies that the filter is an exact filter.
lfi_next Pointer to the LDAPFiltInfo structure representing the next filter in the filter list.

The following example prints out information about a filter.

LDAPFiltInfo *lfip;
/* Print out the filter */
printf( "Filter:\t%s\n", lfdp->lfd_filter );
printf( "Description:\t%s\n", lfdp->lfd_desc );

For example, in the filter configuration file, if the first filter that applies to the value @ is:

"@" " " "(mail=%v)" "email address is" "onelevel"

The code prints out:

Filter: (mail=@)
Description: email address is

LDAP_FREE_CALLBACK

This callback function prototype of ldap_memalloc_fns is used to free allocated memory.

See Also

ldap_memalloc_fns

LDAPHostEnt

The LDAPHostEnt structure represents an entry for a host found by a domain name server.

Note: This type is similar to the hostent structure returned by functions such as gethostbyname_r() on UNIX systems.

If you are writing your own DNS functions for use by the client, they should return the host entry in this type of structure.

The fields in this structure should point to addresses within the buffer that is passed to the DNS callback (referenced in the LDAP callback function). This buffer contains the host data. The pointers in the hostent structure returned by the function point to the data in this buffer.

typedef struct LDAPHostEnt {
  char *ldaphe_name;
  char **ldaphe_aliases;
  int ldaphe_addrtype;
  int ldaphe_length;
  char **ldaphe_addr_list;
} LDAPHostEnt;
LDAPHostEnt Field Descriptions
Field What It Contains
ldaphe_name Canonical name of the host
ldaphe_aliases List of aliases for this host
ldaphe_addrtype Address type of the host
ldaphe_length Length of the address
ldaphe_addr_list List of addresses for this host as returned by the name server
See Also

LDAP_DNSFN_GETHOSTBYADDR, LDAP_DNSFN_GETHOSTBYNAME

LDAP_IOF_CLOSE_CALLBACK

LDAP_IOF_CLOSE_CONNECT_CALLBACK specifies the prototype for a callback function equivalent to the standard close() system call.

Description

If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.

typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_CLOSE_CALLBACK )( LBER_SOCKET );

LDAP_IOF_CONNECT_CALLBACK

LDAP_IOF_CONNECT_CALLBACK specifies the prototype for a callback function equivalent to the standard connect() network I/O function.

Description

If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.

typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_CONNECT_CALLBACK )( LBER_SOCKET,
  struct sockaddr *, int );

LDAP_IOF_IOCTL_CALLBACK

LDAP_IOF_IOCTL_CALLBACK specifies the prototype for a callback function equivalent to the standard ioctl() system call.

Description

If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.

typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_IOCTL_CALLBACK)( LBER_SOCKET, int, ... );

LDAP_IOF_READ_CALLBACK

LDAP_IOF_READ_CALLBACK specifies the prototype for a callback function equivalent to the standard read() I/O function.

Description

If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.

typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_READ_CALLBACK)( LBER_SOCKET, void *, int );

LDAP_IOF_SELECT_CALLBACK

LDAP_IOF_SELECT_CALLBACK specifies the prototype for a callback function equivalent to the standard select() I/O function.

Description

If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.

typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_SELECT_CALLBACK)( int, fd_set *, fd_set *,
  fd_set *, struct timeval * );

LDAP_IOF_SOCKET_CALLBACK

LDAP_IOF_SOCKET_CALLBACK specifies the prototype for a callback function equivalent to the standard socket() network I/O function.

Description

If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.

typedef LBER_SOCKET (LDAP_C LDAP_CALLBACK
  LDAP_IOF_SOCKET_CALLBACK)( int, int, int );

LDAP_IOF_SSL_ENABLE_CALLBACK

LDAP_IOF_SSL_ENABLE_CALLBACK specifies the prototype for a callback function equivalent to the ssl_enable() function.

Description

If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.

typedef int (LDAP_C LDAP_CALLBACK
  LDAP_IOF_SSL_ENABLE_CALLBACK )( LBER_SOCKET );

LDAP_IOF_WRITE_CALLBACK

LDAP_IOF_WRITE_CALLBACK specifies the prototype for a callback function equivalent to the standard write() I/O function.

Description

If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called by your LDAP client.

typedef int (LDAP_C LDAP_CALLBACK LDAP_IOF_WRITE_CALLBACK)
  ( LBER_SOCKET, const void *, int );

ldap_io_fns

The ldap_io_fns structure contains a set of pointers to input/output functions that you want used with SDK. You need to set up this structure if you want to connect to the LDAP server using a Secure Sockets Layer (SSL).

struct ldap_io_fns {
  LDAP_IOF_READ_CALLBACK *liof_read;
  LDAP_IOF_WRITE_CALLBACK *liof_write;
  LDAP_IOF_SELECT_CALLBACK *liof_select;
  LDAP_IOF_SOCKET_CALLBACK *liof_socket;
  LDAP_IOF_IOCTL_CALLBACK *liof_ioctl;
  LDAP_IOF_CONNECT_CALLBACK *liof_connect;
  LDAP_IOF_CLOSE_CALLBACK *liof_close;
  LDAP_IOF_SSL_ENABLE_CALLBACK *liof_ssl_enable;
};
ldap_io_fns Field Descriptions
Field What It Contains
liof_read Function pointer to the equivalent of the standard read() I/O function. The function must have the prototype specified by LDAP_IOF_READ_CALLBACK.
liof_write Function pointer to the equivalent of the standard write() I/O function. The function must have the prototype specified by LDAP_IOF_WRITE_CALLBACK.
liof_select Function pointer to the equivalent of the standard select() I/O function. The function must have the prototype specified by LDAP_IOF_SELECT_CALLBACK.
liof_socket Function pointer to the equivalent of the standard socket() network I/O function. The function must have the prototype specified by LDAP_IOF_SOCKET_CALLBACK.
liof_ioctl Function pointer to the equivalent of the standard ioctl() system call. The function must have the prototype specified by LDAP_IOF_IOCTL_CALLBACK.
liof_connect Function pointer to the equivalent of the standard connect() network I/O function. The function must have the prototype specified by LDAP_IOF_CONNECT_CALLBACK.
liof_close Function pointer to the equivalent of the standard close() system call. The function must have the prototype specified by LDAP_IOF_CLOSE_CALLBACK.
liof_ssl_enable Function pointer to the equivalent of the ssl_enable() function. The function must have the prototype specified by LDAP_IOF_SSL_ENABLE_CALLBACK.
LDAP_KEYCMP_CALLBACK

LDAP_KEYCMP_CALLBACK specifies the prototype for a callback function to sort a specified set of entries.

Definition

If you define a function with this prototype and specify it when calling ldap_keysort_entries(), the function will be called by your LDAP client to sort a specified set of entries.

See Also

ldap_keysort_entries

LDAP_KEYFREE_CALLBACK

LDAP_KEYFREE_CALLBACK specifies the prototype for a callback function that frees a sorting key.

Description

ldap_keysort_entries() requires a function pointer that matches the signature defined by this type.

LDAP_KEYGEN_CALLBACK

LDAP_KEYGEN_CALLBACK specifies the prototype for a callback function that generates a key for sorting.

Description

ldap_keysort_entries() requires a function pointer that matches the signature defined by this type.

LDAP_MALLOC_CALLBACK

This callback function prototype of ldap_memalloc_fns represents memory allocation.

See Also

ldap_memalloc_fns

ldap_memalloc_fns

ldap_memalloc_fns is a structure representing callback functions for memory allocation. These are global and can not be set on a per-LDAP session handle basis. Install your own functions by making a call similar to the one detailed in the following example.

ldap_set_option(NULL, LDAP_OPT_MEMALLOC_FN_PTRS, &memalloc_fns);
See Also
  • LDAP_MALLOC_CALLBACK
  • LDAP_CALLOC_CALLBACK
  • LDAP_REALLOC_CALLBACK
  • LDAP_FREE_CALLBACK

LDAPMemCache

LDAPMemCache is a type of structure representing an in-memory, client-side cache. You can create a cache and specify the following information:

  • The maximum size of the cache.
  • The maximum amount of time to keep an item in the cache.
  • A set of base DNs for the search requests that you want to cache (optional).
  • A set of functions to ensure the thread-safety of the cache.

To use a cache, you need to associate it with a connection handle (and LDAP structure). Before a search request is sent to the server, the cache is checked to determine if the same request was made before. If an earlier request was cached, the search results are retrieved from the cache.

Note: The cache uses the search criteria as the key to cached items. Search requests with different criteria are cached as separate items. For example, suppose you send a search request specifying that you just want to retrieve the uid attribute. Your client caches the result of that search. If you send a similar search request specifying that you want to retrieve all attributes instead of just the uid, the result cached from the previous search are not used.

The cache uses a combination of the following information as the key to a cached item:

  • The host name and port number of the LDAP server that you are searching.
  • The DN to which you are currently authenticated.

From the search criteria, the base DN, scope, filter, attributes to be returned, and an indication of whether to return attribute types only or attribute types and values.

Related Functions

The following table lists functions related to the LDAPMemCache structure.

Functions for LDAPMemCache Structure
Function Description
ldap_memcache_init() Creates an LDAPMemCache structure and initialize the caching mechanism.
ldap_memcache_set() Associates an LDAPMemCache structure with a connection handle (an LDAP structure).
ldap_memcache_get() Returns the LDAPMemCache structure that is associated with a connection handle (an LDAP structure).
ldap_memcache_update() Forces the cache to remove expired items.
ldap_memcache_flush() Removes entries from the cache.
ldap_memcache_destroy() Frees the memory used by the cache and frees the LDAPMemCache structure.
LDAPMessage

LDAPMessage is a structure representing the results of an LDAP operation such as a chain of search results, an entry in the search results, or a search reference in the search results.

Note: Calling the ldap_search_ext_s() or ldap_search_ext() followed by the ldap_result function creates an LDAPMessage structure to represent the chain of results from the search. Calling the ldap_first_entry() or ldap_next_entry() function creates an LDAPMessage structure to represent an entry in the search results. Calling ldap_first_reference() or ldap_next_reference() creates an LDAPMessage structure to represent a search reference in the search results. To free the LDAPMessage structure, call the ldap_msgfree() routine.

LDAPMod

LDAPMod is a structure that you use to specify changes to an attribute in a directory entry.

Description

Before you call the ldap_add_ext(), ldap_add_ext_s(), ldap_modify_ext(), or ldap_modify_ext_s() functions to add or modify an entry in the directory, you need to fill LDAPMod structures with the attribute values that you intend to add or change.

typedef struct ldapmod {
  int mod_op;
  char *mod_type;
  union {
  char **modv_strvals;
  struct berval **modv_bvals;
  } mod_vals;
  #define mod_values mod_vals.modv_strvals
  #define mod_bvalues mod_vals.modv_bvals
} LDAPMod;
LDAPMod Field Descriptions
Field What It Contains
mod_op The operation to be performed on the attribute and the type of data specified as the attribute values. This field can have one of the following values:
  • LDAP_MOD_ADD adds a value to the attribute.
  • LDAP_MOD_DELETE removes the value from the attribute.
  • LDAP_MOD_REPLACE replaces all existing values of the attribute.

In addition, if you are specifying binary values in the mod_bvalues field, you should use the bitwise OR operator ( | ) to combine LDAP_MOD_BVALUES with the operation type. For example: mod->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES Note the following caveats when defining:

  • If you specify LDAP_MOD_DELETE and remove all values in an attribute, the attribute is removed from the entry.
  • If you specify LDAP_MOD_DELETE and NULL in the mod_values field, the attribute is removed from the entry.
  • If you specify LDAP_MOD_REPLACE and NULL in the mod_values field, the attribute is removed from the entry.
  • If you specify LDAP_MOD_REPLACE and the attribute does not exist in the entry, the attribute is added to the entry.
  • If you specify LDAP_MOD_ADD and the attribute does not exist in the entry, the attribute is added to the entry. Also, if you are using the structure to add a new entry, you can specify 0 for the mod_op field, unless you are adding binary values and need to specify LDAP_MOD_BVALUES.
mod_type The attribute type that you want to add, delete, or replace the values of such as sn or telephoneNumber.
mod_values A pointer to a NULL terminated array of string values for the attribute.
mod_bvalues A pointer to a NULL terminated array of berval structures for the attribute.

If you have allocated memory for the structures yourself, you should free them when finished by calling the ldap_mods_free() function.

Example

The following example sets up an LDAPMod structure to change the email address of a user’s entry to bjensen@example.com.

LDAP *ld;
LDAPMod attribute1;
LDAPMod *list_of_attrs[2];
char *mail_values[] = { "bjensen@example.com", NULL };
char *dn;
...
/* Identify the entry that you want changed */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* Specify that you want to replace the value of an attribute */
attribute1.mod_op = LDAP_MOD_REPLACE;
/* Specify that you want to change the value of the mail attribute */
attribute1.mod_type = "mail";
/* Specify the new value of the mail attribute */
attribute1.mod_values = mail_values;
/* Add the change to the list of attributes that you want changed */
list_of_attrs[0] = &attribute_change;
list_of_attrs[1] = NULL;
/* Update the entry with the change */
if ( ldap_modify_s( ld, dn, list_of_attrs ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_modify_s" );
  return( 1 );
}
...

LDAPpwdpolicy

An LDAPpwdpolicy structure holds values concerning the password policy governing a user account.

You fill this structure by passing it to the ldap_parse_pwdpolicy_control() function.

LDAPpwdpolicy Description

An LDAPpwdpolicy structure has the following definition:

typedef struct LDAPpwdpolicy {         /* password policy               */
  unsigned int pp_warning;       /* warning status                */
#define LDAP_PP_WARNING_NONE     0x00
#define LDAP_PP_WARNING_EXP      0x01
#define LDAP_PP_WARNING_GRACE    0x02
  int          pp_warning_info;  /* warning information           */
  int          pp_error;         /* error information             */
#define LDAP_PP_ERROR_NONE      -1     /* no error                      */
#define LDAP_PP_ERROR_EXPIRED    0     /* password expired              */
#define LDAP_PP_ERROR_LOCKED     1     /* account locked                */
#define LDAP_PP_ERROR_MUSTCHANGE 2     /* paasword has to be changed    */
#define LDAP_PP_ERROR_NOTMOD     3     /* modification not allowed      */
#define LDAP_PP_ERROR_OLDPASSWD  4     /* must provide old password     */
#define LDAP_PP_ERROR_NOQUALITY  5     /* insufficient password quality */
#define LDAP_PP_ERROR_TOOSHORT   6     /* password too short            */
#define LDAP_PP_ERROR_MINAGE     7     /* min age still in effect       */
#define LDAP_PP_ERROR_INHISTORY  8     /* password in history           */
} LDAPpwdpolicy;
LDAPpwdpolicy Field Descriptions
Field What It Contains
pp_warning Warning code
pp_warning_info If pp_warning is LDAP_PP_WARNING_EXP, this holds the number of seconds before the password expires. If pp_warning is LDAP_PP_WARNING_GRACE, this holds the number of grace logins remaining.
pp_error One of the following error codes:
  • LDAP_PP_ERROR_NONE, meaning no errors
  • LDAP_PP_ERROR_EXPIRED, meaning the password has expired, and must be reset
  • LDAP_PP_ERROR_LOCKED, meaning the account is locked
  • LDAP_PP_ERROR_MUSTCHANGE, meaning the password has been reset, and must be changed
  • LDAP_PP_ERROR_NOTMOD, meaning the user may not change the password
  • LDAP_PP_ERROR_OLDPASSWD, meaning the old password must be supplied for this operation
  • LDAP_PP_ERROR_NOQUALITY, meaning the password does not pass the server's password quality check
  • LDAP_PP_ERROR_TOOSHORT, meaning the password is too short
  • LDAP_PP_ERROR_MINAGE, meaning the password is too new to be modified, yet
  • LDAP_PP_ERROR_INHISTORY, meaning the password matches a password stored in the password history, and thus cannot be reused
Memory Concerns

You allocate and free space for the LDAPpwdpolicy structure.

LDAP_REALLOC_CALLBACK

This callback function prototype of ldap_memalloc_fns represents memory allocation.

See Also

ldap_memalloc_fns

LDAP_REBINDPROC_CALLBACK

LDAP_REBINDPROC_CALLBACK specifies the prototype for a callback function that retrieves authentication information when automatically following referrals to other servers.

Description

If you define a function with this prototype and specify it when calling the ldap_set_rebind_proc() function, the function will be called by your LDAP client.

typedef int (LDAP_CALL LDAP_CALLBACK
  LDAP_REBINDPROC_CALLBACK)( LDAP *ld, char **dnp, char **passwdp,
  int *authmethodp, int freeit, void *arg);
See Also

ldap_set_rebind_proc

LDAPsortkey

LDAPsortkey represents the criteria to be used by a server control to sort search results before sending the results back to the client.

Note: Controls are part of the LDAP v3 and are used to extend the functionality of an LDAP operation. The two types of controls described in the LDAP v3 are:

  • Server controls are controls that are sent from the client to the server along with an LDAP request. (In some cases, a server can include a control in the response it sends back to the client.) For example, you can include a server control in a search request to specify that you want the server to sort the search results before sending them back.
  • Client controls are controls that can extend the client but that are never sent to the server. As a general example, you might be able to pass a client control to an LDAP API function, which might parse the control and use the data that you have specified in the control. Directory SDK For C does not currently support any client controls.
Description
typedef struct LDAPsortkey {
  char *sk_attrtype;
  char *sk_matchruleoid;
  int sk_reverseorder;
} LDAPsortkey;
LDAPsortkey Field Descriptions
Field What It Contains
sk_attrtype Pointer to a NULL terminated string that specifies the name of the attribute that you want to use for sorting.
sk_matchruleoid Pointer to a NULL terminated string that specifies the object identifier (OID) of the matching rule that you want to use for sorting.
sk_reverseorder Specifies whether or not the results are sorted in reverse order. This field can have one of the following values:
  • A non-zero value specifies that the results should be sorted in reverse order.
  • 0 specifies that the results should be sorted in normal (forward) order.

As an example, you can use LDAPsortkey to specify that you want the server to sort search results by the roomNumber attribute.

To create an array of LDAPsortkey structures, you can call the ldap_create_sort_keylist() function. To free an array of LDAPsortkey structures, you can call the ldap_free_sort_keylist() function.

LDAP_TF_GET_ERRNO_CALLBACK

LDAP_TF_GET_ERRNO_CALLBACK specifies the prototype for a callback function to get the value of the errno variable for a thread.

typedef int (LDAP_C LDAP_CALLBACK
  LDAP_TF_GET_ERRNO_CALLBACK) ( void );

LDAP_TF_GET_LDERRNO_CALLBACK

LDAP_TF_GET_LDERRNO_CALLBACK specifies the prototype for a callback function to retrieve the LDAP result code for an operation.

Description

If you define a function with this prototype and set it in the ldap_thread_fns structure, your callback function is called when the ldap_get_lderrno() function is called. The arguments of ldap_get_lderrno() are passed to your function, and the value returned by your function is returned by ldap_get_lderrno().

Note: For more details on the arguments and return values that your function must use, see ldap_get_lderrno().

typedef int (LDAP_C LDAP_CALLBACK
  LDAP_TF_GET_LDERRNO_CALLBACK)( char **, char **, void * );

LDAP_TF_SET_ERRNO_CALLBACK

LDAP_TF_SET_ERRNO_CALLBACK specifies the prototype for a callback function to set the value of the errno variable for a thread.

typedef void (LDAP_C LDAP_CALLBACK
  LDAP_TF_SET_ERRNO_CALLBACK)( int );

LDAP_TF_SET_LDERRNO_CALLBACK

LDAP_TF_SET_LDERRNO_CALLBACK specifies the prototype for a callback function to set the LDAP result code for an operation.

Note: For more details on the arguments that your function must use, see ldap_set_lderrno().

Description

If you define a function with this prototype and set it in the ldap_thread_fns structure, your callback function is called when the ldap_set_lderrno() function is called. The arguments of ldap_set_lderrno() are passed to your function.

typedef void (LDAP_C LDAP_CALLBACK
  LDAP_TF_SET_LDERRNO_CALLBACK)( int, char *, char *, void * );

LDAP_TF_MUTEX_ALLOC_CALLBACK

LDAP_TF_MUTEX_ALLOC_CALLBACK specifies the prototype for a callback function to allocate a mutex.

Description
typedef void *(LDAP_C LDAP_CALLBACK
  LDAP_TF_MUTEX_ALLOC_CALLBACK)( void );
See Also

ldap_thread_fns

LDAP_TF_MUTEX_FREE_CALLBACK

LDAP_TF_MUTEX_FREE_CALLBACK specifies the prototype for a callback function to free a mutex.

Description
typedef void (LDAP_C LDAP_CALLBACK
  LDAP_TF_MUTEX_FREE_CALLBACK)( void * );
See Also

ldap_thread_fns

LDAP_TF_MUTEX_LOCK_CALLBACK

LDAP_TF_MUTEX_LOCK_CALLBACK specifies the prototype for a callback function to lock a mutex.

Description
typedef int (LDAP_C LDAP_CALLBACK
  LDAP_TF_MUTEX_LOCK_CALLBACK)( void * );
See Also

ldap_thread_fns

LDAP_TF_MUTEX_TRYLOCK_CALLBACK

This function prototype is not supported in this release of Directory SDK For C.

LDAP_TF_MUTEX_UNLOCK_CALLBACK

LDAP_TF_MUTEX_UNLOCK_CALLBACK specifies the prototype for a callback function to unlock a mutex.

Description
typedef int (LDAP_C LDAP_CALLBACK
  LDAP_TF_MUTEX_UNLOCK_CALLBACK)( void * );
See Also

ldap_thread_fns

LDAP_TF_SEMA_ALLOC_CALLBACK

This function prototype is not supported in this release of Directory SDK For C.

LDAP_TF_SEMA_FREE_CALLBACK

This function prototype is not supported in this release of Directory SDK For C.

LDAP_TF_SEMA_POST_CALLBACK

This function prototype is not supported in this release of Directory SDK For C.

LDAP_TF_SEMA_WAIT_CALLBACK

This function prototype is not supported in this release of Directory SDK For C.

LDAP_TF_THREADID_CALLBACK

LDAP_TF_THREADID_CALLBACK specifies the prototype for a callback function to return an identifier that is unique to the calling thread, much like the POSIX pthread_self() function does.

Description
typedef void *(LDAP_C LDAP_CALLBACK
  LDAP_TF_THREADID_CALLBACK)( void );
See Also

ldap_thread_fns

ldap_thread_fns

The ldap_thread_fns structure contains a set of pointers to functions that you want to use when write a multithreaded client.

Description
struct ldap_thread_fns {
  LDAP_TF_MUTEX_ALLOC_CALLBACK *ltf_mutex_alloc;
  LDAP_TF_MUTEX_FREE_CALLBACK *ltf_mutex_free;
  LDAP_TF_MUTEX_LOCK_CALLBACK *ltf_mutex_lock;
  LDAP_TF_MUTEX_UNLOCK_CALLBACK *ltf_mutex_unlock;
  LDAP_TF_GET_ERRNO_CALLBACK *ltf_get_errno;
  LDAP_TF_SET_ERRNO_CALLBACK *ltf_set_errno;
  LDAP_TF_GET_LDERRNO_CALLBACK *ltf_get_lderrno;
  LDAP_TF_SET_LDERRNO_CALLBACK *ltf_set_lderrno;
  void *ltf_lderrno_arg;
};
ldap_thread_fns Field Descriptions
Field What It Contains
ltf_mutex_alloc Function pointer for allocating a mutex. This function is called by the client when needed if the function pointer is not NULL. The function must have the prototype specified by LDAP_TF_MUTEX_ALLOC_CALLBACK.
ltf_mutex_free Function pointer for freeing a mutex. This function is called by the client when needed if the function pointer is not NULL. The function must have the prototype specified by LDAP_TF_MUTEX_FREE_CALLBACK.
ltf_mutex_lock Function pointer for locking critical sections of code. This function is called by the client when needed if the function pointer is not NULL. The function must have the prototype specified by LDAP_TF_MUTEX_LOCK_CALLBACK.
ltf_mutex_unlock Function pointer for unlocking critical sections of code. This function is called by the client when needed if the function pointer is not NULL. The function must have the prototype specified by LDAP_TF_MUTEX_UNLOCK_CALLBACK.
ltf_get_errno Function pointer for getting the value of the <symbol>errno</symbol> variable. This function is called by the client when needed if the function pointer is not NULL. In a threaded environment, errno is typically redefined at compile time so that it has a value for each thread, rather than a global value for the entire process. Because the libldap library does not know what method your code and threading environment will use to get the value of errno for each thread, it calls this function to obtain the value. The function must have the prototype specified by LDAP_TF_GET_ERRNO_CALLBACK.
ltf_set_errno Function pointer for setting the value of the <symbol>errno</symbol> variable. This function is called by the client when needed if the function pointer is not NULL. In a threaded environment, errno is typically redefined at compile time so that it has a value for each thread, rather than a global value for the entire process. Because the libldap library does not know what method your code and threading environment will use to get the value of errno for each thread, it calls this function to obtain the value. The function must have the prototype specified by LDAP_TF_SET_ERRNO_CALLBACK.
ltf_get_lderrno Function pointer for getting error values from calls to functions in the libldap library. This function is called by the client as needed if the function pointer isn’t NULL. If this function pointer is not set, the libldap library records these errors in fields in the LDAP structure. The function must have the prototype specified by LDAP_TF_GET_LDERRNO_CALLBACK.
ltf_set_lderrno Function pointer for setting error values from calls to functions in the libldap library. This function is called by the client as needed if the function pointer is not NULL. If this function pointer is not set, the libldap library records these errors in fields in the LDAP structure. The function must have the prototype specified by LDAP_TF_SET_LDERRNO_CALLBACK.
ltf_lderrno_arg Additional parameter passed to the functions for getting and setting error values from calls to functions in the libldap library. (*ltf_get_lderrno) and (*ltf_set_lderrno) identify these functions.

LDAPURLDesc

LDAPURLDesc is a structure that represents the components of an LDAP URL.

Description

LDAP URLs have the following syntax:

ldap://''host'':''port''/''dn''?''attributes''?''scope''?(''filter'')

Where, for example:

ldap://ldap.example.com/c=US?o,description?one?(o=Sales)

Calling the ldap_url_parse() function creates an LDAPURLDesc structure with the components of the URL.

typedef struct ldap_url_desc {
  char *lud_host;
  int lud_port;
  char *lud_dn;
  char **lud_attrs;
  int lud_scope;
  char *lud_filter;
  unsigned long lud_options;
} LDAPURLDesc
LDAPURLDesc Field Descriptions
Field What It Contains
lud_host Name of the host in the URL.
lud_port Number of the port in the URL.
lud_dn Distinguished name in the URL. This base entry DN identifies the starting point of the search.
lud_attrs Pointer to a NULL terminated list of the attributes specified in the URL.
lud_scope Integer representing the scope of the search specified in the URL:
  • LDAP_SCOPE_BASE specifies a search of the base entry.
  • LDAP_SCOPE_ONELEVEL specifies a search of all entries one level under the base entry (not including the base entry).
  • LDAP_SCOPE_SUBTREE specified a search of all entries at all levels under the base entry (including the base entry).
lud_filter Search filter included in the URL.
lud_options Options; if LDAP_URL_OPT_SECURE, indicates that the protocol is ldaps:// instead of ldap://.

For example, suppose you pass the following URL to the ldap_url_parse() function:

ldap://ldap.example.com:5000/dc=example,dc=com?cn,mail, \
telephoneNumber?sub?(sn=Jensen)

The resulting LDAPURLDesc structure - ludpp, in this example -- will contain the values in the following table .

LDAPURLDesc Parsed URL Values
Component Value
ludpp->lud_host ldap.example.com
ludpp->lud_port 5000
ludpp->lud_dn dc=example,dc=com
ludpp->lud_attrs[0] cn
ludpp->lud_attrs[1] mail
ludpp->lud_attrs[2] telephoneNumber
ludpp->lud_attrs[3] NULL
ludpp->lud_scope LDAP_SCOPE_SUBTREE
ludpp->lud_filter (sn=Jensen)

To free the LDAPURLDesc structure, call the ldap_free_urldesc() routine.

LDAPuserstatus

An LDAPuserstatus structure holds the values concerning the status of a user account. You fill this structure by passing it to the ldap_parse_userstatus_control() function.

LDAPuserstatus Description

An LDAPuserstatus structure has the following definition:

typedef struct LDAPuserstatus {     /* user account availability   */
  unsigned int us_available;  /* availability status         */
#define LDAP_US_ACCOUNT_USABLE      0
#define LDAP_US_ACCOUNT_NOT_USABLE  1
  int          us_expire;     /* will expire in seconds      */
  int          us_inactive;   /* boolean inactivation status */
#define LDAP_US_ACCOUNT_ACTIVE      0
#define LDAP_US_ACCOUNT_INACTIVE    1
  int          us_reset;      /* boolean password reset      */
#define LDAP_US_ACCOUNT_NOT_RESET   0
#define LDAP_US_ACCOUNT_RESET       1
  int          us_expired;    /* boolean password expired    */
#define LDAP_US_ACCOUNT_NOT_EXPIRED 0
#define LDAP_US_ACCOUNT_EXPIRED     1
  int          us_remaining;  /* remaining logins            */
  int          us_seconds;    /* will unlock in seconds      */
} LDAPuserstatus;
LDAPuserstatus Field Descriptions
Field What It Contains
us_available Whether the account is currently usable
us_expire Number of seconds before the password expires -1 means the password is not set to expire at all.
us_inactive Whether the account is locked
us_reset Whether the password has been reset
us_expired Whether the password has expired
us_remaining Number of remaining grace logins
us_seconds Number of seconds before the server unlocks the account
Memory Concerns

You allocate and free space for the LDAPuserstatus structure.

LDAP_VALCMP_CALLBACK

LDAP_VALCMP_CALLBACK specifies the prototype for a callback function to sort a specified set of values.

Description

If you define a function with this prototype and specify it when calling the ldap_sort_strcasecmp() function, the function will be called by your LDAP client.

typedef int (LDAP_C LDAP_CALLBACK
  LDAP_VALCMP_CALLBACK)(const char**, const char**);

ldap_sort_values() requires a function pointer that matches the signature defined by this type.

ldap_sort_strcasecmp() is a value comparison function defined using this type which can therefore be passed to ldap_sort_values().

See Also

ldap_sort_values(), ldap_sort_strcasecmp()

LDAPVersion

The LDAPVersion structure contains version information about Directory SDK For C.

Call the ldap_version() function to return a pointer to an LDAPVersion structure containing version information.

typedef struct _LDAPVersion {
  int sdk_version;
  int protocol_version;
  int SSL_version;
  int security_level;
} LDAPVersion;
LDAPVersion Field Definitions
Field What It Contains
sdk_version Version number of Directory SDK For C multiplied by 100. For example, the value 600 in this field represents version 6.0.
protocol_version Highest supported LDAP protocol version multiplied by 100. For example, the value 300 in this field represents LDAP v3.
SSL_version Supported SSL version multiplied by 100. For example, the value 300 in this field represents SSL 3.0).
security_level Level of encryption supported in bits. For example, 128 for US domestic or 40 for export. If SSL is not enabled, the value of this field is LDAP_SECURITY_NONE .

LDAPVirtualList

LDAPVirtualList specifies the information that can be used to create a virtual list view control.

Description

A virtual list view control is a LDAP v3 control designed to allow the client to retrieve subsets of search results to display in a virtual list box.

A virtual list box is typically a graphical user interface that displays a long list of entries with a few entries visible.

To display the list, the client usually does not retrieve the entire list of entries from the server. Instead, the client just retrieves the subset of entries to be displayed.

After you create an LDAPVirtualList structure and specify values for its fields, you can create the virtual list view control by calling the function ldap_create_virtuallist_control(). You can pass this control and a server-side sorting control-created by calling the ldap_create_sort_keylist() function and the ldap_create_sort_control() function-to the ldap_search_ext() or ldap_search_ext_s() function.

To get the virtual list view response control sent back from the server, call the ldap_parse_result() function to get the list of controls returned by the server, then call the ldap_parse_virtuallist_control() function to retrieve information from the control. End users can display different sections of the list by scrolling up or down.

Note: The object identifier (OID) for this control is OID 2.16.840.1.113730.3.4.9, or LDAP_CONTROL_VLVREQUEST as defined in ldap.h. It is supported by Directory Server.

The virtual list view control provides the means for your client to request and retrieve certain subsets of a long, sorted list of entries. The control specifies the following information:

  • The entry in the list that is currently selected.
  • The number of entries to be displayed in the list before the selected item.
  • The number of entries to be displayed in the list after the selected entry.

The currently selected entry can be identified in one of the following ways:

  • By the index of the entry in the entire list in which case, the control specifies both the offset of the entry and the total number of entries in the list.
  • By the value of the entry in which case, the control specifies that value.

For example, a virtual list view control might specify that you want to retrieve entries 15 through 24 in a list of 100 results with entry 20 being the selected entry. The control uses the following information to specify this:

  • The selected entry is the 20th entry from the top—in other words, the index or offset of the entry is 20—of a list of 100.
  • Get 5 entries before the selected entry in the list (entries 15 - 19).
  • Get 4 entries after the selected entry in the list (entries 21 - 24).

As another example, a virtual list view control might specify that you want to retrieve a subset of entries that start with the letter c or a later letter in the alphabet. The control might specify the following information:

  • The selected entry is the first entry that starts with the letter c. The size of the list is not relevant in determining the selected entry in this case.
  • Get 5 entries before the selected entry in the list.
  • Get 4 entries after the selected entry in the list.
typedef struct ldapvirtuallist {
  unsigned long ldvlist_before_count;
  unsigned long ldvlist_after_count;
  char *ldvlist_attrvalue;
  unsigned long ldvlist_index;
  unsigned long ldvlist_size;
  void *ldvlist_extradata;
} LDAPVirtualList;
LDAPVirtualList Field Descriptions
Field What It Contains
ldvlist_before_count Number of entries before the selected entry that you want to retrieve.
ldvlist_after_count Number of entries after the selected entry that you want to retrieve.
ldvlist_attrvalue Specifies the value that you want to find in the list. The selected entry in the list is the first entry that is greater than or equal to this value. If this field is NULL, the ldvlist_index and ldvlist_size fields are used to determine the selected entry instead.
ldvlist_index If the ldvlist_attrvalue field is NULL, specifies the offset or index of the selected entry in the list. This field is used in conjunction with the ldvlist_size field to identify the selected entry.
ldvlist_size If the ldvlist_attrvalue field is NULL, specifies the total number items in the list. This field is used in conjunction with the ldvlist_index field to identify the selected entry.
ldvlist_extradata Reserved for application-specific use. This data is not used in the virtual list view control.

LDAP_X_EXTIOF_CLOSE_CALLBACK

This specifies the prototype for an extended I/O callback function to close a socket connection.

Description
typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_CLOSE_CALLBACK )(
  int s, void *arg );
See Also

ldap_x_ext_io_fns

LDAP_X_EXTIOF_CONNECT_CALLBACK

This specifies the prototype for an extended I/O callback function to open a socket connection.

Description

LDAP_X_EXTIOF_CONNECT_CALLBACK takes a timeout parameter whose value in milliseconds can be set by calling ldap_set_option().

typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_CONNECT_CALLBACK )(
  int s, LDAP_X_SockAddr *saddr, int saddr_len,
  int timeout /* milliseconds */, void *arg );
See Also

ldap_x_ext_io_fns

LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK

This specifies the prototype for an extended I/O callback function to dispose of a session handle.

Description

LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK is called right before the LDAP session handle and its contents are destroyed during ldap_unbind(). The value of the arg parameter passed to the callback is always the default one.

typedef void (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK)(
  LDAP *ld, void *arg );
See Also

ldap_x_ext_io_fns

LDAP_X_EXTIOF_NEWHANDLE_CALLBACK

This specifies the prototype for an extended I/O callback function to define a new session handle.

Description

LDAP_X_EXTIOF_NEWHANDLE_CALLBACK is called right after the LDAP session handle is created during ldap_init(). The value of the arg parameter passed to the callback is always the default one. If the callback returns anything other than LDAP_SUCCESS, the session handle allocation fails.

typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_NEWHANDLE_CALLBACK)(
  LDAP *ld, void *arg );
See Also

ldap_x_ext_io_fns

ldap_x_ext_io_fns

This is a structure to hold extended I/O function pointers.

struct ldap_x_ext_io_fns {
/* lextiof_size should always be set to LDAP_X_EXTIO_FNS_SIZE */
  int                                     lextiof_size;
  LDAP_X_EXTIOF_CONNECT_CALLBACK          *lextiof_connect;
  LDAP_X_EXTIOF_CLOSE_CALLBACK            *lextiof_close;
  LDAP_X_EXTIOF_READ_CALLBACK             *lextiof_read;
  LDAP_X_EXTIOF_WRITE_CALLBACK            *lextiof_write;
  LDAP_X_EXTIOF_POLL_CALLBACK             *lextiof_poll;
  LDAP_X_EXTIOF_NEWHANDLE_CALLBACK        *lextiof_newhandle;
  LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK    *lextiof_disposehandle;
  void                                    *lextiof_session_arg;
  LDAP_X_EXTIOF_WRITEV_CALLBACK           *lextiof_writev;
};
#define LDAP_X_EXTIO_FNS_SIZE   sizeof(struct ldap_x_ext_io_fns)

LDAP_X_EXTIOF_POLL_CALLBACK

This specifies the prototype for an extended I/O callback function to close a socket connection.

Description

The LDAP_X_EXTIOF_POLL_CALLBACK interface is provided instead of a standard select() interface. The time out is in milliseconds. The value of the <parameter>arg</parameter> parameter passed to the callback is always the default one.

typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_POLL_CALLBACK)(
  LDAP_X_PollFD fds[], int nfds, int timeout /* milliseconds */,
  void *arg );
See Also

ldap_x_ext_io_fns, LDAP_X_PollFD

ldap_x_hostlist_status

This structure contains utility functions for parsing space-separated host lists.

Description
struct ldap_x_hostlist_status;
LDAP_API(int) LDAP_CALL ldap_x_hostlist_first( const char *hostlist,
  int defport, char **hostp, int *portp /* host byte order */,
  struct ldap_x_hostlist_status **statusp );
  LDAP_API(int) LDAP_CALL ldap_x_hostlist_next( char **hostp,
  int *portp /* host byte order */,
  struct ldap_x_hostlist_status *status
);
LDAP_API(void) LDAP_CALL ldap_x_hostlist_statusfree(
  struct ldap_x_hostlist_status *status );

LDAP_X_PollFD

This is a structure to hold the set of file descriptors that will be surveyed for I/O by the LDAP_X_EXTIOF_POLL_CALLBACK.

Description
typedef struct ldap_x_pollfd {    /* used by LDAP_X_EXTIOF_POLL_CALLBACK */
  int  lpoll_fd; /* integer file descriptor / socket */
  void *lpoll_arg; /* pointer socket and for use by application */
  short lpoll_events; /* requested event */
  short lpoll_revents; /* returned event */
} LDAP_X_PollFD;

Directory SDK for C Function Reference

This section contains detailed reference material for each public function of Directory SDK for C. Each reference gives a description of the function, and its usage syntax, parameters and return values. In many cases, an example program is also included.

Typographic Conventions

The general purpose of a function is usually given by its name. The following table lists the naming conventions used when adding suffixes to function names.

Function Naming Conventions
Suffix Description
_ext Identifies extended functions introduced for LDAP v3. These functions are augmented through additional parameters, as compared to the functions they replace. As LDAP v3 has become widely adopted, it is recommended you use extended functions whenever possible in your new applications.
_s Identifies the synchronous form of functions. A synchronous function will not return until it receives a response from the server, thereby blocking the caller. Similar function names without this suffix are asynchronous, allowing the caller to perform other operations while waiting for a result. The synchronous and asynchronous forms exist only for functions which involve possible delays due to communication with the LDAP server. Functions which do not involve communication do not use this suffix.

Function Summary by Task

In the following sections the functions of Directory SDK For C are grouped into task categories.

Working with Basic Encoding Rules

The functions listed in the following table may be used to encode and decode with Basic Encoding Rules (BER). They are often used inside of control and extension values.

Functions to Encode and Decode BER
Function Description
ber_alloc(), ber_alloc_t(), ber_sockbuf_alloc(), ber_special_alloc() Allocate new BER elements.
ber_bvecfree(), ber_bvfree(), ber_free(), ber_sockbuf_free(), ber_sockbuf_free_data() Free allocated memory.
ber_bvdup(), ber_dup() Duplicate BER structures.
ber_init(), ber_init_w_nullchar() Construct new structures.
ber_get_boolean(), ber_get_int, ber_get_next(), ber_get_next_buffer(), ber_get_next_buffer_ext(), ber_get_null(), ber_get_option, ber_get_stringa(), ber_get_stringal(), ber_get_stringb() Retrieve miscellaneous information.
ber_put_bitstring(), ber_put_boolean(), ber_put_enum(), ber_put_int(), ber_put_null(), ber_put_ostring(), ber_put_seq(), ber_put_set(), ber_put_string() Write miscellaneous information.
ber_first_element(), ber_next_element(), ber_peek_tag(), ber_skip_tag() Target specific elements and tags.
ber_set_option(), ber_set_string_translators() Set session parameters.
ber_flatten(), ber_printf(), ber_read(), ber_reset(), ber_scanf(), ber_sockbuf_get_option(), ber_sockbuf_set_option(), ber_start_seq(), ber_start_seq(), ber_start_set(), ber_svecfree(), ber_write() Miscellaneous functions.

Managing LDAP Sessions

The functions listed in the following table manage the different phases of an LDAP session: initialization, configuration, authentication (binding) and termination (unbinding).

Functions to Manage an LDAP Session
Function Description
ldap_init(), prldap_init() (IPv6) Initializes an LDAP session.
ldapssl_init() Initializes an LDAP session over SSL.
ldapssl_pkcs_init() Initializes a thread-safe session over SSL.
ldap_get_option(), ldap_set_option Read and writes the current preference settings for a session.
ldap_memcache_init(), ldap_memcache_set(), ldap_memcache_get(), ldap_memcache_update(), ldap_memcache_flush(), ldap_memcache_destroy() Creates a memory cache and uses it for search results from this session. Manages the data in the cache and frees the memory when the cache is no longer needed. The in-memory cache for search results is an extension to the API.
ldap_unbind_ext() Ends an LDAP session and frees the associated data structures.

Performing LDAP Operations

The functions listed in the following table perform LDAP operations on a server and retrieve the results.

Functions to Perform Operations on LDAP Server
Function Description
ldap_add_ext() or ldap_add_ext_s() Adds a new entry to the directory.
ldap_modify_ext() or ldap_modify_ext_s() Modifies an entry in the directory
ldap_delete_ext() or ldap_delete_ext_s() Deletes an entry from the directory.
ldap_rename() orldap_rename_s() Renames or moves one or more entries.
ldap_search_ext() or ldap_search_ext_s() Searches the directory.
ldap_compare_ext() or ldap_compare_ext_s() Compares a value with the values of an entry's attribute.
ldap_result() Checks the results of an asynchronous operation.
ldap_abandon_ext() Cancels an asynchronous operation.
ldap_extended_operation() or ldap_extended_operation_s() Performs an LDAP v3 extended operation.
ldap_parse_extended_result() Parses the results of an LDAP v3 extended operation.
ldap_msgfree() Frees the memory used by the data structure for the results.
ldap_simple_bind() or ldap_simple_bind_s() Authenticates to an LDAP server using a password.
ldap_sasl_bind() and ldap_parse_sasl_bind_result() or ldap_sasl_bind_s Authenticates to an LDAP server using a SASL mechanism.
ldap_set_rebind_proc() Specifies the function used to get authentication information when following referrals.

Processing Search Results

Search results are given as a chain of LDAPMessage structures which can contain both entry messages and search reference messages. The functions listed in the following table retrieve the results of a search operation and process the data structures which are returned.

Functions to Process Search Results
Function Description
ldap_first_message() Gets the first message (an entry or search reference) in a chain of search results.
ldap_next_message() Gets the next message (an entry or search reference) in a chain of search results.
ldap_count_messages() Counts the number of messages (entries and search references) in a chain of search results.
ldap_msgid() Gets the ID number of a message structure containing part of a result.
ldap_msgtype() Determines whether a message structure contains an entry or a search reference.
ldap_msgfree() Frees the memory allocated for search results or other LDAP operation results.
ldap_first_entry() Gets the first entry in a chain of search results.
ldap_next_entry() Gets the next entry in a chain of search results.
ldap_count_entries() Counts the number of entries in a chain of search results.
ldap_first_reference() Gets the first search reference in a chain of search results.
ldap_next_reference() Gets the next search reference in a chain of search results.
ldap_count_references() Counts the number of search references in a chain of search results.
ldap_parse_reference() Extracts the referral strings from a search reference.

Reading the Contents of an Entry

The functions listed in the following table are used to access the contents of an entry returned as a search result.

Functions to Access Contents of an Entry
Function Description
ldap_get_dn() Get the DN for an entry.
ldap_explode_dn() ldap_explode_rdn() Split a DN or relative DN into its components.
ldap_explode_dns() Takes a DNS-style DN and breaks it up into its components.
ldap_is_dns_dn() Determines the style of the DN.
ldap_dn2ufn() Removes cryptic type names to make a DN easier to read.
ldap_first_attribute() Get the name of the first attribute in an entry.
ldap_next_attribute() Get the name of the next attribute in an entry.
ldap_get_values() Get the string values of an attribute.
ldap_get_values_len() Get the binary values of an attribute.
ldap_count_values() Count the string values of an attribute.
ldap_count_values_len() Count the binary values of an attribute.
ldap_value_free() Free the memory allocated for the string values of an attribute.
ldap_value_free_len() Free the memory allocated for the binary values of an attribute.

Sorting Search Results

With the functions listed in the following table, your LDAP client can sort the data structures returned as search results.

Client-side Sorting Functions
Function Description
ldap_sort_entries() Sorts search results by DN or by a single attribute.
ldap_multisort_entries() Sorts search results by multiple attributes
ldap_keysort_entries() Sorts search results using key(s).
ldap_sort_values() Sorts the values of an attribute.
ldap_sort_strcasecmp() A case-insensitive comparison function that you can pass to ldap_sort_values().

Directory Server and others also provide server-side sorting through LDAP v3 controls.

Server-Side Sorting Functions
Function Description
ldap_create_sort_keylist() Define the criteria for sorting entries by attribute values.
ldap_free_sort_keylist() Free the memory for the sort criteria data structure.
ldap_create_sort_control() Create the sort control structure needed for server-side sorting.
ldap_control_free() Free the memory for the sort control data structure.
ldap_parse_sort_control() Analyze the server’s response to the sort control.
ldap_controls_free() Free the memory for the sort control response data structure.

Working with Search Filters

The functions listed in the following table retrieve and build filters using a filter configuration file. Use this mechanism to create complex filters to pass to the search functions.

Functions to Initialize, Retrieve, and Build Filters
Function Description
ldap_init_getfilter() Read a filter configuration file into memory.
ldap_init_getfilter_buf() Read a filter configuration string from a buffer.
ldap_getfilter_free() Free the filter configuration data structure from memory.
ldap_set_filter_additions() Specify the prefix and suffix to be added to all filters retrieved from the filter configuration.
ldap_getfirstfilter() Retrieve the first matching filter from the filter configuration.
ldap_getnextfilter() Retrieve the next matching filter from the filter configuration.
ldap_create_filter() Build a filter without using the filter configuration file mechanism.

Using LDAP v3 Controls

Directory Server and others also provide additional functionality through LDAP v3 controls. The functions listed in the following table configure LDAP v3 control structures which ask the server to perform advanced operations.

Functions to Manage LDAP v3 Controls
Function Description
ldap_create_authzid_control(), ldap_parse_authzid_control() Examine the authorization ID used for the operation.
ldap_create_persistentsearch_control(), ldap_get_entry_controls(), ldap_parse_entrychange_control() Track changes to an entry or a set of entries by setting the persistent search control and analyzing the entry change control sent by the server.
ldap_create_proxiedauth_control() Define a proxy authorization control to perform an operation under a different bind DN
ldap_create_pwdpolicy_control(), ldap_parse_pwdpolicy_control() Examine password policy information for an entry.
ldap_create_sort_keylist(), ldap_free_sort_keylist(), ldap_create_sort_control(), ldap_parse_sort_control() Define and send criteria for server-side sorting of search results and check the server’s response
ldap_create_userstatus_control(), ldap_parse_userstatus_control() Examine account availability information for an entry.
ldap_create_virtuallist_control(), ldap_parse_virtuallist_control() Use in conjunction with server-side sorting to limit and handle the number of results returned to the client.
ldap_parse_result() Parse an LDAP response from the server to extract the result and the response to the control.

Using Extensions

The functions listed in the following table are utility functions for parsing space-separated host lists. This is useful for implementing an extended I/O CONNECT callback function.

Extensions Provided
Function Description
ldap_x_hostlist_first(), ldap_x_hostlist_next(), ldap_x_hostlist_status() Utility functions for parsing space-separated host lists.

Working with LDAP URLs

The functions listed in the following table interpret LDAP URLs, universal resource locators of the form ldap://... .

Functions to Interpret LDAP URLs
Function Description
ldap_is_ldap_url() Determine if a URL is an LDAP URL.
ldap_url_parse() Split up an LDAP URL into its components.
ldap_url_search(), ldap_url_search_s, ldap_url_search_st() Perform the search specified by an LDAP URL.
ldap_free_urldesc() Free the memory allocated for a parsed URL.

Working with UTF-8 Encoding

The functions listed in the following table work with strings and characters that use UTF-8 encoding.

Functions to Handle UTF-8 Encoding
Function Description
ldap_utf8len() Function to determine byte length.
ldap_utf8next() Function to get next character.
ldap_utf8prev() Function to get previous character.
ldap_utf8copy() Function to copy a character to a destination.
ldap_utf8characters() Function to return the number of characters.
ldap_utf8getcc() Function moves the pointer to the next character following a UCS-4 character.
ldap_utf8strtok_r() Function moves the pointer to the next character following a UCS-4 character.
ldap_utf8isalnum(), ldap_utf8isalpha, ldap_utf8isdigit(), ldap_utf8len(), ldap_utf8isspace() Functions to determine characteristics of the character.

Handling Errors

The functions listed in the following table handle errors returned by the functions. See Directory SDK for C Result Codes for a list of all of the error and status codes used in the Directory SDK For C. You can also find details about possible errors in the reference section for each function.

Functions for Error Handling
Function Description
ldap_parse_result() Get the error code resulting from an asynchronous LDAP operation.
ldap_get_lderrno() Get information about the last error that occurred.
ldap_set_lderrno() Set information about an error.
ldap_err2string() Get the error message for a specific error code.
ldapssl_err2string() Get the error message for a specific SSL error code.

Managing Memory

The functions listed in the following table free memory allocated by the Directory SDK For C functions.

Functions to Free Memory
Function Description
ber_bvfree() Free the memory allocated for a berval structure.
ber_free() Free the memory of a BerElement structure.
ldap_control_free() Free the memory of an LDAPControl structure.
ldap_controls_free() Free an array of LDAPControl structures.
ldap_free_friendlymap() Free the memory of a FriendlyMap structure
ldap_free_sort_keylist() Free an array of LDAPsortkey structures
ldap_free_urldesc() Free the memory of an LDAPURLDesc structure
ldap_getfilter_free() Free the memory of an LDAPFiltDesc structure.
ldap_memfree() General function for freeing memory of any other data structure
ldap_mods_free() Free an array of LDAPMod structure.
ldap_msgfree() Free the memory of an LDAPMessage structure.
ldap_value_free() Free the memory allocated for the string values of an attribute.
ldap_value_free_len() Free the memory allocated for the binary values of an attribute (an array of berval structures)

You may also manage memory directly with the functions in the following table.

Functions to Directly Manage Memory
Function Description
ldap_x_malloc() Allocates memory.
ldap_x_calloc() Allocates memory for an array of elements.
ldap_x_realloc() Changes the size of a memory block.
ldap_x_free() Frees a block of memory.

Working with NSPR

The functions listed in the following table tie libldap into Netscape Portable Runtime, NSPR.

Functions to Work with NSPR
Function Description
prldap_get_default_socket_info() Gets default socket information.
prldap_get_session_info() Gets application-specific data.
prldap_get_session_option() Gets a session option specific to the prldap layer.
prldap_get_socket_info() Gets socket information.
prldap_init() Creates a new NSPR session handle.
prldap_install_routines() Installs NSPR functions for use with LDAP handle.
prldap_set_default_socket_info() Sets default socket information.
prldap_set_session_info() Sets application-specific data.
prldap_set_session_option() Sets a session option specific to the prldap layer.
prldap_set_socket_info() Sets socket information.

Deprecated and Outdated Functions

The functions listed in first column of the following table should no longer be used; they have been superseded by the newer functions listed in the second column. Deprecated functions are those being dropped from the standard or from extensions to Directory SDK For C. Outdated functions are those which are not officially deprecated but which have newer, extended functions for performing the same operation.

Deprecated Functions and Their Replacements
Deprecated Function Replacement
ldap_ber_free() Replaced by ber_free().
ldap_bind(), ldap_bind_s() Replaced by ldap_simple_bind() and ldap_simple_bind_s() respectively.
ldap_build_filter() Replaced by ldap_create_filter().
ldap_cache_flush() Replaced by ldap_memcache_*() functions.
ldap_charray_add(), ldap_charray_dup, ldap_charray_free(), ldap_charray_inlist(), ldap_charray_merge(), ldap_charray_position(), ldap_str2charray() None documented to replace these character array functions.
ldap_create_proxyauth_control() Replaced by ldap_create_geteffectiveRights_control().
ldap_get_lang_values(), ldap_get_lang_values_len() Rarely used, no replacement.
ldap_modrdn() Replaced by ldap_modrdn2(), itself outdated by ldap_rename().
ldap_modrdn_s() Replaced by ldap_modrdn2_s(), itself outdated by ldap_rename_s().
ldap_open() Replaced by ldap_init() and one of the bind functions.
ldap_result2error() Replaced by ldap_parse_result().
ldap_setfilteraffixes() Replaced by ldap_set_filter_additions().
ldap_ufn_search_c(), ldap_ufn_search_ct(), ldap_ufn_search_s(), ldap_ufn_setfilter(), ldap_ufn_setprefix(), ldap_ufn_timeout() None documented to replace these user-friendly search functions.
ldap_version() Replaced by ldap_get_option().

Outdated Standard Functions and Equivalents

Many LDAP v2 functions are outdated now that LDAP v3 has been widely adopted. The following table lists both the outdated function and its new equivalent. Although LDAP v2 functions remain in the standard specification, you should use the LDAP v3 functions in any new client applications. Again, for maintenance reasons, the outdated functions have often been implemented to call the newer function.

Outdated LDAP v2 Functions and New Equivalents
LDAP v2 Functions LDAP v3 Equivalent
ldap_abandon() ldap_abandon_ext()
ldap_add(), ldap_add_s() ldap_add_ext(), ldap_add_ext_s()
ldap_compare(), ldap_compare_s() ldap_compare_ext(), ldap_compare_ext_s
ldap_delete(), ldap_delete_s() ldap_delete_ext(), ldap_delete_ext_s
ldap_modify(), ldap_modify_s() ldap_modify_ext(), ldap_modify_ext_s
ldap_modrdn2(), ldap_modrdn2_s() ldap_rename(), ldap_rename_s()
ldap_search(), ldap_search_s(), ldap_search_st() ldap_search_ext(), ldap_search_ext_s, ldap_search_ext_s() - use timeout argument
ldap_unbind(), ldap_unbind_s() ldap_unbind_ext() replaces both forms which are identical besides the suffix.

Functions Alphabetically

This sections lists the functions in alphabetical order.

ber_alloc()

The ber_alloc() function is used to allocate a new Basic Encoding Rules (BER) BerElement structure.

Syntax
#include <lber.h>
  BerElement* ber_alloc( void );
Parameters

This function has no parameters.

Returns
  • If successful, a pointer to the newly allocated BerElement structure.
  • If unsuccessful, a NULL pointer.
Description

ber_alloc() is used to allocate a new BerElement structure for encoding data with the BER.

See Also

ber_printf(), BerElement

ber_alloc_t()

The ber_alloc_t() function constructs and returns a BerElement structure.

Syntax
#include <lber.h>
  BerElement* ber_alloc_t( int options );
Parameters
ber_alloc_t() Function Parameter
Parameter Description
options Contains bitwise OR of options to be used when generating the encoding of the 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. This option does not cause values of sets and sequences to be rearranged in tag and byte order, so these functions are not suitable for generating DER output as defined in X.509 and X.680.
Returns
  • If successful, a pointer to the newly allocated BerElement structure.
  • If unsuccessful, a NULL pointer.
Description

This function is the same as ber_alloc() except it has an option.

See Also

ber_printf(), BerElement

ber_bvecfree()

The ber_bvecfree() function frees an array of berval structures.

Syntax
#include <lber.h>
  void ber_bvecfree( struct berval **bv );
Parameters
ber_bvecfree() Function Parameter
Parameter Description
bv Pointer to the array that you want to free from memory.
Description

Each berval in the array is freed using ber_bvfree(), and then the array itself is freed.

See Also

ber_bvfree()

ber_bvdup()

The ber_bvdup() function returns a copy of a berval structure.

Syntax
#include <lber.h>
  berval* ber_bvdup( const struct berval *bv );
Parameters
ber_bvdup() Function Parameter
Parameter Description
bv Pointer to the berval structure to be duplicated.
Returns
  • If successful, a pointer to the newly allocated berval structure.
  • If unsuccessful, a NULL pointer.
Description

The ber_bvdup() function returns a copy of a berval structure. The data referenced in the structure is also duplicated. The bv_val field in the returned berval points to a different area of memory than the bv_val field in the argument berval.

ber_bvfree()

The ber_bvfree() function frees a berval structure.

Syntax
#include <lber.h>
  void ber_bvfree( struct berval *bv );
Parameters
ber_bvfree() Function Parameter
Parameter Description
bv Pointer to the berval structure that you want to free from memory.
Description

The ber_bvfree() function frees a berval structure from memory. Call this function to free a berval passed back from the ldap_extended_operation_s() , ldap_parse_extended_result(), ldap_sasl_bind_s(), or ldap_parse_sasl_bind_result() functions.

See Also

ldap_extended_operation_s(), ldap_parse_extended_result(), ldap_sasl_bind_s() , ldap_parse_sasl_bind_result()

ber_dup()

The ber_dup() function returns a copy of a BerElement structure.

Syntax
#include <lber.h>
  BerElement* ber_dup( BerElement *ber );
Parameters
ber_dup() Function Parameter
Parameter Description
ber Pointer to the BerElement to be duplicated.
Returns
  • If successful, a pointer to the newly allocated BerElement structure.
  • If unsuccessful, a NULL pointer.
Description

The ber_dup() function returns a copy of a BerElement structure.

ber_first_element()

The ber_first_element() function is used to return the tag and length of the first element in a set or sequence.

Syntax
#include <lber.h>
unsigned long ber_first_element( BerElement *ber, unsigned long *len,
  char **last );
Parameters
ber_first_element() Function Parameters
Parameter Description
ber Pointer to a BerElement.
len Pointer to the address of the unsigned long which returns the length of the first element.
last Address of the pointer to return the address of the last byte of the element.
Returns

NULL pointer is returned on error.

Description

The ber_first_element() function is used to return the tag and length of the first element in a set or sequence. It also returns a magic cookie parameter that should be passed to subsequent calls to ber_next_element() .

See Also

ber_next_element()

ber_flatten()

The ber_flatten() function allocates a berval structure whose contents are taken from a source BerElement structure.

Syntax
#include <lber.h>
  int ber_flatten( BerElement *ber, struct berval **bvPtr );
Parameters
ber_flatten() Function Parameters
Parameter Description
ber Pointer to the source BerElement.
bvPtr Pointer to the newly allocated berval structure which must be freed using ber_bvfree().
Returns

Returns 0 on success and -1 on error.

Description

This function is usually used when encoding LDAP v3 controls or extended operations values.

See Also

ber_bvfree()

ber_free()

The ber_free() function frees a BerElement structure previously allocated with ber_alloc() , ber_alloc_t(), ber_init(), or the ldap_first_attribute() and ldap_next_attribute() search functions.

Syntax
#include <ldap.h>
  void ber_free( BerElement *ber, int freebuf );
Parameters
ber_free() Function Parameters
Parameter Description
ber Pointer to the BerElement structure that you want to free.
freebuf Specifies whether or not to free the buffer in the BerElement structure.
Description

This function frees a BerElement structure, which is used to keep track of the current attribute. When you are done working with the attributes, you should free this structure from memory, if it still exists.

Note: To retrieve attributes from a search result entry, you need to call either the ldap_first_attribute() or ldap_next_attribute() function. When freeing structures allocated by these functions, you should specify 0 for the freebuf argument. Otherwise, it should always be set to 1.

Example

the following example frees the BerElement structure allocated by the ldap_first_attribute() function.

LDAP *ld;
LDAPMessage *a, *e;
BerElement *ber;
...
for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL;
  a =ldap_next_attribute( ld, e, ber ) {
    ...
    /* Retrieve the value of each attribute */
    ...
}
/* Free the BerElement when done */
if ( ber != NULL ) {
  ber_free( ber, 0 );
}
...
See Also

ber_alloc(), ber_alloc_t() , ber_init(), ldap_first_attribute(), ldap_next_attribute()

ber_get_boolean()

The ber_get_boolean() function is used to read a boolean value.

Syntax
#include <lber.h>
unsigned long ber_get_boolean( BerElement *ber,
  int *boolval );
Parameters
ber_get_boolean() Function Parameters
Parameter Description
ber Pointer to the BerElement structure that contains the boolean.
boolval Specifies the boolean to read.
Returns

The value is returned on success and LBER_ERROR (-1) on failure.

ber_get_int()

The ber_get_int() function tries to interpret the next element as an integer, returning the result in num.

Syntax
#include <lber.h>
unsigned long ber_get_int( BerElement *ber, int *num );
Parameters
ber_get_int() Function Parameters
Parameter Description
ber Pointer to the BerElement structure that contains the boolean.
num Pointer to the result.
Returns

The tag of whatever it finds is returned on success and LBER_ERROR (-1) on failure.

ber_get_next()

The ber_get_next() function reads the next BER element.

Syntax
#include <lber.h>
unsigned long ber_get_next( Sockbuf *sb, unsigned long *len,
  BerElement *ber );
Parameters
ber_get_next() Function Parameters
Parameter Description
sb Descriptor (socket or file descriptor) from which to read.
len The length of the entire element.
ber Pointer to the BerElement structure.
Description

ber_get_next() strips off and returns the leading tag, strips off and returns the length of the entire element, and sets up a pointer to ber for subsequent calls to decode the element.

ber_get_next_buffer()

The ber_get_next_buffer() function reads the next BER element from a byte buffer.

The ber_get_next_buffer_ext() function reads the next BER element from a byte buffer.

Note: ber_get_next_buffer_ext() is a new version of the ber_get_next_buffer() function. If you are writing a new LDAP client, use ber_get_next_buffer_ext() .

Syntax
#include <lber.h>
unsigned long ber_get_next_buffer_ext( void *buffer,
  size_t buffer_size, unsigned long *len, BerElement *ber,
  unsigned long *Bytes_Scanned, Sockbuf *sb );
Parameters
ber_get_next_buffer_ext() Function Parameters
Parameter Description
buffer Pointer to the buffer.
buffer_size The size of the buffer.
len The length of the entire element.
ber Pointer to a BerElement.
Bytes_Scanned Returns the number of bytes actually searched through.
sb Descriptor (socket or file descriptor) from which to read.

ber_get_null()

The ber_get_null() function is used to read a NULL element.

Syntax
#include <lber.h>
unsigned long ber_get_null( BerElement *ber );
Parameters
ber_get_null() Function Parameter
Parameter Description
ber Pointer to a BerElement.
Returns

Returns the tag of the element it skips over.

ber_get_option()

The ber_get_option() function is used to retrieve information about the API and about the specific implementation being used.

Syntax
#include <lber.h>
int ber_get_option( BerElement *ber, int option, void *value );

ber_get_stringa()

The ber_get_stringa() function is used to allocate memory space into which an octet string is read.

Syntax
#include <lber.h>
unsigned long ber_get_stringa( BerElement *ber, char **buf );

ber_get_stringal()

The ber_get_stringal() function is used to allocate memory space into which an octet string and its length are read.

Syntax
#include <lber.h>
unsigned long ber_get_stringal( BerElement *ber, struct berval **bv );
Description

It takes a berval structure, and returns the result in this parameter.

ber_get_stringb()

The ber_get_stringb() function is used to read an octet string into a preallocated buffer.

Syntax
#include <lber.h>
unsigned long ber_get_stringb( BerElement *ber, char *buf,
  unsigned long *len );
Description

The len parameter should be initialized to the size of the buffer, and will contain the length of the octet string read upon return. The buffer should be big enough to take the octet string value plus a terminating NULL byte.

ber_init()

The ber_init() function constructs a new BerElement.

Syntax
#include <lber.h>
BerElement * ber_init( const struct berval *bv );
Parameters
ber_init() Function Parameter
Parameter Description
bv Pointer to a berval.
Returns
  • If successful, returns a new BerElement containing a copy of the data in the bv argument.
  • If not, returns a NULL pointer.

ber_init_w_nullchar()

The ber_init_w_nullchar() function constructs a new BerElement with a NULL character.

Syntax
#include <lber.h>
void ber_init_w_nullchar( BerElement *ber, int options );

ber_next_element()

The ber_next_element() function is used to return the tag and length of the next element in a set or sequence.

Syntax
#include <lber.h>
unsigned long ber_next_element( BerElement *ber, unsigned long *len,
  char *last );
Parameters
ber_next_element() Function Parameters
Parameter Description
ber Pointer to a BerElement.
len Pointer to the address of the unsigned long which returns the length of the next element.
last Address of the pointer to return the address of the last byte of the element.
Returns

NULL pointer is returned on error.

Description

The ber_next_element() function is used to return the tag and length of the first element in a set or sequence.

See Also

ber_first_element()

ber_peek_tag()

The ber_peek_tag() function returns the tag of the next element to be parsed in the supplied BerElement structure.

Syntax
#include <lber.h>
unsigned long ber_peek_tag( BerElement *ber, unsigned long *len );
Parameters
ber_peek_tag() Function Parameters
Parameter Description
ber Pointer to a BerElement.
len Pointer to the address of the unsigned long which returns the length of the next element.
Returns

Returns the tag of the next element to be read in the BerElement structure. LBER_DEFAULT is returned if there is no further data to be read.

ber_printf()

The ber_printf() function encodes a BER element.

Syntax
#include <lber.h>
ber_printf( BerElement *ber, const char *fmt, ... );
Parameters
ber_printf() Function Parameters
Parameter Description
ber Pointer to a BerElement returned by ber_alloc() or ber_alloc_t().
fmt Defines the encoding format string. The format string can contain the following characters:
  • -b Boolean. An integer parameter should be supplied. A boolean element is output.
  • -i Integer. An integer parameter should be supplied. An integer element is output.
  • -B Bitstring. A char * pointer to the start of the bitstring is supplied, followed by the number of bits in the bitstring. A bitstring element is output.
  • -n Null. No parameter is required. A NULL element is output.
  • -o Octet string. A char * is supplied, followed by the length of the string pointed to. An octet string element is output.
  • -s Octet string. A NULL terminated string is supplied. An octet string element is output, not including the trailing NULL octet.
  • -t Tag. An int specifying the tag to give the next element is provided. This works across calls.
  • -v Several octet strings. A NULL terminated array of char *s is supplied. Note that a construct like '{v}' is required to get an actual sequence of octet strings.
  • -{ Begin sequence. No parameter is required.
  • -} End sequence. No parameter is required.
  • -[ Begin set. No parameter is required.
  • -] End set. No parameter is required.
... Values to be encoded.
Description

State information is kept with the ber parameter so multiple calls can be made to ber_printf() to append things to the end of the BerElement. ber_printf() interprets and formats its arguments according to the format string fmt. Each character in fmt refers to an argument to ber_printf() .

Returns

-1 if there is an error during encoding.

ber_put_bitstring()

The ber_put_bitstring() function writes a bitstring value to the given BerElement.

Syntax
#include <lber.h>
int ber_put_bitstring( BerElement *ber, char *str,
  unsigned long bitlen, unsigned long tag );
Description

The ber_put_bitstring() function writes bitlen bits starting at str as a bitstring value to the given BerElement.

ber_put_boolean()

The ber_put_boolean() function writes a boolean value to a BerElement.

Syntax
#include <lber.h>
int ber_put_boolean( BerElement *ber, int boolval, unsigned long tag );
Description

The boolean value is given by boolval to the BerElement.

ber_put_enum()

The ber_put_enum() function writes an enumerated value to a BerElement.

Syntax
#include <lber.h>
int ber_put_enum( BerElement *ber, long num, unsigned long tag );

ber_put_int()

The ber_put_int() function writes an integer to a BerElement.

Syntax
#include <lber.h>
int ber_put_int( BerElement *ber, long num, unsigned long tag );

ber_put_null()

The ber_put_null() function writes a writes a NULL element to a BerElement.

Syntax
#include <lber.h>
int ber_put_null( BerElement *ber, unsigned long tag );

ber_put_ostring()

The ber_put_ostring() function writes bytes to a BerElement() as an octet string.

Syntax
#include <lber.h>
int ber_put_ostring( BerElement *ber, char *str,
  unsigned long len, unsigned long tag );

ber_put_seq()

The ber_put_seq() function puts a sequence to a BerElement.

Syntax
#include <lber.h>
int ber_put_seq( BerElement *ber );
Parameters
ber_put_seq() Function Parameter
Parameter Description
ber Pointer to a BerElement.
Description

The ber_start_seq() function is used to start a sequence in the BerElement. The end of the sequence is marked by the nearest matching call to ber_put_seq().

ber_put_set()

The ber_put_set() function puts a set to a BerElement.

Syntax
#include <lber.h>
int ber_put_set( BerElement *ber );
Parameters
ber_put_set() Function Parameter
Parameter Description
ber Pointer to a BerElement.
Description

The ber_start_set() function is used to start a set in the BerElement. The end of the set is marked by the nearest matching call to ber_put_set().

ber_put_string()

The ber_put_string() function writes a NULL terminated string (minus the terminating 0) to a BerElement as an octet string.

Syntax
#include <lber.h>
int ber_put_string( BerElement *ber, char *str, unsigned long tag );

ber_read()

Syntax
#include <lber.h>
long ber_read( BerElement *ber, char *buf, unsigned long len );

ber_reset()

Syntax
#include <lber.h>
void ber_reset( BerElement *ber, int was_writing );

ber_scanf()

The ber_scanf() function decodes a BerElement.

Syntax
#include <lber.h>
unsigned long ber_scanf( BerElement *ber, const char *fmt, ... );
Parameters
ber_scanf() Function Parameters
Parameter Description
ber Pointer to a BerElement as returned by ber_get_next().
fmt Defines the encoding format string. The format string can contain the following characters:
  • -a Octet string. A char ** should be supplied. Memory is allocated, filled with the contents of the octet string, NULL terminated, and returned in the parameter.
  • -s Octet string. A char * buffer should be supplied, followed by a pointer to an integer initialized to the size of the buffer. Upon return, the NULL terminated octet string is put into the buffer, and the integer is set to the actual size of the octet string.
  • -O Octet string. A struct ber_val** should be supplied, which upon return points to a memory allocated struct berval containing the octet string and its length. Call ber_bvfree() to free allocated memory.
  • -b Boolean. A pointer to an integer should be supplied.
  • -i Integer. A pointer to an integer should be supplied.
  • -B Bitstring. A char ** should be supplied which will point to the memory allocated bits, followed by an unsigned long *, which will point to the length (in bits) of the bitstring returned.
  • -n Null. No parameter is required. The element is simply skipped if it is recognized.
  • -v Sequence of octet strings. A char*** should be supplied, which upon return points to a memory allocated NULL terminated array of char *s containing the octet strings. NULL is returned if the sequence is empty.
  • -V Sequence of octet strings with lengths. A struct berval *** should be supplied, which upon return points to a memory allocated, NULL terminated array of struct berval *s containing the octet strings and their lengths. NULL is returned if the sequence is empty. ber_bvecfree() can be called to free the allocated memory.
  • -x Skip element. The next element is skipped.
  • -{ Begin sequence. No parameter is required. The initial sequence tag and length are skipped.
  • -} End sequence. No parameter is required and no action is taken.
  • -[ Begin set. No parameter is required. The initial set tag and length are skipped.
  • -] End set. No parameter is required and no action is taken.
... Values to be encoded.
Description

ber_scanf() reads from ber, interprets the bytes according to the format string fmt, and stores the results in its additional arguments. The format string contains conversion specifications which are used to direct the interpretation of the BER element.

See Also

ber_printf()

ber_set_option()

Syntax
#include <lber.h>
int ber_set_option( BerElement *ber, int option, void *value );

ber_set_string_translators()

Syntax
#include <lber.h>
unsigned long ber_skip_tag( BerElement *ber, unsigned long *len );

ber_skip_tag()

The ber_skip_tag() function advances the pointer to a BerElement past the first tag and length to the next tag.

Syntax
#include <lber.h>
unsigned long ber_skip_tag( BerElement *ber, unsigned long *len );
Parameters
ber_skip_tag() Function Parameters
Parameter Description
ber Pointer to a BerElement.
len Pointer to the length of the value to be skipped.
Description

ber_skip_tag() should only be used with constructed types and situations when a BER encoding is used as the value of an octet string.

See Also

ber_peek_tag()

ber_sockbuf_alloc()

Syntax
#include <lber.h>
Sockbuf* ber_sockbuf_alloc( void );

ber_sockbuf_free()

Syntax
#include <lber.h>
void ber_sockbuf_free( Sockbuf* p );

ber_sockbuf_free_data()

Syntax
#include <lber.h>
void ber_sockbuf_free_data(Sockbuf *p);

ber_sockbuf_get_option()

Syntax
#include <lber.h>
int ber_sockbuf_get_option( Sockbuf *sb, int option, void *value );

ber_sockbuf_set_option()

Syntax
#include <lber.h>
int ber_sockbuf_set_option( Sockbuf *sb, int option, void *value );

ber_special_alloc()

The ber_special_alloc() function allocates a BerElement structure plus some extra memory.

Syntax
#include <lber.h>
void* ber_special_alloc( size_t size, BerElement **ppBer );
Returns

Returns a pointer to the BerElement and a pointer to the extra memory.

Description

ber_special_alloc() allocates a ber data buffer within the same block, thus saving a call to calloc later when we read data.

ber_special_free()

The ber_special_free() function frees an allocated BerElement structure.

Syntax
#include <lber.h>
void ber_special_free( void* buf, BerElement *ber );
See Also

ber_special_alloc()

ber_stack_init()

Syntax
#include <lber.h>
int LDAP_CALL ber_stack_init(BerElement *ber, int options,
  char * buf, size_t size);

ber_start_seq()

The ber_start_seq() function is used to start a sequence in a BerElement.

Syntax
#include <lber.h>
int ber_start_seq( BerElement *ber, unsigned long tag );
See Also

ber_put_seq()

ber_start_set()

The ber_start_seq() function is used to start a set in a BerElement.

Syntax
#include <lber.h>
int ber_start_set( BerElement *ber, unsigned long tag );
See Also

ber_put_set()

ber_svecfree()

Syntax
#include <lber.h>
void ber_svecfree( char **vals );

ber_write()

Syntax
#include <lber.h>
long ber_write( BerElement *ber, char *buf,
  unsigned long len, int nosos );

ldap_abandon()

The ldap_abandon() function cancels an asynchronous LDAP operation that is in progress.

#include <ldap.h>
int ldap_abandon( LDAP *ld, int msgid );
Parameters
ldap_abandon() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
msgid Message ID of an LDAP operation.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • -1 if unsuccessful.

Note: The appropriate LDAP error code is also set in the LDAP structure. You can retrieve the error code by calling ldap_get_lderrno(). Some possible codes are:

  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.
Description

Please use the newer version of this function, ldap_abandon_ext().

Example

The following example cancels an ldap_url_search() operation, abandoning the results of the operation.

LDAP *ld;
char *url = "ldap://ldap.example.com/c=US?o,description?one?o=sales";
int msgid;
...
/* Initiate a search operation */
msgid = ldap_url_search( ld, url, 0 );
...
/* Abandon the search operation */
if ( ldap_abandon( ld, msgid ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_abandon" );
  return( 1 );
}
...
See Also

ldap_abandon_ext()

ldap_abandon_ext()

The ldap_abandon_ext() function cancels an asynchronous LDAP operation that is in progress.

#include <ldap.h>
int ldap_abandon_ext( LDAP *ld, int msgid,
  LDAPControl **serverctrls, LDAPControl **clientctrls );
Parameters
ldap_abandon_ext() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
msgid Message ID of an LDAP operation to identify the operation to be cancelled. When you call an asynchronous function such as ldap_search_ext(), the msgidp argument returns a pointer to a message ID that uniquely identifies the operation. Thus, when you call ldap_abandon_ext(), your LDAP client is able to send a request specifying the message ID of the operation to be cancelled.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.
Description

The ldap_abandon_ext() function cancels an asynchronous LDAP operation that is in progress. For example, if you called ldap_search_ext() to initiate an LDAP search operation on the server, you can call ldap_abandon_ext() to cancel it. When you call ldap_abandon_ext(), the function checks to see if the results of the operation have already been returned. If so, ldap_abandon_ext() deletes the message ID from the queue of pending messages. If the results have not been returned, ldap_abandon_ext() sends a request to abandon the operation. Once cancelled, the results of the operation will not be returned, even if you subsequently call ldap_result() to retrieve them. To identify the operation to be cancelled, specify the message ID of the operation in the msgid argument of the ldap_abandon_ext() function.

Example

the following example cancels an ldap_url_search() operation, abandoning the results of the operation. Using ldap_abandon_ext()

LDAP *ld;
char *url = "ldap://ldap.example.com/c=US?o,description?one?o=sales";
int msgid;
LDAPControl **srvrctrls, **clntctrls;
...
/* Initiate a search operation */
msgid = ldap_url_search( ld, url, 0 );
...
/* Abandon the search operation */
if ( ldap_abandon_ext( ld, msgid, srvrctrls, clntctrls )
  != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_abandon" );
    return( 1 );
}
...
See Also

ldap_add_ext(), ldap_compare_ext() , ldap_delete_ext(), ldap_extended_operation(), ldap_modify_ext(), ldap_rename(), ldap_sasl_bind , ldap_search_ext(), ldap_simple_bind(), ldap_url_search()

ldap_add()

The ldap_add() function adds a new entry to the directory asynchronously.

Note: This is an older function that is included in the SDK for backward-compatibility. If you are writing a new LDAP client, use ldap_add_ext() instead.

Syntax
#include <ldap.h>
int ldap_add( LDAP *ld, const char *dn, LDAPMod **attrs );
Parameters
ldap_add() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to add. With the exception of the leftmost component, all components of the DN (for example, o=organization or c=country) must already exist.
attrs Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes of the new entry.
Returns

The message ID of the ldap_add() operation. Please use the newer version of this function, ldap_add_ext() .

Example

the following example adds a new entry to the directory. Using ldap_add()

#include <ldap.h>
...
LDAP *ld;
LDAPMod *list_of_attrs[4];
LDAPMod attribute1, attribute2, attribute3;
LDAPMessage *result;
int msgid, rc;
struct timeval tv;
/* Distinguished name of the new entry. Note that "dc=example,dc=com" and
"ou=People,dc=example,dc=com" must already exist in the directory. */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* To add a "person" entry, you must specify values for the sn, cn,
and objectClass attributes. (These are required attributes.) */
char *sn_values[] = { "Jensen", NULL };
/* To specify multiple values for an attribute, add the different values
to the array. */
char *cn_values[] = { "Barbara Jensen", "Babs Jensen", NULL };
/* The object class for a "person" entry is "inetOrgPerson", which is a
subclass of "top", "person", and "organizationalPerson". You should add
all of these classes as values of the objectClass attribute. */
char *objectClass_values[] = { "top", "person", "organizationalPerson",
  "inetOrgPerson", NULL };
...
/* Specify the value and type of each attribute in separate LDAPMod
structures */
attribute1.mod_type = "sn";
attribute1.mod_values = sn_values;
attribute2.mod_type = "cn";
attribute2.mod_values = cn_values;
attribute3.mod_type = "objectClass";
attribute3.mod_values = objectClass_values;
/* Add the pointers to these LDAPMod structures to an array */
list_of_attrs[0] = &attribute1;
list_of_attrs[1] = &attribute2;
list_of_attrs[2] = &attribute3;
list_of_attrs[3] = NULL;
...
/* Set up the timeout period for adding the new entry */
tv.tv_sec = tv.tv_usec = 0;
/* Add the user "Barbara Jensen" */
if ( ( msgid = ldap_add( ld, dn, list_of_attrs ) ) == -1 ) {
  ldap_perror( ld, "ldap_add" );
  return( 1 );
}
/* Check to see if the operation has completed */
while ( ( rc = ldap_result( ld, msgid, 0, &tv, &result ) ) == 0 ) {
  ...
  /* do other work while waiting for the operation to complete */
  ...
}
/* Check the result to see if any errors occurred */
if (( rc = ldap_result2error( ld, result, 1 )) != LDAP_SUCCESS ) {
  printf( "Error while adding entry: %s\n", ldap_err2string( rc ));
}
...
See Also

ldap_add_ext()

ldap_add_ext()

The ldap_add_ext() function adds a new entry to the directory asynchronously.

Note: ldap_add_ext() is a new version of the ldap_add() function. If you are writing a new LDAP client, use ldap_add_ext().

Syntax
#include <ldap.h>
int ldap_add_ext( LDAP *ld, const char *dn, LDAPMod **attrs,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  int *msgidp );
Parameters
ldap_add_ext() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to add. With the exception of the leftmost component, all components of the DN (for example, o=organization or c=country) must already exist.
attrs Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes of the new entry.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
msgidp Pointer to an integer that will be set to the message ID of the LDAP operation.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
Description

The ldap_add_ext() adds a new entry to the directory.

To add a new entry to the directory, you need to specify:

  • A unique DN identifying the new entry.
    Use the dn argument to specify the DN of the new entry. The parents of the entry should already exist. For example, if you are adding the entry uid=bjensen,ou=People,dc=example,dc=com , the entries ou=People and dc=example,dc=com must already exist in the directory.
  • A set of attributes for the new entry.
    Create an LDAPMod structure for each attribute. Set the mod_op field to 0 if the attribute values are string values. To specify values that consist of binary data (such as a sound file or a JPEG file), set the mod_op field to LDAP_MOD_BVALUES. Create an array of these LDAPMod structures and pass the array as the attrs argument. ldap_add_ext() is an asynchronous function; it does not directly return results. In order to get the results of the asynchronous operation, you need to call the ldap_result() and ldap_parse_result() functions. If you want the results to be returned directly by the function, call the synchronous function ldap_add_ext_s(). For a list of possible result codes for an LDAP add operation, see the ldap_add_ext_s() function.
See Also

ldap_add_ext_s(), ldap_result, ldap_parse_result(), LDAPMod

ldap_add_ext_s()

The ldap_add_ext_s() function adds a new entry to the directory synchronously.

#include <ldap.h>
int ldap_add_ext_s( LDAP *ld, const char *dn, LDAPMod **attrs,
  LDAPControl **serverctrls, LDAPControl **clientctrls );
Parameters
ldap_add_ext_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to add. With the exception of the leftmost component, all components of the DN (for example, o=organization or c=country) must already exist.
attrs Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes of the new entry.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

Note: Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.

Description

The ldap_add_ext_s() function adds a new entry to the directory. To add a new entry to the directory, you need to specify:

  • A unique DN identifying the new entry.
    Use the dn argument to specify the DN of the new entry. The parents of the entry should already exist. For example, if you are adding the entry uid=bjensen,ou=People,dc=example,dc=com , the entries ou=People and dc=example,dc=com must already exist in the directory.
  • A set of attributes for the new entry.
    Create an LDAPMod structure for each attribute. Set the mod_op field to 0 if the attribute values are string values. To specify values that consist of binary data (such as a sound file or a JPEG file), set the mod_op field to LDAP_MOD_BVALUES. Create an array of these LDAPMod structures and pass the array as the attrs argument. ldap_add_ext_s() is a synchronous function; it directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_add_ext().
See Also

ldap_add_ext(), LDAPMod

ldap_add_s()

The ldap_add_s() function adds a new entry to the directory synchronously.

#include <ldap.h>
int ldap_add_s( LDAP *ld, const char *dn, LDAPMod **attrs );
Parameters
ldap_add_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to add. With the exception of the leftmost component, all components of the DN (for example, o=organization or c=country) must already exist.
attrs Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes of the new entry.
Returns

See ldap_add_ext_s() for a list of possible return codes.

Description

Please use the newer version of this function, ldap_add_ext_s() .

Example

The following example adds a new entry to the directory.

#include <ldap.h>
...
LDAP *ld;
LDAPMod *list_of_attrs[4];
LDAPMod attribute1, attribute2, attribute3;
/* Distinguished name of the new entry. Note that "dc=example,dc=com" and
"ou=People,dc=example,dc=com" must already exist in the directory. */
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
/* To add a "person" entry, you must specify values for the sn, cn,
and objectClass attributes. (These are required attributes.) */
char *sn_values[] = { "Jensen", NULL };
/* To specify multiple values for an attribute, add the different values
to the array. */
char *cn_values[] = { "Barbara Jensen", "Babs Jensen", NULL };
/* The object class for a "person" entry is "inetOrgPerson", which is a
* subclass of "top", "person", and "organizationalPerson". You should add
* all of these classes as values of the objectClass attribute. */
char *objectClass_values[] = { "top", "person", "organizationalPerson",
  "inetOrgPerson", NULL };
...
/* Specify the value and type of each attribute in separate LDAPMod
structures */
attribute1.mod_type = "sn";
attribute1.mod_values = sn_values;
attribute2.mod_type = "cn";
attribute2.mod_values = cn_values;
attribute3.mod_type = "objectClass";
attribute3.mod_values = objectClass_values;
/* Add the pointers to these LDAPMod structures to an array */
list_of_attrs[0] = &attribute1;
list_of_attrs[1] = &attribute2;
list_of_attrs[2] = &attribute3;
list_of_attrs[3] = NULL;
...
/* Add the user "Barbara Jensen" */
if ( ldap_add_s( ld, dn, list_of_attrs ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_add_s" );
  return( 1 );
}
...
See Also

ldap_add_ext_s()

ldap_ber_free()

The ldap_ber_free() function frees a BerElement structure from memory.

Note: This is an older function that is included in the SDK for backward-compatibility. If you are writing a new LDAP client, use ber_free() instead. Except in name, the two functions are identical.

Syntax
#include <ldap.h>
void ldap_ber_free( BerElement *ber, int freebuf );
Parameters
ldap_ber_free() Function Parameters
Parameter Description
ber Pointer to the BerElement structure that you want to free.
freebuf Specifies whether or not to free the buffer in the BerElement structure.
Description

Please use the newer version of this function, ber_free().

See Also

ber_free()

ldap_bind()

#include <ldap-deprecated.h>
ldap_bind( LDAP *ld, const char *who, const char *passwd, int method );
Parameters
ldap_bind() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
who DN of the user who wants to authenticate. For anonymous authentication, set this or the passwd argument to NULL.
passwd Password of the user who wants to authenticate. For anonymous authentication, set this or the who argument to NULL.
method Defines the authentication method to be used. It should be set to LDAP_AUTH_SIMPLE to select simple authentication.
Returns

ldap_bind() returns the message ID of the request it initiates.

Description

This is an asynchronous function that authenticates a specified entry to the directory. After a connection is made to an LDAP server using ldap_open(), a bind operation must be performed before other operations can be attempted over the connection.

See Also

ldap_open(), ldap_init(), prldap_init() (IPv6), ldap_bind_s()

ldap_bind_s()

Note: This function is deprecated and should not be used. It is included in ldap-deprecated.h for backward-compatibility. Use ldap_simple_bind_s() instead.

ldap_bind_s() can be used when the authentication method needs to be selected at runtime.

Syntax
#include <ldap-deprecated.h>
ldap_bind_s( LDAP *ld, const char *who, const char *cred, int method );
Parameters
ldap_bind_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
who DN of the user who wants to authenticate. For anonymous authentication, set this or the passwd argument to NULL.
cred Password of the user who wants to authenticate. For anonymous authentication, set this or the who argument to NULL.
method Defines the authentication method to be used. It should be set to LDAP_AUTH_SIMPLE to select simple authentication.
Returns

ldap_bind_s() returns an LDAP error indication.

Description

This is a synchronous function that authenticates a specified entry to the directory. After a connection is made to an LDAP server using ldap_open() , a bind operation must be performed before other operations can be attempted over the connection.

See Also

ldap_open(), ldap_init(), prldap_init() (IPv6), ldap_bind()

ldap_build_filter()

See also ldap_create_filter().

ldap_cache_flush()

Note: This function is deprecated and should not be used. It is included in ldap-deprecated.h for backward-compatibility. Use the ldap_memcache_* functions instead.

For more specific information, see the header file ldap-deprecated.h .

See Also

ldap_memcache_init(), ldap_memcache_set(), ldap_memcache_get(), ldap_memcache_update(), ldap_memcache_flush() , ldap_memcache_destroy()

ldap_charray_add()

Note: This function is deprecated and should not be used. It is included in ldap-to-be-deprecated.h for backward-compatibility.

For more specific information, see the header file ldap-to-be-deprecated.h.

ldap_charray_free()

Note: This function is deprecated and should not be used. It is included in ldap-to-be-deprecated.h for backward-compatibility.

For more specific information, see the header file ldap-to-be-deprecated.h.

ldap_charray_merge()

Note: This function is deprecated and should not be used. It is included in ldap-to-be-deprecated.h for backward-compatibility.

For more specific information, see the header file ldap-to-be-deprecated.h.

ldap_compare()

The ldap_compare() function asynchronously determines if an attribute of an entry contains a specified value.

#include <ldap.h>
int ldap_compare( LDAP *ld, const char *dn, const char *attr,
  const char *value );
Parameters
ldap_compare() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry used in the comparison.
attr Attribute type that you want to check the value against.
value Value that you want to compare against the attribute values.
Returns

Returns the message ID of the ldap_compare() operation.

Note: To check the result of this operation, call ldap_result() and ldap_result2error(). See ldap_compare_ext_s() function for a list of possible result codes for the LDAP compare operation.

Description

Please use the newer version of this function, ldap_compare_ext() .

Example

the following example checks to see if Barbara Jensen has the email address bjensen@example.com.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
int msgid;
...
msg_id = ldap_compare( ld, dn, "mail", "bjensen@example.com" );
...
See Also

ldap_compare_ext()

ldap_compare_ext()

The ldap_compare_ext() function asynchronously determines if an attribute of an entry contains a specified value.

#include <ldap.h>
int ldap_compare_ext( LDAP *ld, const char *dn, const char *attr,
  struct berval *bvalue, LDAPControl **serverctrls,
  LDAPControl **clientctrls, int *msgidp );
Parameters
ldap_compare_ext() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry used in the comparison.
attr Attribute type that you want to check the value against.
value Value that you want to compare against the attribute values.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
msgidp Pointer to an integer that will be set to the message ID of the LDAP operation.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

Note: To check the result of this operation, call ldap_result() and ldap_parse_result().

Returns

For a list of the possible result codes for an LDAP compare operation, see ldap_compare_ext_s().

Description

The ldap_compare_ext() function compares the value of an attribute in an entry against a specified value. Because ldap_compare_ext() is an asynchronous function, it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_compare_ext_s().

See Also

ldap_compare_ext_s(), ldap_result(), ldap_parse_result()

ldap_compare_ext_s()

The ldap_compare_ext_s() function synchronously determines if an attribute of an entry contains a specified value.

Syntax
#include <ldap.h>
int ldap_compare_ext_s( LDAP *ld, const char *dn,
  const char *attr, struct berval *bvalue,
  LDAPControl **serverctrls, LDAPControl **clientctrls );
Parameters
ldap_compare_ext_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry used in the comparison.
attr Attribute type that you want to check the value against.
value Value that you want to compare against the attribute values.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
Returns

One of the following values:

  • LDAP_COMPARE_TRUE if the entry contains the attribute value.
  • LDAP_COMPARE_FALSE if the entry does not contain the attribute value.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

The ldap_compare_ext_s() function compares the value of an attribute in an entry against a specified value. ldap_compare_ext_s() is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_compare_ext().

See Also

ldap_compare_ext()

ldap_compare_s()

The ldap_compare_s() function synchronously determines if an attribute of an entry contains a specified value.

Note: This is an older function that is included in the SDK for backward-compatibility. If you are writing a new LDAP client, use ldap_compare_ext_s() instead.

Syntax
#include <ldap.h>
int ldap_compare_s( LDAP *ld, const char *dn,
  const char *attr, const char *value );
Parameters
ldap_compare_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry used in the comparison.
attr Attribute type that you want to check the value against.
value Value that you want to compare against the attribute values.
Returns

For a list of the possible result codes for an LDAP compare operation, see ldap_compare_ext_s().

Description

Please use the newer version of this function, ldap_compare_ext_s() .

Example

The following example checks to see if Barbara Jensen has the email address bjensen@example.com.

#include <stdio.h>
#include <ldap.h>
LDAP *ld;
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
int has_value;
...
has_value = ldap_compare_s( ld, dn, "mail", "bjensen@example.com" );
switch ( has_value ) {
  case LDAP_COMPARE_TRUE:
    printf( "The mail attribute contains bjensen@example.com.\n");
    break;
  case LDAP_COMPARE_FALSE:
    printf( "The mail attribute does not contain bjensen@example.com.\n");
    break;
  default:
    ldap_perror( ld, "ldap_compare_s" );
    return( 1 );
}
...
See Also

ldap_compare_ext_s()

ldap_control_free()

The ldap_control_free() function frees an LDAPControl structure from memory.

Syntax
#include <ldap.h>
void ldap_control_free( LDAPControl *ctrl );
Parameters
ldap_control_free() Function Parameter
Parameter Description
ctrl Pointer to an LDAPControl structure that you want to free from memory.
Description

The ldap_control_free() function frees an LDAPControl structure from memory. You should call this function to free controls that you create; for example, if you call the ldap_create_sort_control() function.

See Also

ldap_controls_free()

ldap_controls_free()

The ldap_controls_free() function frees an array of LDAPControl structures from memory.

Syntax
#include <ldap.h>
void ldap_controls_free( LDAPControl **ctrls );
Parameters
ldap_controls_free() Function Parameter
Parameter Description
ctrls Pointer to an array of LDAPControl structures that you want to free from memory.
Description

The ldap_controls_free() function frees an array of LDAPControl structures from memory. You should call this function to free arrays of controls that you create or any arrays returned by ldap_parse_result().

See Also

ldap_control_free(), ldap_parse_result()

ldap_count_entries()

The ldap_count_entries() function returns the number of LDAPMessage structures representing directory entries in a chain of search results.

Syntax
#include <ldap.h>
int ldap_count_entries( LDAP *ld, LDAPMessage *result );
Parameters
ldap_count_entries() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
result Chain of search results, represented by pointer to an LDAPMessage structure.
Returns

One of the following values:

  • If successful, the number of LDAPMessage() structures of the type LDAP_RES_SEARCH_ENTRY in a chain of search results. If there are no structures of this type, returns 0.
  • -1 if ld is not a valid connection handle.
Description

The ldap_count_entries() function returns the number of LDAPMessage structures representing directory entries in a chain of search results. These messages have the type LDAP_RES_SEARCH_ENTRY .

See the examples under ldap_search_ext() and ldap_search_ext_s().

See Also

ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_first_entry(), ldap_next_entry(), ldap_first_entry(), ldap_next_message()

ldap_count_messages()

The ldap_count_messages() function returns the number of LDAPMessage structures in a chain of search results.

Syntax
#include <ldap.h>
int ldap_count_messages( LDAP *ld, LDAPMessage *res );
Parameters
ldap_count_messages() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
result Chain of search results, represented by pointer to an LDAPMessage structure.
Returns

One of the following values:

  • The number of LDAPMessage structures in a chain of search results, if successful. If there are no structures, returns 0.
  • -1 if ld is not a valid connection handle.
Description

The ldap_count_messages() function returns the number of LDAPMessage structures in a chain of search results. The count is the number of search entries plus the number of search references.

Note: If you pass in a pointer to an LDAPMessage structure in the middle of the chain of results, the function counts only between that structure and the last structure in the chain. In this type of situation, the function does not return the count of all structures in the chain.

Example

See the examples under ldap_search_ext() and ldap_search_ext_s().

See Also

ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_first_message(), ldap_next_message(), ldap_first_entry(), ldap_next_entry() , ldap_first_reference(), ldap_next_reference()

ldap_count_references()

The ldap_count_references() function returns the number of LDAPMessage structures representing search references in a chain of search results.

Syntax
#include <ldap.h>
int ldap_count_references( LDAP *ld, LDAPMessage *res );
Parameters
ldap_count_references() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
result Chain of search results, represented by pointer to an LDAPMessage structure.
Returns

One of the following values:

  • The number of LDAPMessage structures of the type LDAP_RES_SEARCH_REFERENCE in a chain of search results, if successful. (If there are no structures of this type, returns 0.)
  • -1 if ld is not a valid connection handle.
Description

The ldap_count_references() function returns the number of LDAPMessage structures representing search references in a chain of search results. These messages have the type LDAP_RES_SEARCH_REFERENCE, continuation references as specified in LDAPv3 that are stored as referral entries. Like a referral, each continuation reference itself may contain a number of URLs assumed to be equivalent, and the client should use one of those URLs.

See the examples under ldap_search_ext() and ldap_search_ext_s().

See Also

ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_first_reference(), ldap_next_reference()

ldap_count_values()

The ldap_count_values() function returns the number of values in an array of strings. Note: Use the ldap_count_values_len() function if the array contains berval structures.

Syntax
#include <ldap.h>
int ldap_count_values( char **values );
Parameters
ldap_count_values() Function Parameter
Parameter Description
values Array of values.
Returns

One of the following values:

  • The number of values in the array, if successful.
  • -1 if unsuccessful.
Example

The following example counts the number of values assigned to an attribute.

#include <ldap.h>
...
LDAP *ld;
LDAPMessage *e;
char *a="cn";
char **vals;
int count;
...
/* Get the values of the cn attribute */
vals = ldap_get_values( ld, e, a );
/* Count the values of the attribute */
count = ldap_count_values( vals );
...
See Also

ldap_count_values_len(), ldap_get_values()

ldap_count_values_len()

The ldap_count_values_len() function returns the number of values in an array of berval structures.

#include <ldap.h>
int ldap_count_values_len( struct berval **vals );
Parameters
ldap_count_values_len() Function Parameter
Parameter Description
values Array of berval structures.
Returns

One of the following values:

  • The number of values in the array, if successful.
  • -1 if unsuccessful.
Example

The following example counts the number of values assigned to an attribute.

#include <ldap.h>
LDAP *ld;
LDAPMessage *e;
char *a="jpegPhoto";
struct berval **bvals;
int count;
...
/* Get the values of the jpegPhoto attribute */
bvals = ldap_get_values_len( ld, e, a );
/* Count the values of the attribute */
count = ldap_count_values_len( vals );
...
See Also

ldap_count_values(), ldap_get_values_len()

ldap_create_authzid_control()

The ldap_create_authzid_control() function creates a control that requests the authorization ID for a bind operation. This is defined in RFC 3829.

Note: In order for the control to work, the LDAP server that you are connecting to must support the server controls for authorization bind identity (OID 2.16.840.1.113730.3.4.16 or LDAP_CONTROL_AUTHZID_REQ, and OID 2.16.840.1.113730.3.4.15 or LDAP_CONTROL_AUTHZID_RES).

Calling ldap_create_authzid_control() creates an LDAP control that you can pass to the ldap_simple_bind() function to retrieve the authorization ID in the response. You call ldap_parse_authzid_control() function on the controls returned with an entry to retrieve a char * containing the authorization ID. When you are done with the search, you should free the control by calling the ldap_control_free() function.

Syntax
#include <ldap.h>
LDAP_API(int) LDAP_CALL ldap_create_authzid_control( LDAP *ld,
  const char ctl_iscritical, LDAPControl **ctrlp );
Parameters
ldap_create_authzid_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
ctl_iscritical Specifies whether the control is critical to the operation.
  • If non-zero, the control is critical to the operation. If the server does not support it, the server returns an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error.
  • If 0, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
ctrlp Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
See Also

ldap_parse_authzid_control()

ldap_create_filter()

The ldap_create_filter() routine constructs an LDAP search filter.

Syntax
#include <ldap.h>
int ldap_create_filter( char *buf, unsigned long buflen,
  char *pattern, char *prefix, char *suffix, char *attr,
  char *value, char **valwords );
Parameters
ldap_create_filter() Function Parameters
Parameter Description
buf Buffer to contain the constructed filter.
buflen Size of the buffer.
pattern Pattern for the filter.
prefix Prefix to prepend to the filter. (NULL if not used.)
suffix Suffix to append to the filter. (NULL if not used.)
attr Replaces %a in the pattern.
value Replaces %v in the pattern.
valwords Replaces %vM through %vN in the pattern.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_SIZELIMIT_EXCEEDED if the created filter exceeds the size of the buffer.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
Example

The following example builds the filter (mail=bjensen@example.com).

char buf[LDAP_FILT_MAXSIZ];
char *pattern = "(%a=%v)";
char *attr = "mail";
char *value = "bjensen@example.com";
...
ldap_create_filter( buf, LDAP_FILT_MAXSIZ, pattern, NULL,
  NULL, attr, value, NULL );
...
See Also

ldap_init_getfilter(), ldap_init_getfilter_buf(), ldap_getfirstfilter() , ldap_getnextfilter(), ldap_set_filter_additions()

ldap_create_geteffectiveRights_control()

The ldap_create_geteffectiveRights_control() function allows a user having correct privileges to query about the access rights another identity has on one or more entries in the directory.

Syntax
#include <ldap.h>
LDAP_API(int) LDAP_CALL ldap_create_geteffectiveRights_control( LDAP *ld,
  const char *authzid, const char **attrlist, const char ctl_iscritical,
  LDAPControl **ctrlp );
Parameters
ldap_create_geteffectiveRights_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
authzid The DN of the identity for which you are checking access rights.
attrlist List of attributes to return, such as aclRights and aclRightsInfo.
ctl_iscritical Specifies whether the control is critical to the operation. *If non-zero, the control is critical to the operation. If the server does not support it, the server will return an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error. *If 0, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
ctrlp Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().

ldap_create_persistentsearch_control()

The ldap_create_persistentsearch_control() function creates a control that allows your client to perform a search of an LDAP v3 server that continues without termination until your client abandons it.

#include <ldap.h>
int ldap_create_persistentsearch_control( LDAP *ld,
  int changetypes, int changesonly, int return_echg_ctls,
  char ctl_iscritical, LDAPControl **ctrlp );
Parameters
ldap_create_persistentsearch_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
changetypes Specifies the types of changes that you want to keep track of. This field can have one or more of the following values:
  • LDAP_CHANGETYPE_ADD specifies that you want to keep track of entries added to the directory.
  • LDAP_CHANGETYPE_DELETE specifies that you want to keep track of entries deleted from the directory.
  • LDAP_CHANGETYPE_MODIFY specifies that you want to keep track of entries that are modified.
  • LDAP_CHANGETYPE_MODDN specifies that you want to keep track of entries that are renamed.
  • LDAP_CHANGETYPE_ANY specifies that you want to keep track of all of the above changes to the directory. You can OR the values together to specify multiple types.
changesonly Specifies whether or not you want skip the initial search and only get the latest changes as they occur:
  • If non-zero, the initial search is skipped and only entries that have changed after the initial search are returned.
  • If 0, the results of the initial search are returned first.
return_echg_ctls Specifies whether or not entry controls are included with each entry returned to your client:
  • If non-zero, a control is included with each entry.
  • If 0, controls are not included with the entries returned from the server.
ctl_iscritical Specifies whether the control is critical to the operation.
  • If non-zero, the control is critical to the operation. If the server does not support it, the server will return an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error.
  • If 0, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
ctrlp Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred

when BER-encoding the control.

Description

The ldap_create_persistentsearch_control() function allows you to perform persistent searches. A persistent search provides the means to track changes to a set of entries that match the search criteria. After the initial search is performed, the server keeps track of the search criteria and sends back information when any entry that matches the criteria is added, deleted, modified, or renamed. Calling ldap_create_persistentsearch_control() creates an LDAP server control that you can pass to the ldap_search_ext() function.

As stated, after you create the control, you can pass it to the LDAP server during a search operation. If you specify that you want “entry change notification” controls sent back (that is, if you specify a non-zero value for the return_echg_ctls parameter), the server includes controls with each changed entry it sends back. To retrieve the controls from each entry, call the ldap_get_entry_controls() function. To get data about the changes made to the entry from the control, call the ldap_parse_entrychange_control() function. When you are done with the search, you can cancel the persistent search by calling the ldap_abandon_ext() function. You should also free the control from memory by calling the ldap_control_free() function.

See Also

ldap_search_ext(), ldap_abandon_ext, ldap_get_entry_controls(), ldap_parse_entrychange_control(), ldap_control_free()

ldap_create_pwdpolicy_control()

The ldap_create_pwdpolicy_control() function creates a control that requests information about the status of a user account.

Note: ldap_create_pwdpolicy_control() implements an extension to the LDAP v3 supported by Directory Server. In order for the control to work, the LDAP server that you are connecting to must support the server control for password policy (OID 1.3.6.1.4.1.42.2.27.8.5.1, or LDAP_CONTROL_ACCOUNT_USABLE).

Calling ldap_create_pwdpolicy_control() creates an LDAP control that you can pass to the ldap_simple_bind() functions to retrieve password policy information from bind, modify, add, compare, and potentially extended operation responses including password policy response controls. You call ldap_parse_pwdpolicy_control() function on the controls returned with an entry to retrieve a LDAPpwdpolicy structure containing information about the status of the account. When you are done with the search, you should free the control by calling the ldap_control_free() function.

Syntax
#include <ldap.h>
LDAP_API(int) LDAP_CALL ldap_create_pwdpolicy_control( LDAP *ld,
  const char ctl_iscritical, LDAPControl **ctrlp );
Parameters
ldap_create_pwdpolicy_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
ctl_iscritical Specifies whether the control is critical to the operation.
  • If non-zero, the control is critical to the operation. If the server does not support it, the server returns an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error.
  • If 0, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
ctrlp Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
See Also

ldap_parse_pwdpolicy_control(), LDAPpwdpolicy()

ldap_create_proxiedauth_control()

The ldap_create_proxiedauth_control() function creates an LDAP v3 control that allows a bound entity to assume the identity of another directory entry.

#include <ldap.h>
int ldap_create_proxiedauth_control( LDAP *ld, char *authzid,
  LDAPControl **ctrlp);
Parameters
ldap_create_proxiedauth_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
authzid The string representing the identity to assume for the access rights, defined in the format specified by the following Augmented Backus-Naur Form (ABNF) from RFC 4513: ; Specific predefined authorization (authz) ; id schemes are defined below -- ; new schemes may be defined in the future. authzId = dnAuthzId / uAuthzId ; distinguished-name-based authz id. dnAuthzId = "dn:" dn dn = utf8string ; syntax from RFC 4514 ; unspecified userid, UTF-8 encoded. uAuthzId = "u:" userid userid = utf8string ; syntax unspecified
ctrlp Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
Description

More information on proxy authorization can be found in the LDAP Proxied Authorization Control Internet Draft(http://ietfreport.isoc.org/ids/draft-weltman-ldapv3-proxy-12.txt).

Note: Proxy authorization is an optional feature; it may not be supported on all LDAP servers. In order for the control to work, the server that you are connecting to must support the server control for proxy authorization (OID 2.16.840.1.113730.3.4.18, or LDAP_CONTROL_PROXIEDAUTH, as defined in the ldap-extension.h header file).

ldap_create_proxyauth_control()

The ldap_create_proxyauth_control() function creates an LDAP v3 control that allows a bound entity to assume the identity of another directory entry.

#include <ldap.h>
int ldap_create_proxyauth_control( LDAP *ld, char *DN,
  char ctl_iscritical, LDAPControl **ctrlp);
Parameters
ldap_create_proxyauth_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
DN String representing the DN of the entry who's identity the client will be assuming.
ctl_iscritical Specifies whether the control is critical to the operation.
  • If non-zero, the control is critical to the operation. If the server does not support it, the server will return an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error.
  • If 0, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
ctrlp Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
  • LDAP_UNAVAILABLE_CRITICAL_EXTENSION if the server does not support proxy authorization and ctl_iscritical is set to a non-zero value.
See Also

ldap_control_free()

ldap_create_sort_control()

The ldap_create_sort_control() function creates a control that specifies the order in which you want search results returned.

Note: This function implements an extension to the LDAP v3. Server-side sorting is an optional feature; it may not be supported on all LDAP servers. Call this function when interacting with LDAP servers that support this LDAP v3 extension.

Syntax
#include <ldap.h>
int ldap_create_sort_control( LDAP *ld,
  LDAPsortkey **sortKeyList, const char ctl_iscritical,
  LDAPControl **ctrlp );
Parameters
ldap_create_sort_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
sortKeyList Pointer to an array of LDAPsortkey structures that specify the attribute types or matching rules used for sorting and the order (ascending or descending) in which to sort the results.
ctl_iscritical Specifies whether the control is critical to the operation. *If non-zero, the control is critical to the operation. If the server does not support it, the server will return an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error. *If 0, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
ctrlp Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
Description

The ldap_create_sort_control() function allows you to specify the order in which you want to receive data from the server. Calling this function creates an LDAP control that you can pass to the ldap_search_ext() and ldap_search_ext_s() functions.

See also ldap_create_sort_keylist(), ldap_search_ext(), ldap_search_ext_s(), ldap_control_free().

ldap_create_sort_keylist()

The ldap_create_sort_keylist() function creates an array of LDAPsortkey structures from a string representation of a set of sort keys.

Syntax
#include <ldap.h>
int ldap_create_sort_keylist(LDAPsortkey ***sortKeyList,
  const char *string_rep);
Parameters
ldap_create_sort_keylist() Function Parameters
Parameter Description
sortKeyList Pointer to an array of LDAPsortkey structures that specify the attribute types or matching rules used for sorting and the order (ascending or descending) in which to sort the results.
string_rep String representation of a set of sort keys. The value should specify the name of the attribute that you want to sort by. To sort in reverse order, precede the attribute name with a hyphen, -. To use a matching rule for sorting, append a colon to the attribute name and specify the object identifier (OID) of a matching rule after the colon. For example:
  • cn (sorts by the cn attribute)
  • -cn (sorts by the cn attribute in reverse order)
  • -cn:1.2.3.4 (sorts by the cn attribute in reverse order using the matching rule identified by the OID 1.2.3.4)
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • -1 if an error occurred.
Description

Calling the ldap_create_sort_keylist() function allows you to create an array of LDAPsortkey structures from a string representation of a set of sort keys. You can then pass the array to the ldap_create_sort_control() function. The string representation specified by the string_rep argument should specify the name of the attribute that you want to sort by and how the sort will work. When you are done sorting the results, you should free the array of LDAPsortkey() structures by calling the ldap_free_sort_keylist() function.

See Also

ldap_create_sort_control(), ldap_free_sort_keylist()

ldap_create_userstatus_control()

The ldap_create_userstatus_control() function creates a control that requests information about the status of a user account.

Note: ldap_create_userstatus_control() implements an extension to the LDAP v3 supported by Directory Server. In order for the control to work, the LDAP server that you are connecting to must support the server control for account availability (OID 1.3.6.1.4.1.42.2.27.9.5.8, or LDAP_CONTROL_ACCOUNT_USABLE).

Calling ldap_create_userstatus_control() creates an LDAP control that you can pass to the ldap_search_ext() and ldap_search_ext_s() functions. You call ldap_parse_userstatus_control() function on the controls returned with an entry to retrieve a LDAPuserstatus structure containing information about the status of the account. When you are done with the search, you should free the control by calling the ldap_control_free() function.

Syntax
#include <ldap.h>
LDAP_API(int) LDAP_CALL ldap_create_userstatus_control( LDAP *ld,
  const char ctl_iscritical, LDAPControl **ctrlp );
Parameters
ldap_create_userstatus_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
ctl_iscritical Specifies whether the control is critical to the operation.
  • If non-zero, the control is critical to the operation. If the server does not support it, the server returns an LDAP_UNAVAILABLE_CRITICAL_EXTENSION error.
  • If 0, the control is not critical to the operation. Even if the server does not support the control, the operation is still attempted and the control is ignored.
ctrlp Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
See Also

ldap_parse_userstatus_control(), LDAPuserstatus()

ldap_create_virtuallist_control()

The ldap_create_virtuallist_control() function creates a control that requests a subset of search results for use in a virtual list box.

#include <ldap.h>
int ldap_create_virtuallist_control( LDAP *ld,
  LDAPVirtualList *ldvlistp, LDAPControl **ctrlp );
Parameters
ldap_create_virtuallist_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
ldvlistp Pointer to an LDAPVirtualList structure that specifies the subset of entries that you want retrieved from the server and the selected entry.
ctrlp Pointer to an LDAPControl structure created by this function. When you are done using this control, you should free it by calling ldap_control_free().
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
Description

The ldap_create_virtuallist_control() function allows you to retrieve a subset of entries from the server for use in a virtual list box. To specify the subset of entries that you want to retrieve, create an LDAPVirtualList structure and pass in a pointer to this structure as the ldvlistp argument.

Note: In order for the control to work, the LDAP server that you are connecting to must support the server control for sorting search results (OID 2.16.840.1.113730.3.4.9, or LDAP_CONTROL_VLVREQUEST, as defined in the ldap.h header file).

Calling ldap_create_virtuallist_control() creates an LDAP control that you can pass to the ldap_search_ext() and ldap_search_ext_s() functions. You also need to pass a server-side sorting control to the search functions. You can call ldap_create_sort_keylist() and ldap_create_sort_control() to create a server-side sorting control. When you are done with the search, you should free the control by calling the ldap_control_free() function.

See Also

LDAPVirtualList, ldap_parse_virtuallist_control(), ldap_search_ext() , ldap_search_ext_s(), ldap_control_free()

ldap_delete()

The ldap_delete() function removes an entry from the directory asynchronously.

#include <ldap.h>
int ldap_delete( LDAP *ld, const char *dn );
Parameters
ldap_delete() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to remove.
Returns

Returns the message ID of the ldap_delete() operation.

Note: To check the result of this operation, call ldap_result and ldap_result2error(). See ldap_delete_ext_s() for a list of possible result codes for the LDAP delete operation.

Description

Please use the newer version of this function, ldap_delete_ext() .

Example

The following example uses the asynchronous ldap_delete() function to remove the entry for Barbara Jensen from the directory.

#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result;
int msgid, rc;
struct timeval tv;
/* Distinguished name of the entry that you want to delete. */
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
...
/* Set up the timeout period to wait for the "modify" operation */
tv.tv_sec = tv.tv_usec = 0;
/* Delete the entry */
if ( ( msgid = ldap_delete( ld, dn ) ) == -1 ) {
  ldap_perror( ld, "ldap_delete" );
  return( 1 );
}
/* Check to see if the operation has completed */
while ( ( rc = ldap_result( ld, msgid, 0, &tv, &result ) ) == 0 ) {
  ...
  /* do other work while waiting for the operation to complete */
  ...
}
/* Check the result to see if any errors occurred */
ldap_result2error( ld, result, 1 );
ldap_perror( ld, "ldap_delete" );
...
See Also

ldap_delete_ext()

ldap_delete_ext()

The ldap_delete_ext() function deletes an entry from the directory asynchronously.

#include <ldap.h>
int ldap_delete_ext( LDAP *ld, const char *dn,
  LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp );
Parameters
ldap_delete_ext() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to remove.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
msgidp Pointer to an integer that will be set to the message ID of the LDAP operation.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

Note: To check the result of this operation, call ldap_result and ldap_result2error(). See ldap_delete_ext_s() for a list of possible result codes for the LDAP delete operation.

Description

The ldap_delete_ext() function deletes an entry from the directory, using the dn argument to specify the entry that you want to delete. ldap_delete_ext() is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_delete_ext_s() .

See Also

ldap_delete_ext_s(), ldap_result(), ldap_parse_result()

ldap_delete_ext_s()

The ldap_delete_ext_s() function deletes an entry from the directory synchronously.

#include <ldap.h>
int ldap_delete_ext_s( LDAP *ld, const char *dn,
  LDAPControl **serverctrls, LDAPControl **clientctrls );
Parameters
ldap_delete_ext_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to remove.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
Returns

One of the following values:

Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
  • LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.

Note: Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.

Description

The ldap_delete_ext_s() function deletes an entry from the directory, using the dn argument to specify the entry that you want to delete. ldap_delete_ext_s() is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_delete_ext() instead.

See Also

ldap_delete_ext()

ldap_delete_s()

The ldap_delete_s() deletes an entry from the directory synchronously.

#include <ldap.h>
int ldap_delete_s(LDAP *ld, const char *dn);
Parameters
ldap_delete_s() Function Parameters
Parameters Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to remove.
Returns

For a list of possible result codes for an LDAP delete operation, see the ldap_delete_ext_s() function.

Description

Please use the newer version of this function, ldap_delete_ext_s() .

Example

The following example uses the synchronous ldap_delete_s() function to delete the entry for Barbara Jensen from the directory.

#include <ldap.h>
LDAP *ld;
/* Distinguished name of the entry that you want to delete. */
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
...
/* Delete the entry */
if ( ldap_delete_s( ld, dn ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_delete_s" );
  return( 1 );
}
...
See Also

ldap_delete_ext_s()

ldap_dn2ufn()

The ldap_dn2ufn() function converts a DN into a more user-friendly form by stripping off the cryptic type names.

Syntax
#include <ldap.h>
char * ldap_dn2ufn( const char *dn );
Parameters
ldap_dn2ufn() Function Parameter
Parameter Description
dn The DN that you want converted.
Returns

One of the following values:

  • If successful, returns the DN in its friendlier form.
  • If unsuccessful, returns NULL.
Description

For more information on user friendly naming (UFN), see RFC 1781,<citetitle> Using the OSI Directory to Achieve User Friendly Naming </citetitle> (<ulink url="http://www.faqs.org/rfcs/rfc1781.html" type="text_url"></ulink>).

ldap_entry2html()

The ldap_entry2html() function writes the HTML representation of an LDAP entry.

Syntax
#include <disptmpl.h>
int ldap_entry2html( LDAP *ld, char *buf, LDAPMessage *entry,
  struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals,
  writeptype writeproc, void *writeparm, char *eol, int rdncount,
  unsigned long opts, char *urlprefix, char *base );
Parameters
ldap_entry2html() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
buf A pointer to a buffer of size LDAP_DTMPL_BUFSIZ or larger. If NULL, a buffer is allocated and freed internally.
entry Specifies the attribute values to be represented.
tmpl Pointer to the display template to be used, usually obtained by calling ldap_oc2template().
defattrs A NULL terminated array of LDAP attribute names for which you wish to provide default values. It is only used if the entry contains no values for the attribute.
defvals An array of NULL terminated arrays of default values corresponding to the attributes.
writeproc Your writeproc() function should be declared as: int writeproc( writeparm, p, len ) void *writeparm; char *p; int len; where p is a pointer to text to be written and len is the length of the text. p is guaranteed to be zero terminated.
writeparm A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
eol Lines of text are terminated with this string.
rdncount Limits the number of components that are displayed for DN attributes.
opts Specifies output options. The allowed values are:
  • zero (default output)
  • LDAP_DISP_OPT_AUTOLABELWIDTH which causes the width for labels to be determined based on the longest label in tmpl.
  • LDAP_DISP_OPT_HTMLBODYONLY which instructs the library not to include <HTML>, <HEAD>, <TITLE>, and <BODY> tags. In other words, an HTML fragment is generated, and the caller is responsible for prepending and appending the appropriate HTML tags to construct a correct HTML document.
urlprefix Starting text to use when constructing an LDAP URL. The default is the string ldap://.
base The base with which to begin when executing search actions. If NULL , search action template items are ignored.
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP error code on error.
Description

ldap_entry2html() produces an HTML representation of an entry. It behaves exactly like ldap_entry2text() except for the output and the addition of two parameters.

See Also

ldap_entry2text(), ldap_oc2template

ldap_entry2html_search()

The ldap_entry2html_search() function determines the appropriate display template to use by calling ldap_oc2template().

Syntax
#include <disptmpl.h>
int ldap_entry2html_search( LDAP *ld, char *dn, char *base,
  LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs,
  char ***defvals, writeptype writeproc, void *writeparm, char *eol,
  int rdncount, unsigned long opts, char *urlprefix );
Parameters
ldap_entry2html_search() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to write as HTML.
base The base with which to begin when executing search actions. If NULL , search action template items are ignored.
entry Specifies the attribute values to be represented.
tmpllist Pointer to the entire list of templates available, usually obtained by calling ldap_init_templates() or ldap_init_templates_buf(). If NULL, will attempt to read a load templates from the default template configuration file.
defattrs A NULL terminated array of LDAP attribute names for which you wish to provide default values. It is only used if the entry contains no values for the attribute.
defvals An array of NULL terminated arrays of default values corresponding to the attributes.
writeproc writeproc() function should be declared as: int writeproc( writeparm, p, len ) void *writeparm; char *p; int len; where p is a pointer to text to be written and len is the length of the text. p is guaranteed to be zero terminated.
writeparm A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
eol Lines of text are terminated with this string.
rdncount Limits the number of components that are displayed for DN attributes.
opts Specifies output options. The allowed values are:
  • zero (default output)
  • LDAP_DISP_OPT_AUTOLABELWIDTH which causes the width for labels to be determined based on the longest label in tmpl.
  • LDAP_DISP_OPT_HTMLBODYONLY which instructs the library not to include <HTML>, <HEAD>, <TITLE>, and <BODY> tags. In other words, an HTML fragment is generated, and the caller is responsible for prepending and appending the appropriate HTML tags to construct a correct HTML document.
urlprefix Starting text to use when constructing an LDAP URL. The default is the string ldap://
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP error code on error.
Description

ldap_entry2html_search() will call ldap_search_s() to retrieve any attribute values to be displayed. It behaves exactly like ldap_entry2text_search(), except the urlprefix parameter is required and HTML is the output.

See Also

ldap_search_s(), ldap_entry2text_search(), ldap_init_templates(), ldap_init_templates_buf(), ldap_entry2text()

ldap_entry2text()

The ldap_entry2text() function writes the text representation of an LDAP entry.

Syntax
#include <disptmpl.h>
int ldap_entry2text( LDAP *ld, char *buf, LDAPMessage *entry,
  struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals,
  writeptype writeproc, void *writeparm, char *eol, int rdncount,
  unsigned long opts );
Parameters
ldap_entry2text() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
buf A pointer to a buffer of size LDAP_DTMPL_BUFSIZ or larger. If NULL, a buffer is allocated and freed internally.
entry Specifies the attribute values to be represented.
tmpl Pointer to the display template to be used, usually obtained by calling ldap_oc2template().
defattrs A NULL terminated array of LDAP attribute names for which you wish to provide default values. It is only used if the entry contains no values for the attribute.
defvals An array of NULL terminated arrays of default values corresponding to the attributes.
writeproc writeproc() function should be declared as: int writeproc( writeparm, p, len ) void *writeparm; char *p; int len; where p is a pointer to text to be written and len is the length of the text. p is guaranteed to be zero terminated.
writeparm A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
eol Lines of text are terminated with this string.
rdncount Limits the number of components that are displayed for DN attributes.
opts Specifies output options. The allowed values are:
  • zero (default output)
  • LDAP_DISP_OPT_AUTOLABELWIDTH which causes the width for labels to be determined based on the longest label in tmpl.
  • LDAP_DISP_OPT_HTMLBODYONLY which instructs the library not to include <HTML>, <HEAD>, <TITLE>, and <BODY> tags. In other words, an HTML fragment is generated, and the caller is responsible for prepending and appending the appropriate HTML tags to construct a correct HTML document.
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP error code on error.
Description

ldap_entry2text() produces a text representation of an entry and writes the text by calling the writeproc function. All of the attribute values to be displayed must be present in entry as no interaction with the LDAP server will be performed.

See Also

ldap_entry2html(), ldap_oc2template

ldap_entry2text_search()

The ldap_entry2text_search() function determines the appropriate display template to use by calling ldap_oc2template().

Syntax
#include <disptmpl.h>
int ldap_entry2text_search( LDAP *ld, char *dn, char *base,
  LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs,
  char ***defvals, writeptype writeproc, void *writeparm,
  char *eol, int rdncount, unsigned long opts );
Parameters
ldap_entry2text_search() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to write.
base If NULL, the search action template items are ignored. If not NULL, it is the search base to use when executing search actions.
entry If entry is not NULL, it should contain the objectClass attribute values for the entry to be displayed. If NULL, dn can not be NULL, and ldap_entry2text_search() will retrieve the objectClass values itself by calling ldap_search_s().
tmpllist Pointer to the entire list of templates available, usually obtained by calling ldap_init_templates() or ldap_init_templates_buf(). If NULL, will attempt to read a load templates from the default template configuration file.
defattrs A NULL terminated array of LDAP attribute names for which you wish to provide default values. It is only used if the entry contains no values for the attribute.
defvals An array of NULL terminated arrays of default values corresponding to the attributes.
writeproc writeproc() function should be declared as: int writeproc( writeparm, p, len ) void *writeparm; char *p; int len; where p is a pointer to text to be written and len is the length of the text. p is guaranteed to be zero terminated.
writeparm A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
eol Lines of text are terminated with this string.
rdncount Limits the number of components that are displayed for DN attributes.
opts Specifies output options. The allowed values are:
  • zero (default output)
  • LDAP_DISP_OPT_AUTOLABELWIDTH which causes the width for labels to be determined based on the longest label in tmpl.
  • LDAP_DISP_OPT_HTMLBODYONLY which instructs the library not to include <HTML>, <HEAD>, <TITLE>, and <BODY> tags. In other words, an HTML fragment is generated, and the caller is responsible for prepending and appending the appropriate HTML tags to construct a correct HTML document.
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP error code on error.
Description

ldap_entry2text_search() will call ldap_search_s() to retrieve any attribute values to be displayed.

See Also

ldap_entry2html_search(), ldap_oc2template(), ldap_search_s(), ldap_init_templates(), ldap_init_templates_buf()

ldap_err2string()

The ldap_err2string() function returns the corresponding error message for an error code.

Syntax
#include <ldap.h>
char * ldap_err2string( int err );
Parameters
ldap_err2string() Function Parameter
Parameter Description
err Error code that you want interpreted into an error message.
Returns

One of the following values:

  • If successful, returns the corresponding error message for the error code.
  • If unsuccessful (for example, if the error code is not a valid LDAP API error code), returns Unknown error.
Example

The following example sets the variable err_msg to the error message corresponding to the error code returned by the ldap_simple_bind_s() function.

#include <ldap.h>
...
LDAP *ld;
char *dn = "uid=bjensen,ou=People,dc=example, dc=com";
char *pw = "hifalutin";
char *err_msg;
...
err_msg = ldap_err2string( ldap_simple_bind_s( ld, dn, pw ) );
...
See Also

ldap_get_lderrno(), ldap_perror(), ldap_result2error(), ldap_set_lderrno(), ldapssl_err2string()

ldap_explode_dn()

The ldap_explode_dn() function converts a DN into its component parts.

Syntax
#include <ldap.h>
char ** ldap_explode_dn( const char *dn, int notypes );
Parameters
ldap_explode_dn() Function Parameters
Parameter Description
dn DN that you want separated into components.
notypes Specifies whether or not type names in the DN are returned. This parameter can have the following possible values: *0 specifies that type names are returned. *A non-zero value specifies that type names are not returned.
Returns

One of the following values:

  • If successful, returns a NULL terminated array containing the components of the DN.
  • If unsuccessful, returns NULL.
Example

The following function call:

ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 0 );

returns this array:

{ "uid=bjensen", "ou=People", "dc=example,dc=com", NULL }

If you change the notypes parameter from 0 to 1:

ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 1 );

The component names are not returned in the array:

{ "bjensen", "People", "example.com", NULL }
See Also

ldap_explode_rdn(), ldap_get_dn()

ldap_explode_dns()

Note: This function is to be deprecated and should not be used. It is included in ldap-to-be-deprecated.h for backward-compatibility.

The ldap_explode_dns() function takes a DNS-style DN, breaks it up into its component parts, and returns a NULL terminated array. For example, the DN ldap.example.com will return { "ldap", "example", "com", NULL }. The result can be freed by calling ldap_value_free().

Syntax
#include <ldap-to-be-deprecated.h>
char ** ldap_explode_dns( const char *dn );
Parameters
ldap_explode_dns() Function Parameter
Parameter Description
dn DN that you want separated into components.
Returns

One of the following values:

  • If successful, returns a NULL terminated array containing the components of the DN.
  • If unsuccessful, returns NULL.

ldap_explode_rdn()

The ldap_explode_rdn() function converts a relative distinguished name (RDN) into its component parts.

Syntax
#include <ldap.h>
char ** ldap_explode_rdn( const char *dn, int notypes );
Parameters
ldap_explode_rdn() Function Parameters
Parameter Description
dn RDN that you want separated into components.
notypes Specifies whether or not type names in the RDN are returned. This parameter can have the following possible values: *0 specifies that type names are returned. *A non-zero value specifies that type names are not returned.
Returns

One of the following values:

  • If successful, returns a NULL terminated array containing the components of the RDN.
  • If unsuccessful, returns NULL.
Example

The following function call:

ldap_explode_rdn( "ou=Sales + cn=Barbara Jensen", 0 );

returns this array:

{ "ou=Sales", "cn=Barbara Jensen", NULL }
See Also

ldap_explode_dn(), ldap_get_dn

ldap_extended_operation()

The ldap_extended_operation() function sends a request to the server to perform an extended operation asynchronously.

Syntax
#include <ldap.h>
int ldap_extended_operation( LDAP *ld, const char *requestoid,
  struct berval *requestdata, LDAPControl **serverctrls,
  LDAPControl **clientctrls, int *msgidp );
Parameters
ldap_extended_operation() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
requestoid Object identifier (OID) of the extended operation that you want the server to perform. After processing an LDAP v3 extended operation, an LDAP server can return an OID and data in the result. To parse the OID and data from the result, call the ldap_parse_extended_result() function.
requestdata Pointer to a berval structure containing the data that you want passed to the server to perform the extended operation. The data in the berval is a buffer of the BER encoded data type, usually obtained using the ber_flatten() function.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
msgidp Pointer to an integer that will be set to the message ID of the LDAP operation.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

The ldap_extended_operation() function sends a request to the server to perform an LDAP v3 extended operation. ldap_extended_operation() is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_extended_operation_s().

See Also

ldap_extended_operation_s(), ldap_result(), ldap_parse_extended_result(), ldap_get_lderrno(), ber_flatten()

ldap_extended_operation_s()

The ldap_extended_operation_s() function sends a request to the server to perform an extended operation synchronously.

Syntax
#include <ldap.h>
int ldap_extended_operation_s( LDAP *ld, const char *requestoid,
  struct berval *requestdata, LDAPControl **serverctrls,
  LDAPControl **clientctrls, char **retoidp, struct berval **retdatap );
Parameters
ldap_extended_operation_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
requestoid Object identifier (OID) of the extended operation that you want the server to perform.
requestdata Pointer to a berval structure containing the data that you want passed to the server to perform the extended operation. The data in the berval is a buffer of the BER encoded data type, usually obtained using the ber_flatten() function.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
retoidp Pointer to the OID returned by the server after performing the extended operation. When done, you can free this by calling the ldap_memfree() function.
retdatap Pointer to the pointer for a berval structure containing the data returned by the server after performing the extended operation. When done, you can free this by calling the ber_bvfree() function.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

Note: Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.

Description

The ldap_extended_operation_s() function sends a request to the server to perform an LDAP v3 extended operation. See also ldap_extended_operation(), ber_flatten()

ldap_first_attribute()

The ldap_first_attribute() function returns the name of the first attribute in an entry returned by the ldap_first_entry() , the ldap_next_entry(), or the ldap_result() functions.

Syntax
#include <ldap.h>
char * ldap_first_attribute( LDAP *ld, LDAPMessage *entry,
  BerElement **ber );
Parameters
ldap_first_attribute() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
entry Pointer to the LDAPMessage structure representing the entry returned by the ldap_first_entry() or ldap_next_entry() function.
ber Pointer to a BerElement allocated to keep track of its current position. Pass this pointer to subsequent calls to ldap_next_attribute() to step through the entry's attributes.
Returns

One of the following values:

  • If successful, returns the pointer to the name of the first attribute in an entry. When you are done using this data, you should free the memory by calling the ldap_memfree() function.
  • If unsuccessful, returns a NULL and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
Example

The following example retrieves each attribute for an entry.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)"
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE,
  my_filter, NULL, 0, &result ) !=
  LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );
  /* Retrieve the attributes the entry */
  for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL;
    a = ldap_next_attribute( ld, e, ber ) ) {
      ...
      /* Code to get and manipulate attribute values */
      ...
    }
    ldap_memfree( a );
  }
  /* Free the BerElement from memory when done */
  if ( ber != NULL ) {
    ldap_ber_free( ber, 0 );
  }
...
See Also

ldap_first_entry(), ldap_next_entry(), ldap_next_attribute(), BerElement

ldap_first_disptmpl()

The ldap_first_disptmpl() function returns the first template in a list.

Syntax
#include <disptmpl.h>
ldap_first_disptmpl( struct ldap_disptmpl *tmpllist );
Parameters
ldap_first_disptmpl() Function Parameter
Parameter Description
tmpllistp Pointer to a list of template data structures.
Description

ldap_first_disptmpl() returns the first template in the list of templates pointed to by the parameter tmpllistp. tmpllistp is typically obtained by calling ldap_init_templates() .

See Also

ldap_next_disptmpl(), ldap_init_templates(), ldap_init_templates_buf()

ldap_first_entry()

The ldap_first_entry() function returns a pointer to the LDAPMessage structure representing the first directory entry in a chain of search results.

Syntax
#include <ldap.h>
LDAPMessage * ldap_first_entry( LDAP *ld, LDAPMessage *result );
Parameters
ldap_first_entry() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
result Chain of search results, which are represented by a pointer to the LDAPMessage structure.
Returns

One of the following values:

  • If successful, returns the pointer to the first LDAPMessage structure of the type LDAP_RES_SEARCH_ENTRY in the chain of search results.
  • If no LDAPMessage structure of the type LDAP_RES_SEARCH_ENTRY are in the chain of the search results or if the function is unsuccessful, returns a NULLMSG.
Description

The ldap_first_entry() function returns a pointer to the LDAPMessage structure representing the first directory entry in a chain of search results. Search result entries are in messages of the type LDAP_RES_SEARCH_ENTRY. You can use this function in conjunction with the ldap_next_entry() function to iterate through the directory entries in a chain of search results. These functions skip over any messages in the chain that do not have the type LDAP_RES_SEARCH_ENTRY. Do not free the LDAPMessage structure returned by this function. Because this is a structure within a chain of search results, freeing this structure will free part of the chain of search results. When you are done working with the search results, you can free the chain itself, rather than individual structures within the chain.

See Also

ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_next_entry()

ldap_first_message()

The ldap_first_message() function returns a pointer to the first LDAPMessage structure in a chain of search results.

Syntax
#include <ldap.h>
LDAPMessage * ldap_first_message( LDAP *ld, LDAPMessage *res );
Parameters
ldap_first_message() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
res Chain of search results, represented by a pointer to the LDAPMessage structure.
Returns

One of the following values:

  • If successful, returns the pointer to the first LDAPMessage structure in the chain of search results.
  • If no LDAPMessage structures are in the chain or if the function is unsuccessful, returns a NULLMSG.
Description

The ldap_first_message() function returns a pointer to the first LDAPMessage structure in a chain of search results. You can use this function in conjunction with the ldap_next_message() function to iterate through the chain of search results. You can also call the ldap_msgtype() function to determine if each message contains a matching entry, a message of the type LDAP_RES_SEARCH_ENTRY, or a search reference, a message of the type LDAP_RES_SEARCH_REFERENCE. Do not free the LDAPMessage structure returned by this function. Because this is a structure within a chain of search results, freeing this structure will free part of the chain of search results. When you are done working with the search results, you can free the chain itself, rather than individual structures within the chain.

See Also

ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_next_message(), ldap_first_entry(), ldap_first_reference()

ldap_first_reference()

The ldap_first_reference() function returns a pointer to the LDAPMessage structure representing the first search reference in a chain of search results.

Syntax
#include <ldap.h>
LDAPMessage * ldap_first_reference(LDAP *ld, LDAPMessage *res );
Parameters
ldap_first_reference() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
res Chain of search results, which are represented by a pointer to the LDAPMessage structure.
Returns

One of the following values:

  • If successful, returns the pointer to the first LDAPMessage structure of the type LDAP_RES_SEARCH_REFERENCE in the chain of search results.
  • If no LDAPMessage structures of the type LDAP_RES_SEARCH_REFERENCE are in the chain of the search results or if the function is unsuccessful, returns a NULLMSG.
Description

The ldap_first_reference() function returns a pointer to the LDAPMessage structure representing the first search reference in a chain of search results. Search references are in messages of the type LDAP_RES_SEARCH_REFERENCE, continuation references as specified in LDAPv3 that are stored as referral entries. Like a referral, each continuation reference itself may contain a number of URLs assumed to be equivalent, and the client should use one of those URLs. You can use this function in conjunction with the ldap_next_reference function to iterate through the search references in a chain of search results. These functions skip over any messages in the chain that do not have the type LDAP_RES_SEARCH_REFERENCE. Do not free the LDAPMessage structure returned by this function. Because this is a structure within a chain of search results, freeing this structure will free part of the chain of search results. When you are done working with the search results, you can free the chain itself, rather than individual structures within the chain.

See Also

ldap_result(), ldap_search_ext() , ldap_search_ext_s(), ldap_next_reference(), ldap_first_message()

ldap_first_searchobj()

The ldap_first_searchobj() function returns the first search preference configuration from a data structure defined in the list solist .

Syntax
#include <ldap.h>
ldap_searchobj * ldap_first_searchobj( struct ldap_searchobj *solist );
Parameters
ldap_first_searchobj() Function Parameter
Parameter Description
solist Pointer to the search preference data structures, typically obtained by calling ldap_init_searchprefs().
Description

ldap_first_searchobj provides access to LDAP search preference configuration data. LDAP search preference configurations are typically used by LDAP client programs to specify which attributes a user may search by, the labels for the attributes, and the LDAP filters and scopes associated with those searches.

See Also

ldap_init_searchprefs(), ldap_init_searchprefs_buf()

ldap_first_tmplcol()

The ldap_first_tmplcol() function returns a pointer to the first item within a template.

Syntax
#include <disptmpl.h>
struct ldap_tmplitem * ldap_first_tmplcol( struct ldap_disptmpl *tmpl,
  struct ldap_tmplitem *row );
Parameters
ldap_first_tmplcol() Function Parameters
Parameter Description
tmpl The name of the template to be retrieved.
row The row in which the item is to be retrieved from.
Returns
  • If successful, a pointer to an ldap_tmplitem structure.
  • A NULL pointer on error.
Description

ldap_first_tmplcol() returns a pointer to the first item (in the first column) of the row, defined by row, within the template defined by tmpl.

See Also

ldap_first_tmplrow(), ldap_next_tmplcol()

ldap_first_tmplrow()

The ldap_first_tmplrow() function returns a pointer to the first row of items in a template.

Syntax
#include <disptmpl.h>
struct ldap_tmplitem * ldap_first_tmplrow( struct ldap_disptmpl *tmpl );
Parameters
ldap_first_tmplrow() Function Parameter
Parameter Description
tmpl The name of the template to be retrieved.
Returns
  • If successful, a pointer to an ldap_tmplitem structure.
  • A NULL pointer on error.
See Also

ldap_next_tmplrow(), ldap_first_tmplcol()

ldap_free_friendlymap()

The ldap_free_friendlymap() function frees the FriendlyMap structures allocated by the ldap_friendly_name() function when no more calls to it are to be made.

Syntax
#include <ldap.h>
void ldap_free_friendlymap( FriendlyMap *map );
Parameters
ldap_free_friendlymap() Function Parameter
Parameter Description
map Pointer to the FriendlyMap() mapping structure in memory.
Example

The following example frees memory allocated by the ldap_friendly_name() function.

#include <ldap.h>
#include <stdio.h>
...
FriendlyMap map = NULL;
char *map_file = "/u/mozilla/ldapsdk/examples/ldapfriendly";
char *unfriendly_name = "IS";
char *friendly_name;
...
/* Read the ldapfriendly file into the map in memory */
friendly_name = ldap_friendly_name( map_file, unfriendly_name, &map );
printf( "Friendly Name for %s: %s\n", unfriendly_name, friendly_name );
/* Since file is in memory, no need to reference it in subsequent calls */
friendly_name = ldap_friendly_name( NULL, "VI", &map );
printf( "Friendly Name for VI: %s\n", friendly_name );
...
ldap_free_friendlymap( map );
...
See Also

ldap_friendly_name(), FriendlyMap()

ldap_free_searchprefs()

The ldap_free_searchprefs() function disposes of the data structures allocated by ldap_init_searchprefs().

Syntax
#include <ldap.h>
void ldap_free_searchprefs( struct ldap_searchobj *solist );
Parameters
ldap_free_searchprefs() Function Parameter
Parameter Description
solist Pointer to the data structures, typically obtained by calling ldap_init_searchprefs().
See Also

ldap_init_searchprefs(), ldap_init_searchprefs_buf()

ldap_free_sort_keylist()

The ldap_free_sort_keylist() function frees the structures allocated by the ldap_create_sort_keylist() function.

Syntax
#include <ldap.h>
void ldap_free_sort_keylist (LDAPsortkey **sortKeyList);
Parameters
ldap_free_sort_keylist() Function Parameter
Parameter Description
sortKeyList Array of LDAPsortkey structures that you want to free from memory.
Description

The ldap_free_sort_keylist() function frees the array of LDAPsortkey structures allocated by the ldap_create_sort_keylist() function. When done sorting results, call this function to free the memory that you have allocated. This function must be called after the ldap_create_sort_control() function has completed.

See Also

ldap_create_sort_keylist(), ldap_create_sort_control()

ldap_free_templates()

The ldap_free_templates() function disposes of the templates allocated by ldap_init_templates().

Syntax
#include <disptmpl.h>
void ldap_free_templates( struct ldap_disptmpl *tmpllist );
Parameters
ldap_free_templates() Function Parameter
Parameter Description
tmpllistp Pointer to a list of template data structures.
Description

ldap_free_templates() releases the templates allocated by ldap_init_templates(). Each template defined in the file is an ldap_disptmpl structure.

ldap_free_urldesc()

The ldap_free_urldesc() function frees memory allocated by the ldap_url_parse() function.

Syntax
#include <ldap.h>
void ldap_free_urldesc( LDAPURLDesc *ludp );
Parameters
ldap_free_urldesc() Function Parameter
Parameter Description
ludp Pointer to a LDAPURLDesc structure.
Example

The following example parses an LDAP URL and then frees the LDAPURLDesc structure from memory after verifying that the LDAP URL is valid.

#include <stdio.h>
#include <ldap.h>
...
char *my_url =
"ldap://ldap.example.com:1389/dc=example,dc=com?cn,mail,telephoneNumber?
sub?(sn=Jensen)";
LDAPURLDesc *ludpp;
int res, i;
...
if ( ( res = ldap_url_parse( my_url, &ludpp ) ) != 0 ) {
  switch( res ){
    case LDAP_URL_ERR_NOTLDAP:
      printf( "URL does not begin with \"ldap://\"\n" );
      break;
    case LDAP_URL_ERR_NODN:
      printf( "URL does not contain a distinguished name\n" );
      break;
    case LDAP_URL_ERR_BADSCOPE:
      printf( "URL contains an invalid scope\n" );
      break;
    case LDAP_URL_ERR_MEM:
      printf( "Not enough memory\n" );
      break;
    default:
      printf( "Unknown error\n" );
  }
  return( 1 );
}
printf( "URL is a valid LDAP URL\n" );
ldap_free_urldesc( ludpp );
...
See Also

ldap_url_parse()

ldap_friendly_name()

The ldap_friendly_name() function maps a set of standard identifiers to their user-friendly counterparts. For example, you can represent the list of two-letter state codes (CA, IA) with their corresponding state names (California, Iowa), or map country ISO codes to the full country names. Note: ldapfriendly, located in lib/ldapcsdk/etc, is a sample file that maps two letter country codes to their full names. It can be used in context with ldap_friendly_name().

Syntax
#include <ldap.h>
char * ldap_friendly_name( char *filename, char *uname,
  FriendlyMap *map );
Parameters
ldap_friendly_name() function parameters
Parameter Description
filename Name of the file mapping the standard identifiers to the user-friendly names.
uname Standard identifier name for which you want to find the user-friendly name.
map Pointer to the FriendlyMap() mapping in memory. Initialize this pointer to NULL on the first call, then use it during subsequent calls so that the mapping file does not need to be read again.
Returns

One of the following values:

  • If successful, returns the user-friendly name for the specified identifier.
  • If unsuccessful—for example, if the file cannot be read, if the file is in a bad format, or if the map parameter is set to NULL—returns the original identifier (the value passed as the uname parameter).
Description

This function relies on the existence of a text file mapping standard identifiers to user-friendly names. The names in the file are tab-delimited. Unfriendly to Friendly Name Mapping File

<unfriendly_name>        <friendly_name>
AD        Andorra
AE        United Arab Emirates
AF        Afghanistan
AG        Antigua and Barbuda
AI        Anguilla
Example

The following example reads in a map of user-friendly names and prints the name corresponding to the standard identifier IS.

#include <ldap.h>
#include <stdio.h>
...
FriendlyMap map = NULL;
char *map_file = "/u/mozilla/ldapsdk/examples/ldapfriendly";
char *unfriendly_name = "IS";
char *friendly_name;
...
/* Read the ldapfriendly file into the map in memory */
friendly_name = ldap_friendly_name( map_file, unfriendly_name, &map );
printf( "Friendly Name for %s: %s\n", unfriendly_name, friendly_name );
/* Since file is in memory, no need to reference it in subsequent calls */
friendly_name = ldap_friendly_name( NULL, "VI", &map );
printf( "Friendly Name for VI: %s\n", friendly_name );
...
See Also

ldap_free_friendlymap(), FriendlyMap()

ldap_get_dn()

The ldap_get_dn() routine returns the DN for an entry in a chain of search results.

Syntax
#include <ldap.h>
char * ldap_get_dn( LDAP *ld, LDAPMessage *entry );
Parameters
ldap_get_dn() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
entry Pointer to an entry in a chain of search results, as returned by the ldap_first_entry() and ldap_next_entry() functions.
Returns

One of the following values:

  • If successful, returns the DN for the specified entry.
  • If unsuccessful, returns a NULL and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
Description

You can get an entry from a chain of search results by calling the ldap_first_entry() and ldap_next_entry() functions.

Example

The following example prints the DN for each entry found in a search.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result, *e;
char *dn;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  NULL, 0, &result ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* For each matching entry found, print out the name of the entry.*/
for ( e = ldap_first_entry( ld, result ); e != NULL;
  e = ldap_next_entry( ld, e ) ) {
    if ( ( dn = ldap_get_dn( ld, e ) ) != NULL ) {
      printf( "dn: %s\n", dn );
      /* Free the memory used for the DN when done */
      ldap_memfree( dn );
    }
}
/* Free the result from memory when done. */
ldap_msgfree( result );
...
See Also

ldap_first_entry(), ldap_next_entry(), ldap_get_lderrno()

ldap_get_entry_controls()

The ldap_get_entry_controls() function gets the LDAP controls included with a directory entry in a set of search results.

Syntax
#include <ldap.h>
int ldap_get_entry_controls( LDAP *ld, LDAPMessage *entry,
  LDAPControl ***serverctrlsp );
Parameters
ldap_get_entry_controls() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
entry Pointer to an LDAPMessage structure representing an entry in a chain of search results.
serverctrlsp Pointer to an array of LDAPControl structures, which represent the LDAP v3 server controls returned by the server.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
Description

The ldap_get_entry_controls() function retrieves the LDAP v3 controls included in a directory entry in a chain of search results. The LDAP controls are specified in an array of LDAPControl structures with each structure representing one LDAP control. Other controls are returned with results sent from the server. You can call ldap_parse_result() to retrieve those controls.

ldap_getfilter_free()

The ldap_getfilter_free() function frees the memory used by a filter set.

Syntax
#include <ldap.h>
void ldap_getfilter_free( LDAPFiltDesc *lfdp );
Parameters
ldap_getfilter_free() Function Parameter
Parameter Description
lfdp Pointer to a LDAPFiltDesc structure.
Description

Once you call ldap_getfilter_free(), the LDAPFiltDesc structure is no longer valid and cannot be used again.

Example

The following example frees the LDAPFiltDesc structure from memory after all searches are completed.

#include <ldap.h>
...
LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";
...
/* Read the filter configuration file into an LDAPFiltDesc structure */
lfdp = ldap_init_getfilter( filter_file );
...
/* Retrieve filters and perform searches */
...
/* Free the configuration file (the LDAPFiltDesc structure) */
ldap_getfilter_free( lfdp );
...
See Also

ldap_init_getfilter(), ldap_init_getfilter_buf()

ldap_getfirstfilter()

The ldap_getfirstfilter() function retrieves the first filter that is appropriate for a given value.

Syntax
#include <ldap.h>
LDAPFiltInfo * ldap_getfirstfilter( LDAPFiltDesc *lfdp,
  char *tagpat, char *value );
Parameters
ldap_getfirstfilter() Function Parameters
Parameter Description
lfdp Pointer to an LDAPFiltDesc structure.
tagpat Regular expression for a tag in the filter configuration.
value Value for which to find the first appropriate filter.
Returns

One of the following values:

  • If successful, returns a pointer to an LDAPFiltInfo() structure.
  • If no more filters can be returned, returns a NULL.
  • If unsuccessful, returns a NULL.
Example

The following example is based on the getfilt command-line program example provided with the Directory SDK For C. The program prompts the user to enter search criteria and, based on the criteria entered, it retrieves filters that match the criteria.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a, *dn;
char **vals;
int i;
LDAPFiltDesc *ldfp;
LDAPFiltInfo *ldfi;
char buf[ 80 ]; /* Contains the search criteria */
int found;
...
/* Load the filter configuration file into an LDAPFiltDesc structure */
if ( ( ldfp = ldap_init_getfilter( "myfilters.conf" ) ) == NULL ) {
  perror( "Cannot open filter configuration file" );
  return( 1 );
}

/* Read a string to search for */
printf( "Enter a string to search for: " );
gets( buf );
if ( strlen( buf ) == 0 ) {
  fprintf( stderr, "usage: %s search-string\n", argv[ 0 ]);
  return( 1 );
}

/* Select a filter to use when searching for the value in buf */
found = 0;
for ( ldfi = ldap_getfirstfilter( ldfp, "people", buf );
      ldfi != NULL;
      ldfi = ldap_getnextfilter( ldfp ) ) {

  /* Use the selected filter to search the directory */
  if ( ldap_search_s( ld, "dc=example,dc=com, ldfi->lfi_scope,
   ldfi->lfi_filter, NULL, 0, result ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
  } else {

    /* Once a filter gets results back, stop iterating through
       the different filters */
    if ( ( found = ldap_count_entries( ld, result ) > 0 ) ) {
      break;
    } else {
      ldap_msgfree( result );
    }
  }
}

if ( found == 0 ) {
  printf( "No matching entries found.\n" );
} else {
  printf( "Found %d %s match%s for \"%s\"\n\n", found,
   ldfi->lfi_desc, found == 1 ? "" : "es", buf );
}

ldap_msgfree( result );
ldap_getfilter_free( ldfp );
...
See Also

ldap_init_getfilter(), ldap_init_getfilter_buf(), ldap_getnextfilter()

ldap_get_lang_values()

#include <ldap.h>
char ** ldap_get_lang_values( LDAP *ld, LDAPMessage *entry,
  const char *target, char **type );
Parameters
ldap_get_lang_values() Function Parameters
Parameters Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
entry Entry retrieved from the directory.
target Attribute type (including an optional language subtype) that you want to retrieve the values of.
type Pointer to a buffer that returns the attribute type retrieved by this function.
Returns

One of the following values:

  • If successful, returns a NULL terminated array of the attribute’s values.
  • If unsuccessful or if no such attribute exists in the entry, returns a NULL and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
Description

Unlike the ldap_get_values() function, if a language subtype is specified, this function first attempts to find and return values that match that subtype—for example, cn;lang-en. If you want to retrieve binary data from an attribute, call the ldap_get_lang_values_len() function.

See Also

ldap_first_entry(), ldap_first_attribute(), ldap_get_lang_values_len() , ldap_get_values(), ldap_next_entry(), ldap_next_attribute()

ldap_get_lang_values_len()

Note: This function is deprecated and should not be used. It is included in ldap-deprecated.h for backward-compatibility. Please use ldap_get_values_len().

The ldap_get_lang_values_len() function returns a NULL terminated array of pointers to berval structures, each containing the length and pointer to a binary value of an attribute for a given entry.

Syntax
#include <ldap-deprecated.h>
struct berval ** ldap_get_lang_values_len( LDAP *ld,
  LDAPMessage *entry, const char *target, char **type );
Parameters
ldap_get_lang_values_len() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
entry Result returned by the ldap_result() or ldap_search_s() function.
target Attribute returned by ldap_first_attribute() or ldap_next_attribute(), or the attribute as a literal string, such as jpegPhoto or audio.
type Pointer to a buffer that returns the attribute type retrieved by this function.
Returns

One of the following values:

  • If successful, returns a NULL terminated array of pointers to berval structures, which, in turn, contain pointers to the attribute’s binary values.
  • If unsuccessful or if no such attribute exists in the entry, returns a NULL and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
Description

Use the ldap_get_lang_values() routine if the attribute values are string values.

See Also

ldap_first_attribute(), ldap_first_entry(), ldap_get_lang_values(), ldap_next_entry(), ldap_next_attribute()

ldap_get_lderrno()

The ldap_get_lderrno() function gets information about the last error that occurred for an LDAP operation.

Syntax
#include <ldap.h>
int ldap_get_lderrno( LDAP *ld, char **m, char **s );
Parameters
ldap_get_lderrno() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
m In the event of an LDAP_NO_SUCH_OBJECT error return, this parameter contains the portion of the DN that identifies an existing entry.
s The text of the error message.
Returns

The LDAP error code for the last operation.

Description

ldap_get_lderrno() gets information about the last error that occurred for an LDAP operation. You can also call this function to get error codes for functions that do not return errors, such as ldap_next_attribute().

Example

The following example attempts to add a new user to the directory. If the entry identified by a DN does not exist, the server returns the portion of the DN that matches an existing entry; this is the variable matched.

#include <ldap.h>
LDAP *ld;
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
LDAPMod **list_of_attrs;
char *matched;
int rc;
...
if ( ldap_add_s( ld, dn, list_of_attrs ) != LDAP_SUCCESS ) {
  rc = ldap_get_lderrno( ld, &matched, NULL );
  return( rc );
}
...

If no organizational unit named People exists, the matched variable is set to dc=example,dc=com .

See Also

ldap_err2string(), ldap_perror, ldap_result2error(), ldap_set_lderrno()

ldap_getnextfilter()

The ldap_getnextfilter() function retrieves the next filter that is appropriate for a given value.

Syntax
#include <ldap.h>
LDAPFiltInfo * ldap_getnextfilter( LDAPFiltDesc *lfdp );
Parameters
ldap_getnextfilter() Function Parameter
Parameter Description
lfdp Pointer to an LDAPFiltDesc structure.
Returns

One of the following values:

  • If successful, returns a pointer to an LDAPFiltInfo() structure.
  • If no more filters can be returned, returns a NULL.
  • If unsuccessful, returns a NULL.
Description

Call this function to get subsequent filters after calling ldap_getfirstfilter().

Example

See the following example.

See Also

ldap_getfirstfilter()

ldap_get_option()

The function ldap_get_option() retrieves session preferences from an LDAP structure.

Syntax
#include <ldap.h>
int ldap_get_option( LDAP *ld, int option, void *optdata );
Parameters
ldap_get_option() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
option Option that you want to retrieve. This parameter must be set to one of the option values.
optdata Pointer to the buffer in which the value of the option will be put.

The following table describes the options that you can retrieve with ldap_get_option().

Options for the ldap_get_options() Function
Option Description
LDAP_OPT_API_FEATURE_INFO Retrieves information about the revision of a supported LDAP feature. This option is READ-ONLY and cannot be set. The data type for the optdata parameter is (LDAPAPIFeatureInfo*).
LDAP_OPT_API_INFO Retrieves information about the API implementation at execution time (API version, protocol version, the names of supported API extensions with their vendor name version, etc.). For details on the structure returned, refer to the ldap.h header file. This option is READ-ONLY and cannot be set. The data type for the optdata parameter is (LDAPAPIInfo*).
LDAP_OPT_CLIENT_CONTROLS Pointer to an array of LDAPControl structures representing the LDAP v3 client controls you want sent with every request by default. The data type for the optdata parameter is (LDAPControl***).
LDAP_OPT_DESC Socket descriptor underlying the main LDAP connection. The LBER_SOCKET data type depends on the platform that you are using:
  • int in UNIX.
  • SOCKET in Windows. The data type for the optdata parameter is (LBER_SOCKET*).
LDAP_OPT_DEREF Determines how aliases work during a search. optdata can be one of the following values:
  • LDAP_DEREF_NEVER specifies that aliases are never dereferenced.
  • LDAP_DEREF_SEARCHING specifies that aliases are dereferenced when searching under the base object (but not when finding the base object).
  • LDAP_DEREF_FINDING specifies that aliases are dereferenced when finding the base object (but not when searching under the base object).
  • LDAP_DEREF_ALWAYS specifies that aliases are always dereferenced when finding and searching under the base object. The data type for the optdata parameter is (int*).
LDAP_OPT_DNS_FN_PTRS DEPRECATED OPTION: Lets you use alternate DNS functions for getting the host entry of the LDAP server. The data type for the optdata parameter is (struct ldap_dns_fns *).
LDAP_OPT_ERROR_NUMBER Retrieves the result code for the most recent LDAP error that occurred in this session. The data type for the optdata parameter is (int *).
LDAP_OPT_ERROR_STRING Retrieves the error message returned with the result code for the most recent LDAP error that occurred in this session. The data type for the optdata parameter is (char **).
LDAP_OPT_EXTRA_THREAD_FN_PTRS Lets you specify the locking and semaphore functions that you want called when getting results from the server. The data type for the optdata parameter is (struct ldap_extra_thread_fns *).
LDAP_OPT_HOST_NAME Sets the host name (or list of hosts) for the primary LDAP server. The data type for the optdata parameter is (char **).
LDAP_OPT_IO_FN_PTRS DEPRECATED OPTION: Lets you use alternate communication stacks. The data type for the optdata parameter is (struct ldap_io_fns *).
LDAP_OPT_MATCHED_DN Gets the matched DN value returned with the most recent LDAP error that occurred for this session. The data type for the optdata parameter is (char **)
LDAP_OPT_MEMALLOC_FN_PTRS Gets a pointer to the callback structure which you previously set. The data type for the optdata parameter is (struct ldap_memalloc_fnsldap_io_fns *).
LDAP_OPT_PROTOCOL_VERSION Version of the protocol supported by your client. You can specify either LDAP_VERSION2 or LDAP_VERSION3. If no version is set, the default is LDAP_VERSION2. In order to use LDAP v3 features, you need to set the protocol version to LDAP_VERSION3. The data type for the optdata parameter is (int *).
LDAP_OPT_REBIND_ARG Lets you set the last argument passed to the routine specified by LDAP_OPT_REBIND_FN. You can also set this option by calling the ldap_set_rebind_proc() function. The data type for the optdata parameter is (void *).
LDAP_OPT_REBIND_FN Lets you set the routine to be called when you need to authenticate a connection with another LDAP server (for example, during the course of following a referral). You can also set this option by calling the ldap_set_rebind_proc function. The data type for the optdata parameter is (LDAP_REBINDPROC_CALLBACK *).
LDAP_OPT_RECONNECT If the connection to the server is lost, determines whether or not the same connection handle should be used to reconnect to the server. By default, this option is off. You handle failover with the following values:
  • LDAP_OPT_ON specifies that the same connection handle can be used to reconnect to the server.
  • LDAP_OPT_OFF specifies that you want to create a new connection handle to connect to the server. The data type for the optdata parameter is (int *).
LDAP_OPT_REFERRALS Determines whether or not the client should follow referrals. By default, the client follows referrals. optdata can be one of the following values:
  • LDAP_OPT_ON specifies that the server should follow referrals.
  • LDAP_OPT_OFF specifies that the server should not follow referrals. The data type for the optdata parameter is (int *).
LDAP_OPT_REFERRAL_HOP_LIMIT Maximum number of referrals the client should follow in a sequence. In other words, the client can only be referred this number of times before it gives up. By default, the maximum number of referrals that the client can follow in a sequence is 5 for the initial connection. This limit does not apply to individual requests that generate multiple referrals in parallel. The data type for the optdata parameter is (int *).
LDAP_OPT_RESTART Determines whether or not LDAP I/O operations should be restarted automatically if they are prematurely aborted. optdata can be one of the following values:
  • LDAP_OPT_ON specifies that I/O operations should be restarted automatically.
  • LDAP_OPT_OFF specifies that I/O operations should not be restarted automatically. The data type for the optdata parameter is (int *).
LDAP_OPT_SERVER_CONTROLS Pointer to an array of LDAPControl structures representing the LDAP v3 server controls you want sent with every request by default. Typically, since controls are specific to the type of request, you may want to pass the controls using operation-specific functions, such as ldap_add_ext(), instead. The data type for the optdata parameter is (LDAPControl ***).
LDAP_OPT_SIZELIMIT Maximum number of entries that should be returned by the server in search results. The LDAP server may impose a smaller size limit than the limit you specify as the server administrator also has the ability to set this limit. The data type for the optdata parameter is (int *).
LDAP_OPT_SSL Determines whether or not SSL is enabled. optdata can be one of the following values:
  • LDAP_OPT_ON specifies that SSL is enabled.
  • LDAP_OPT_OFF specifies that SSL is disabled. The data type for the optdata parameter is (int *).
LDAP_OPT_THREAD_FN_PTRS Lets you specify the thread function pointers. The data type for the optdata parameter is (struct ldap_thread_fns *).
LDAP_OPT_TIMELIMIT Maximum number of seconds that should be spent by the server when answering a search request. The LDAP server may impose a shorter time limit than the limit you specify as the server administrator also has the ability to set this limit. The data type for the optdata parameter is (int *).
LDAP_X_OPT_EXTIO_FN_PTRS Extended I/O function callback option.
LDAP_X_OPT_CONNECT_TIMEOUT Value of a time out (expressed in milliseconds) for non-blocking connect call. The data type for the optdata parameter is (int *).
LDAP_X_OPT_SOCKBUF Socket buffer structure associated to the LDAP connection.

See also ldap_get_option() for details on LDAP_OPT_X_SASL* parameters.

Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • -1 if unsuccessful.
Examples

The following example gets the session preference for the maximum number of entries to be returned from search operations.

#include <ldap.h>
...
LDAP *ld;
int max_ret;
...
/* Get the maximum number of entries returned */
if (ldap_get_option, LDAP_OPT_SIZELIMIT, &max_ret) != LDAP_SUCCESS) {
  ldap_perror( ld, "ldap_get_option" );
  return( 1 );
}

This example could also include the following two small sections of code that show how to use the LDAP_OPT_API_FEATURE_INFO and the LDAP_OPT_API_INFO options, respectively.

LDAPIIFeatureInfo ldfi;
ldfi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
ldfi.ldapaif_name = "VIRTUAL_LIST_VIEW";
if (ldap_get_option(NULL, LDAP_OPT_API_FEATURE_INFO, &ldfi)==0) {
  /* use the info here */ }
LDAPIInfo ldai;
ldai.ldapiai_info_version = LDAP_API_INFO_VERSION;
if (ldap_get_option( NULL, LDAP_OPT_API_INFO, &ldia ) == 0) {
  /* use the ldai info here */
}
See Also

ldap_init(), prldap_init() (IPv6), ldap_set_option()

ldap_get_values()

The ldap_get_values() function returns a NULL terminated array of an attribute’s string values for a given entry.

Syntax
#include <ldap.h>
char ** ldap_get_values( LDAP *ld, LDAPMessage *entry,
  const char *target );
Parameters
ldap_get_values() Function Parameters
Parameters Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
entry Result returned by the ldap_result() or ldap_search_s() function.
target Attribute returned by ldap_first_attribute() or ldap_next_attribute(), or the attribute as a literal string, such as jpegPhoto or audio.
Returns

One of the following values:

  • If successful, returns a NULL terminated array of the attribute’s values.
  • If unsuccessful or if no such attribute exists in the entry, returns a NULL and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
Description

Use the ldap_get_values_len() function if the attribute values are binary.

Example

The following example gets and prints the values of an attribute in an entry. This example assumes that all attributes have string values.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a;
char **vals;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
int i;
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  NULL, 0, &result ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );
/* Get the first matching attribute */
a = ldap_first_attribute( ld, e, &ber );
/* Get the values of the attribute */
if ( ( vals = ldap_get_values( ld, e, a ) ) != NULL ) {
  for ( i = 0; vals[i] != NULL; i++ ) {
    /* Print the name of the attribute and each value */
    printf( "%s: %s\n", a, vals[i] );
  }
  /* Free the attribute values from memory when done. */
  ldap_value_free( vals );
}
...
See Also

ldap_first_entry(), ldap_first_attribute(), ldap_get_values_len(), ldap_next_entry(), ldap_next_attribute()

ldap_get_values_len()

The ldap_get_values_len() function returns a NULL terminated array of pointers to berval structures, each containing the length and pointer to a binary value of an attribute for a given entry.

Syntax
#include <ldap.h>
struct berval ** ldap_get_values_len( LDAP *ld,
 LDAPMessage *entry, const char *target );
Parameters
ldap_get_values_len() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
entry Result returned by the ldap_result() or ldap_search_s() function.
target Attribute returned by ldap_first_attribute() or ldap_next_attribute(), or the attribute as a literal string, such as jpegPhoto or audio.
Returns

One of the following values:

  • If successful, returns a NULL terminated array of pointers to berval structures, which in turn contains pointers to the attribute’s binary values.
  • If unsuccessful or if no such attribute exists in the entry, returns NULL and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
Description

Use the ldap_get_values() routine if the attribute values are string values.

Example

The following example gets the first value of the jpegPhoto attribute and saves the JPEG data to a file.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
struct berval photo_data;
struct berval **list_of_photos;
FILE *out;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter, NULL,
  0, &result ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Get the first matching entry.*/
e = ldap_first_entry( ld, result );
/* Get the value of the jpegPhoto attribute */
if ( ( list_of_photos = ldap_get_values_len( ld, e, "jpegPhoto" ) ) !=
  NULL ) {
    /* Prepare to write the JPEG data to a file */
    if ( ( out = fopen( "photo.jpg", "wb" ) ) == NULL ) {
      perror( "fopen" );
      return( 1 );
    }
   /* Get the first JPEG */
   photo_data = *list_of_photos[0];
   /* Write the JPEG data to a file */
   fwrite( photo_data.bv_val, photo_data.bv_len, 1, out );
   fclose( out );
   /* Free the attribute values from memory when done. */
   ldap_value_free_len( list_of_photos );
}
...
See Also

ldap_first_entry(), ldap_first_attribute(), ldap_get_values(), ldap_next_entry(), ldap_next_attribute()

ldap_init()

The ldap_init() function initializes a session with an LDAP server and returns an LDAP structure that represents the context of the connection to that server.

Syntax
#include <ldap.h>
LDAP * ldap_init( const char *defhost, int defport );
Parameters
ldap_init() Function Parameters
Parameter Description
defhost Space-delimited list of one or more host names (or IP address in dotted notation, such as "141.211.83.36") of the LDAP servers that you want the LDAP client to connect to. The names can be in hostname:portnumber format (in which case, portnumber overrides the port number specified by the defport argument.
defport Default port number of the LDAP server. To specify the standard LDAP port (port 389), use LDAP_PORT as the value for this parameter.
Returns

One of the following values:

  • If successful, returns a pointer to an LDAP() structure.
  • If unsuccessful, returns a NULL.
Description

The ldap_init() function initializes a session with an LDAP server by allocating an LDAP structure containing information about the session including the host name and port of the LDAP server, preferences for the session (such as the maximum number of entries to return in a search), and the error code of the last LDAP operation performed. The LDAP structure defaults to LDAP v2. It is highly recommended to set it to LDAP v3 using the ldap_set_option().

...
LDAP *ld
...
ld = ldap_init( "ld1.example.com ld2.example.com ld3.example.com",
  LDAP_PORT );

If any of the servers do not use the default port specified by the defport argument, use the hostname:portnumber format to specify the server name. In the following example ld1.example.com, port 389. If that server does not respond, the client will attempt to connect to the LDAP server on ld2.example.com, port 1389.

...
LDAP *ld
...
ld = ldap_init( "ld1.example.com ld2.example.com:1389", LDAP_PORT );

Note: If you are connecting to a secure LDAP server over SSL, you should be calling the ldapssl_init() function.

Example

The following example initializes a session with the LDAP server at ldap.example.com:389, and sets a session preference that identifies the client as an LDAP v3 client.

#include <ldap.h>
...
LDAP *ld;
/* Specify the host name of the LDAP server. */
char *ldap_host = "ldap.example.com";
/* Because the LDAP server is running on the standard LDAP port (port 389),
* you can use LDAP_PORT to identify the port number. */
int ldap_port = LDAP_PORT;
...
/* Initialize the session with ldap.example.com:389 */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( ldap_host, ldap_port ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* Specify the LDAP version supported by the client. */
version = LDAP_VERSION3;
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
...
/* Subsequent calls that authenticate to the LDAP server. */
...
See Also

prldap_init() (IPv6), ldap_unbind(), ldap_unbind_s() , ldap_simple_bind(), ldap_simple_bind_s()

ldap_init_getfilter()

The ldap_init_getfilter() function reads a valid LDAP filter configuration file (such as ldapfilter.conf) and returns a pointer to an LDAPFiltDesc structure.

#include <ldap.h>
LDAPFiltDesc * ldap_init_getfilter( char *fname );
Parameters
ldap_init_getfilter() Function Parameter
Parameter Description
fname Name of the LDAP filter configuration file to use.
Returns

One of the following values:

  • If successful, returns a pointer to an LDAPFiltDesc() structure.
  • If unsuccessful (for example, if there is an error reading

the file), returns a NULL.

Example

The following example loads a filter configuration file named myfilters.conf into memory.

#include <ldap.h>
...
LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";
...
lfdp = ldap_init_getfilter( filter_file );
...
See Also

ldap_init_getfilter_buf(), ldap_getfilter_free()

ldap_init_getfilter_buf()

The ldap_init_getfilter_buf() function reads LDAP filter configuration information from a buffer and returns a pointer to an LDAPFiltDesc structure.

Syntax
#include <ldap.h>
LDAPFiltDesc * ldap_init_getfilter_buf(char *buf, long buflen );
Parameters
ldap_init_getfilter_buf() Function Parameters
Parameter Description
buf Buffer containing LDAP filter configuration information.
buflen Size of the buffer
Returns

One of the following values:

  • If successful, returns a pointer to an LDAPFiltDesc() structure.
  • If unsuccessful—for example, if there is an error reading the file—returns a NULL.
Example

The following example copies the following filter configuration to a buffer in memory and uses this buffer to fill an LDAPFiltDesc structure.

"ldap-example"
"@"      " "    "(mail=%v)"            "email address"
"(mail=%v*)"            "start of email address"

Using ldap_init_getfilter()

#include <string.h>
#include <ldap.h>
...
LDAPFiltDesc *lfdp;
char filtbuf[ 1024 ];
...
/* Create the filter config buffer */
strcpy( filtbuf, "\"ldap-example\"\n" );
strcat( filtbuf, " \"@\"\t\" \"\t\"(mail=%v)\"\t\"email address\"\n" );
strcat( filtbuf, " \t\t\"(mail=%v*)\"\t\"start of email address\"\n" );
lfdp = ldap_init_getfilter( filtbuf, strlen( filtbuf ) );
...
See Also

ldap_init_getfilter(), ldap_getfilter_free()

ldap_init_searchprefs()

The ldap_init_searchprefs() function reads a sequence of search preference configurations from a valid LDAP searchpref configuration file.

Syntax
#include <ldap.h>
int ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp );
Parameters
ldap_init_searchprefs() Function Parameters
Parameter Description
file Pointer to a valid LDAP searchpref configuration file.
solistp Pointer to a list of search preference data structures.
Returns

One of the following values:

  • LDAP_SEARCHPREF_ERR_VERSION.
  • LDAP_SEARCHPREF_ERR_MEM if there is a memory allocation problem.
  • Upon success, 0 is returned and solistp is set to point to a list of search preference data structures.
Description

ldap_init_searchprefs() provides a standard way to access LDAP search preference configuration data.

Note: LDAP search preference configurations are typically used by LDAP client programs to specify which attributes a user may search by, labels for the attributes, and LDAP filters and scopes associated with those searches. Client software presents these choices to a user, who can then specify the type of search to be performed.

See Also

ldap_free_searchprefs(), ldap_init_searchprefs_buf()

ldap_init_searchprefs_buf()

The ldap_init_searchprefs_buf() function reads a sequence of search preference configurations from the parameter, buf.

Syntax
#include <ldap.h>
int ldap_init_searchprefs_buf( char *buf, long buflen,
  struct ldap_searchobj **solistp );
Parameters
ldap_init_searchprefs_buf() Function Parameters
Parameter Description
buf Pointer to data in the format defined for an LDAP search preference configuration file.
buflen The size of buf.
solistp Pointer to a list of search preference data structures.
Returns

One of the following values:

  • LDAP_SEARCHPREF_ERR_VERSION if buf points to data that is newer than can be handled.
  • LDAP_SEARCHPREF_ERR_MEM if there is a memory allocation problem.
  • Upon success, 0 is returned and solistp is set to point to a list of search preference data structures.
Description

ldap_init_searchprefs_buf() reads a sequence of search preference configurations from buf. See also ldap_init_searchprefs(), ldap_free_searchprefs()

ldap_init_templates()

The ldap_init_templates() function reads a sequence of templates from a valid LDAP template configuration file.

Syntax
#include <disptmpl.h>
int ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp );
Parameters
ldap_init_templates() Function Parameters
Parameter Description
file Pointer to a valid LDAP template configuration file.
tmpllistp Pointer to a list of template data structures.
Returns
  • If successful, 0 is returned and tmpllistp is configured.
  • Upon error:
    • LDAP_TMPL_ERR_VERSION if buf points to data that is newer than can be handled.
    • LDAP_TMPL_ERR_MEM if there is a memory allocation problem.
    • LDAP_TMPL_ERR_SYNTAX if there is a problem with the format of the templates buffer or file.
    • LDAP_TMPL_ERR_FILE if the file cannot be read.
Description

ldap_init_templates() reads a sequence of templates from a valid LDAP template configuration file. Each template defined in the file is an ldap_disptmpl structure.

See Also

ldap_init_templates_buf(), ldap_free_templates()

ldap_init_templates_buf()

The ldap_init_templates_buf() function reads a sequence of templates from a buffer.

Syntax
#include <disptmpl.h>
int ldap_init_templates_buf( char *buf, long buflen,
  struct ldap_disptmpl **tmpllistp );
Parameters
ldap_init_templates_buf() Function Parameters
Parameter Description
buf Pointer to data in the format defined for a valid LDAP template configuration file.
buflen The size of buf.
tmpllistp Pointer to a list of template data structures.
Returns

If successful, 0 is returned and tmpllistp is configured. Upon error:

  • LDAP_TMPL_ERR_VERSION if buf points to data that is newer than can be handled.
  • LDAP_TMPL_ERR_MEM if there is a memory allocation problem.
  • LDAP_TMPL_ERR_SYNTAX if there is a problem with the format of the templates buffer or file.
  • LDAP_TMPL_ERR_FILE if the file cannot be read.
Description

The ldap_init_templates_buf() function reads a sequence of templates from a buffer.

See Also

ldap_init_templates(), ldap_free_templates()

ldap_is_dns_dn()

Note: This function is deprecated and should not be used. It is included in ldap-to-be-deprecated.h for backward-compatibility.

The ldap_is_dns_dn() function determines whether a DN string is of the experimental DNS-style DN (generally in the form of an RFC 822 email address) or the RFC 1779 formatted DN.

Description

This function is specific to LDAP v2 and should not be used when dealing with LDAP v3 servers or data.

The ldap_is_ldap_url() function determines whether or not a URL is an LDAP URL.

Syntax
#include <ldap.h>
int ldap_is_ldap_url( const char *url );
Parameters
ldap_is_ldap_url() Function Parameter
Parameter Description
url The URL that you want to check.
Returns

One of the following values:

  • 1 if the URL is an LDAP URL.
  • 0 if the URL is not an LDAP URL.
Description

The ldap_is_ldap_url() function determines whether or not a URL is an LDAP URL. An LDAP URL is a URL with the protocol set to ldap:// (or ldaps://, if the server is communicating over a SSL connection).

Example

The following example determines if a URL is a LDAP URL.

#include <stdio.h>
#include <ldap.h>
...
char *my_url = "ldap://ldap.sun.com/dc=example,dc=com";
...
if ( ldap_is_ldap_url( my_url ) != 0 ) {
  printf( "%s is an LDAP URL.\n", my_url );
} else {
  printf( "%s is not an LDAP URL.\n", my_url );
}
...
See Also

ldap_url_parse()

ldap_keysort_entries()

The ldap_keysort_entries() function is used for sorting entries.

Syntax
#include <ldap-extension.h>
int ldap_keysort_entries( LDAP *ld, LDAPMessage **chain,
  void *arg, LDAP_KEYGEN_CALLBACK *gen, LDAP_KEYCMP_CALLBACK *cmp,
  LDAP_KEYFREE_CALLBACK *fre );
Parameters
ldap_keysort_entries() Function Parameter
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
chain Chain of entries returned by the ldap_result() or ldap_search_s() function.
arg Pointer to an additional argument that you want to pass.
gen Callback used to generate the key(s) for sorting once the compare function has been applied.
cmp Comparison function used when sorting the values.
fre Callback used to free the key once the compare function has been applied.
See Also

LDAP_KEYGEN_CALLBACK(), LDAP_KEYCMP_CALLBACK(), LDAP_KEYFREE_CALLBACK()

ldap_memcache_destroy()

The ldap_memcache_destroy() function frees an LDAPMemCache structure from memory.

Syntax
#include <ldap.h>
void ldap_memcache_destroy( LDAPMemCache *cache );
Parameters
ldap_memcache_destroy() Function Parameter
Parameter Description
cache Pointer to the LDAPMemCache structure that you want freed from memory.
Description

The ldap_memcache_destroy() function frees the specified LDAPMemCache structure from memory. Call this function after you are done working with a cache.

See Also

ldap_memcache_init()

ldap_memcache_flush()

The ldap_memcache_flush() function flushes items from the specified cache.

Syntax
#include <ldap.h>
void ldap_memcache_flush( LDAPMemCache *cache, char *dn,
  int scope );
Parameters
ldap_memcache_flush() Function Parameters
Parameter Description
cache Pointer to the LDAPMemCache structure that you want to flush entries from.
dn Base DN identifying the search requests that you want flushed from the cache. If the base DN of a search request is within the scope specified by this DN and the scope argument, the search request is flushed from the cache. If this argument is NULL, the entire cache is flushed.
scope Scope that (together with the dn argument) identifies the search requests that you want flushed from the cache. If the base DN of the request is within the scope specified by this argument and the dn argument, the request is flushed from the cache. This argument can have one of the following values: *LDAP_SCOPE_BASE *LDAP_SCOPE_ONELEVEL *LDAP_SCOPE_SUBTREE
Description

The ldap_memcache_flush() function flushes search requests from the cache. If the base DN of a search request is within the scope specified by the dn and scope arguments, the search request is flushed from the cache. If no DN is specified, the entire cache is flushed.

ldap_memcache_get()

The ldap_memcache_get() function gets the in-memory cache associated with an LDAP connection handle.

Syntax
#include <ldap.h>
int ldap_memcache_get( LDAP *ld, LDAPMemCache **cachep );
Parameters
ldap_memcache_get() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
cachep When you call ldap_memcache_get(), it sets this parameter to the pointer to the LDAPMemCache structure associated with the connection handle.
Returns

One of the following values:

  • LDAP_SUCCESS if the cache for the specified connection handle was retrieved successfully.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
Description

The ldap_memcache_get() function gets the cache associated with the specified connection handle (LDAP structure). This cache is used by all search requests made through that connection. You can call this function if you want to associate a cache with multiple LDAP connection handles. For example, you can call this function to get the cache associated with one connection, then you can call the ldap_memcache_set() function to associate the cache with another connection.

See Also

ldap_memcache_set()

ldap_memcache_init()

The ldap_memcache_init() function creates an in-memory cache for your LDAP client that you can associate with an LDAP connection.

Syntax
#include <ldap.h>
int ldap_memcache_init( unsigned long ttl, unsigned long size,
  char **baseDNs, struct ldap_thread_fns *thread_fns,
  LDAPMemCache **cachep );
Parameters
ldap_memcache_init() Function Parameters
Parameter Description
ttl The maximum amount of time (in seconds) that an item can be cached. If 0, there is no limit to the amount of time that an item can be cached.
size Maximum amount of memory (in bytes) that the cache will consume. If 0, the cache has no size limit.
baseDNs An array of the base DN strings representing the base DNs of the search requests you want cached. If not NULL, only the search requests with the specified base DNs will be cached. If NULL, all search requests are cached.
thread_fns An ldap_thread_fns structure specifying the functions that you want used to ensure that the cache is thread-safe. You should specify this if you have multiple threads that are using the same connection handle and cache. If you are not using multiple threads, pass NULL for this parameter.
cachep When you call this function, it sets this parameter to the pointer to the newly created LDAPMemCache structure.
Returns

One of the following values:

  • LDAP_SUCCESS if the cache for the specified connection handle was retrieved successfully.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_SIZELIMIT_EXCEEDED if the initial size of the cache (specified by the size argument) is too small.
Description

The ldap_memcache_init() function creates an in-memory, client-side cache that you can use to cache search requests. The function passes back a pointer to an LDAPMemCache structure, which represents the cache. You should call the ldap_memcache_set() function to associate this cache with an LDAP connection handle (an LDAP structure). The cache uses search criteria as the key to cached items. When you send a search request, the cache checks the search criteria to determine if that request has been cached previously. If the request was cached, the search results are read from the cache. To flush the cache, call the ldap_memcache_flush() function. When you are done with the cache, you can free it from memory by calling the ldap_memcache_destroy() function.

Note: On Windows systems, if the ldap_memcache_init() function returns an LDAP_PARAM_ERROR result code, verify that your client is using the version of the nsldap32v30.dll file provided with the Directory SDK For C.

See Also

LDAPMemCache(), ldap_memcache_set() , ldap_memcache_flush(), ldap_memcache_destroy(), ldap_memcache_update()

ldap_memcache_set()

The ldap_memcache_set() function associates an in-memory cache with an LDAP connection handle.

Syntax
#include <ldap.h>
int ldap_memcache_set( LDAP *ld, LDAPMemCache *cache );
Parameters
ldap_memcache_set() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
cache Pointer to an LDAPMemCache structure, which represents the cache that you want used for this connection.
Returns

One of the following values:

  • LDAP_SUCCESS if the cache for the specified connection handle was retrieved successfully.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_SIZELIMIT_EXCEEDED if the initial size of the cache (specified by the size argument) is too small.
Description

The ldap_memcache_set() function associates a cache (created by calling ldap_memcache_init()) with an LDAP connection handle. You can call this function if you want to associate a cache with multiple LDAP connection handles. For example, you can call the ldap_memcache_get() function to get the cache associated with one connection, then you can call ldap_memcache_set() to associate the cache with another connection. After you call this function, search requests made over the specified LDAP connection will use this cache. Calling the ldap_unbind() function will disassociate the cache from the LDAP connection handle.

See Also

ldap_memcache_init(), ldap_memcache_get()

ldap_memcache_update()

The ldap_memcache_update() function checks the cache for items that have expired and removes them.

Syntax
#include <ldap.h>
void ldap_memcache_update( LDAPMemCache *cache );
Parameters
ldap_memcache_update() Function Parameter
Parameter Description
cache Pointer to an LDAPMemCache structure, which represents the cache that you want to updated.
Description

The ldap_memcache_update() function checks the cache for items that have expired and removes them. This check is typically done as part of the way the cache normally works. You do not need to call this function unless you want to update the cache at this point in time.

Note: This function is only useful in a multithreaded application, since it will not return until the cache is destroyed.

See Also

ldap_memcache_flush()

ldap_memfree()

The ldap_memfree() function frees memory allocated by an LDAP API function call.

Syntax
#include <ldap.h>
void ldap_memfree( void *p );
Parameters
ldap_memfree() Function Parameter
Parameter Description
p Pointer to memory used by the LDAP library.
Example

the following example frees the memory allocated by the ldap_get_dn() function. Using ldap_memfree()

#include <ldap.h>
...
LDAP *ld;
char *dn;
LDAPMessage *entry;
...
/* Get the distinguished name (DN) for an entry */
dn = ldap_get_dn( ld, entry );
...
/* When you are finished working with the DN, free the memory allocated. */
ldap_memfree( dn );
...
See Also

ldap_free_friendlymap(), ldap_free_urldesc(), ldap_msgfree(), ldap_value_free(), ldap_value_free_len()

ldap_modify()

The ldap_modify() function modifies an existing entry in the directory asynchronously.

#include <ldap.h>
int ldap_modify( LDAP *ld, const char *dn, LDAPMod **mods );
Parameters
ldap_modify() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to modify.
mods Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes that you want to modify.
Returns

Returns the message ID of the ldap_modify() operation. To check the result of this operation, call ldap_result() and ldap_result2error(). For a list of possible result codes for an LDAP modify operation, see ldap_modify_ext_s().

Description

Please use the newer version of this function, ldap_modify_ext() .

Example

The following example uses the asynchronous ldap_modify() function to modify the entry for Barbara Jensen in the directory. It makes the following changes to the entry:

  • Adds the homePhone attribute.
  • Changes the telephoneNumber attribute.
  • Removes the facsimileTelephoneNumber attribute.
#include <ldap.h>
...
LDAP *ld;
LDAPMod *list_of_attrs[4];
LDAPMod attribute1, attribute2, attribute3;
LDAPMessage *result;
int msgid, rc;
struct timeval tv;
/* Distinguished name of the entry that you want to modify. */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* Values to add or change */
char *homePhone_values[] = { "555-1212", NULL };
char *telephoneNumber_values[] = { "869-5309", NULL };
...
/* Specify each change in separate LDAPMod structures */
attribute1.mod_type = "homePhone";
attribute1.mod_op = LDAP_MOD_ADD;
attribute1.mod_values = homePhone_values;
attribute2.mod_type = "telephoneNumber";
attribute2.mod_op = LDAP_MOD_REPLACE;
attribute2.mod_values = telephoneNumber_values;
attribute3.mod_type = "facsimileTelephoneNumber";
attribute3.mod_op = LDAP_MOD_DELETE;
attribute3.mod_values = NULL;
/* NOTE: When removing entire attributes, you need to specify a NULL value
* for the mod_values field. */
/* Add the pointers to these LDAPMod structures to an array */
list_of_attrs[0] = &attribute1;
list_of_attrs[1] = &attribute2;
list_of_attrs[2] = &attribute3;
list_of_attrs[3] = NULL;
...
/* Set up the timeout period to wait for the "modify" operation */
tv.tv_sec = tv.tv_usec = 0;
/* Change the entry */
if ( ( msgid = ldap_modify( ld, dn, list_of_attrs ) ) == -1 ) {
  ldap_perror( ld, "ldap_modify" );
  return( 1 );
}
/* Check to see if the operation has completed */
while ( ( rc = ldap_result( ld, msgid, 0, &tv, &result ) ) == 0 ) {
  ...
  /* do other work while waiting for the operation to complete */
  ...
}
/* Check the result to see if any errors occurred */
ldap_result2error( ld, result, 1 );
ldap_perror( ld, "ldap_modify" );
...
See Also

ldap_modify_ext()

ldap_modify_ext()

The ldap_modify_ext() function modifies an existing entry in the directory asynchronously. Note: ldap_modify_ext() is a new version of the ldap_modify() function. If you are writing a new LDAP client, use ldap_modify_ext().

Syntax
#include <ldap.h>
int ldap_modify_ext( LDAP *ld, const char *dn, LDAPMod **mods,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  int *msgidp );
Parameters
ldap_modify_ext() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to modify.
mods Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes that you want to modify.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
msgidp Pointer to an integer that will be set to the message ID of the LDAP operation. To check the result of this operation, call ldap_result() and ldap_parse_result().
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
Description

The ldap_modify_ext() modifies an entry in the directory asynchronous; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_modify_ext_s() instead. In order to get the results of this LDAP modify operation, you need to call the ldap_result() and the ldap_parse_result() functions. To make changes to an entry to the directory, you need to specify the following information:

  • A unique DN identifying the new entry

Use the dn argument to specify the DN of the entry you want to modify.

  • A set of attributes for the new entry

Create an LDAPMod structure for changes that you want to make to an attribute. Create an array of these LDAPMod structures and pass the array as the mods argument.

See Also

ldap_modify_ext_s(), ldap_result(), ldap_parse_result(), LDAPMod()

ldap_modify_ext_s()

The ldap_modify_ext_s() modifies an existing entry in the directory synchronously.

#include <ldap.h>
int ldap_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods,
  LDAPControl **serverctrls, LDAPControl **clientctrls );
Parameters
ldap_modify_ext_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to modify.
mods Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes that you want to modify.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

Note: Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.

Description

The ldap_modify_ext_s() modifies an entry in the directory. ldap_modify_ext_s() is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_modify_ext() instead. To make changes to an entry to the directory, you need to specify the following information:

  • A unique DN identifying the new entry

Use the dn argument to specify the DN of the entry that you want to modify.

  • A set of attributes for the new entry

Create an LDAPMod structure for change that you want to make to an attribute. Create an array of these LDAPMod structures and pass the array as the mods argument.

See Also

ldap_modify_ext(), LDAPMod

ldap_modify_s()

The ldap_modify_s() function modifies an existing entry in the directory synchronously.

#include <ldap.h>
int ldap_modify_s( LDAP *ld, const char *dn, LDAPMod **mods );
Parameters
ldap_modify_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to modify.
mods Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes that you want to modify.
Returns

For a list of possible result codes for an LDAP modify operation, see ldap_modify_ext_s().

Description

Use the newer version of this function, ldap_modify_ext_s() .

Example

The following example uses the synchronous ldap_modify_s() function to makes the following changes to the Barbara Jensen entry:

  • Adds the homePhone attribute.
  • Changes the telephoneNumber attribute.
  • Removes the facsimileTelephoneNumber attribute.
#include <ldap.h>
...
LDAP *ld;
LDAPMod *list_of_attrs[4];
LDAPMod attribute1, attribute2, attribute3;
LDAPControl **srvrctrls, **clntctrls;
/* Distinguished name of the entry that you want to modify. */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* Values to add or change */
char *homePhone_values[] = { "555-1212", NULL };
char *telephoneNumber_values[] = { "869-5309", NULL };
...
/* Specify each change in separate LDAPMod structures */
attribute1.mod_type = "homePhone";
attribute1.mod_op = LDAP_MOD_ADD;
attribute1.mod_values = homePhone_values;
attribute2.mod_type = "telephoneNumber";
attribute2.mod_op = LDAP_MOD_REPLACE;
attribute2.mod_values = telephoneNumber_values;
attribute3.mod_type = "facsimileTelephoneNumber";
attribute3.mod_op = LDAP_MOD_DELETE;
attribute3.mod_values = NULL;
/* NOTE: When removing entire attributes, you need to specify a NULL value
* for the mod_values or mod_bvalues field. */
/* Add the pointers to these LDAPMod structures to an array */
list_of_attrs[0] = &attribute1;
list_of_attrs[1] = &attribute2;
list_of_attrs[2] = &attribute3;
list_of_attrs[3] = NULL;
...
/* Change the entry */
if ( ldap_modify_s( ld, dn, list_of_attrs ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_modify_s" );
  return( 1 );
}
...
See Also

ldap_modify_ext_s()

ldap_modrdn()

Note: This function is deprecated and should not be used. It is included in ldap-deprecated.h for backward-compatibility. Use ldap_rename() instead.

ldap_modrdn_s()

Note: This function is deprecated and should not be used. It is included in ldap-deprecated.h for backward-compatibility. Use ldap_rename() instead.

The ldap_modrdn2() function changes the relative distinguished name (RDN) of an entry in the directory asynchronously.

Syntax
#include <ldap-deprecated.h>
int ldap_modrdn2( LDAP *ld, const char *dn, const char *newrdn,
  int deleteoldrdn );
Parameters
ldap_modrdn2() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to modify.
newrdn New RDN to assign to the entry.
deleteoldrdn If this is a non-zero value, the old RDN is not retained as a value in the modified entry. If 0, the old RDN is retained as an attribute in the modified entry.
Returns

Returns the message ID of the ldap_modrdn2() operation. To check the result of this operation, call ldap_result() and ldap_result2error(). For a list of possible result codes, see ldap_rename().

Description

Please use the newer version of this function, ldap_rename() .

Example

The following example uses the asynchronous ldap_modrdn2() function to change the RDN of an entry from uid=bjensen to uid=babs. The code removes the existing RDN bjensen from the uid attribute of the entry.

#include <ldap-deprecated.h>
...
LDAP *ld;
LDAPMessage *result;
int msgid, rc;
struct timeval tv;
/* Distinguished name of the entry that you want to rename. */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* New relative distinguished name (RDN) of the entry */
char *rdn = "uid=babs";
...
/* Set up the timeout period to wait for the "modify RDN" operation */
tv.tv_sec = tv.tv_usec = 0;
/* Rename the entry */
if ( ( msgid = ldap_modrdn2( ld, dn, rdn, 1 ) ) == -1 ) {
  ldap_perror( ld, "ldap_modrdn2" );
  return( 1 );
}
/* Check to see if the operation has completed */
while ( ( rc = ldap_result( ld, msgid, 0, &tv, &result ) ) == 0 ) {
  ...
  /* do other work while waiting for the operation to complete */
  ...
}
/* Check the result to see if any errors occurred */
ldap_result2error( ld, result, 1 );
ldap_perror( ld, "ldap_modrdn2" );
...
See Also

ldap_rename()

ldap_modrdn2_s()

#include <ldap-deprecated.h>
int ldap_modrdn2_s( LDAP *ld, const char *dn,
  const char *newrdn, int deleteoldrdn );
Parameters
ldap_modrdn2_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to modify.
newrdn New RDN to assign to the entry.
deleteoldrdn If this is a non-zero value, the old RDN is not retained as a value in the modified entry. If 0, the old RDN is retained as an attribute in the modified entry.
Returns

For a list of possible result codes, see ldap_rename_s() .

Description

Please use the newer version of this function, ldap_rename_s() .

Example

The following example uses the synchronous ldap_modrdn2_s() function to change the RDN of an entry from uid=bjensen to uid=babs. The code removes the existing RDN babs from the uid attribute of the entry.

#include <ldap.h>
...
LDAP *ld;
/* Distinguished name of the entry that you want to rename. */
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
/* New relative distinguished name (RDN) of the entry */
char *rdn = "uid=babs";
...
/* Rename the entry */
if ( ldap_modrdn2_s( ld, dn, rdn, 1 ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_modrdn2_s" );
  return( 1 );
}
...
See Also

ldap_rename_s()

ldap_mods_free()

The ldap_mods_free() function frees the LDAPMod structures that you’ve allocated to add or modify entries.

Note: You need to call this function only if you’ve allocated memory for these structures yourself. For more information, see the ldap-extension.h header file.

Syntax
#include <ldap.h>
void ldap_mods_free( LDAPMod **mods, int freemods );
Parameters
ldap_mods_free() Function Parameters
Parameter Description
mods Pointer to a NULL terminated array of pointers to LDAPMod structures.
freemods If this is a non-zero value, frees the array of pointers as well as the LDAPMod structures. If 0, just frees the LDAPMod structures.
Example

The following example allocates memory for LDAPMod structures and frees them when done.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
char *dn;
int i, msgid;
LDAPMod **mods;
...
/* Construct the array of values to add */
mods = ( LDAPMod ** ) malloc(( NMODS + 1 ) * sizeof( LDAPMod * ));
if ( mods == NULL ) {
  fprintf( stderr, "Cannot allocate memory for mods array\n" );
}
for ( i = 0; i < NMODS; i++ ) {
  if (( mods[ i ] = ( LDAPMod * ) malloc( sizeof( LDAPMod ))) == NULL) {
    fprintf( stderr, "Cannot allocate memory for mods element\n" );
    exit( 1 );
  }
}
...
/* Code for filling the structures goes here. */
...
/* Initiate the add operation */
if (( msgid = ldap_add( ld, dn, mods )) < 0 ) {
  ldap_perror( ld, "ldap_add" );
  ldap_mods_free( mods, 1 );
  return( 1 );
}
...

ldap_msgfree()

The ldap_msgfree() function frees the memory allocated for a result by ldap_result() or ldap_search_s().

Syntax
#include <ldap.h>
int ldap_msgfree( LDAPMessage *lm );
Parameters
ldap_msgfree() Function Parameter
Parameter Description
lm Pointer to the result to be freed from memory.
Returns

One of the following values:

  • LDAP_RES_BIND indicates that the LDAPMessage structure contains the result of an LDAP bind operation.
  • LDAP_RES_SEARCH_ENTRY indicates that the LDAPMessage structure contains an entry found during an LDAP search operation.
  • LDAP_RES_SEARCH_REFERENCE indicates that the LDAPMessage structure contains an LDAP v3 search reference (a referral to another LDAP server) found during an LDAP search operation.
  • LDAP_RES_SEARCH_RESULT indicates that the LDAPMessage structure contains the result of an LDAP search operation.
  • LDAP_RES_MODIFY indicates that the LDAPMessage structure contains the result of an LDAP modify operation.
  • LDAP_RES_ADD indicates that the LDAPMessage structure contains the result of an LDAP add operation.
  • LDAP_RES_DELETE indicates that the LDAPMessage structure contains the result of an LDAP delete operation.
  • LDAP_RES_MODRDN or LDAP_RES_RENAME indicates that the LDAPMessage structure contains the result of an LDAP modify DN operation.
  • LDAP_RES_COMPARE indicates that the LDAPMessage structure contains the result of an LDAP compare operation.
  • LDAP_RES_EXTENDED indicates that the LDAPMessage structure contains the result of an LDAP v3 extended operation.
  • LDAP_SUCCESS if the operation times out.
  • -1 indicates that the lm argument is not a pointer to a valid LDAPMessage structure.
  • If unsuccessful, returns the LDAP error code for the operation.
Example

The following example frees the results of a search.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
char *get_attr[] = { "cn", "mail", NULL };
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  get_attr, 0, &result ) != LDAP_SUCCESS ) {
     ldap_perror( ld, "ldap_search_s" );
     return( 1 );
}
...
/* Free the results when done */
ldap_msgfree( result );
...
See Also

ldap_result(), ldap_search_s()

ldap_msgid()

The ldap_msgid() function determines the message ID of a result obtained by calling ldap_result() or ldap_search_s().

Syntax
#include <ldap.h>
int ldap_msgid( LDAPMessage *lm );
Parameters
ldap_msgid() Function Parameter
Parameter Description
lm Pointer to the result to check.
Returns

One of the following values:

  • The message ID if successful.
  • -1 if unsuccessful.
Example

The following example prints the message ID from the result obtained from a synchronous LDAP search operation.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result;
...
/* Perform a search */
if ( ldap_search_s( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE, MY_FILTER,
  NULL, 0, &result ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Get and print the message ID */
if ( ldap_msgid( result ) != -1 ) {
  printf( "Message ID: %d\n" );
} else {
  printf( "An error occurred.\n" );
}
...
See Also

ldap_msgtype(), ldap_result() , ldap_search_s()

ldap_msgtype()

The ldap_msgtype() function determines the type of result obtained by calling ldap_result() or ldap_search_s().

Syntax
#include <ldap.h>
int ldap_msgtype( LDAPMessage *lm );
Parameters
ldap_msgtype() Function Parameter
Parameter Description
lm Pointer to the LDAPMessage structure to check.
Returns

One of the following values:

  • LDAP_RES_BIND indicates that the LDAPMessage structure contains the result of an LDAP bind operation.
  • LDAP_RES_SEARCH_ENTRY indicates that the LDAPMessage structure contains an entry found during an LDAP search operation.
  • LDAP_RES_SEARCH_REFERENCE indicates that the LDAPMessage structure contains an LDAP v3 search reference (a referral to another LDAP server) found during an LDAP search operation.
  • LDAP_RES_SEARCH_RESULT indicates that the LDAPMessage structure contains the result of an LDAP search operation.
  • LDAP_RES_MODIFY indicates that the LDAPMessage structure contains the result of an LDAP modify operation.
  • LDAP_RES_ADD indicates that the LDAPMessage structure contains the result of an LDAP add operation.
  • LDAP_RES_DELETE indicates that the LDAPMessage structure contains the result of an LDAP delete operation.
  • LDAP_RES_MODRDN or LDAP_RES_RENAME indicates that the LDAPMessage structure contains the result of an LDAP modify DN operation.
  • LDAP_RES_COMPARE indicates that the LDAPMessage structure contains the result of an LDAP compare operation.
  • LDAP_RES_EXTENDED indicates that the LDAPMessage structure contains the result of an LDAP v3 extended operation.
  • -1 indicates that the lm argument is not a pointer to a valid LDAPMessage structure.
Example

The following example prints the message type for a result obtained from a synchronous LDAP search operation.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result;
int msgtype;
...
/* Perform a search */
if ( ldap_search_s( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE, MY_FILTER,
  NULL, 0, &result ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Get and print the message type */
msgtype = ldap_msgtype( result );
if ( msgtype != -1 ) {
  printf( "Message type: %d\n", msgtype );
} else {
  printf( "An error occurred.\n" );
}
...
See Also

ldap_msgid(), ldap_result() , ldap_search_s()

ldap_multisort_entries()

The ldap_multisort_entries() function sorts a chain of entries retrieved from an LDAP search call (ldap_search_s() or ldap_result()) by either a specified set of attributes in the entries or DN.

Syntax
#include <ldap.h>
int ldap_multisort_entries( LDAP *ld, LDAPMessage **chain,
  char **attr, LDAP_CMP_CALLBACK *cmp );
Parameters
ldap_multisort_entries() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
chain Chain of entries returned by the ldap_result() or ldap_search_s() function.
attr Array of attributes to use for sorting the results. If NULL, results are sorted by DN.
cmp Comparison function used when sorting the values.
Returns

One of the following values:

  • 0 if successful.
  • -1 if memory cannot be allocated by this function. (The error code LDAP_NO_MEMORY is set in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.)
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function
Example

The following example sorts entries first by the roomNumber attribute, then by the telephoneNumber attribute.

#include <stdio.h>
#include <string.h>
#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
char *attrs[3];
attrs[0] = "roomNumber";
attrs[1] = "telephoneNumber";
attrs[2] = NULL;
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  NULL, 0, &result ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
/* Sort the results, using strcasecmp */
if ( ldap_multisort_entries( ld, &result, attrs, strcasecmp ) !=
  LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_multisort_entries" );
    return( 1 );
}
...
See Also

ldap_result(), ldap_search_s() , ldap_sort_entries(), LDAP_CMP_CALLBACK()

ldap_name2template()

The ldap_name2template() function obtains a pointer to the correct ldap_disptmpl structure.

Syntax
#include <disptmpl.h>
struct ldap_disptmpl * ldap_name2template( char *name
  struct ldap_disptmpl *tmpllist );
Parameters
ldap_name2template() Function Parameters
Parameter Description
name Name of the template.
tmpllistp Pointer to a list of template data structures.
Returns
  • If successful, 0 is returned and tmpllistp is configured.
  • Upon error:
    • LDAP_TMPL_ERR_VERSION if buf points to data that is newer than can be handled.
    • LDAP_TMPL_ERR_MEM if there is a memory allocation problem.
    • LDAP_TMPL_ERR_SYNTAX if there is a problem with the format of the templates buffer or file.
    • LDAP_TMPL_ERR_FILE if the file cannot be read.
Description

ldap_name2template() obtains a pointer to the correct ldap_disptmpl structure. Links to templates can be defined by name.

ldap_next_attribute()

The ldap_next_attribute() function returns the name of the next attribute in an entry returned by ldap_first_entry() or ldap_next_entry().

Syntax
#include <ldap.h>
char * ldap_next_attribute( LDAP *ld, LDAPMessage *entry,
  BerElement *ber);
Parameters
ldap_next_attribute() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
entry Pointer to the LDAPMessage structure representing the entry returned by the ldap_first_entry() or ldap_next_entry() function.
ber A pointer to a BerElement allocated to keep track of its current position. Pass this pointer to subsequent calls to ldap_next_attribute() to step through the entry's attributes.
Returns

One of the following values:

  • If successful, returns the name of the next attribute in an entry. When you are done using this data, you should free the memory by calling the ldap_memfree() function.
  • If no more attributes exist in the entry, returns a NULL .
  • If unsuccessful, returns a NULL and sets the appropriate error code in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
Description

The ldap_first_attribute() function returns a pointer to a BerElement. You use this pointer with ldap_next_attribute() to iterate through the list of elements. After the last call to ldap_next_element(), you should free the BerElement pointer using ldap_ber_free(). When calling ldap_ber_free(), make sure to specify that the buffer is not freed (pass 0 for the freebuf parameter).

Example

See the example under ldap_first_attribute().

See Also

ldap_first_attribute(), ldap_getfirstfilter(), ldap_next_entry()

ldap_next_disptmpl()

The ldap_next_disptmpl() function returns the next template in a list.

Syntax
#include <disptmpl.h>
struct ldap_disptmpl * ldap_next_disptmpl( struct ldap_disptmpl *tmpllist,
  struct ldap_disptmpl *tmpl );;
Parameters
ldap_next_disptmpl() Function Parameters
Parameter Description
tmpl Defines a template from the template list tmpllist. A NULL pointer is returned if tmpl is the last template in the list.
tmpllistp Pointer to a list of template data structures typically obtained by calling ldap_init_templates().
Returns
  • If successful, 0 is returned and tmpllistp is configured.
  • Upon error:
    • LDAP_TMPL_ERR_VERSION if buf points to data that is newer than can be handled.
    • LDAP_TMPL_ERR_MEM if there is a memory allocation problem.
    • LDAP_TMPL_ERR_SYNTAX if there is a problem with the format of the templates buffer or file.
    • LDAP_TMPL_ERR_FILE if the file cannot be read.
Description

ldap_next_disptmpl() returns the template following the previous one in the list of templates pointed to by the parameter tmpllistp. tmpllistp is typically obtained by calling ldap_init_templates() .

See Also

ldap_first_disptmpl()

ldap_next_entry()

The ldap_next_entry() function returns a pointer to the LDAPMessage structure representing the next directory entry in a chain of search results.

Syntax
#include <ldap.h>
LDAPMessage * ldap_next_entry( LDAP *ld, LDAPMessage *entry );
Parameters
ldap_next_entry() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
entry Pointer to an LDAPMessage structure in a chain of search results.
Returns

One of the following values:

  • If successful, returns the pointer to the next LDAPMessage structure of the type LDAP_RES_SEARCH_ENTRY in a chain of search results.
  • If no more LDAPMessage structures of the type LDAP_RES_SEARCH_ENTRY are in the chain or if the function is unsuccessful, returns a NULLMSG.
Description

The ldap_next_entry() function returns a pointer to the LDAPMessage structure representing the next directory entry in a chain of search results. You can use this function in conjunction with the ldap_first_entry() function to iterate through the directory entries in a chain of search results. These functions skip over any messages in the chain that do not have the type LDAP_RES_SEARCH_ENTRY as messages containing directory entries have the type LDAP_RES_SEARCH_ENTRY.

See Also

ldap_first_entry()

ldap_next_message()

The ldap_next_message() function returns a pointer to the next LDAPMessage structure in a chain of search results.

Syntax
#include <ldap.h>
LDAPMessage * ldap_next_message( LDAP *ld, LDAPMessage *msg );
Parameters
ldap_next_message() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
msg Pointer to an LDAPMessage structure in a chain of search results.
Returns

One of the following values:

  • If successful, returns the pointer to the next LDAPMessage structure in a chain of search results.
  • If no more LDAPMessage structures are in the chain or if the function is unsuccessful, returns a NULLMSG.
Description

The ldap_next_message() function returns a pointer to the next LDAPMessage structure in a chain of search results. You can use this function in conjunction with the ldap_first_message() function to iterate through the chain of search results. You can also call the ldap_msgtype() function to determine if each message contains a matching entry (a message of the type LDAP_RES_SEARCH_ENTRY ) or a search reference (a message of the type LDAP_RES_SEARCH_REFERENCE).

See Also

ldap_first_message(), ldap_msgtype()

ldap_next_reference()

The ldap_next_reference() function returns a pointer to the LDAPMessage structure representing the next search reference in a chain of search results.

Syntax
#include <ldap.h>
LDAPMessage * ldap_next_reference( LDAP *ld, LDAPMessage *ref );
Parameters
ldap_next_reference() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
msg Pointer to an LDAPMessage structure in a chain of search results.
Returns

One of the following values:

  • If successful, returns the pointer to the next LDAPMessage structure of the type LDAP_RES_SEARCH_REFERENCE in a chain of search results.
  • If no more LDAPMessage structures of the type LDAP_RES_SEARCH_REFERENCE are in the chain or if the function is unsuccessful, returns a NULLMSG.
Description

The ldap_next_reference() function returns a pointer to the LDAPMessage structure representing the next search reference in a chain of search results. You can use this function in conjunction with the ldap_first_reference() function to iterate through the search references in a chain of search results. These functions skip over any messages in the chain that do not have the type LDAP_RES_SEARCH_REFERENCE. Messages containing search references have the type LDAP_RES_SEARCH_REFERENCE, continuation references as specified in LDAPv3 that are stored as referral entries. Like a referral, each continuation reference itself may contain a number of URLs assumed to be equivalent, and the client should use one of those URLs.

See Also

ldap_first_reference()

ldap_next_searchobj()

The ldap_next_searchobj() function returns the following search preference in a defined list.

Syntax
#include <ldap.h>
struct ldap_searchobj * ldap_next_searchobj
  ( struct ldap_searchobj *sollist, struct ldap_searchobj *so );
Parameters
ldap_next_searchobj() Function Parameters
Parameter Description
sollist Pointer to a list of data structures, typically obtained by calling ldap_init_searchprefs().
so Pointer to the most recent search object returned in the template list sollist. The search object returned by ldap_next_searchobj() follows this one.
Returns
  • If successful, a pointer to an ldap_searchobj structure.
  • A NULL pointer is returned if so is the last entry in the list.
Description

The search object returned by ldap_next_searchobj() follows the one defined by the so parameter.

See Also

ldap_init_searchprefs(), ldap_first_searchobj()

ldap_next_tmplcol()

The ldap_next_tmplcol() function returns a pointer to the following item (in the column) within a template.

Syntax
#include <disptmpl.h>
struct ldap_tmplitem * ldap_next_tmplcol( struct ldap_disptmpl *tmpl,
  struct ldap_tmplitem *row, struct ldap_tmplitem *col );
Parameters
ldap_next_tmplcol() Function Parameters
Parameter Description
tmpl The name of the template to be retrieved.
row The row in which the item is to be retrieved from.
col The column in which the item is to be retrieved from.
Returns
  • If successful, a pointer to an ldap_tmplitem structure.
  • A NULL pointer on error or if col was the last item.
Description

ldap_next_tmplcol() returns a pointer to the next item (in the column) of the row, defined by row, within the template defined by tmpl.

See Also

ldap_first_tmplcol()

ldap_next_tmplrow()

The ldap_next_tmplrow() function returns a pointer to the following row in a template.

Syntax
#include <disptmpl.h>
struct ldap_tmplitem * ldap_next_tmplrow( struct ldap_disptmpl *tmpl,
  struct ldap_tmplitem *row );
Parameters
ldap_next_tmplrow() Function Parameters
Parameter Description
tmpl The name of the template to be retrieved.
row The row in the template to be retrieved.
Returns
  • If successful, a pointer to an ldap_tmplitem structure.
  • A NULL pointer on error.
Description

ldap_next_tmplrow() returns a pointer to the row that follows the one defined by row in the template defined by tmpl .

ldap_oc2template()

The ldap_oc2template() function obtains a pointer to the correct ldap_disptmpl structure.

Syntax
#include <disptmpl.h>
struct ldap_disptmpl * ldap_oc2template( char **oclist,
  struct ldap_disptmpl *tmpllist );
Parameters
ldap_oc2template() Function Parameters
Parameter Description
oclist A NULL terminated array of strings that contains the values of the objectClass attribute of the entry.
tmpllistp Pointer to a list of template data structures.
Returns
  • Pointer to the first template where all of the object classes listed in one of the template's dt_oclist elements are contained in oclist.
  • A NULL pointer if no appropriate template is found.
Description

ldap_oc2template()searches tmpllist for the best template to use to display an entry that has a specific set of objectClass values.

ldap_open()

#include <ldap-deprecated.h>
ldap_open( const char *host, int port );
Parameters
ldap_open() Function Parameters
Parameter Description
host The hostname on which the LDAP server is running. It may contain a blank-separated list of hosts to try to connect to, and each host may optionally be of the form host:port. If present, port overrides the port parameter. Upon successfully making a connection to an LDAP server, ldap_open() returns a pointer to an LDAP structure, which should be passed to subsequent calls ldap_bind(), ldap_search()
port The port number to which to connect. If the default IANA-assigned port of 389 is desired, LDAP_PORT should be specified as the value of port.
Description

Please use a newer version of this function, ldap_init() or prldap_init() (IPv6).

ldap_parse_authzid_control()

The ldap_parse_authzid_control() function parses the authorization identity bind response control retrieved from the server to extract the authorization ID.

Syntax
#include <ldap.h>
LDAP_API(int) LDAP_CALL ldap_parse_authzid_control( LDAP *ld,
  LDAPControl **ctrlp, char **authzid );
Parameters
ldap_parse_authzid_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
ctrlp Pointer to an LDAPControl structure retrieved from the server.
authzid Pointer to string holding the authorization ID.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
  • LDAP_CONTROL_NOT_FOUND if no control can be found in the response returned from the server.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
See Also

ldap_create_authzid_control()

ldap_parse_entrychange_control()

The ldap_parse_entrychange_control() function examines a list of controls returned from a persistent search operation, retrieves an entry change control, and parses that control for information (such as the type of change made to the entry and the change number).

Note: This function implements an extension to the LDAP v3. Entry change notification is an optional feature; it may not be supported on all LDAP servers. Call this function when interacting with LDAP servers that support this LDAP v3 extension.

Syntax
#include <ldap.h>
int ldap_parse_entrychange_control( LDAP *ld,
  LDAPControl **ctrls, int *chgtypep, char **prevdnp,
  int *chgnumpresentp, long *chgnump );
Parameters
ldap_parse_entrychange_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
ctrlp An array of controls returned by the server. You obtain these controls by calling the ldap_get_entry_controls() function on an entry returned by the server.
changetypes Pointer to an integer specifying the type of change made to the entry. This field can have one of the following values:
  • LDAP_CHANGETYPE_ADD specifies that the entry was added to the directory.
  • LDAP_CHANGETYPE_DELETE specifies that the entry was deleted from the directory.
  • LDAP_CHANGETYPE_MODIFY specifies that the entry was modified.
  • LDAP_CHANGETYPE_MODDN specifies that the DN or RDN of the entry was changed (a modify RDN or modify DN operation was performed).
prevdnp Pointer to the previous DN of the entry, if the changetypes argument is LDAP_CHANGETYPE_MODDN. If the changetypes argument has a different value, this argument is set to NULL. When done, you can free this by calling the ldap_memfree() function.
chgnumpresentp Pointer to an integer specifying whether or not to the change number is included in the control. The parameter can have the following possible values:
  • 0 specifies that the change number is not included.
  • A non-zero value specifies that the change number is included and is available as the chgnump argument.
chgnump Pointer to the change number identifying the change made to the entry, if chgnumpresentp points to a non-zero value.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_DECODING_ERROR if an error occurred when BER-decoding the control.
Description

The ldap_parse_entrychange_control() function can be called:

  • To parse an entry returned from a persistent search operation and retrieve an entry change control.
  • After receiving an entry from a persistent search and retrieving the controls from the entry. Call ldap_get_entry_controls() to get the controls.
See Also

ldap_create_persistentsearch_control(), ldap_get_entry_controls()

ldap_parse_extended_result()

The ldap_parse_extended_result() function parses the results of an LDAP extended operation and retrieves the object identifier (OID) and data returned by the server.

#include <ldap.h>
int ldap_parse_extended_result( LDAP *ld, LDAPMessage *res,
  char **retoidp, struct berval **retdatap, int freeit );
Parameters
ldap_parse_extended_result() Function Parameters
Parameters Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
res Pointer to the LDAPMessage structure containing the results of an LDAP operation.
retoidp Pointer to the OID returned by the server after performing the extended operation. When done, you can free this by calling the ldap_memfree() function.
retdatap Pointer to the pointer to a berval structure containing the data returned by the server after performing the extended operation. When done, you can free this by calling the ber_bvfree() function.
freeit Specifies whether or not to free the results of the operation (the LDAPMessage structure specified by the res argument). The parameter can have the following possible values: *0 specifies that the result should not be freed. *A non-zero value specifies that the result should be freed.
Returns

One of the following values, which indicates the result of parsing the server’s response:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function. Note: This value does not apply to the operation itself.
Description

ldap_parse_extended_result() parses the server’s response to an extended operation. After you call the ldap_extended_operation() and the ldap_result() functions, you can pass the results to ldap_parse_extended_result(). This function gets the following data from the server’s response:

  • The extended operation OID received from the server is passed back as the retoidp argument.
  • The data received from the server is passed back in the berval structure as the retdatap argument.
  • The LDAP result code for the LDAP extended operation is placed in the ld structure. You can get the result code by calling the ldap_get_lderrno() function. For a list of possible result codes for an LDAP extended operation, see ldap_extended_operation_s() . See also ldap_extended_operation_s(), ldap_get_lderrno().

ldap_parse_passwd()

The ldap_parse_passwd() function lets you examine the result of an LDAP Password Modify extended operation to obtain the password generated by the server when you reset a password without providing a new password value.

Syntax
#include <ldap.h>
LDAP_API(int) LDAP_CALL ldap_parse_passwd( LDAP *ld, LDAPMessage *result,
  struct berval *genpasswd );
Parameters
ldap_parse_passwd() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
result Pointer to the message retrieved using the message ID from ldap_passwd().
genpasswd Pointer to the BER value structure to hold the password generated by the server.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_NO_MEMORY if memory cannot be allocated for the authorization identity.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
  • LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

ldap_parse_passwd_result()

The ldap_parse_passwd_result() function lets you examine the result of an LDAP Password Modify extended operation to obtain the password generated by the server when you reset a password without providing a new password value.

Syntax
#include <ldap.h>
LDAP_API(int) LDAP_CALL ldap_parse_passwd_result( LDAP *ld, int *msgidp,
  struct timeval *timeout, struct berval *genpasswd );
Parameters
ldap_parse_passwd_result() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
msgidp Pointer to the message ID retrieved using ldap_passwd().
timeout Specifies a maximum interval to wait for the selection to complete. If timeout is a NULL pointer, the select blocks indefinitely. To effect a poll, the timeout parameter should be a non-NULL pointer, pointing to a zero-valued <structname> timeval</structname> structure.
genpasswd Pointer to the BER value structure to hold the password generated by the server.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_NO_MEMORY if memory cannot be allocated for the authorization identity.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
  • LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

ldap_parse_pwdpolicy_control()

The ldap_parse_pwdpolicy_control() function parses information about the password policy relative to a user account contained in a control returned with a bind, add, modify, or compare result after the ldap_create_userstatus_control() is used to create a request control sent to the server. The ldap_parse_pwdpolicy_control() function populates an LDAPpwdpolicy structure.

Syntax
#include <ldap.h>
LDAP_API(int) LDAP_CALL ldap_parse_pwdpolicy_control( LDAP *ld,
  LDAPControl **ctrlp, LDAPpwdpolicy *pp );
Parameters
ldap_parse_pwdpolicy_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
ctrlp Pointer to an LDAPControl structure retrieved from the server.
pp Pointer to an LDAPpwdpolicy structure to hold the information about password policy.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
  • LDAP_CONTROL_NOT_FOUND if no control can be found in the response returned from the server.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
See Also

ldap_create_pwdpolicy_control(), LDAPpwdpolicy()

ldap_parse_reference()

The ldap_parse_reference() function parses search references from the results received from an LDAP server. Note: Search references are part of the LDAP v3. When calling this function, make sure that you are working with a server that supports the LDAP v3.

Syntax
#include <ldap.h>
int ldap_parse_reference( LDAP *ld, LDAPMessage *ref,
  char ***referralsp, LDAPControl ***serverctrlsp,
  int freeit );
Parameters
ldap_parse_reference() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
ref Pointer to an LDAPMessage structure of the type LDAP_RES_SEARCH_REFERENCE.
referralsp Pointer to an array of strings representing the referrals found by an LDAP search operation and returned by the server (applicable only if the LDAP operation was a search operation). When done, you can free this by calling the ldap_value_free() function.
serverctrlsp Pointer to an array of LDAPControl structures, which represent the LDAP v3 server controls returned by the server. When done, you can free this by calling the ldap_controls_free() function.
freeit Specifies whether or not to free the results of the operation (the LDAPMessage structure specified by the res argument). The parameter can have the following possible values: *0 specifies that the result should not be freed. *A non-zero value specifies that the result should be freed.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
  • LDAP_NO_MEMORY if memory cannot be allocated.
Description

The ldap_parse_reference() function parses the referral URLs from an LDAPMessage structure of the type LDAP_RES_SEARCH_REFERENCE, continuation references as specified in LDAPv3 that are stored as referral entries. Like a referral, each continuation reference itself may contain a number of URLs assumed to be equivalent, and the client should use one of those URLs.

ldap_parse_result()

The ldap_parse_result() function parses the results of an LDAP operation received from an LDAP server.

Syntax
#include <ldap.h>
int ldap_parse_result( LDAP *ld, LDAPMessage *res,
  int *errcodep, char **matcheddnp, char **errmsgp,
  char ***referralsp, LDAPControl ***serverctrlsp, int freeit);
Parameters
ldap_parse_result() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
res Pointer to the LDAPMessage structure containing the results of an LDAP operation.
errcodep Pointer to the LDAP result code specifying the result of the operation.
matcheddnp Pointer to a string specifying the portion of a DN that finds an existing entry (in cases where the server cannot find the entry specified by a DN). When done, you can free this by calling the ldap_memfree() function.
errmsgp Pointer to an additional error message string sent from the server. When done, you can free this by calling the ldap_memfree() function.
referralsp Pointer to an array of strings representing the referrals returned by the server. When done, you can free this by calling the ldap_value_free function.
serverctrlsp Pointer to an array of LDAPControl structures, which represent the LDAPv3 server controls returned by the server. When done, you can free this by calling the ldap_controls_free() function.
freeit Specifies whether or not to automatically free the results of the operation (the LDAPMessage structure specified by the res argument). The parameter can have the following possible values:
  • 0 specifies that the result should not be freed.
  • A non-zero value specifies that the result should be freed.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_NO_RESULTS_RETURNED if the specified LDAPMessage structure does not contain the result of an LDAP operation (for example, if it contains an entry, search reference, or chain of search results instead of the result of an LDAP operation).
  • LDAP_MORE_RESULTS_TO_RETURN if the result in the LDAPMessage structure is part of a chain of results and the last result is not included.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
  • LDAP_NO_MEMORY if memory cannot be allocated.
Description

The ldap_parse_result() function parses the results of an LDAP operation (received from an LDAP server) and retrieves:

  • The LDAP result code that indicates the result of the LDAP operation (errcodep).
  • An additional error message (optional) sent by the server (errmsgp).
  • The portion of the DN that finds an entry, if the server is unable to find an entry from a DN that you specify (matcheddnp).
  • A set of referrals, if the server does not contain the entries that you’ve specified and if the server is configured to refer clients to other servers (referralsp).
  • A set of server response controls that are relevant to the operation (serverctrlsp). Calling this function creates an array of LDAPControl structures that you can pass to subsequent API functions (such as the ldap_parse_sort_control() function.

See also ldap_result().

ldap_parse_sasl_bind_result()

The ldap_parse_sasl_bind_result() function parses the results of an LDAP SASL bind operation and retrieves data returned by the server.

Note: SASL authentication is part of the LDAP v3. When calling this function, make sure that you are working with a server that supports the LDAP v3.

Syntax
#include <ldap.h>
int ldap_parse_sasl_bind_result( LDAP *ld, LDAPMessage *res,
  struct berval **servercredp, int freeit );
Parameters
ldap_parse_sals_bind_result() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
res Pointer to the LDAPMessage structure containing the results of an LDAP operation.
servercredp Pointer to a pointer to an berval structure containing any challenge or credentials returned by the server. When done, you can free this by calling the ber_bvfree() function.
freeit Specifies whether or not to free the results of the operation (the LDAPMessage structure specified by the res argument). The parameter can have the following possible values:
  • 0 specifies that the result should not be freed.
  • A non-zero value specifies that the result should be freed.
Returns

One of the following values, which indicates the result of parsing the server’s response:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

After you call the ldap_sasl_bind() function and the ldap_result() function, you can pass the results to ldap_parse_sasl_bind_result() for parsing. This function gets the following data from the server’s response:

  • The challenge or credentials sent back from the server are passed back in the berval structure as the servercredp argument.
  • The LDAP result code for the SASL bind operation is placed in the ld structure. You can get the result code by calling the ldap_get_lderrno() function. (If the result code is LDAP_SASL_BIND_IN_PROGRESS , you can call ldap_sasl_bind() again to send a response to the server’s challenge and call ldap_result() and ldap_parse_sasl_bind_result() again to get the next challenge from the server. For a list of possible result codes for an LDAP SASL bind operation, see ldap_sasl_bind().

Note: The LDAP server must support authentication through SASL mechanisms. Directory Server supports a plug-in interface that you can use to add SASL support to the server.

See Also

ldap_sasl_bind(), ldap_get_lderrno

ldap_parse_sort_control()

The parse_sort_control() function parses the result returned from a search operation that used a server control for sorting search results.

#include <ldap.h>
int ldap_parse_sort_control( LDAP *ld, LDAPControl **ctrls,
  unsigned long *result, char **attribute );
Parameters
ldap_parse_sort_control() Function Parameters
Parameters Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
ctrls An array of controls returned by the server. You obtain these controls by calling the ldap_parse_result() function on the set of results returned by the server.
result Pointer to the sort control result code retrieved by this function.
attribute If the sorting operation fails, the function sets this to point to the name of the attribute that caused the failure. When done, you can free this by calling the ldap_memfree() function.
Returns

One of the following values, which indicates the result of parsing the server’s response:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
  • LDAP_CONTROL_NOT_FOUND if no control can be found in the response returned from the server.
Description

Call the ldap_parse_sort_control() function as part of the process of retrieving sorted search results from a server. First, though, call ldap_result() to get the results, and ldap_parse_result() to parse the server controls from the results.

See Also

ldap_create_sort_control()

ldap_parse_userstatus_control()

The ldap_parse_userstatus_control() function parses information about the status of a user account contained in a control returned with an entry resulting from a search request that included the control created with ldap_create_userstatus_control(). The ldap_parse_userstatus_control() function populates an LDAPuserstatus structure.

Syntax
#include <ldap.h>
LDAP_API(int) LDAP_CALL ldap_parse_userstatus_control( LDAP *ld,
  LDAPControl **ctrlp, LDAPuserstatus *us );
Parameters
ldap_parse_userstatus_control() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
ctrlp Pointer to an LDAPControl structure retrieved with ldap_get_entry_controls().
us Pointer to an LDAPuserstatus structure to hold the information about account status.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
  • LDAP_CONTROL_NOT_FOUND if no control can be found in the response returned from the server.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
See Also

ldap_create_userstatus_control(), LDAPuserstatus()

ldap_parse_whoami()

The ldap_parse_whoami() function retrieves the authorization identity from the result of an asynchronous Who am I? extended operation request.

Syntax
#include <ldap.h>
LDAP_API(int) LDAP_CALL ldap_parse_whoami_result( LDAP *ld,
  LDAPMessage *result, char **authzid );
Parameters
ldap_parse_whoami() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
result Pointer to the message retrieved using the message ID from ldap_whoami().
authzid Pointer to the string to hold the authorization identity retrieved for the connection.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_NO_MEMORY if memory cannot be allocated for the authorization identity.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
  • LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

ldap_parse_whoami_result()

The ldap_parse_whoami_result() function retrieves the authorization identity from the result of an asynchronous Who am I? extended operation request.

Syntax
#include <ldap.h>
LDAP_API(int) LDAP_CALL ldap_parse_whoami_result( LDAP *ld, int *msgidp,
  struct timeval *timeout, char **authzid );
Parameters
ldap_parse_whoami_result() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
msgidp Pointer to the message ID retrieved using ldap_whoami().
timeout Specifies a maximum interval to wait for the selection to complete. If timeout is a NULL pointer, the select blocks indefinitely. To effect a poll, the timeout parameter should be a non-NULL pointer, pointing to a zero-valued <structname> timeval</structname> structure.
authzid Pointer to the string to hold the authorization identity retrieved for the connection.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_NO_MEMORY if memory cannot be allocated for the authorization identity.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
  • LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

ldap_parse_virtuallist_control()

The ldap_parse_virtuallist_control() function parses the result returned from a search operation that used a server control for virtual list views. Note: This function implements an extension to the LDAP v3. A virtual list viewis an optional LDAP server feature that may not be supported on all LDAP servers.

Syntax
#include <ldap.h>
int ldap_parse_virtuallist_control( LDAP *ld,
  LDAPControl **ctrls, unsigned long *target_posp,
  unsigned long *list_sizep, int *errcodep );
Parameters
ldap_parse_virtuallist_control() Function Parameters
Parameters Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
ctrls An array of controls returned by the server. You obtain these controls by calling the ldap_parse_result() function on the set of results returned by the server.
target_posp Pointer to an unsigned long that is set by the function. The function sets this to the index or offset of the selected entry in the list of entries.
list_sizep Pointer to an unsigned long that is set by the function. The function sets this to the number of entries in the total number of entries in the entire list (not just the subset).
errcodep Pointer to the sort control result code retrieved by this function.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded message.
  • LDAP_CONTROL_NOT_FOUND if no control can be found in the response returned from the server.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
Description

The ldap_parse_virtuallist_control() function can be called:

  • As part of the process of retrieving a subset of entries from a list when working with a virtual list view box.
  • After, calling ldap_result() to get the results, and ldap_parse_result() to parse the server controls from the results.
See Also

ldap_create_virtuallist_control()

ldap_passwd()

The ldap_passwd() asynchronous function allows you to perform an LDAP Password Modify extended operation, as defined in RFC 3062.

Syntax
#include <ldap.h>
int ldap_passwd( LDAP *ld, struct berval *userid,
  struct berval *oldpasswd, struct berval *newpasswd,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  int *msgidp );
Parameters
ldap_passwd() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
userid DN of the user whose password you want to modify.
oldpasswd Old password used before expiration. If the password has not yet expired, this is the current password.
newpasswd New password to use after modification
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this LDAP operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this LDAP operation. If you do not want to pass any client controls, specify NULL for this argument.
msgidp Pointer to an integer to be set to the message ID of the operation. To check the result of this operation, call the ldap_result() and ldap_parse_passwd() function, or ldap_parse_passwd_result() function.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

ldap_passwd_s()

The ldap_passwd_s() synchronous function allows you to perform an LDAP Password Modify extended operation, as defined in RFC 3062.

Syntax
#include <ldap.h>
int ldap_passwd_s( LDAP *ld, struct berval *userid,
  struct berval *oldpasswd, struct berval *newpasswd,
  struct berval *genpasswd, LDAPControl **serverctrls,
  LDAPControl **clientctrls );
Parameters
ldap_passwd() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
userid DN of the user whose password you want to modify.
oldpasswd Old password used before expiration. If the password has not yet expired, this is the current password.
newpasswd New password to use after modification
genpasswd New password generated by the server when an expired password is reset, but no newpasswd value is provided.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this LDAP operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this LDAP operation. If you do not want to pass any client controls, specify NULL for this argument.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the control.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NOT_SUPPORTED if your LDAP client does not specify that it is using LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

ldap_perror()

#include <ldap-deprecated.h>
void ldap_perror( LDAP *ld, const char *s );
Parameters
ldap_perror() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
s Optional text to print out before printing the error message.
Description

Use the newer version of this function, ldap_get_lderrno() .

Example

The following example prints out an error message if the search operation cannot complete successfully.

...
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  get_attr, 0, &result ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
}
...
See Also

ldap_get_lderrno(), ldap_err2string(), ldap_result2error(), ldap_set_lderrno()

ldap_rename()

The ldap_rename() function changes the DN of an entry in the directory asynchronously.

Note: ldap_rename() is a new version of the ldap_modrdn2() function. If you are writing a new LDAP client, you should call ldap_rename().

Syntax
#include <ldap.h>
int ldap_rename( LDAP *ld, const char *dn, const char *newrdn,
  const char *newparent, int deleteoldrdn,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  int *msgidp );
Parameters
ldap_rename() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to rename.
newrdn New Relative Distinguished Name (RDN) to assign to the entry.
newparent DN of the new parent entry you want to move the entry under. Pass NULL if you do not want to move the entry to a different location in the directory tree.
deleteoldrdn Specifies whether or not the old RDN is retained as an attribute of the entry. For example, an entry has the following values for the cn attribute: cn: Barbara Jensen cn: Babs Jensen
If you change the RDN to cn=Barbie Jensen and pass 1 as deleteoldrdn, the resulting entry has the following values: cn: Barbie Jensen cn: Babs Jensen
If instead you pass 0 as deleteoldrdn, the Barbara Jensen value is not removed from the entry: cn: Barbie Jensen cn: Babs Jensen cn: Barbara Jensen
So, if this is a non-zero value, the old RDN is not retained as a value in the entry.
If 0, the old RDN is retained as an attribute in the entry.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this LDAP operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this LDAP operation. If you do not want to pass any client controls, specify NULL for this argument.
msgidp Pointer to an integer that will be set to the message ID of the LDAP operation. To check the result of this operation, call the ldap_result() and ldap_parse_result() functions.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
Description

The ldap_rename() changes the DN of an entry in the directory and allows you to move the entry under a different parent entry in the directory tree. ldap_rename() is an asynchronous function; it does not directly return results. In order to get the results of the LDAP rename operation, you need to call the ldap_result() function and the ldap_parse_result() function. If you want the results to be returned directly by the function, call the synchronous function ldap_rename_s() instead.

See Also

ldap_rename_s(), ldap_result(), ldap_parse_result()

ldap_rename_s()

The ldap_rename_s() function changes the DN of an entry in the directory synchronously.

#include <ldap.h>
int ldap_rename_s( LDAP *ld, const char *dn, const char *newrdn,
  const char *newparent, int deleteoldrdn,
  LDAPControl **serverctrls, LDAPControl **clientctrls );
Parameters
ldap_rename() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the entry to rename.
newrdn New Relative Distinguished Name (RDN) to assign to the entry.
newparent DN of the new parent entry you want to move the entry under. Pass NULL if you do not want to move the entry to a different location in the directory tree.
deleteoldrdn Specifies whether or not the old RDN is retained as an attribute of the entry. For example, an entry has the following values for the cn attribute: cn: Barbara Jensen cn: Babs Jensen
If you change the RDN to cn=Barbie Jensen and pass 1 as deleteoldrdn, the resulting entry has the following values: cn: Barbie Jensen cn: Babs Jensen
If instead you pass 0 as deleteoldrdn, the Barbara Jensen value is not removed from the entry: cn: Barbie Jensen cn: Babs Jensen cn: Barbara Jensen
So, if this is a non-zero value, the old RDN is not retained as a value in the entry.
If 0, the old RDN is retained as an attribute in the entry.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_NO_MEMORY if memory cannot be allocated to decode the control returned by the server.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAPv3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

Note: Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.

Description

The ldap_rename_s() changes the DN of an entry in the directory and allows you to move the entry under a different parent entry in the directory tree. The function ldap_rename_s() is synchronous; it directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_rename().

See Also

ldap_rename()

ldap_result()

The function ldap_result() waits for and returns the result of an LDAP operation initiated by one of the asynchronous LDAP API functions.

Syntax
#include <ldap.h>
int ldap_result( LDAP *ld, int msgid, int all,
  struct timeval *timeout, LDAPMessage **result );
Parameters
ldap_result() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
msgid Asynchronous functions return a unique message ID. This parameter takes message ID of the operation for which you want the results. To check any operation, pass LDAP_RES_ANY as the value of this parameter.
all Specifies how the results of a search are returned. This parameter can have the following values:
  • 0 specifies that the results are returned one entry at a time, using separate calls to ldap_result().
  • A non-zero value specifies that all results are returned at the same time (after the final search result is obtained by the library).
timeout Specifies a maximum interval to wait for the selection to complete. If timeout is a NULL pointer, the select blocks indefinitely. To effect a poll, the timeout parameter should be a non-NULL pointer, pointing to a zero-valued timeval structure.
result Result of the operation. To interpret the results, pass this to the LDAP parsing routines, such as ldap_result2error(), ldap_parse_result(), and ldap_first_entry.
Returns

One of the following values:

  • LDAP_RES_BIND indicates that the LDAPMessage structure contains the result of an LDAP bind operation.
  • LDAP_RES_SEARCH_ENTRY indicates that the LDAPMessage structure contains an entry found during an LDAP search operation.
  • LDAP_RES_SEARCH_REFERENCE indicates that the LDAPMessage structure contains an LDAPv3 search reference (a referral to another LDAP server) found during an LDAP search operation.
  • LDAP_RES_SEARCH_RESULT indicates that the LDAPMessage structure contains the result of an LDAP search operation.
  • LDAP_RES_MODIFY indicates that the LDAPMessage structure contains the result of an LDAP modify operation.
  • LDAP_RES_ADD indicates that the LDAPMessage structure contains the result of an LDAP add operation.
  • LDAP_RES_DELETE indicates that the LDAPMessage structure contains the result of an LDAP delete operation.
  • LDAP_RES_MODDN or LDAP_RES_RENAME indicates that the LDAPMessage structure contains the result of an LDAP modify DN operation.
  • LDAP_RES_COMPARE indicates that the LDAPMessage structure contains the result of an LDAP compare operation.
  • LDAP_RES_EXTENDED indicates that the LDAPMessage structure contains the result of an LDAP v3 extended operation.
  • -1 indicates that an error occurred. The error code is set in the LDAP structure. To get the error code, call the ldap_get_lderrno() function.
  • 0 indicates that the operation has timed out.
See Also

ldap_add_ext(), ldap_compare_ext() , ldap_delete_ext(), ldap_modify_ext(), ldap_rename(), ldap_simple_bind(), ldap_url_search()

ldap_result2error()

#include <ldap-deprecated.h>
int ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit );
Parameters
ldap_result2error() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
r Pointer to the LDAPMessage structure representing the results returned by the ldap_result() or ldap_search() function.
freeit Specifies whether or not the result should be freed after the error code is extracted. The parameter can have the following possible values:
  • 0 specifies that the result should not be freed.
  • A non-zero value specifies that the result should be freed.
Returns

One of the following values:

  • If successful, sets the error code and other error information in the LDAP structure and returns the error code.
  • If unsuccessful, returns LDAP_PARAM_ERROR.
Example

See ldap_result().

See Also

ldap_parse_result(), ldap_get_lderrno(), ldap_err2string(), ldap_result(), ldap_set_lderrno

ldap_sasl_bind()

The ldap_sasl_bind() function authenticates your client to an LDAP server using an Simple Authentication and Security Layer (SASL) mechanism.

Note: The LDAP server must support authentication through SASL. Directory Server supports a server plug-in interface that you can use to add SASL support to the server.

Syntax
#include <ldap.h>
int ldap_sasl_bind( LDAP *ld, const char *dn,
  const char *mechanism, const struct berval *cred,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  int *msgidp );
Parameters
ldap_sasl_bind() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the user who wants to authenticate. For anonymous authentication, set this to NULL.
mechanism Name of the SASL mechanism that you want to use for authentication.
cred Pointer to the berval structure containing the credentials that you want to use for authentication.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
msgidp Pointer to an integer that will be set to the message ID of the LDAP operation. To check the result of this operation, call ldap_result() and ldap_parse_sasl_bind_result() functions.
Returns

One of the following values:

  • LDAP_SUCCESS if the SASL bind request was sent successfully.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NOT_SUPPORTED if controls are included in your request—for example, as a session preference—and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request to send to the server.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
Description

The ldap_sasl_bind() function authenticates your client to an LDAP server by using a specified SASL mechanism. ldap_sasl_bind() is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_sasl_bind_s(). In order to get the results of the LDAP SASL bind operation, call the ldap_result(), the ldap_parse_sasl_bind_result(), and the ldap_get_lderrno() functions.

See Also

ldap_result(), ldap_parse_sasl_bind_result() , ldap_get_lderrno(), ldap_sasl_bind_s()

ldap_sasl_bind_s()

The ldap_sasl_bind_s() function authenticates your client to an LDAP server synchronously using an SASL mechanism.

#include <ldap.h>
int ldap_sasl_bind_s( LDAP *ld, const char *dn,
  const char *mechanism, const struct berval *cred,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  struct berval **servercredp );
Parameters
ldap_sasl_bind_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
dn DN of the user who wants to authenticate. For anonymous authentication, set this to NULL.
mechanism Name of the SASL mechanism that you want to use for authentication.
cred Pointer to the berval structure containing the credentials that you want to use for authentication.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
servercredp Pointer to a pointer to an berval structure containing any credentials returned by the server. When done, you can free this by calling the ber_alloc() function.
Returns

One of the following values:

  • LDAP_SUCCESS if the SASL bind request was sent successfully.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAPv3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request to send to the server.
  • LDAP_DECODING_ERROR if an error occurred when the LDAP API library was decoding the BER-encoded results received from the server.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.

Note: Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.

Description

The ldap_sasl_bind_s() function authenticates your client to an LDAP server by using a specified SASL mechanism. It is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_sasl_bind(). After authenticating a client through SASL, an LDAP server can return a set of credentials in the results. The servercredp argument points to this value.

See Also

ldap_sasl_bind()

ldap_search()

The ldap_search() function searches the directory asynchronously.

#include <ldap.h>
int ldap_search( LDAP *ld, const char *base, int scope,
  const char* filter, char **attrs, int attrsonly );
Parameters
ldap_search() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
base DN of the entry that serves as the starting point for the search. For example, setting base to dc=example,dc=com restricts the search to entries at example.com.
scope Scope of the search, which can be one of the following values:
  • LDAP_SCOPE_BASE searches the entry specified by base.
  • LDAP_SCOPE_ONELEVEL searches all entries one level beneath the entry specified by base.
  • LDAP_SCOPE_SUBTREE searches the entry specified by base and all entries at all levels beneath the entry specified by base.
filter String representation of the filter to apply in the search. You can specify simple filters with the following syntax: (attributetype=attributevalue)
attrs A NULL terminated array of attribute types to return from entries that match filter. If you specify a NULL, all attributes will be returned.
attrsonly Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
  • 0 specifies that both attribute types and attribute values are returned.
  • 1 specifies that only attribute types are returned.
Returns

Returns the message ID of the ldap_search() operation.

Note: To check the result of this operation, call ldap_result and ldap_result2error().

See ldap_search_ext_s() for a list of possible result codes.

Description

Please use the newer version of this function, ldap_search_ext() .

Example

The following example searches a directory.


#include "examples.h"

static void do_other_work();
unsigned long global_counter = 0;

int
main( int argc, char **argv )
{
  LDAP *ld;
  LDAPMessage *result, *e;
  BerElement *ber;
  char *a, *dn;
  char **vals;
  int i, rc, finished, msgid;
  int num_entries = 0;
  struct timeval zerotime;

  zerotime.tv_sec = zerotime.tv_usec = 0L;

/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* authenticate to the directory as nobody */
if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_simple_bind_s" );
  return( 1 );
}
/* search for all entries with surname of Jensen */
if (( msgid = ldap_search( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE,
      MY_FILTER, NULL, 0 )) == -1 ) {
  ldap_perror( ld, "ldap_search" );
  return( 1 );
}

/* Loop, polling for results until finished */
finished = 0;
while ( !finished ) {
  /*
  * Poll for results.   We call ldap_result with the "all" parameter
  * set to zero. This causes ldap_result() to return exactly one
  * entry if at least one entry is available. This allows us to
  * display the entries as they are received.
  */
  result = NULL;
  rc = ldap_result( ld, msgid, 0, zerotime, result );
  switch ( rc ) {
  case -1:
    /* some error occurred */
    ldap_perror( ld, "ldap_result" );
    return( 1 );
  case 0:
  /* Timeout was exceeded. No entries are ready for retrieval. */
    if ( result != NULL ) {
      ldap_msgfree( result );
    }
    break;
  default:
  /*
  * Either an entry is ready for retrieval, or all entries have
  * been retrieved.
  */
    if (( e = ldap_first_entry( ld, result )) == NULL ) {
      /* All done */
      finished = 1;
      if ( result != NULL ) {
        ldap_msgfree( result );
      }
      continue;
      }
    /* for each entry print out name + all attrs and values */
    num_entries++;
    if (( dn = ldap_get_dn( ld, e )) != NULL ) {
      printf( "dn: %s\n", dn );
      ldap_memfree( dn );
    }
    for ( a = ldap_first_attribute( ld, e, ber );
     a != NULL; a = ldap_next_attribute( ld, e, ber ) ) {
      if (( vals = ldap_get_values( ld, e, a )) != NULL ) {
        for ( i = 0; vals[ i ] != NULL; i++ ) {
          printf( "%s: %s\n", a, vals[ i ] );
        }
      ldap_value_free( vals );
      }
      ldap_memfree( a );
    }
    if ( ber != NULL ) {
      ldap_ber_free( ber, 0 );
    }
    printf( "\n" );
    ldap_msgfree( result );
  }
  /* Do other work here while you are waiting... */
  do_other_work();
}

/* All done. Print a summary. */
printf( "%d entries retrieved. I counted to %ld "
      "while waiting.\n", num_entries, global_counter );
ldap_unbind( ld );
return( 0 );
}

/*
 * Perform other work while polling for results. */
static void
do_other_work()
{
    global_counter++;
}
See Also

ldap_search_ext()

ldap_search_ext()

The ldap_search_ext() function searches the directory asynchronously.

#include <ldap.h>
int ldap_search_ext( LDAP *ld, const char *base, int scope,
  const char *filter, char **attrs, int attrsonly,
  LDAPControl **serverctrls, LDAPControl **clientctrls,
  struct timeval *timeoutp, int sizelimit, int *msgidp );
Parameters
ldap_search_ext() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
base DN of the entry that serves as the starting point for the search. For example, setting base to dc=example,dc=com restricts the search to entries at example.com.
scope Scope of the search, which can be one of the following values:
  • LDAP_SCOPE_BASE searches the entry specified by base.
  • LDAP_SCOPE_ONELEVEL searches all entries one level beneath the entry specified by base.
  • LDAP_SCOPE_SUBTREE searches the entry specified by base and all entries at all levels beneath the entry specified by base.
filter String representation of the filter to apply in the search. You can specify simple filters with the following syntax: (attributetype= attributevalue)
attrs A NULL terminated array of attribute types to return from entries that match filter. If you specify a NULL, all attributes will be returned.
attrsonly Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
  • 0 specifies that both attribute types and attribute values are returned.
  • 1 specifies that only attribute types are returned.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
timeoutp Pointer to a timeval structure specifying the maximum time to wait for the results of the search. Pass NULL to use the default time limit for the current connection. To specify an infinite time limit, set the tv_sec and tv_usec fields in the timeval structure to 0.
sizelimit Maximum number of results to return in the search. Pass -1 to use the default size limit for the current connection.
msgidp Pointer to an integer that will be set to the message ID of the LDAP operation.
Returns

One of the following values:

  • LDAP_SUCCESS if the SASL bind request was sent successfully.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NOT_SUPPORTED if controls are included in your request—for example, as a session preference—and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request to send to the server.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
Description

The ldap_search_ext() function searches the directory for matching entries. ldap_search_ext() is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_search_ext_s() . You can also use this function to pass LDAP server controls to the server if you want the server to sort the results or if you want to request a persistent search. (See ldap_create_sort_control() and ldap_create_persistentsearch_control() for more information.) In order to get the results of the ldap_search_ext() operation, you need to call the ldap_result() and the ldap_parse_result() functions.

See Also

ldap_search_ext_s(), ldap_result(), ldap_parse_result()

ldap_search_ext_s()

The ldap_search_ext_s() function searches the directory synchronously.

Note: ldap_search_ext_s() is a new version of the ldap_search_s() function. If you are writing a new LDAP client, you should call ldap_search_ext_s().

Syntax
#include <ldap.h>
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 *timeoutp, int sizelimit, LDAPMessage **res );
Parameters
ldap_search_ext_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
base DN of the entry that serves as the starting point for the search. For example, setting base to dc=example,dc=com restricts the search to entries at example.com.
scope Scope of the search, which can be one of the following values:
  • LDAP_SCOPE_BASE searches the entry specified by base.
  • LDAP_SCOPE_ONELEVEL searches all entries one level beneath the entry specified by base.
  • LDAP_SCOPE_SUBTREE searches all entries at all levels beneath the entry specified by base.
filter String representation of the filter to apply in the search. You can specify simple filters with the following syntax: (attributetype=attributevalue)
attrs A NULL terminated array of attribute types to return from entries that match filter. If you specify a NULL, all attributes will be returned.
attrsonly Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
  • 0 specifies that both attribute types and attribute values are returned.
  • 1 specifies that only attribute types are returned.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
timeoutp Pointer to a timeval structure specifying the maximum time to wait for the results of the search.
sizelimit Maximum number of results to return in the search.
res Results of the search (when the call is completed).
Returns

One of the following values:

  • LDAP_SUCCESS if the SASL bind request was sent successfully.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NOT_SUPPORTED if controls are included in your request—for example, as a session preference—and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
  • LDAP_FILTER_ERROR if an error occurred when parsing and BER-encoding the search filter specified by the filter argument.
  • LDAP_TIMEOUT if the search exceeded the time specified by the timeoutp argument.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request to send to the server.
  • LDAP_DECODING_ERROR if an error occurred when the LDAP API library was decoding the BER-encoded results received from the server.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.

The ldap_search_ext_s() searches the directory for matching entries. The function ldap_search_ext_s() is synchronous; it directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_search_ext(). You can also use <function> ldap_search_ext_s</function> to pass LDAP server controls to the server if you want the server to sort the results or if you want to request a persistent search. (See ldap_create_sort_control() and ldap_create_persistentsearch_control() for more information.)

See Also

ldap_search_ext()

ldap_search_s()

The ldap_search_s() function searches the directory synchronously. Note: This is an older function that is included in the SDK for backward-compatibility. If you are writing a new LDAP client, use ldap_search_ext_s() instead.

Syntax
#include <ldap.h>
int ldap_search_s( LDAP *ld, const char *base, int scope,
  const char* filter, char **attrs, int attrsonly,
  LDAPMessage **res );
Parameters

This function has the parameters listed in ldap_search_s() .

ldap_search_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
base DN of the entry that serves as the starting point for the search. For example, setting base to dc=example,dc=com restricts the search to entries at example.com.
scope Scope of the search, which can be one of the following values:
  • LDAP_SCOPE_BASE searches the entry specified by base.
  • LDAP_SCOPE_ONELEVEL searches all entries one level beneath the entry specified by base.
  • LDAP_SCOPE_SUBTREE searches all entries at all levels beneath the entry specified by base.
filter String representation of the filter to apply in the search. You can specify simple filters with the following syntax:
(attributetype=attributevalue)
attrs A NULL terminated array of attribute types to return from entries that match filter. If you specify a NULL, all attributes will be returned.
attrsonly Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
  • 0 specifies that both attribute types and attribute values are returned.
  • 1 specifies that only attribute types are returned.
res Results of the search (when the call is completed).
Returns

For a list of possible result codes for an LDAP search operation, see ldap_search_ext_s().

Description

Use the newer version of this function, ldap_search_ext_s() .

Example

The following example searches the directory for all people whose surname (last name) is Jensen.

#include "examples.h"

int main( int argc, char **argv )
{
  LDAP *ld;
  LDAPMessage *result, *e;
  BerElement *ber;
  char *a, *dn;
  char **vals;
  int i;
  /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
  /* authenticate to the directory as nobody */
  if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_simple_bind_s" );
    return( 1 );
  }
  /* search for all entries with surname of Jensen */
  if ( ldap_search_s( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE,
    MY_FILTER, NULL, 0, result ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_search_s" );
    return( 1 );
  }
  /* for each entry print out name + all attrs and values */
  for ( e = ldap_first_entry( ld, result ); e != NULL;
   e = ldap_next_entry( ld, e ) ) {
    if ( (dn = ldap_get_dn( ld, e )) != NULL ) {
      printf( "dn: %s\n", dn );
      ldap_memfree( dn );
    }
    for ( a = ldap_first_attribute( ld, e, ber );
     a != NULL; a = ldap_next_attribute( ld, e, ber ) ) {
      if ((vals = ldap_get_values( ld, e, a)) != NULL ) {
        for ( i = 0; vals[i] != NULL; i++ ) {
          printf( "%s: %s\n", a, vals[i] );
        }
        ldap_value_free( vals );
      }
      ldap_memfree( a );
    }
    if ( ber != NULL ) {
      ldap_ber_free( ber, 0 );
    }
    printf( "\n" );
  }
  ldap_msgfree( result );
  ldap_unbind( ld );
  return( 0 );
}
See Also

ldap_search_ext_s()

ldap_search_st()

The ldap_search_st() function searches the directory synchronously within a specified time limit.

#include <ldap.h>
int ldap_search_st( LDAP *ld, const char *base, int scope,
  const char* filter, char **attrs, int attrsonly,
  struct timeval *timeout, LDAPMessage **res );
Parameters
ldap_search_st() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
base DN of the entry that serves as the starting point for the search. For example, setting base to dc=example,dc=com restricts the search to entries at example.com.
scope Scope of the search, which can be one of the following values:
  • LDAP_SCOPE_BASE searches the entry specified by base.
  • LDAP_SCOPE_ONELEVEL searches all entries one level beneath the entry specified by base.
  • LDAP_SCOPE_SUBTREE searches all entries at all levels beneath the entry specified by base.
filter String representation of the filter to apply in the search. You can specify simple filters with the following syntax:
(attributetype=attributevalue)
attrs A NULL terminated array of attribute types to return from entries that match filter. If you specify a NULL, all attributes will be returned.
attrsonly Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
  • 0 specifies that both attribute types and attribute values are returned.
  • 1 specifies that only attribute types are returned.
timeout Maximum time to wait for the results of the search.
res Results of the search (when the call is completed).
Returns

For a list of possible result codes for an LDAP search operation, see ldap_search_ext_s().

Description

Please use the newer version of this function, ldap_search_ext_s() .

See Also

ldap_search_ext_s()

ldap_set_filter_additions()

The ldap_set_filter_additions() function sets a prefix to be prepended and a suffix to be appended to all filters returned by the ldap_getfirstfilter() and ldap_getnextfilter() function calls.

Syntax
#include <ldap.h>
int ldap_set_filter_additions( LDAPFiltDesc *lfdp, char *prefix,
  char *suffix );
Parameters
ldap_set_filter_additions() Function Parameters
Parameter Description
lfdp Pointer to an LDAPFiltDesc structure.
prefix Prefix to prepend to all filters. If NULL, no prefix is prepended.
suffix Suffix to append to all filters. If NULL, no suffix is appended.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • If unsuccessful, returns an LDAP error code.
Example

The following example loads the filter configuration file named myfilters.conf into memory and adds the prefix "(&(objectClass=person)" and the suffix ")" to each filter retrieved.

#include <ldap.h>
...
LDAPFiltDesc *lfdp;
char *filter_file = "myfilters.conf";
char *prefix = "(&(objectClass=person)";
char *suffix = ")";
int rc;
...
lfdp = ldap_init_getfilter( filter_file );
rc = ldap_set_filter_additions( ldfp, prefix, suffix );
if ( rc != LDAP_SUCCESS ) {
  printf( "Error setting filter prefix and suffix\n");
  return( rc );
}
...
See Also

ldap_getfirstfilter(), ldap_getnextfilter()

ldap_setfilteraffixes()

Note: This function is deprecated and should not be used. It is included in ldap-deprecated.h for backward-compatibility. Use ldap_set_filter_additions() instead.

See Also

ldap_set_filter_additions()

ldap_set_lderrno()

The ldap_set_lderrno() function sets an error code and information about an error in an LDAP structure.

Syntax
#include <ldap.h>
int ldap_set_lderrno( LDAP *ld, int e, char *m, char *s );
Parameters
ldap_set_lderrno() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
e The error code that you want to set.
m In the event that an entry for a specified DN cannot be found, set this parameter to the portion of the DN that identifies an existing entry.
s The text of the error message that you want associated with this error code.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • If unsuccessful, returns an LDAP error code.
Description

The ldap_set_lderrno() function sets an error code and information about an error in an LDAP structure. You can call this function to set error information that will be retrieved by subsequent ldap_get_lderrno() function calls.

Example

The following example attempts to perform an operation. If the operation fails, the LDAP_PARAM_ERROR error code is placed in the LDAP structure.

#include <ldap.h>
int rc;
char *errmsg = "Invalid parameter";
...
if ( ldap_my_function() != LDAP_SUCCESS ) {
  rc = ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, errmsg );
  if ( rc != LDAP_SUCCESS ) {
    printf( "Error: %d\nError code could not be set.\n", rc );
  }
  return( rc );
}
...
See Also

ldap_err2string(), ldap_perror, ldap_result2error()

ldap_set_option()

The function ldap_set_option() sets session preferences in the LDAP structure.

Syntax
#include <ldap.h>
int ldap_set_option( LDAP *ld, int option, const void *optdata );
Parameters
ldap_set_option() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server. If NULL, you are setting the default options that will apply to any new LDAP connection handles that are subsequently created.
option Option that you want to set. See Table 21–182 for available options of this parameter.
optdata Pointer to the value of the option that you want to set. Available data types are also listed in the following table.

The option parameter can have one of the values listed in the following table.

Options for ldap_set_option()
Option Description
LDAP_OPT_API_FEATURE_INFO Retrieves information about the revision of a supported LDAP feature. This option is READ-ONLY and cannot be set. The data type for the optdata parameter is (LDAPAPIFeatureInfo *).
LDAP_OPT_API_INFO Retrieves information about the API implementation at execution time (API version, protocol version, the names of supported API extensions with their vendor name version, etc.). For details on the structure returned, refer to the ldap.h header file. This option is READ-ONLY and cannot be set. The data type for the optdata parameter is (LDAPAPIInfo *).
LDAP_OPT_CLIENT_CONTROLS Pointer to an array of LDAPControl structures representing the LDAP v3 client controls you want sent with every request by default. The data type for the optdata parameter is (LDAPControl ***).
LDAP_OPT_DESC Socket descriptor underlying the main LDAP connection. The LBER_SOCKET data type depends on the platform that you are using:
  • int in UNIX.
  • SOCKET in Windows. The data type for the optdata parameter is (LBER_SOCKET *).
LDAP_OPT_DEREF Determines how aliases work during a search. optdata can be one of the following values:
  • LDAP_DEREF_NEVER specifies that aliases are never dereferenced.
  • LDAP_DEREF_SEARCHING specifies that aliases are dereferenced when searching under the base object (but not when finding the base object).
  • LDAP_DEREF_FINDING specifies that aliases are dereferenced when finding the base object (but not when searching under the base object).
  • LDAP_DEREF_ALWAYS specifies that aliases are always dereferenced when finding and searching under the base object. The data type for the optdata parameter is (int *).
LDAP_OPT_DNS_FN_PTRS DEPRECATED OPTION: Lets you use alternate DNS functions for getting the host entry of the LDAP server. The data type for the optdata parameter is (struct ldap_dns_fns *).
LDAP_OPT_ERROR_NUMBER Retrieves the result code for the most recent LDAP error that occurred in this session. The data type for the optdata parameter is (int *).
LDAP_OPT_ERROR_STRING Retrieves the error message returned with the result code for the most recent LDAP error that occurred in this session. The data type for the optdata parameter is (char **).
LDAP_OPT_EXTRA_THREAD_FN_PTRS Lets you specify the locking and semaphore functions that you want called when getting results from the server. The data type for the optdata parameter is (struct ldap_extra_thread_fns *).
LDAP_OPT_HOST_NAME Sets the host name (or list of hosts) for the primary LDAP server. The data type for the optdata parameter is (char **).
LDAP_OPT_IO_FN_PTRS DEPRECATED OPTION: Lets you use alternate communication stacks. The data type for the optdata parameter is (struct ldap_io_fns *).
LDAP_OPT_MATCHED_DN Gets the matched DN value returned with the most recent LDAP error that occurred for this session. The data type for the optdata parameter is (char **)
LDAP_OPT_MEMALLOC_FN_PTRS Gets a pointer to the callback structure which you previously set. The data type for the optdata parameter is (struct ldap_memalloc_fnsldap_io_fns *).
LDAP_OPT_PROTOCOL_VERSION Version of the protocol supported by your client. You can specify either LDAP_VERSION2 or LDAP_VERSION3. If no version is set, the default is LDAP_VERSION2. In order to use LDAP v3 features, you need to set the protocol version to LDAP_VERSION3. The data type for the optdata parameter is (int *).
LDAP_OPT_REBIND_ARG Lets you set the last argument passed to the routine specified by LDAP_OPT_REBIND_FN. You can also set this option by calling the ldap_set_rebind_proc() function. The data type for the optdata parameter is (void *).
LDAP_OPT_REBIND_FN Lets you set the routine to be called when you need to authenticate a connection with another LDAP server (for example, during the course of following a referral). You can also set this option by calling the ldap_set_rebind_proc function. The data type for the optdata parameter is (LDAP_REBINDPROC_CALLBACK *).
LDAP_OPT_RECONNECT If the connection to the server is lost, determines whether or not the same connection handle should be used to reconnect to the server. By default, this option is off. To handle failover use following values: *LDAP_OPT_ON specifies that the same connection handle can be used to reconnect to the server. *LDAP_OPT_OFF specifies that you want to create a new connection handle to connect to the server. The data type for the optdata parameter is (int *).
LDAP_OPT_REFERRALS Determines whether or not the client should follow referrals. By default, the client follows referrals. optdata can be one of the following values:
  • LDAP_OPT_ON specifies that the server should follow referrals.
  • LDAP_OPT_OFF specifies that the server should not follow referrals. The data type for the optdata parameter is (int *).
LDAP_OPT_REFERRAL_HOP_LIMIT Maximum number of referrals the client should follow in a sequence. In other words, the client can only be referred this number of times before it gives up. By default, the maximum number of referrals that the client can follow in a sequence is 5 for the initial connection. This limit does not apply to individual requests that generate multiple referrals in parallel. The data type for the optdata parameter is (int *).
LDAP_OPT_RESTART Determines whether or not LDAP I/O operations should be restarted automatically if they are prematurely aborted. optdata can be one of the following values:
  • LDAP_OPT_ON specifies that I/O operations should be restarted automatically.
  • LDAP_OPT_OFF specifies that I/O operations should not be restarted automatically. The data type for the optdata parameter is (int *).
LDAP_OPT_SERVER_CONTROLS Pointer to an array of LDAPControl structures representing the LDAP v3 server controls you want sent with every request by default. Typically, since controls are specific to the type of request, you may want to pass the controls using operation-specific functions (such as ldap_add_ext()) instead. The data type for the optdata parameter is (LDAPControl ***).
LDAP_OPT_SIZELIMIT Maximum number of entries that should be returned by the server in search results. The LDAP server may impose a smaller size limit than the limit you specify as the server administrator also has the ability to set this limit. The data type for the optdata parameter is (int *).
LDAP_OPT_SSL Determines whether or not SSL is enabled. optdata can be one of the following values:
  • LDAP_OPT_ON specifies that SSL is enabled.
  • LDAP_OPT_OFF specifies that SSL is disabled. The data type for the optdata parameter is (int *).
LDAP_OPT_THREAD_FN_PTRS Lets you specify the thread function pointers. The data type for the optdata parameter is (struct ldap_thread_fns *).
LDAP_OPT_TIMELIMIT Maximum number of seconds that should be spent by the server when answering a search request. The LDAP server may impose a shorter time limit than the limit you specify as the server administrator also has the ability to set this limit. The data type for the optdata parameter is (int *).
LDAP_X_OPT_EXTIO_FN_PTRS Extended I/O function callback option.
LDAP_X_OPT_CONNECT_TIMEOUT Value of a time out (expressed in milliseconds) for non-blocking connect call. The data type for the optdata parameter is (int *).
LDAP_X_OPT_SOCKBUF Socket buffer structure associated to the LDAP connection.

See also ldap_set_option() for details on LDAP_OPT_X_SASL* parameters.

Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • -1 if unsuccessful.
Example
#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
int max_ret = 100, max_tim = 30;
char *host = "ldap.sun.com";
...
/* Initialize a session with the LDAP server ldap.sun.com:389 */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* Set the maximum number of entries returned */
if ( ldap_set_option( ld, LDAP_OPT_SIZELIMIT, &max_ret) !
  LDAP_SUCCESS) {
  ldap_perror( ld, "ldap_set_option" );
  return( 1 );
}
...
See Also

ldap_init(), prldap_init() (IPv6), ldap_get_option()

ldap_set_rebind_proc()

The ldap_set_rebind_proc() function sets a rebind, which is called by your client to obtain authentication credentials when following a referral.

Syntax
#include <ldap.h>
void ldap_set_rebind_proc( LDAP *ld,
  LDAP_REBINDPROC_CALLBACK *rebindproc, void *arg );
Parameters
ldap_set_rebind_proc() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
rebindproc Pointer to a function called back to obtain bind credentials when a new server is contacted during an LDAP referral.
arg Pointer to an additional argument that you want to pass to the rebind function.
Description

Call ldap_set_rebind_proc() to specify the rebind function. This rebind function is called by the LDAP client when following a referral to a new LDAP server. It is responsible for obtaining the credentials used to authenticate to the new server. For example, suppose LDAP server A sends a referral to your client. The referral points your client to LDAP server B. When automatically following the referral, your client calls the rebind function to obtain a DN and credentials; your client uses these to authenticate to server B. By default, if you do not call ldap_set_rebind_proc() or if you pass NULL for the rebindproc argument, your client authenticates anonymously when following referrals. The rebind function that you specify with ldap_set_rebind_proc() should have the following prototype:

int LDAP_CALL LDAP_CALLBACK rebindproc( LDAP *ld, char **dnp,
  char **passwdp, int *authmethodp, int freeit, void *arg );
  1. The LDAP server sends a referral back to the client.
  2. The client calls the rebind function, passing 0 as the freeit argument.
  3. The rebind function sets the dnp, passwdp, and authmethodp arguments to point to the following information:
    • The dnp argument is set to point to the DN to be used to authenticate to the new LDAP server.
    • The passwdp argument is set to point to the credentials for this DN.
    • The authmethodp argument is set to point to the method of authentication used (for example, LDAP_AUTH_SIMPLE).
  4. If successful, the rebind function returns LDAP_SUCCESS and referral processing continues. (If any other value is returned, referral processing stops, and that value is returned as the result code for the original LDAP request.)
  5. The client gets the DN, credentials, and authentication method from the arguments of the rebind function and uses this information to authenticate to the new LDAP server.
  6. The client calls the rebind function again, passing 1 as the freeit argument.
  7. The rebind function frees any memory allocated earlier to specify the DN and credentials.

You need to write a rebind function that does the following:

  • If freeit is 0, set the following pointers:
    • Set dnp to point to the DN to be used for authentication.
    • Set passwdp to point to the credentials to be used for authentication.
    • Set authmethodp to point to the method of authentication used (for example, LDAP_AUTH_SIMPLE).

You can also make use of the arg argument, which is a pointer to the argument specified in the ldap_set_rebind_proc() function. If successful, returns LDAP_SUCCESS. Otherwise, returns the appropriate LDAP error code. If freeit is 1, free any memory that you allocated to create the DN and credentials.

After you have defined this function, pass the function name to ldap_set_rebind_proc() to register your rebind function.

Note: In order to use the rebind function, the LDAP_OPT_REFERRALS option must be set to LDAP_OPT_ON, so that your client automatically follows referrals. This option is set to LDAP_OPT_ON by default.

Example

The following example demonstrates how to write and register a rebind function.

#include "ldap.h"
...
/* Declare your rebind function */
int rebindproc( LDAP *ld, char **dnp, char **passwdp,
  int *authmethodp, int freeit, void *arg );
...
int main( int argc, char **argv )
{
  LDAP *ld;
  /* Additional argument to be passed to the rebind function */
  char *testarg = "cn=admin,cn=Administrators,cn=config";
  /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
  if ( (ld = ldap_init( "directory.example.com", 389 )) == NULL ) {
    perror( "ldap_init" );
    return( 1 );
  }
  /* Specify the function used for reauthentication on referrals */
  ldap_set_rebind_proc( ld, rebindproc, (void *)testarg );
  /* Authenticate */
  if ( ldap_simple_bind_s( ld, "uid=bjensen,ou=People,dc=example,dc=com",
      "hifalutin" ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_simple_bind_s" );
    return( 1 );
  }
  ...
  /* Your code to interact with the LDAP server */
  ...
}
...
/* rebindproc is the rebind function responsible for providing the DN,
  credentials, and authentication method used for authenticating the
  client to other Directory Servers.
  The function should set the following arguments:
  - dnp should point to the DN that will be used for authentication.
  - passwdp should point to the credentials used for authentication.
  - authmethodp should point to the method of authentication to be used
  (for example, LDAP_AUTH_SIMPLE).
  The function should return LDAP_SUCCESS if successful or an LDAP
  error code if an error occurs.
  In order to demonstrate how the freeit argument works, this example
  uses strdup() to copy the DN and password.  You can also just copy
  string pointers if the DN and password are already available as
  global variables.
*/
int LDAP_CALL LDAP_CALLBACK rebindproc(
  LDAP *ld, char **dnp, char **passwdp,
  int *authmethodp, int freeit, void *arg )
{
  printf( "Rebind function called.\n" );
  switch ( freeit ) {
  /* Your client calls the rebind function with freeit==1 when it needs
    to free any memory you've allocated. */
  case 1:
    printf( "\tFreeing memory.\n" );
    if ( dnp  *dnp ) {
      free( *dnp );
    }
    if ( passwdp  *passwdp ) {
      free( *passwdp );
    }
    break;
  /* Your client calls the rebind function with freeit==0 when it needs
  to get the DN, credentials, and authentication method. */
  case 0:
    printf( "\tGetting DN and credentials.\n" );
    *dnp = strdup( "uid=username,o=OtherServerSuffix" );
    *passwdp = strdup( "23skidoo" );
    *authmethodp = LDAP_AUTH_SIMPLE;
    break;
  default:
    printf( "\tUnknown value of freeit argument: %d\n", freeit );
    break;
  }
  /* If you successfully set the DN and credentials, you should return
    LDAP_SUCCESS.  (Any other return code will stop the client from
    automatically following the referral. */
  return LDAP_SUCCESS;
}
See Also

ldap_simple_bind(), ldap_simple_bind_s()

ldap_simple_bind()

The ldap_simple_bind() function synchronously authenticates your client to the LDAP server using a DN and a password.

Syntax
#include <ldap.h>
int ldap_simple_bind(LDAP *ld, const char *who, const char *passwd);
Parameters
ldap_simple_bind() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
who DN of the user who wants to authenticate. For anonymous authentication, set this or the passwd argument to NULL.
passwd Password of the user who wants to authenticate. For anonymous authentication, set this or the who argument to NULL.
Returns

Returns the message ID of the ldap_simple_bind() operation. To check the result of this operation, call ldap_result() and ldap_result2error().

Description

The ldap_simple_bind() function authenticates to the LDAP server. It verifies that the password supplied for authentication matches the userPassword attribute of the given entry. <function> ldap_simple_bind</function> is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_simple_bind_s().

The following example calls ldap_simple_bind() to authenticate the user Barbara Jensen to the directory.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
char *host = "ldap.sun.com";
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
char *pw = "hifalutin";
struct timeval zerotime;
zerotime.tv_sec = zerotime.tv_usec = 0L;
...
/* Initialize a session with the LDAP server ldap.example.com:389 */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* Attempt to bind with the LDAP server */
msgid = ldap_simple_bind( ld, dn, pw );

/* Initialize the value returned by ldap_result() */
rc = 0;

/* While the operation is still running, do this: */
while ( rc == 0 ) {
  ... /* do other work while waiting */...

  /* Check the status of the LDAP operation */
  rc = ldap_result( ld, msgid, NULL, zerotime, result );
  switch( rc ) {
    /* If -1 was returned, an error occurred */
    case -1:
      ldap_perror( ld, "Error in results: " );
      return( 1 );
    /* If 0 was returned, the operation is still in progress */
    case 0:
      continue;
    /* If any other value is returned, assume we are done */
    default:
      /* Check if the "bind" operation was successful */
      if ( ldap_result2error( result ) != LDAP_SUCCESS ) {
        ldap_perror( ld, "Error binding to server: " );
        return( 1 );
        }
  }
}
...
See Also

ldap_simple_bind_s()

ldap_simple_bind_s()

The ldap_simple_bind() function synchronously authenticates your client to the LDAP server using a DN and a password.

Syntax
#include <ldap.h>
int ldap_simple_bind_s( LDAP *ld, const char *who, const char *passwd );
Parameters
ldap_simple_bind_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
who DN of the user who wants to authenticate. For anonymous authentication, set this or the passwd argument to NULL.
passwd Password of the user who wants to authenticate. For anonymous authentication, set this or the who argument to NULL.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if an invalid parameter was passed to the function.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request to send to the server.
  • LDAP_DECODING_ERROR if an error occurred when the LDAP API library was decoding the BER-encoded results received from the server.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.

Note: Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.

Description

The ldap_simple_bind_s() function authenticates to the LDAP server. It verifies that the password supplied for authentication matches the userPassword attribute of the given entry. <function> ldap_simple_bind_s</function> is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_simple_bind() instead.

The following example uses the synchronous ldap_simple_bind_s() function to authenticate to the directory as the user Barbara Jensen.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
char *host = "ldap.sun.com";
char *dn = "uid=bjensen,ou=People,dc=example,dc=com";
char *pw = "hifalutin";
...
/* Initialize a session with the LDAP server ldap.sun.com:389 */
/* Use prldap_init() for IPv6 support. */
if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* Attempt to bind with the LDAP server */
if ( ldap_simple_bind_s( ld, dn, pw ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "Authentication failed: " );
  return( 1 );
}
...
See Also

ldap_simple_bind()

ldap_sort_entries()

The ldap_sort_entries() function sorts a chain of entries retrieved from an LDAP search call.

Syntax
#include <ldap.h>
int ldap_sort_entries( LDAP *ld, LDAPMessage *chain, char *attr,
  LDAP_CMP_CALLBACK *cmp );
Parameters
ldap_sort_entries() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
chain Chain of entries returned by the ldap_result() or ldap_search_s() function.
attr Attribute to use when sorting the results. To sort by DN instead of by attribute, use NULL.
cmp Comparison function used when sorting the values.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • If unsuccessful, returns a NULL and sets the appropriate error code in the LDAP structure. To get the error code, call ldap_get_lderrno().
Description

The ldap_sort_entries() function sorts a chain of entries retrieved from an LDAP search call (ldap_search_s() or ldap_result()) either by DN or a specified attribute in the entries.

Example

The following example sorts entries by the roomNumber attribute.

#include <stdio.h>
#include <string.h>
#include <ldap.h>
LDAP *ld;
LDAPMessage *result;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
char *sortby = "roomNumber";
...
/* Search the directory */
if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter,
  NULL, 0, &result ) !=
  LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_search_s" );
  return( 1 );
}
/* Sort the results by room number, using strcasecmp */
if ( ldap_sort_entries( ld, &result, sortby, strcasecmp ) !=
  LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_sort_entries" );
  return( 1 );
}
...
See Also

ldap_multisort_entries(), ldap_result(), ldap_search_s(), LDAP_CMP_CALLBACK()

ldap_start_tls_s()

The ldap_start_tls_s() initiates a Start Transport Layer Security (TLS) operation as defined in RFC 4513. Before using this function, call ldapssl_client_init(), ldapssl_clientauth_init(), or ldapssl_advclientauth_init() to initialize use of the certificate database.

Syntax
#include <ldap_ssl.h>
int ldap_start_tls_s( LDAP *ld, LDAPControl **serverctrls,
  LDAPControl **clientctrls );
Parameters
ldap_start_tls_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
serverctrls List of LDAP server controls.
clientctrls List of client controls.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_OPERATIONS_ERROR if TLS has already been established.
  • LDAP_PROTOCOL_ERROR if TLS is not supported.
  • LDAP_REFERRAL if this server does not support TLS, but the server referred to may.
  • LDAP_UNAVAILABLE if the server is shutting down, or supports TLS but cannot provide it at this time.

ldap_sort_strcasecmp()

The ldap_sort_strcasecmp() routine compares two strings and ignores any differences in case when comparing uppercase and lowercase characters.

Syntax
#include <ldap.h>
int ldap_sort_strcasecmp( const char **a, const char **b );
Parameters
ldap_sort_strcasecmp() Function Parameters
Parameter Description
a Pointer to first string to compare
b Pointer to second string to compare
Returns

One of the following values:

  • If a is greater than b, returns a value greater than 0.
  • If a is equal to b, returns 0.
  • If a is less than b, returns a value less than 0.
Description

The ldap_sort_strcasecmp() routine compares two strings and ignores any differences in case when comparing uppercase and lowercase characters. This function is similar to the C function strcasecmp(). When sorting attribute values with ldap_sort_strcasecmp(), call ldap_sort_strcasecmp() to compare the attribute values.

Note: This function works with ASCII values only. For UTF-8 data, the comparison result is unspecified.

See Also

ldap_sort_strcasecmp(), LDAP_VALCMP_CALLBACK()

ldap_sort_values()

The ldap_sort_values() function sorts an array of values retrieved from an ldap_get_values() call.

Syntax
#include <ldap.h>
int ldap_sort_values( LDAP *ld, char **vals,
  LDAP_VALCMP_CALLBACK cmp );
Parameters
ldap_sort_values() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
vals The array of values to sort.
cmp Comparison function used when sorting the values. In the ldap_sort_strcasecmp() function, the comparison function must pass char ** parameters. Because of this, you need to use the ldap_sort_strcasecmp() function, rather than a function like strcasecmp().
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • If unsuccessful, returns an LDAP error code.
Example

The following example sorts the values of attributes before printing them.

#include <stdio.h>
#include <string.h>
#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result, *e;
BerElement *ber;
char *a, *dn;
char **vals;
int i;
char *my_searchbase = "dc=example,dc=com";
char *my_filter = "(sn=Jensen)";
...
if ( ( vals = ldap_get_values( ld, e, a ) ) != NULL ) {
  /* Sort the values of the attribute */
  if ( ldap_sort_values( ld, vals, strcasecmp ) ) != LDAP_SUCCESS ) {
    ldap_perror( ld, "ldap_sort_values" );
    return( 1 );
  }
  /* Print the values of the attribute */
  for ( i = 0; vals[i] != NULL; i++ ) {
    printf( "%s: %s\n", a, vals[i] );
  }
  /* Free the values from memory */
  ldap_value_free( vals );
}
...
See Also

ldap_get_values(), ldap_sort_strcasecmp, LDAP_VALCMP_CALLBACK().

ldapssl_advclientauth_init()

The ldapssl_advclientauth_init() function initialize the secure parts (Security and SSL) of the runtime for use by a client application that may want to do SSL client authentication.

Syntax
#include <ldap_ssl.h>
int LDAP_CALL ldapssl_advclientauth_init( char *certdbpath,
  void *certdbhandle, int needkeydb, char *keydbpath,
  void *keydbhandle, int needsecmoddb, char *secmodpath,
  const int sslstrength);
Parameters
ldapssl_advclientauth_init() Function Parameters
Parameter Description
certdbpath Specifies the path to the database containing certificates for your client. You can include the database filename in the path (for example, /usr/mozilla/ cert_file_name.db).
certdbhandle Pass a NULL value for this. (This parameter is not currently used.)
needkeydb Specifies whether or not the private key database needs to be opened for use. This parameter can have one of the following values:
  • If it is a non-zero value, the function opens the private key database, which is identified by the keydbpath argument.
  • If 0, the function does not open the private key database.
keydbpath Specifies the path to the database containing the private key certified by your certificate. You can include the database filename in the path (for example, /usr/mozilla/key_file_name.db).
needsecmoddb Specifies whether or not the security module database file needs to be opened for use. This parameter can have one of the following values:
  • If it is a non-zero value, the function opens the security module database, which is identified by the keydbpath argument.
  • If 0, the function does not open the security modules database.
secmodpath Path to the database containing security modules. You can include the database filename in the path (for example, /usr/mozilla/secmod_file_name .db).
sslstrength Specifies how the server certificate is evaluated. It takes one of the following:
  • LDAPSSL_AUTH_WEAK indicates that you accept the server’s certificate without checking the for certificate authority (CA) that issued the certificate.
  • LDAPSSL_AUTH_CERT indicates that you accept the server’s certificate only if you trust the CA that issued the certificate.
  • LDAPSSL_AUTH_CNCHECK indicates that you accept the server’s certificate only if you trust the CA that issued the certificate and if the value of the cn attribute is the DNS hostname of the server. If this option is selected, ensure that the defhost parameter passed to ldapssl_init() consists of only one hostname and not a list of hosts. Furthermore, the port number must be passed via the defport parameter, and cannot be passed via a host:port option.
Returns

One of the following values:

  • 0 if successful.
  • -1 if unsuccessful.
Description

You can call ldapssl_advclientauth_init() to initialize your client application for SSL and certificate-based client authentication. This function is similar to ldapssl_clientauth_init() and allows you to:

  • Specify the name and path of a security module database.
  • Specify the method used to verify the server’s certificate.

Note: You must call ldapssl_advclientauth_init() before calling ldapssl_init() to connect to the server.

Example

The following example initializes a client before connecting with a secure LDAP server.

#include <ldap.h>
#include <ldap_ssl.h>
#include <stdio.h>
...
/* Initialize client, using mozilla’s certificate database */
if ( ldapssl_advclientauth_init( "/u/mozilla/.netscape/
  ''cert_file_name''.db",
  NULL, 1, "/u/mozilla/.netscape/
  ''key_file_name''.db", NULL , 1,
  "/u/mozilla/.netscape/
  ''secmod_file_name''.db", LDAPSSL_AUTH_CNCHECK) < 0 ) {
  perror( "ldap_advclientauth_init" );
  return( 1 );
  }
}
...
See Also

ldap_init(), prldap_init() (IPv6), ldapssl_clientauth_init(), ldapssl_init(), ldapssl_install_routines()

ldapssl_client_init()

The ldapssl_client_init() function initializes the secure parts (Security and SSL) of the runtime for use by your client application to connect to a secure LDAP server over SSL.

Syntax
#include <ldap_ssl.h>
int ldapssl_client_init( const char *certdbpath, void *certdbhandle );
Parameters
ldapssl_client_init() Function Parameters
Parameter Description
certdbpath Specifies the path to the database containing certificates for your client.
certdbhandle Pass a NULL value for this. (This parameter is not used currently.)
Returns

One of the following values:

  • 0 if successful.
  • -1 if unsuccessful.
Description

You can call the ldapssl_client_init() function to initialize your client application for SSL. It is only called once and returns 0 if all goes well. If you plan to use certificate-based authentication, you should call either the ldapssl_clientauth_init() or the ldapssl_advclientauth_init() function.

The following example initializes a client before connecting with a secure LDAP server.

#include <ldap.h> 
#include <ldap_ssl.h> 
#include <stdio.h>

... /* Initialize client using a certificate database copied from Directory Server. */
if ( ldapssl_client_init( "/local/client/alias/", NULL ) < 0) { 
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}

The certdbpath is a path to the file system directory containing the certificate database files. For example:

$ ls /local/client/alias/*.db
/local/client/alias/cert8.db
/local/client/alias/key3.db
/local/client/alias/secmod.db
$
See Also

ldap_start_tls_s(), ldap_init(), prldap_init() (IPv6), ldapssl_init(), ldapssl_install_routines()

ldapssl_clientauth_init()

The ldapssl_clientauth_init() function initializes your client application to connect to a secure LDAP server over SSL and to use certificate-based client authentication.

Syntax
#include <ldap_ssl.h>
int ldapssl_clientauth_init( char *certdbpath, void *certdbhandle,
  int needkeydb, char *keydbpath, void *keydbhandle );
Parameters
ldapssl_clientauth_init() Function Parameters
Parameter Description
certdbpath Specifies the path to the database containing certificates for your client. You can include the database filename in the path (for example, /usr/mozilla/ cert_file_name.db).
needkeydb Specifies whether or not the private key database needs to be opened for use. This parameter can have one of the following values:
  • If it is a non-zero value, the function opens the private key database, which is identified by the keydbpath argument.
  • If 0, the function does not open the private key database.
keydbpath Specifies the path to the database containing the private key certified by your certificate. You can include the database filename in the path (for example, /usr/mozilla/ key_file_name.db).
certdbhandle Pass a NULL value for this. (This parameter is not currently used.)
Returns

One of the following values:

  • 0 if successful.
  • -1 if unsuccessful.
Description

You can call the ldapssl_clientauth_init() function to initialize your client application for SSL and certificate-based client authentication. However, if you need to specify the name and path of the security modules database or if you need to specify how the server’s certificate will be verified, you should call the ldapssl_advclientauth_init() function instead.

Note: You must call ldapssl_clientauth_init() before calling ldapssl_init() to connect to the server.

Example

The following example initializes a client before connecting with a secure LDAP server.

#include <ldap.h>
#include <ldap_ssl.h>
#include <stdio.h>
...
/* Initialize client, using mozilla’s certificate database */
if ( ldapssl_clientauth_init( "/u/mozilla/.netscape/
  ''cert_file_name''.db", NULL, 1,
  "/u/mozilla/.netscape/
  ''key_file_name''.db", NULL ) < 0 ) {
  perror( "ldap_clientauth_init" );
  return( 1 );
  }
}
...
See Also

ldap_init(), prldap_init() (IPv6), ldapssl_init(), ldapssl_install_routines()

ldapssl_enable_clientauth()

The ldapssl_enable_clientauth() function enables SSL client authentication on the given connection (passed using the ld parameter).

Syntax
#include <ldap_ssl.h>
int ldapssl_enable_clientauth( LDAP *ld, char *keynickname,
  char *keypasswd, char *certnickname );
Parameters
ldapssl_enable_clientauth() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
keynickname Pass an empty string, "", for this value. (This parameter is not currently used.)
keypasswd Password to the encrypted private key database.
certnickname Nickname of the certificate that you want to use for client authentication.
Returns

One of the following values:

  • 0 if successful.
  • -1 if unsuccessful.
See Also

ldapssl_clientauth_init()

ldapssl_err2string()

The ldapssl_err2string() function returns the corresponding error message for an SSL-specific error code.

Syntax
#include <ldap_ssl.h>
const char * LDAP_CALL ldapssl_err2string ( const int prerrno );
Parameters
ldapssl_err2string() Function Parameters
Parameter Description
prerrno The SSL error code that you want interpreted into an error message.
Returns

One of the following values:

  • If successful, returns the corresponding error message for the given error code.
  • If unsuccessful (for example, if the error code is not a known SSL error code), returns a pointer to the string Unknown error.
Description

ldapssl_err2string() provides support for SSL-specific error messages that are not covered by the regular message routine ldap_err2string(). If any ldapssl_*() function returns an error code that is unknown to ldap_err2string()–it returns Unknown error– this function should be called to determine the SSL-specific error message. To check for SSL errors, call ldapssl_err2string() after you call any of the following SSL initialization functions:

  • ldapssl_client_init()
  • ldapssl_clientauth_init()
  • ldapssl_advclientauth_init()
  • ldapssl_pkcs_init()

The errors returned by these functions are usually related to certificate database corruption, missing certificates in a certificate database, client authentication failures, and other general SSL errors.

See Also

ldapssl_client_init(), ldapssl_clientauth_init(), ldapssl_advclientauth_init(), ldapssl_pkcs_init(), ldap_err2string()

ldapssl_init()

The ldapssl_init() function initializes the LDAP library for SSL and installs the I/O routines for SSL.

Syntax
#include <ldap_ssl.h>
LDAP *ldapssl_init( const char *defhost, int defport, int defsecure );
Parameters
ldapssl_init() Function Parameters
Parameter Description
defhost Connect to this LDAP server, if no other server is specified.
defport Connect to this server port, if no other port is specified. To specify the default port 389, use LDAP_PORT as the value for this parameter.
defsecure Determines whether or not to establish the default connection over SSL. Set this to a non-zero value to establish the default connection over SSL.
Returns

One of the following values:

  • If successful, returns a pointer to an LDAP() structure, which should be passed to subsequent calls to other LDAP API functions.
  • If unsuccessful, returns -1.
Description

ldapssl_init() allocates an LDAP() structure but does not open an initial connection. Before calling this function, call ldapssl_client_init() to initialize your client for SSL.

The following example connects your client to a secure LDAP server.

#include <ldap.h>
#include <ldap_ssl.h>
#include <stdio.h>
...
/* Initialize client, using mozilla’s certificate database */
if ( ldapssl_client_init( "/u/mozilla/.netscape/
  ''cert_file_name''.db", NULL ) < 0) {
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}
/* get a handle to an LDAP connection */
if ( (ld = ldapssl_init( "cert.example.com", LDAPS_PORT, 1 )) == NULL {
  perror( "ldapssl_init" );
  return( 1 );
}
...
/* Client can now perform LDAP operations on the secure LDAP server */
...
See Also

ldap_init(), prldap_init() (IPv6), ldapssl_client_init(), ldapssl_install_routines()

ldapssl_install_routines()

The ldapssl_install_routines() function installs the I/O routines that enable SSL over LDAP.

Syntax
#include <ldap_ssl.h>
int ldapssl_install_routines( LDAP *ld );
Parameters
ldapssl_install_routines() Function Parameter
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
Returns

One of the following values:

  • 0 if successful.
  • -1 if unsuccessful.
Description

You need to call ldapssl_install_routines() in combination with ldap_init() or prldap_init() (IPv6) and ldap_set_option(). As an alternative, you can call ldapssl_init() rather than these three functions.

Note: As is the case with the ldapssl_init() function, you need to call ldapssl_client_init() to initialize your client for SSL before calling ldapssl_install_routines().

Example

The following example connects your client to a secure LDAP server.

#include <ldap.h>
#include <ldap_ssl.h>
#include <stdio.h>
...
/* Initialize client, using mozilla’s certificate database */
if ( ldapssl_client_init( "/u/mozilla/.netscape/
  ''cert_file_name''.db", NULL ) < 0) {
  printf( "Failed to initialize SSL client...\n" );
  return( 1 );
}
/* Get the handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( MY_HOST, 636 )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* Load SSL routines */
if ( ldapssl_install_routines( ld ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldapssl_install_routines" );
  return( 1 );
}
/* Set the option to use SSL with the default connection */
if (ldap_set_option( ld, LDAP_OPT_SSL, LDAP_OPT_ON ) != LDAP_SUCCESS) {
  ldap_perror( ld, "ldap_set_option" );
  return( 1 );
}
...
See Also

ldap_init(), prldap_init() (IPv6), ldapssl_init(), ldapssl_client_init()

ldapssl_pkcs_init()

int ldapssl_pkcs_init( const struct ldapssl_pkcs_fns *pfns);
Description

The ldap_pkcs_init() structure sets up callbacks for the security library to obtain required runtime information. It should be used in place of ldapssl_client_init(), ldapssl_clientauth_init(), and ldapssl_advclientauth_init().

Note: The Directory SDK For C uses the Public Key Cryptography Standard (PKCS) API implemented in Network Security Services (NSS) to provide SSL security support. Specifically, NSS implements the security API as defined in the PKCS#11 standard.

Because ldap_pkcs_init() is based on the ldapssl_pkcs_fns structure, you do not need to know all of the security parameters at initialization, unlike the other SSL initialization functions (ldapssl_*_init()), which require all security parameters to be known at the time of initialization. The following example defines the ldapssl_pkcs_fns structure.

typedef int (LDAP_PKCS_GET_TOKEN_CALLBACK)
  (void *context, char **tokenname);
typedef int (LDAP_PKCS_GET_PIN_CALLBACK)
  (void *context, const char *tokenname, char **tokenpin);
typedef int (LDAP_PKCS_GET_CERTPATH_CALLBACK)
  (void *context, char **certpath);
typedef int (LDAP_PKCS_GET_KEYPATH_CALLBACK)(void *context,
  char **keypath);
typedef int (LDAP_PKCS_GET_MODPATH_CALLBACK)
  (void *context, char **modulepath);
typedef int (LDAP_PKCS_GET_CERTNAME_CALLBACK)
  (void *context, char **certname);
typedef int (LDAP_PKCS_GET_DONGLEFILENAME_CALLBACK)
  (void *context, char **filename);
#define PKCS_STRUCTURE_ID 1
struct ldapssl_pkcs_fns {
  int local_structure_id;
  void *local_data;
  LDAP_PKCS_GET_CERTPATH_CALLBACK *pkcs_getcertpath;
  LDAP_PKCS_GET_CERTNAME_CALLBACK *pkcs_getcertname;
  LDAP_PKCS_GET_KEYPATH_CALLBACK *pkcs_getkeypath;
  LDAP_PKCS_GET_MODPATH_CALLBACK *pkcs_getmodpath;
  LDAP_PKCS_GET_PIN_CALLBACK *pkcs_getpin;
  LDAP_PKCS_GET_TOKEN_CALLBACK *pkcs_gettokenname;
  LDAP_PKCS_GET_DONGLEFILENAME_CALLBACK *pkcs_getdonglefilename;
};
Parameters
ldapssl_pkcs_init() Function Parameters
Parameter Description
pfns Specifies the ldap_pkcs_fns structure for initialization.
Returns

One of the following values:

  • 0 is successful.
  • -1 if unsuccessful.
  • n (a positive integer) denotes a Netscape Portable Runtime (NSPR) error as returned by the PR_GetError() NSPR function.
See Also

ldapssl_client_init(), ldapssl_clientauth_init(), ldapssl_advclientauth_init()

ldapssl_serverauth_init()

The ldapssl_serverauth_init() function is a server-authentication only version of ldapssl_clientauth_init().

Syntax
#include <ldap_ssl.h>
int ldapssl_serverauth_init(
  const char *certdbpath, void *certdbhandle, const int sslstrength );
Parameters
ldapssl_serverauth_init() Function Parameters
Parameter Description
certdbpath Specifies the path to the database containing certificates for your client. You can include the database filename in the path (for example, /usr/mozilla/cert_file_name.db).
certdbhandle Pass a NULL value for this. (This parameter is not currently used.)
sslstrength Specifies how the server certificate is evaluated. It takes one of the following:
  • LDAPSSL_AUTH_WEAK indicates that you accept the server’s certificate without checking the for certificate authority (CA) that issued the certificate.
  • LDAPSSL_AUTH_CERT indicates that you accept the server’s certificate only if you trust the CA that issued the certificate.
  • LDAPSSL_AUTH_CNCHECK indicates that you accept the server’s certificate only if you trust the CA that issued the certificate and if the value of the cn attribute is the DNS hostname of the server. If this option is selected, please ensure that the defhost parameter passed to ldapssl_init consists of only one hostname and not a list of hosts. Furthermore, the port number must be passed via the defport parameter, and cannot be passed via a host:port option.
Returns

One of the following values:

  • 0 if successful.
  • -1 if unsuccessful.
Description

ldapssl_serverauth_init() is a server-authentication only version of ldapssl_clientauth_init(). This function allows the sslstrength parameter to be passed in.

See Also

ldap_init(), prldap_init() (IPv6), ldapssl_init(), ldapssl_install_routines(), ldapssl_clientauth_init()

ldapssl_set_strength()

The ldapssl_set_strength() sets the SSL strength for an existing SSL-enabled LDAP session handle.

Syntax
#include <ldap_ssl.h>
int LDAP_CALL ldapssl_set_strength( LDAP *ld, int sslstrength );
Parameters

Note: See the description of the sslstrength value and note the potential problems that can be caused by passing in wrong host and port name values.

ldapssl_set_strength() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server. If value is NULL, the default for the new LDAP session handles is set.
sslstrength Specifies how the server certificate is evaluated. It takes one of the following:
  • LDAPSSL_AUTH_WEAK indicates that you accept the server’s certificate without checking the for certificate authority (CA) that issued the certificate.
  • LDAPSSL_AUTH_CERT indicates that you accept the server’s certificate only if you trust the CA that issued the certificate.
  • LDAPSSL_AUTH_CNCHECK indicates that you accept the server’s certificate only if you trust the CA that issued the certificate and if the value of the cn attribute is the DNS hostname of the server. If this option is selected, please ensure that the defhost parameter passed to ldapssl_init consists of only one hostname and not a list of hosts. Furthermore, the port number must be passed via the defport parameter, and cannot be passed via a host:port option.

ldapssl_tls_start_s()

The ldapssl_tls_start_s() function starts an SSL handshake on a previously established non-secure connection.

Syntax
#include <ldap_ssl.h>
LDAP_API(int)  LDAP_CALL ldapssl_tls_start_s( LDAP *ld, int defsecure,
  char *certdbpath, char *keydbpath, char ***referralsp );
Parameters
ldapssl_tls_start_s() Function Parameter
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
defsecure Determines whether or not to establish the default connection over SSL. Set this to a non-zero value to establish the default connection over SSL.
certdbpath Specifies the path to the database containing certificates for your client. You can include the database filename in the path (for example, /usr/mozilla/cert_file_name.db).
keydbpath Specifies the path to the database containing the private key certified by your certificate. You can include the database filename in the path (for example, /usr/mozilla/key_file_name.db).
referralsp Pointer to an array of strings representing the referrals found by an LDAP search operation and returned by the server (applicable only if the LDAP operation was a search operation). When done, you can free this by calling the ldap_value_free() function.
Description

The ldapssl_tls_start_s() function starts an SSL handshake on a previously established non-secure connection.

ldap_str2charray()

This function is deprecated and should not be used. It is included in ldap-deprecated.h for backward-compatibility.

ldap_tmplattrs()

The ldap_tmplattrs() function obtains a pointer to the correct ldap_disptmpl structure.

Syntax
#include <disptmpl.h>
char ** ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs,
  int exclude, unsigned long syntaxmask );
Parameters
ldap_tmplattrs() Function Parameters
Parameter Description
tmpl The name of the template to be retrieved.
includeattrs A null terminated array of attributes that should always be included (it may be NULL if no extra attributes are required).
exclude If 0, only attributes where the logical AND of the template item syntax id and the syntaxmask is non-zero are included. If non-zero, attributes where the logical AND of the template item syntax id and the syntaxmask is non-zero are excluded.
syntaxmask When non-zero, it is used to restrict the attribute set returned.
Returns
  • A NULL terminated array that contains the

names of attributes that need to be retrieved if the template, defined by tmpl , is to be used to display an entry.

  • A NULL pointer on error.
Description

The attribute list should be freed using ldap_value_free() .

See Also

ldap_value_free()

ldap_tmplerr2string()

The ldap_templerr2string() function returns a string representation of the error passed in the parameter.

Syntax
#include <disptmpl.h>
char * ldap_tmplerr2string( int err );
Parameters
ldap_tmplerr2string() Function Parameter
Parameter Description
err Error returned.

ldap_ufn_search_c()

Note: This function will be deprecated and should not be used. It is included in ldap-to-be-deprecated.h for backward-compatibility.

ldap_ufn_search_s()

Note: This function will be deprecated and should not be used. It is included in ldap-to-be-deprecated.h for backward-compatibility.

ldap_ufn_setprefix()

Note: This function will be deprecated and should not be used. It is included in ldap-to-be-deprecated.h for backward-compatibility.

ldap_unbind()

The ldap_unbind() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure.

Syntax
#include <ldap.h>
int ldap_unbind( LDAP *ld );
Parameters
ldap_unbind() Function Parameter
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
Returns

For a list of possible results for an LDAP unbind operation, see ldap_unbind_s().

Description

The ldap_unbind() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure. The three unbind functions (ldap_unbind() , ldap_unbind_s(), and ldap_unbind_ext()) all work synchronously in the sense that they send an unbind request to the server, close all open connections associated with the LDAP session handle, and dispose of all resources associated with the session handle before returning.

The following example closes the current connection with the LDAP server.

#include <ldap.h>
...
LDAP *ld;
...
/* After completing your LDAP operations with the server, close the
connection. */
if ( ldap_unbind( ld ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "Error while unbinding from the directory" );
  return( 1 );
}
...
See Also

ldap_unbind_s(), ldap_unbind_ext()

ldap_unbind_s()

The ldap_unbind_s() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure.

Syntax
#include <ldap.h>
int ldap_unbind_s( LDAP *ld );
Parameters
ldap_unbind_s() Function Parameter
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.
Description

The ldap_unbind_s() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure. The three unbind functions ( ldap_unbind(), ldap_unbind_s(), and ldap_unbind_ext()) all work synchronously in the sense that they send an unbind request to the server, close all open connections associated with the LDAP session handle, and dispose of all resources associated with the session handle before returning.

Note: There is no server response to an LDAP unbind operation. All three of the unbind functions return LDAP_SUCCESS (or another LDAP error code if the request cannot be sent to the LDAP server). After a call to one of the unbind functions, the session handle ld is invalid and it is illegal to make any further calls using it.

Example

The following example closes the current connection with the LDAP server.

#include <ldap.h>
...
LDAP *ld;
...
/* After completing your LDAP operations with the server, close the
connection. */
if ( ldap_unbind_s( ld ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "Error while unbinding from the directory" );
  return( 1 );
}
...
See Also

ldap_unbind(), ldap_unbind_ext()

ldap_unbind_ext()

The ldap_unbind_ext() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure.

Syntax
#include <ldap.h>
int ldap_unbind_ext( LDAP *ld, LDAPControl **serverctrls,
  LDAPControl **clientctrls );
Parameters
ldap_unbind_ext() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
serverctrls List of LDAP server controls.
clientctrls List of client controls.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.
Description

The ldap_unbind_ext() function unbinds from the directory, terminates the current association, and frees the resources contained in the LDAP structure. The three unbind functions (ldap_unbind(), ldap_unbind_s(), and ldap_unbind_ext()) all work synchronously in the sense that they send an unbind request to the server, close all open connections associated with the LDAP session handle, and dispose of all resources associated with the session handle before returning.

See also ldap_unbind(), ldap_unbind_s()

ldap_url_parse()

The ldap_url_parse() function parses an LDAP URL into its components.

Syntax
#include <ldap.h>
int ldap_url_parse( const char *url, LDAPURLDesc **ludpp );
Parameters
ldap_url_parse() Function Parameters
Parameter Description
url The URL that you want to check.
ludpp Pointer to a structure containing the components of the URL.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_URL_ERR_NOTLDAP if the URL does not begin with the ldap:// or ldaps:// prefix.
  • LDAP_URL_ERR_NODN if the URL missing trailing slash after host or port.
  • LDAP_URL_ERR_BADSCOPE if the scope within the URL is invalid.
  • LDAP_URL_ERR_MEM if not enough free memory is available for this operation.
  • LDAP_URL_ERR_PARAM if an invalid argument was passed to the function.
Example

The following example parses an LDAP URL and prints out each component of it.

#include <stdio.h>
#include <ldap.h>
...
char *my_url = "ldap://ldap.example.com:1389/dc=example,dc=com?
                cn,mail,telephoneNumber?sub?(sn=Jensen)";
LDAPURLDesc *ludpp;
int res, i;
...
if ( ( res = ldap_url_parse( my_url, ludpp ) ) != 0 ) {
  switch( res ){
    case LDAP_URL_ERR_NOTLDAP:
      printf( "URL does not begin with \"ldap://\"\n" );
      break;
    case LDAP_URL_ERR_NODN:
      printf( "URL missing trailing slash after host or port\n" );
      break;
    case LDAP_URL_ERR_BADSCOPE:
      printf( "URL contains an invalid scope\n" );
      break;
    case LDAP_URL_ERR_MEM:
      printf( "Not enough memory\n" );
      break;
    default:
      printf( "Unknown error\n" );
  }
  return( 1 );
}
printf( "Components of the URL:\n" );
printf( "Host name: %s\n", ludpp->lud_host );
printf( "Port number: %d\n", ludpp->lud_port );
if ( ludpp->lud_dn != NULL ) {
  printf( "Base entry: %s\n", ludpp->lud_dn );
} else {
  printf( "Base entry: Root DN\n" );
}
if ( ludpp->lud_attrs != NULL ) {
  printf( "Attributes returned: \n" );
  for ( i=0; ludpp->lud_attrs[i] != NULL; i++ ) {
    printf( "\t%s\n", ludpp->lud_attrs[i] );
}
} else {
        printf( "No attributes returned.\n" );
}
printf( "Scope of the search: " );
switch( ludpp->lud_scope ) {
  case LDAP_SCOPE_BASE:
    printf( "base\n" );
    break;
  case LDAP_SCOPE_ONELEVEL:
    printf( "one\n" );
    break;
  case LDAP_SCOPE_SUBTREE:
    printf( "sub\n" );
    break;
  default:
    printf( "Unknown scope\n" );
}
printf( "Filter: %s\n", ludpp->lud_filter );
...
See Also

ldap_free_urldesc()

ldap_url_parse_no_defaults()

The ldap_url_parse_no_defaults() function parses an LDAP URL into its components.

Syntax
#include <ldap.h>
int ldap_url_parse_no_defaults( const char *url, LDAPURLDesc **ludpp,
  int dn_required );
Parameters
ldap_url_parse_no_defaults() Function Parameters
Parameter Description
url The URL that you want to check.
ludpp Pointer to a structure containing the components of the URL.
dn_required Specifies if a DN must be present in the URL. Set to 0, the DN is not required. Set to 1, the function will return an error LDAP_URL_ERR_NODN if no DN is present.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_URL_ERR_NODN if a required DN is not present.
  • LDAP_URL_ERR_NOTLDAP if the URL does not begin with the ldap:// or ldaps:// prefix.
  • LDAP_URL_ERR_NODN if the URL missing trailing slash after host or port.
  • LDAP_URL_ERR_BADSCOPE if the scope within the URL is invalid.
  • LDAP_URL_ERR_MEM if not enough free memory is available for this operation.
  • LDAP_URL_ERR_PARAM if an invalid argument was passed to the function.
Description

The ldap_url_parse_no_defaults() function does not set any default value in the fields that would be absent from the URL (for example, the port number).

ldap_url_search()

The ldap_url_search() function searches the directory asynchronously for matching entries, based on the contents of the URL.

Syntax
#include <ldap.h>
int ldap_url_search( LDAP *ld, const char *url, int attrsonly );
Parameters
ldap_url_search() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
url LDAP URL specifying a search of the directory.
attrsonly Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
  • 0 specifies that both attribute types and attribute values are returned.
  • 1 specifies that only attribute types are returned.
Returns

Returns the message ID of the ldap_url_search() operation. To check the result of this operation, call ldap_result() and ldap_result2error().

Description

ldap_url_search() searches the directory for matching entries, based on the contents of the URL. ldap_url_search() is an asynchronous function; it does not directly return results. If you want the results to be returned directly by the function, call the synchronous function ldap_url_search_s().

Example

The following example returns the message ID.

#include "examples.h"

static void do_other_work();
unsigned long global_counter = 0;

int
main( int argc, char **argv )
{
  char *my_url = "ldap://ldap.example.com/dc=example,dc=com?
                  cn,mail,telephoneNumber?sub?(sn=Jensen)";
  LDAP *ld;
  LDAPMessage *result, *e;
  BerElement *ber;
  char *a, *dn;
  char **vals;
  int i, rc, finished, msgid;
  int num_entries = 0;
  struct timeval zerotime;

  zerotime.tv_sec = zerotime.tv_usec = 0L;

/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */
if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) {
  perror( "ldap_init" );
  return( 1 );
}
/* authenticate to the directory as nobody */
if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_simple_bind_s" );
  return( 1 );
}
/* search for all entries with surname of Jensen */
if (( msgid = ldap_url_search( ld, my_url, 0 )) == -1 ) {
  ldap_perror( ld, "ldap_url_search" );
  return( 1 );
}

/* Loop, polling for results until finished */
finished = 0;
while ( !finished ) {
  /*
  * Poll for results.   We call ldap_result with the "all" parameter
  * set to zero. This causes ldap_result() to return exactly one
  * entry if at least one entry is available. This allows us to
  * display the entries as they are received.
  */
  result = NULL;
  rc = ldap_result( ld, msgid, 0, zerotime, result );
  switch ( rc ) {
  case -1:
    /* some error occurred */
    ldap_perror( ld, "ldap_result" );
    return( 1 );
  case 0:
  /* Timeout was exceeded. No entries are ready for retrieval. */
    if ( result != NULL ) {
      ldap_msgfree( result );
    }
    break;
  default:
  /*
  * Either an entry is ready for retrieval, or all entries have
  * been retrieved.
  */
    if (( e = ldap_first_entry( ld, result )) == NULL ) {
      /* All done */
      finished = 1;
      if ( result != NULL ) {
        ldap_msgfree( result );
      }
      continue;
      }
    /* for each entry print out name + all attrs and values */
    num_entries++;
    if (( dn = ldap_get_dn( ld, e )) != NULL ) {
      printf( "dn: %s\n", dn );
      ldap_memfree( dn );
    }
    for ( a = ldap_first_attribute( ld, e, ber );
     a != NULL; a = ldap_next_attribute( ld, e, ber ) ) {
      if (( vals = ldap_get_values( ld, e, a )) != NULL ) {
        for ( i = 0; vals[ i ] != NULL; i++ ) {
          printf( "%s: %s\n", a, vals[ i ] );
        }
      ldap_value_free( vals );
      }
      ldap_memfree( a );
    }
    if ( ber != NULL ) {
      ldap_ber_free( ber, 0 );
    }
    printf( "\n" );
    ldap_msgfree( result );
  }
  /* Do other work here while you are waiting... */
  do_other_work();
}

/* All done. Print a summary. */
printf( "%d entries retrieved. I counted to %ld "
      "while I was waiting.\n", num_entries,
      global_counter );
ldap_unbind( ld );
return( 0 );
}

/*
 * Perform other work while polling for results. */
static void
do_other_work()
{
    global_counter++;
}
See Also

ldap_url_search_s(), ldap_result(), ldap_result2error()

ldap_url_search_s()

The ldap_url_search_s() function searches the directory synchronously for matching entries, based on the contents of the URL.

Syntax
#include <ldap.h>
int ldap_url_search_s( LDAP *ld, const char *url,
  int attrsonly, LDAPMessage **res );
Parameters
ldap_url_search_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
url LDAP URL specifying a search of the directory.
attrsonly Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
  • 0 specifies that both attribute types and attribute values are returned.
  • 1 specifies that only attribute types are returned.
res Results of the search (when the call is completed).
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • If unsuccessful, returns the LDAP error code for the operation.
Description

The ldap_url_search_s() function searches the directory for matching entries, based on the contents of the URL. ldap_url_search_s() is a synchronous function, which directly returns the results of the operation. If you want to perform other operations while waiting for the results of this operation, call the asynchronous function ldap_url_search().

Example

The following example processes a search request from an LDAP URL.

#include <stdio.h>
#include <ldap.h>
...
LDAP *ld;
LDAPMessage *result;
char *my_url = "ldap://ldap.example.com/dc=example,dc=com?
cn,mail,telephoneNumber?sub?(sn=Jensen)";
...
/* Process the search request in the URL */
if ( ldap_url_search_s( ld, my_url, 0, &result ) != LDAP_SUCCESS ) {
  ldap_perror( ld, "ldap_url_search_s" );
  return( 1 );
}
...
See Also

ldap_search(), ldap_search_st()

ldap_url_search_st()

The ldap_url_search_st() function searches the directory, synchronously within a specified time limit, for matching entries, based on the contents of the URL.

Syntax
#include <ldap.h>
int ldap_url_search_st( LDAP *ld, const char *url, int attrsonly,
  struct timeval *timeout, LDAPMessage **res );
Parameters
ldap_url_search_st() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
url LDAP URL specifying a search of the directory.
attrsonly Specifies whether or not attribute values are returned along with the attribute types. This parameter can have the following values:
  • 0 specifies that both attribute types and attribute values are returned.
  • 1 specifies that only attribute types are returned.
timeout Maximum time to wait for the results of the search.
res Results of the search (when the call is completed).
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.
  • LDAP_LOCAL_ERROR if an error occurred when receiving the results from the server.
  • LDAP_DECODING_ERROR if an error occurred when decoding the BER-encoded results from the server.
  • LDAP_FILTER_ERROR if an error occurred when parsing and BER-encoding the search filter specified by the filter argument.
  • LDAP_TIMEOUT if the search exceeded the time specified by the timeoutp argument.
  • LDAP_NOT_SUPPORTED if controls are included in your request (for example, as a session preference) and your LDAP client does not specify that it is using the LDAP v3. Make sure that you set the version of your LDAP client to version 3 before calling this function.

Note: Directory Server and other LDAP server products may send result codes in addition to those described. For example, the server may have loaded a plug-in that returns custom result codes. Check your LDAP server documentation for other result codes.

Description

The ldap_url_search_st() function searches the directory for matching entries, based on the contents of the URL. This function works like ldap_url_search_s() and lets you specify a time out period for the search.

See Also

ldap_search(), ldap_search_s()

ldap_utf8characters()

The ldap_utf8characters() function accepts a Unicode string and returns the number of characters.

Syntax
#include <ldap.h>
size_t ldap_utf8characters( const char* );
Parameters
ldap_utf8characters() Function Parameter
Parameter Description
char Pointer to a UTF-8 string.
Returns

Returns the number of UTF-8 characters in the 0 terminated array.

ldap_utf8copy()

The ldap_utf8copy() function accepts a Unicode string and copies the characters to a destination.

Syntax
#include <ldap.h>
int ldap_utf8copy( char* dst, const char* src );
Parameters
ldap_utf8copy() Function Parameter
Parameter Description
dst Pointer to a destination for the copied characters.
src Pointer to a UTF-8 string to copy.
Description

ldap_utf8copy() copies a character from src to dst. This function handles any valid UTF-8 character (including \0 and ASCII).

Returns

The number of characters copied.

ldap_utf8getcc()

The ldap_utf8getcc() function gets one UCS-4 character and moves the pointer to the next character.

Syntax
#include <ldap.h>
unsigned long ldap_utf8getcc( const char** src );
Parameters
ldap_utf8getcc() Function Parameter
Parameter Description
src Pointer to a UCS-4 character.

ldap_utf8isalnum()

The ldap_utf8isalnum() function determines whether the character is an alphanumeric one.

Syntax
#include <ldap.h>
int ldap_utf8isalnum( char* s );
Parameters
ldap_utf8isalnum() Function Parameter
Parameter Description
s Pointer to a UTF-8 character.

ldap_utf8isalpha()

The ldap_utf8isalpha() function determines whether the character is a letter.

Syntax
#include <ldap.h>
int ldap_utf8isalpha( char* s );
Parameters
ldap_utf8isalpha() Function Parameter
Parameter Description
s Pointer to a UTF-8 character.

ldap_utf8isdigit()

The ldap_utf8isdigit() function determines whether the character is a number.

Syntax
#include <ldap.h>
int ldap_utf8isdigit( char* s );
Parameters
ldap_utf8isdigit() Function Parameter
Parameter Description
s Pointer to a UTF-8 character.

ldap_utf8isspace()

The ldap_utf8isspace() function determines whether the character is a space, tab, newline, return or formfeed.

Syntax
#include <ldap.h>
int ldap_utf8isspace( char* s );
Parameters
ldap_utf8isspace() Function Parameter
Parameter Description
s Pointer to a UTF-8 character.

ldap_utf8len()

The ldap_utf8len() function accepts a Unicode string and returns the number of bytes it contains.

Syntax
#include <ldap.h>
int ldap_utf8len( const char* );
Parameters
ldap_utf8len() Function Parameter
Parameter Description
char Pointer to a UTF-8 string.

ldap_utf8next()

The ldap_utf8next() function accepts a character and returns a pointer to the character immediately following it.

Syntax
#include <ldap.h>
char* ldap_utf8next( char* );
Parameters
ldap_utf8next() Function Parameter
Parameter Description
char Pointer to a UTF-8 character.

ldap_utf8prev()

The ldap_utf8prev() function accepts a character and returns a pointer to the previous character.

Syntax
#include <ldap.h>
char* ldap_utf8prev( char* );
Parameters
ldap_utf8prev() Function Parameter
Parameter Description
char Pointer to a UTF-8 character.

ldap_utf8strtok_r()

The ldap_utf8strtok_r() function gets the next token from a string.

Syntax
#include <ldap.h>
char* ldap_utf8strtok_r( char* src, const char* brk, char** next);
Parameters
ldap_utf8strtok_r() Function Parameter
Parameter Description
src Pointer to a UTF-8 string from which to extract token.
brk Points to a NULL terminated set of delimiter characters.
next Pointer to the next token.
Returns

Returns a pointer to the next token. If there are no remaining tokens, returns a NULL pointer.

ldap_whoami()

The ldap_whoami() function sends an asynchronous Who am I? extended operation request to determine the authorization identity associated with a connection.

Syntax
LDAP_API(int) LDAP_CALL ldap_whoami( LDAP *ld, LDAPControl **serverctrls,
  LDAPControl **clientctrls, int *msgidp );
Parameters
ldap_whoami() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
msgidp Pointer to the message ID for this asynchronous call, for use with ldap_parse_whoami_result(), or to retrieve the result for use with ldap_parse_whoami().
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.

ldap_whoami_s()

The ldap_whoami_s() function sends a synchronous Who am I? extended operation request to determine the authorization identity associated with a connection.

Syntax
LDAP_API(int) LDAP_CALL ldap_whoami_s( LDAP *ld, LDAPControl **serverctrls,
  LDAPControl **clientctrls, char **authzid );
Parameters
ldap_whoami_s() Function Parameters
Parameter Description
ld Pointer to an LDAP structure containing information about the connection to the LDAP server.
serverctrls Pointer to an array of LDAPControl structures representing LDAP server controls that apply to this operation. If you do not want to pass any server controls, specify NULL for this argument.
clientctrls Pointer to an array of LDAPControl structures representing LDAP client controls that apply to this operation. If you do not want to pass any client controls, specify NULL for this argument.
authzid Pointer to the string to hold the authorization identity retrieved from the server.
Returns

One of the following values:

  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR if any of the arguments are invalid.
  • LDAP_ENCODING_ERROR if an error occurred when BER-encoding the request.
  • LDAP_SERVER_DOWN if the LDAP server did not receive the request or if the connection to the server was lost.
  • LDAP_NO_MEMORY if memory cannot be allocated.

ldap_vals2html()

The ldap_vals2html() function writes the HTML representation of a set of values.

Syntax
#include <disptmpl.h>
int ldap_vals2html( LDAP *ld, char *buf, char **vals, char *label,
  int labelwidth, unsigned long syntaxid, writeptype writeproc,
  void *writeparm, char *eol, int rdncount, char *urlprefix );
Parameters
ldap_vals2html() Function Parameters
Parameter Description
ld The LDAP pointer obtained by a previous call to ldap_open() .
buf  
vals A NULL terminated list of values, usually obtained by a call to ldap_get_values().
label A string (usually a friendly form of an LDAP attribute name) shown next to the values.
labelwidth Specifies the label margin (the number of blank spaces displayed to the left of the values). If zero is passed, a default label width is used.
syntaxid Display template attribute syntax identifier for a list of predefined LDAP_SYN_... values.
writeproc writeproc() function should be declared as:
int writeproc( writeparm, p, len )
void *writeparm;
char *p;
int len;
where p is a pointer to text to be written and len is the length of the text. p is guaranteed to be zero terminated.
writeparm A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
eol Lines of text are terminated with this string.
rdncount Limits the number of components that are displayed for DN attributes.
urlprefix Starting text to use when constructing an LDAP URL. The default is the string ldap://
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP error code on error.
Description

ldap_vals2html() produces HTML output of a single set of LDAP attribute values.

See Also

ldap_vals2text()

ldap_vals2text()

The ldap_vals2text() function writes the text representation of an LDAP entry.

Syntax
#include <disptmpl.h>
int ldap_vals2text( LDAP *ld, char *buf, char **vals, char *label,
  int labelwidth, unsigned long syntaxid, writeptype writeproc,
  void *writeparm, char *eol, int rdncount );
Parameters
ldap_vals2text() Function Parameters
Parameter Description
ld The LDAP pointer obtained by a previous call to ldap_open() .
buf  
vals A NULL terminated list of values, usually obtained by a call to ldap_get_values().
label A string (usually a friendly form of an LDAP attribute name) shown next to the values.
labelwidth Specifies the label margin (the number of blank spaces displayed to the left of the values). If zero is passed, a default label width is used.
syntaxid Display template attribute syntax identifier for a list of predefined LDAP_SYN_... values.
writeproc writeproc() function should be declared as:
int writeproc( writeparm, p, len )
void *writeparm;
char *p;
int len;
where p is a pointer to text to be written and len is the length of the text. p is guaranteed to be zero terminated.
writeparm A pointer to a structure that will be passed as the first parameter of the writeproc() procedure. Typically, this is used to pass the file descriptor of the file to write to.
eol Lines of text are terminated with this string.
rdncount Limits the number of components that are displayed for DN attributes.
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP error code on error.
Description

ldap_vals2text() produces a text representation of a single set of LDAP attribute values.

See Also

ldap_vals2html()

ldap_value_free()

The ldap_value_free() function frees an array of values from memory.

Syntax
#include <ldap.h>
void ldap_value_free( char **values );
Parameters
ldap_value_free() Function Parameter
Parameter Description
values Array of values.
Description

Use the ldap_value_free_len() function if the values are berval structures.

Example

See the example under ldap_get_values().

See Also

ldap_get_values(), ldap_value_free_len

ldap_value_free_len()

The ldap_value_free_len() function frees an array of berval structures from memory.

Syntax
#include <ldap.h>
void ldap_value_free_len( struct berval **values );
Parameters
ldap_value_free_len() Function Parameter
Parameter Description
values Array of berval structures.
Description

Use the ldap_value_free() function instead of this function if the values are string values.

Example

See the example under ldap_get_values_len().

See Also

ldap_get_values(), ldap_get_values_len

ldap_version()

#include <ldap.h>
int ldap_version( LDAPVersion *ver );
Parameters
ldap_version() Function Parameter
Parameter Description
ver LDAPVersion structure returning version information. If you only want the SDK version, you can pass NULL for this parameter.
Returns

The version number of the Directory SDK For C, multiplied by 100. For example, for version 1.0, the function returns 100.

See Also

ldap_get_option()

ldap_x_calloc()

The ldap_x_calloc() function allocates space for an array of elements.

Syntax
#include <ldap-extension.h>
void *ldap_x_calloc( size_t nelem, size_t elsize );
Parameters
ldap_x_calloc() Function Parameters
Parameter Description
nelem Number of elements for which memory is to be allocated.
elsize Size of each element.
Returns
  • If successful, returns a pointer to the space.
  • If there is no available memory, returns a NULL pointer.
See Also

ldap_x_free(), ldap_x_malloc() , ldap_x_realloc()

ldap_x_free()

The ldap_x_free() function frees allocated memory.

Syntax
#include <ldap-extension.h>
void ldap_x_free( void *ptr );
Parameters
ldap_x_free() Function Parameter
Parameter Description
ptr Pointer to the block of memory to be freed.
See Also

ldap_x_calloc(), ldap_x_malloc(), ldap_x_realloc()

ldap_x_hostlist_first()

The ldap_x_hostlist_first() function returns the first host and port defined in a host list file.

Syntax
#include <ldap-extension.h>
int ldap_x_hostlist_first( char *hostlist, int defport, char **hostp,
  int *portp, struct ldap_x_hostlist_status **statusp );
Description

ldap_x_hostlist_first() parses a space-separated host list (useful for implementing an extended I/O CONNECT callback function) and returns the first host and port defined.

Returns
  • LDAP_SUCCESS if successful.
  • If unsuccessful returns a valid LDAP API error code.

Note: A NULL or zero-length hostlist causes the host 127.0.0.1 to be returned.

See Also

ldap_x_hostlist_status(), LDAP_X_EXTIOF_CONNECT_CALLBACK(),

ldap_x_hostlist_next()

The ldap_x_hostlist_next() function returns the host and port defined in a host list file following the previous host and port returned.

Syntax
#include <ldap-extension.h>
int ldap_x_hostlist_next( char **hostp, int *portp,
  struct ldap_x_hostlist_status **statusp );
Description

This utility parses a space-separated host list (useful for implementing an extended I/O CONNECT callback function) and returns the host and port defined following the previous host and port returned.

Returns
  • LDAP_SUCCESS if successful. If no more

hosts are available, LDAP_SUCCESS is returned but hostp is set to NULL.

  • If unsuccessful returns a valid LDAP API error code.

Note: A NULL or zero-length hostlist causes the host 127.0.0.1 to be returned.

See Also

ldap_x_hostlist_status(), LDAP_X_EXTIOF_CONNECT_CALLBACK(),

ldap_x_hostlist_status()

See Also

ldap_x_hostlist_first(), ldap_x_hostlist_next(), LDAP_X_EXTIOF_CONNECT_CALLBACK()

ldap_x_hostlist_statusfree()

See Also

ldap_x_hostlist_first(), ldap_x_hostlist_next(), LDAP_X_EXTIOF_CONNECT_CALLBACK()

ldap_x_malloc()

The ldap_x_malloc() function allocates space for an object.

Syntax
#include <ldap-extension.h>
void *ldap_x_malloc( size_t size );
Parameters
ldap_x_malloc() Function Parameter
Parameter Description
size Specifies the size for the allocated block of memory.
See Also

ldap_x_free(), ldap_x_calloc() , ldap_x_realloc()

ldap_x_realloc()

The ldap_x_realloc() function changes the size of a block of memory.

Syntax
#include <ldap-extension.h>
void *ldap_x_realloc( void *ptr, size_t size );
Parameters
ldap_x_realloc() Function Parameter
Parameter Description
ptr Pointer to a block of memory.
size Specifies the new size of the block.
See Also

ldap_x_free(), ldap_x_calloc() , ldap_x_malloc()

prldap_get_default_socket_info()

The prldap_get_default_socket_info() function retrieves default socket information.

Syntax
#include <ldappr.h>
int prldap_get_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip );
Parameters
prldap_get_default_socket_info() Function Parameters
Parameter Description
fd The session handle returned from prldap_init().
soip Pointer to a structure containing socket specific information.
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP API error code if an error occurs.
  • LDAP_PARAM_ERROR is returned if ld is NULL.
See Also

prldap_set_default_socket_info()

prldap_get_session_info()

The prldap_get_session_info() function retrieves application-specific data.

Syntax
#include <ldappr.h>
int prldap_get_session_info( LDAP *ld, void *sessionarg,
  PRLDAPSessionInfo *seip );
Parameters
prldap_get_session_info() Function Parameters
Parameter Description
ld The session handle returned from prldap_init(). If NULL, the functions are installed as the default functions for all new LDAP handles.
seip Pointer to a structure with session information data.
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP API error code if an error occurs.
Description

The prldap_get_session_option() function retrieves an option for an LDAP session handle or a session argument that is passed to the CONNECT , POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks.

See Also

prldap_set_session_info()

prldap_get_session_option()

The prldap_get_session_option() function retrieves an option specific to the prldap layer.

Syntax
#include <ldappr.h>
int prldap_get_session_option( LDAP *ld, void *sessionarg,
  int option, ... );
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP API error code if an error occurs.
Description

The prldap_get_session_option() function retrieves an option for an LDAP session handle or a session argument that is passed to the CONNECT , POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks.

See Also

prldap_set_session_option()

prldap_get_socket_info()

The prldap_get_socket_info() function retrieves socket-specific information based on parameters passed to the extended I/O callback functions.

Syntax
#include <ldappr.h>
int prldap_get_socket_info( int fd, void *socketarg,
  PRLDAPSocketInfo *soip );
Parameters
prldap_get_socket_info() Function Parameters
Parameter Description
fd The session handle returned from prldap_init().
soip Pointer to a structure containing socket information data.
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP API error code if an error occurs.
See Also

prldap_set_socket_info()

prldap_init()

The prldap_init() function creates a new session handle with Netscape Portable Runtime (NSPR) I/O, threading, support for IPv6, and DNS functions installed.

Syntax
#include <ldappr.h>
LDAP * prldap_init( const char *defhost, int defport, int shared );
Parameters
prldap_init() Function Parameters
Parameter Description
defhost Space-delimited list of one or more host names (or IP address in dotted notation, such as 192.168.0.99) of the LDAP servers that you want the LDAP client to connect to. The names can be in hostname :portnumber format (in which case, portnumber overrides the port number specified by the defport argument.
defport Default port number of the LDAP server. To specify the standard LDAP port (port 389), use LDAP_PORT as the value for this parameter.
shared Pass a non-zero value if you plan to use this LDAP handle for more than one thread.
Returns
  • Pointer to LDAP session handle if successful.
  • NULL if an error occurs.
Description

To be able to use LDAP over Internet Protocol, version 6, IPv6, this function should be used rather than ldap_init().

See Also

prldap_install_routines()

prldap_install_routines()

The prldap_install_routines() function installs Netscape Portable Runtime (NSPR) I/O, threading, and DNS functions so they can be used by the LDAP session handle.

Syntax
#include <ldappr.h>
int prldap_install_routines( LDAP *ld, int shared );
Parameters
prldap_install_routines() Function Parameters
Parameter Description
ld The session handle returned from prldap_init(). If NULL, the functions are installed as the default functions for all new LDAP handles.
shared Pass a non-zero value if you plan to use this LDAP handle for more than one thread.
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP API error code if an error occurs.
See Also

prldap_init()

prldap_set_default_socket_info()

The prldap_set_default_socket_info() function sets default socket information.

Syntax
#include <ldappr.h>
int prldap_set_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip );
Parameters
prldap_set_default_socket_info() Function Parameters
Parameter Description
fd The session handle returned from prldap_init().
soip Pointer to a structure containing socket specific information.
Returns
  • LDAP_SUCCESS if successful.
  • LDAP_PARAM_ERROR is returned if ld is NULL.
  • An LDAP API error code if an error occurs.
See Also

prldap_get_socket_info()

prldap_set_session_info()

The prldap_set_session_info() function sets application-specific data.

Syntax
#include <ldappr.h>
int prldap_set_session_info( LDAP *ld, void *sessionarg,
  PRLDAPSessionInfo *seip );
Parameters
prldap_set_session_info() Function Parameters
Parameter Description
ld The session handle returned from prldap_init().
seip Pointer to a structure containing session information data.
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP API error code if an error occurs.
Description

The prldap_set_session_info() function sets application-specific data for an LDAP session handle or a session argument that is passed to the CONNECT, POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks.

See Also

prldap_get_session_info()

prldap_set_session_option()

The prldap_set_session_option() function sets a session option specific to the prldap layer.

Syntax
#include <ldappr.h>
int prldap_set_session_option( LDAP *ld, void *sessionarg,
  int option, ... );
Parameters
prldap_set_session_option() Function Parameters
Parameter Description
ld The session handle returned from prldap_init().
option  
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP API error code if an error occurs.
Description

The prldap_set_session_option() function sets an option for an LDAP session handle or a session argument that is passed to the CONNECT , POLL, NEWHANDLE, or DISPOSEHANDLE extended I/O callbacks.

See Also

prldap_get_session_option()

prldap_set_socket_info()

The prldap_set_socket_info() function sets socket information.

Syntax
#include <ldappr.h>
int prldap_set_socket_info( int fd, void *socketarg,
  PRLDAPSocketInfo *soip );
Parameters
prldap_set_socket_info() Function Parameters
Parameter Description
fd The session handle returned from prldap_init().
soip Pointer to a structure containing socket information data.
Returns
  • LDAP_SUCCESS if successful.
  • An LDAP API error code if an error occurs.
Description

The prldap_set_socket_info() function sets socket-specific information based on parameters passed to the extended I/O callback functions. For more information, see the ldappr.h header file.

See Also

prldap_get_socket_info()

Directory SDK for C Result Codes

This section lists some of the result codes that can be returned by functions in the Directory SDK for C. For ease of use, they are first listed in numerical order, then in alphabetical order.

LDAP result codes are extensible; thus, LDAP v3 extensions may define their own error codes, and register them with the Internet Assigned Numbers Authority (IANA). The IANA maintains a list of registered LDAP parameters, including result codes. This list includes what Directory SDK for C currently knows in terms of result codes. More information can be found in RFC 4520, Internet Assigned Numbers Authority (IANA) Considerations for the Lightweight Directory Access Protocol (LDAP).

Result Codes Summary in Numerical Order

The following table gives the decimal and hexadecimal value of all result codes. Values missing from the sequence are not assigned to a result code.

Numerical Listing of Result Codes
Decimal Hexadecimal Defined Name
0 0x00 LDAP_SUCCESS
1 0x01 LDAP_OPERATIONS_ERROR
2 0x02 LDAP_PROTOCOL_ERROR
3 0x03 LDAP_TIMELIMIT_EXCEEDED
4 0x04 LDAP_SIZELIMIT_EXCEEDED
5 0x05 LDAP_COMPARE_FALSE
6 0x06 LDAP_COMPARE_TRUE
7 0x07 LDAP_STRONG_AUTH_NOT_SUPPORTED
8 0x08 LDAP_STRONG_AUTH_REQUIRED
9 0x09 LDAP_PARTIAL_RESULTS
10 0x0a LDAP_REFERRAL
11 0x0b LDAP_ADMINLIMIT_EXCEEDED
12 0x0c LDAP_UNAVAILABLE_CRITICAL_EXTENSION
13 0x0d LDAP_CONFIDENTIALITY_REQUIRED
14 0x0e LDAP_SASL_BIND_IN_PROGRESS
     
16 0x10 LDAP_NO_SUCH_ATTRIBUTE
17 0x11 LDAP_UNDEFINED_TYPE
18 0x12 LDAP_INAPPROPRIATE_MATCHING
19 0x13 LDAP_CONSTRAINT_VIOLATION
20 0x14 LDAP_TYPE_OR_VALUE_EXISTS
21 0x15 LDAP_INVALID_SYNTAX
     
32 0x20 LDAP_NO_SUCH_OBJECT
33 0x21 LDAP_ALIAS_PROBLEM
34 0x22 LDAP_INVALID_DN_SYNTAX
35 0x23 LDAP_IS_LEAF
36 0x24 LDAP_ALIAS_DEREF_PROBLEM
     
48 0x30 LDAP_INAPPROPRIATE_AUTH
49 0x31 LDAP_INVALID_CREDENTIALS
50 0x32 LDAP_INSUFFICIENT_ACCESS
51 0x33 LDAP_BUSY
52 0x34 LDAP_UNAVAILABLE
53 0x35 LDAP_UNWILLING_TO_PERFORM
54 0x36 LDAP_LOOP_DETECT
     
60 0x3C LDAP_SORT_CONTROL_MISSING
61 0x3D LDAP_INDEX_RANGE_ERROR
     
64 0x40 LDAP_NAMING_VIOLATION
65 0x41 LDAP_OBJECT_CLASS_VIOLATION
66 0x42 LDAP_NOT_ALLOWED_ON_NONLEAF
67 0x43 LDAP_NOT_ALLOWED_ON_RDN
68 0x44 LDAP_ALREADY_EXISTS
69 0x45 LDAP_NO_OBJECT_CLASS_MODS
70 0x46 LDAP_RESULTS_TOO_LARGE
71 0x47 LDAP_AFFECTS_MULTIPLE_DSAS
     
80 0x50 LDAP_OTHER
81 0x51 LDAP_SERVER_DOWN
82 0x52 LDAP_LOCAL_ERROR
83 0x53 LDAP_ENCODING_ERROR
84 0x54 LDAP_DECODING_ERROR
85 0x55 LDAP_TIMEOUT
86 0x56 LDAP_AUTH_UNKNOWN
87 0x57 LDAP_FILTER_ERROR
88 0x58 LDAP_USER_CANCELLED
89 0x59 LDAP_PARAM_ERROR
90 0x5a LDAP_NO_MEMORY
91 0x5b LDAP_CONNECT_ERROR
92 0x5c LDAP_NOT_SUPPORTED
93 0x5d LDAP_CONTROL_NOT_FOUND
94 0x5e LDAP_NO_RESULTS_RETURNED
95 0x5f LDAP_MORE_RESULTS_TO_RETURN
96 0x60 LDAP_CLIENT_LOOP
97 0x61 LDAP_REFERRAL_LIMIT_EXCEEDED

Result Codes Reference in Alphabetical Order

The following section contains the detailed reference information for each result code listed in alphabetical order by code name.

LDAP_ADMINLIMIT_EXCEEDED

This result code indicates that the look-through limit on a search operation has been exceeded. The look-through limit is the maximum number of entries that the server will check when gathering a list of potential search result candidates.

Note: When working with Directory Server, keep in mind the following:

  • If you are bound as the root DN, the server sets an infinite look-through limit.
  • If you are not bound as the root DN, the server sets a time limit.

#define LDAP_ADMINLIMIT_EXCEEDED 0x0b /* 11 */


LDAP_AFFECTS_MULTIPLE_DSAS

This result code indicates that the requested operation needs to be performed on multiple servers, where this operation is not permitted.

#define LDAP_AFFECTS_MULTIPLE_DSAS 0x47 /* 71 */


LDAP_ALIAS_DEREF_PROBLEM

This result code indicates that a problem occurred when dereferencing an alias.

Note: Directory Server does not currently send this result code back to LDAP clients.

#define LDAP_ALIAS_DEREF_PROBLEM 0x24 /* 36 */


LDAP_ALIAS_PROBLEM

This result code indicates that the alias is invalid.

Note: Directory Server does not currently send this result code back to LDAP clients.

#define LDAP_ALIAS_PROBLEM 0x21 /* 33 */


LDAP_ALREADY_EXISTS

This result code indicates that the request is attempting to add an entry that already exists in the directory. Directory Server sends this result code back to the client in the following situations:

  • The request is an add request, and the entry already exists in the directory.
  • The request is a modify DN request, and the new DN of the entry already identifies another entry.
  • The request is adding an attribute to the schema, and an attribute with the specified name or object identifier (OID) already exists.

#define LDAP_ALREADY_EXISTS 0x44 /* 68 */


LDAP_AUTH_UNKNOWN

This result code indicates that an unknown authentication method was specified.

Note: Directory SDK For C library sets this result code if ldap_bind() or ldap_bind_s() are called and an authentication method other than LDAP_AUTH_SIMPLE is specified. These functions only allow you to use simple authentication.

#define LDAP_AUTH_UNKNOWN 0x56 /* 86 */


LDAP_BUSY

This result code indicates that the server is currently too busy to perform the requested operation.

#define LDAP_BUSY 0x33 /* 51 */


LDAP_CLIENT_LOOP

This result code indicates that the LDAP client detected a loop, for example, when following referrals.

#define LDAP_CLIENT_LOOP 0x60 /* 96 */


LDAP_COMPARE_FALSE

This result code is returned after an LDAP compare operation is completed. The result indicates that the specified attribute value is not present in the specified entry.

#define LDAP_COMPARE_FALSE 0x05 /* 5 */


LDAP_COMPARE_TRUE

This result code is returned after an LDAP compare operation is completed. The result indicates that the specified attribute value is present in the specified entry.

#define LDAP_COMPARE_TRUE 0x06 /* 6 */


LDAP_CONFIDENTIALITY_REQUIRED

This result code indicates that confidentiality is required for the operation.

#define LDAP_CONFIDENTIALITY_REQUIRED 0x0d /* 13 */


LDAP_CONNECT_ERROR

This result code indicates that the LDAP client cannot establish a connection, or has lost the connection, with the LDAP server. Directory SDK For C sets this result code. If you have not established an initial connection with the server, verify that you have specified the correct host name and port number and that the server is running.

#define LDAP_CONNECT_ERROR 0x5b /* 91 */


LDAP_CONSTRAINT_VIOLATION

This result code indicates that a value in the request does not comply with certain constraints. Directory Server sends this result code back to the client in the following situations:

  • The request adds or modifies the userpassword attribute, and one of the following is true:
    • The server is configured to check the password syntax, and the length of the new password is less than the minimum password length.
    • The server is configured to check the password syntax, and the new password is the same as one of the values of the uid, cn, sn, givenname, ou, or mail attributes.
    • The server is configured to keep a history of previous passwords, and the new password is the same as one of the previous passwords. The request is a bind request, and the user is locked out of the account. (For example, the server can be configured to lock a user out of the account after a given number of failed attempts to bind to the server.)

#define LDAP_CONSTRAINT_VIOLATION 0x13 /* 19 */


LDAP_CONTROL_NOT_FOUND

This result code indicates that a requested LDAP control was not found. Directory SDK For C sets this result code when parsing a server response for controls and not finding the requested controls. For example:

  • ldap_parse_entrychange_control() is called, but no entry change notification control is found in the server’s response.
  • ldap_parse_sort_control() is called, but no server-side sorting control is found in the server’s response.
  • ldap_parse_virtuallist_control() is called, but no virtual list view response control is found in the server’s response.

#define LDAP_CONTROL_NOT_FOUND 0x5d /* 93 */


LDAP_DECODING_ERROR

This result code indicates that the LDAP client encountered an error when decoding the LDAP response received from the server.

#define LDAP_DECODING_ERROR 0x54 /* 84 */


LDAP_ENCODING_ERROR

This result code indicates that the LDAP client encountered an error when encoding the LDAP request to be sent to the server.

#define LDAP_ENCODING_ERROR 0x53 /* 83 */


LDAP_FILTER_ERROR

This result code indicates that an error occurred when specifying the search filter. Directory SDK For C sets this result code if it cannot encode the specified search filter in an LDAP search request.

#define LDAP_FILTER_ERROR 0x57 /* 87 */


LDAP_INAPPROPRIATE_AUTH

This result code indicates that the type of credentials are not appropriate for the method of authentication used. Directory Server sends this result code back to the client if simple authentication is used in a bind request, but the entry has no userpassword attribute; also, if LDAP_SASL_EXTERNAL is attempted on a non-SSL connection.

#define LDAP_INAPPROPRIATE_AUTH 0x30 /* 48 */


LDAP_INAPPROPRIATE_MATCHING

This result code indicates that an extensible match filter in a search request contained a matching rule that does not apply to the specified attribute type.

#define LDAP_INAPPROPRIATE_MATCHING 0x12 /* 18 */


LDAP_INDEX_RANGE_ERROR

This result code indicates that the search results exceeded the range specified by the requested offsets. This result code applies to search requests that contain virtual list view controls.

#define LDAP_INDEX_RANGE_ERROR 0x3D /* 61 */


LDAP_INSUFFICIENT_ACCESS

This result code indicates that the client has insufficient access to perform the operation. Check that the user you are authenticating as has the appropriate permissions.

#define LDAP_INSUFFICIENT_ACCESS 0x32 /* 50 */


LDAP_INVALID_CREDENTIALS

This result code indicates that the credentials provided in the request are invalid. Directory Server sends this result code back to the client if a bind request contains the incorrect credentials for a user or if a user’s password has already expired.

#define LDAP_INVALID_CREDENTIALS 0x31 /* 49 */


LDAP_INVALID_DN_SYNTAX

This result code indicates than an invalid DN has been specified. Directory Server sends this result code back to the client if an add request or a modify DN request specifies an invalid DN. It also sends this code when an LDAP_SASL_EXTERNAL bind is attempted but certification to DN mapping fails.

#define LDAP_INVALID_DN_SYNTAX 0x22 /* 34 */


LDAP_INVALID_SYNTAX

This result code indicates that the request contains invalid syntax. Directory Server sends this result code back to the client in the following situations:

  • The server encounters an access control instruction (ACI) with invalid syntax.
  • The request attempts to add or modify an aci attribute, and the value of the attribute is an ACI with invalid syntax.
  • The request is a search request with a substring filter, and the syntax of the filter is invalid.
  • The request is a modify request that is attempting to modify the schema, but no values are provided (for example, the request might be attempting to delete all values of the objectclass attribute).

#define LDAP_INVALID_SYNTAX 0x15 /* 21 */


LDAP_IS_LEAF

This result code indicates that the specified entry is a leaf entry.

Note: Directory Server does not currently send this result code back to LDAP clients.

#define LDAP_IS_LEAF 0x23 /* 35 */


LDAP_LOCAL_ERROR

This result code indicates that an error occurred in the LDAP client, though it may also be returned by Directory Server.

#define LDAP_LOCAL_ERROR 0x52 /* 82 */


LDAP_LOOP_DETECT

This result code indicates that the server was unable to perform the requested operation because of an internal loop.

Note: Directory Server does not currently send this result code back to LDAP clients.

#define LDAP_LOOP_DETECT 0x36 /* 54 */


LDAP_MORE_RESULTS_TO_RETURN

This result code indicates that there are more results in the chain of results. The Directory SDK For C sets this result code when the ldap_parse_sasl_bind_result() function is called to retrieve the result code of an operation, and additional result codes from the server are available in the LDAP structure.

#define LDAP_MORE_RESULTS_TO_RETURN 0x5f /* 95 */


LDAP_NAMING_VIOLATION

This result code indicates that the request violates the structure of the DIT.

Note: Directory Server does not currently send this result code back to LDAP clients.

#define LDAP_NAMING_VIOLATION 0x40 /* 64 */


LDAP_NO_MEMORY

This result code indicates that no memory is available. Directory SDK For C sets this result code if a function cannot allocate memory (for example, when creating an LDAP request or an LDAP control).

#define LDAP_NO_MEMORY 0x5a /* 90 */


LDAP_NO_OBJECT_CLASS_MODS

This result code indicates that the request is attempting to modify an object class that should not be modified (for example, a structural object class).

Note: Directory Server does not currently send this result code back to LDAP clients.

#define LDAP_NO_OBJECT_CLASS_MODS 0x45 /* 69 */


LDAP_NO_RESULTS_RETURNED

This result code indicates that no results were returned from the server. The Directory SDK For C sets this result code when the ldap_parse_result() function is called but no result code is included in the server’s response.

#define LDAP_NO_RESULTS_RETURNED 0x5E /* 94 */


LDAP_NO_SUCH_ATTRIBUTE

This result code indicates that the specified attribute does not exist in the entry. Directory Server might send this result code back to the client if, for example, a modify request specifies the modification or removal of a non-existent attribute or if a compare request specifies a non-existent attribute.

#define LDAP_NO_SUCH_ATTRIBUTE 0x10 /* 16 */


LDAP_NO_SUCH_OBJECT

This result code indicates that the server cannot find an entry specified in the request. Directory Server sends this result code back to the client if it cannot find a requested entry and it cannot refer your client to another LDAP server.

#define LDAP_NO_SUCH_OBJECT 0x20 /* 32 */


LDAP_NOT_ALLOWED_ON_NONLEAF

This result code indicates that the requested operation is allowed only on entries that do not have child entries (leaf entries as opposed to branch entries). Directory Server sends this result code back to the client if the request is a delete request or a modify DN request and the entry is a parent entry. You cannot delete or move a branch of entries in a single operation.

#define LDAP_NOT_ALLOWED_ON_NONLEAF 0x42 /* 66 */


LDAP_NOT_ALLOWED_ON_RDN

This result code indicates that the requested operation will affect the RDN of the entry. Directory Server sends this result code back to the client if the request is a modify request that deletes attribute values from the entry that are used in the RDN of the entry. (For example, the request removes the attribute value uid=bjensen from the entry uid=bjensen,ou=People,dc=example,dc=com.)

#define LDAP_NOT_ALLOWED_ON_RDN 0x43 /* 67 */


LDAP_NOT_SUPPORTED

This result code indicates that the LDAP client is attempting to use functionality that is not supported. Directory SDK For C sets this result code if the client identifies itself as an LDAP v2 client, and the client is attempting to use functionality available in LDAP v3. For example:

  • You are passing LDAP controls to a function.
  • You are calling ldap_extended_operation() , ldap_extended_operation_s(), or ldap_parse_extended_result() to request an extended operation or to parse an extended response.
  • You are calling ldap_rename() or ldap_rename_s(), and you are specifying a new superior DN as an argument.
  • You are calling ldap_sasl_bind(), ldap_sasl_bind_s(), or ldap_parse_sasl_bind_result() to request Simple Authentication and Security Layer (SASL) authentication or to parse a SASL bind response.
  • You are calling ldap_parse_virtuallist_control() to parse a virtual list control from the server’s response.

If you want to use these features, make sure to specify that your LDAP client is an LDAP v3 client.

#define LDAP_NOT_SUPPORTED 0x5c /* 92 */


LDAP_OBJECT_CLASS_VIOLATION

This result code indicates that the request specifies a new entry or a change to an existing entry that does not comply with the server’s schema. Directory Server sends this result code back to the client in the following situations:

  • The request is an add request, and the new entry does not comply with the schema. For example, the new entry does not have all the required attributes, or the entry has attributes that are not allowed in the entry.
  • The request is a modify request, and the change will make the entry non compliant with the schema. For example, the change removes a required attribute or adds an attribute that is not allowed.

Check the server error logs for more information, and the schema for the type of entry that you are adding or modifying.

#define LDAP_OBJECT_CLASS_VIOLATION 0x41 /* 65 */


LDAP_OPERATIONS_ERROR

This is a general result code indicating that an error has occurred. Directory Server might send this code if, for example, memory cannot be allocated on the server. To troubleshoot this type of error, check the server’s error logs. You may need to increase the log level of the server to get additional information.

#define LDAP_OPERATIONS_ERROR 0x01 /* 1 */


LDAP_OTHER

This result code indicates than an unknown error has occurred. This error may be returned by Directory Server when an error occurs that is not better described using another LDAP error code. When this error occurs, check the server's error logs. You may need to increase the log level of the server to get additional information.

#define LDAP_OTHER 0x50 /* 80 */


LDAP_PARAM_ERROR

This result code indicates that an invalid parameter was specified. Directory SDK For C sets this result code if a function was called and invalid parameters were specified, for example, if the LDAP structure is NULL.

#define LDAP_PARAM_ERROR 0x59 /* 89 */


LDAP_PARTIAL_RESULTS

Directory Server sends this result code to LDAP v2 clients to refer them to another LDAP server. When sending this code to a client, the server includes a new line-delimited list of LDAP URLs that identifies another LDAP server. If the client identifies itself as an LDAP v3 client in the request, an LDAP_REFERRAL result code is sent instead of this result code.

#define LDAP_PARTIAL_RESULTS 0x09 /* 9 */


LDAP_PROTOCOL_ERROR

This result code indicates that the LDAP client’s request does not comply with the LDAP. Directory Server sends this result code back to the client in the following situations:

  • The server cannot parse the incoming request.
  • The request specifies an attribute type that uses a syntax not supported by the server.
  • The request is a SASL bind request, but your client identifies itself as an LDAP v2 client.
  • The request is a bind request that specifies an unsupported version of the LDAP. Make sure to specify whether your LDAP client is an LDAP v2 client or an LDAP v3 client.
  • The request is an add or a modify request that specifies the addition of an attribute type to an entry, but no values are specified.
  • The request is a modify request, and one of the following is true:
    • An unknown modify operation is specified (an operation other than LDAP_MOD_ADD, LDAP_MOD_DELETE, and LDAP_MOD_REPLACE).
    • No modifications are specified.
  • The request is a modify DN request, and one of the following is true:
    • The new RDN is not a valid RDN.
    • A new superior DN is specified, but your client identifies itself as an LDAP v2 client.
  • The request is a search request, and one of the following is true:
    • An unknown scope is specified, meaning a scope other than LDAP_SCOPE_BASE , LDAP_SCOPE_ONELEVEL, or LDAP_SCOPE_SUBTREE .
    • An unknown filter type is specified.
    • The filter type LDAP_FILTER_GE or LDAP_FILTER_LE is specified, but the type of attribute contains values that cannot be ordered. (For example, if the attribute type uses a binary syntax, the values of the attribute contain binary data, which cannot be sorted.)
    • The request contains an extensible filter (a filter using matching rules), but your client identifies itself as an LDAP v2 client.
    • The request contains an extensible filter (a filter using matching rules), but the matching rule is not supported by the server.
  • The request is a search request with a server-side sorting control, and one of the following is true:
    • The server does not have a syntax plug-in that supports the attribute used for sorting.
    • The syntax plug-in does not have a function for comparing values of the attribute. (This compare function is used for sorting.)
    • The type of attribute specified for sorting contains values that cannot be sorted in any order. For example, if the attribute type uses a binary syntax, the values of the attribute contain binary data, which cannot be sorted.
    • The server encounters an error when creating the sorting response control (the control to be sent back to the client).
    • When sorting the results, the time limit or the look-through limit is exceeded. The look-through limit is the maximum number of entries that the server will check when gathering a list of potential search result candidates.
  • The request is an extended operation request, and the server does not support the extended operation. In Directory Server, extended operations are supported through extended operation server plug-ins. Make sure that the server is loading a plug-in that supports the extended operation. Check the OID of the extended operation in your LDAP client to make sure that it matches the OID of the extended operation registered in the server plug-in.
  • An authentication method other than LDAP_AUTH_SIMPLE or LDAP_AUTH_SASL is specified.

To troubleshoot this type of error, check the server’s error logs. You may need to increase the log level of the server to get additional information.

#define LDAP_PROTOCOL_ERROR 0x02 /* 2 */


LDAP_REFERRAL

This result code indicates that the server is referring the client to another LDAP server. When sending this code to a client, the server includes a list of LDAP URLs that identify another LDAP server. This result code is part of the LDAP v3. For LDAP v2 clients, Directory Server sends an LDAP_PARTIAL_RESULTS result code instead.

#define LDAP_REFERRAL 0x0a /* 10 */


LDAP_REFERRAL_LIMIT_EXCEEDED

This result code indicates that the referral hop limitwas exceeded. Directory SDK For C sets this result code, when following referrals, if the client is referred to other servers more times than allowed by the referral hop limit.

#define LDAP_REFERRAL_LIMIT_EXCEEDED 0x61 /* 97 */


LDAP_RESULTS_TOO_LARGE

This result code indicates that the results of the request are too large.

Note: Directory Server does not currently send this result code back to LDAP clients.

#define LDAP_RESULTS_TOO_LARGE 0x46 /* 70 */


LDAP_SASL_BIND_IN_PROGRESS

This result code is used in multi stage SASL bind operations. The server sends this result code back to the client to indicate that the authentication process has not yet completed.

#define LDAP_SASL_BIND_IN_PROGRESS 0x0E /* 14 */


LDAP_SERVER_DOWN

This result code indicates that Directory SDK For C cannot establish a connection with, or lost the connection to, the LDAP server. If you have not established an initial connection with the server, verify that you have specified the correct host name and port number and that the server is running.

#define LDAP_SERVER_DOWN 0x51 /* 81 */


LDAP_SIZELIMIT_EXCEEDED

This result code indicates that the maximum number of search results to return has been exceeded. This limit is specified in the search request. If you specify no size limit, the server will set one. When working with Directory Server, keep in mind the following:

  • If you are bound as the root DN and specify no size limit, the server enforces no size limit at all.
  • If you are not bound as the root DN and specify no size limit, the server sets the size limit to the value specified by the sizelimit directive in the server’s slapd.conf configuration file.
  • If the size limit that you specify exceeds the value specified by the sizelimit directive in the server’s slapd.conf configuration file, the server uses the size limit specified in the configuration file.

#define LDAP_SIZELIMIT_EXCEEDED 0x04 /* 4 */


LDAP_SORT_CONTROL_MISSING

This result code indicates that server did not receive a required server-side sorting control. Directory Server sends this result code back to the client if the server receives a search request with a virtual list view control but no server-side sorting control as the virtual list view control requires a server-side sorting control.

#define LDAP_SORT_CONTROL_MISSING 0x3C /* 60 */


LDAP_STRONG_AUTH_NOT_SUPPORTED

This result code is returned as the result of a bind operation. It indicates that the server does not recognize or support the specified authentication method.

#define LDAP_STRONG_AUTH_NOT_SUPPORTED 0x07 /* 7 */


LDAP_STRONG_AUTH_REQUIRED

This result code indicates that a stronger method of authentication is required to perform the operation.

#define LDAP_STRONG_AUTH_REQUIRED 0x08 /* 8 */


LDAP_SUCCESS

This result code indicates that the LDAP operation was successful.

#define LDAP_SUCCESS 0x00 /* 0 */


LDAP_TIMELIMIT_EXCEEDED

This result code indicates that the time limit on a search operation has been exceeded. The time limit is specified in the search request. If you specify no time limit, the server will set one. When working with Directory Server, keep in mind the following:

  • If you are bound as the root DN and specify no time limit, the server enforces no limit at all.
  • If you are not bound as the root DN and specify no time limit, the server sets the time limit.
  • If the time limit that you specify exceeds the time limit specified for the server configuration, the server uses the time limit specified in its configuration.

#define LDAP_TIMELIMIT_EXCEEDED 0x03 /* 3 */


LDAP_TIMEOUT

This result code indicates that the LDAP client timed out while waiting for a response from the server. Directory SDK For C sets this result code in the LDAP structure if the time-out period (for example, in a search request) has been exceeded and the server has not responded.

#define LDAP_TIMEOUT 0x55 /* 85 */


LDAP_TYPE_OR_VALUE_EXISTS

This result code indicates that the request attempted to add an attribute type or value that already exists. Directory Server sends this result code back to the client in the following situations:

  • The request attempts to add values that already exist in the attribute.
  • The request is adding an attribute to the schema of the server, but the OID of the attribute is already used by an object class in the schema.
  • The request is adding an object class to the schema of the server, and one of the following occurs:
    • The object class already exists.
    • The OID of the object class is already used by another object class or an attribute in the schema.
    • The superior object class for this new object class does not exist.

#define LDAP_TYPE_OR_VALUE_EXISTS 0x14 /* 20 */


LDAP_UNAVAILABLE

This result code indicates that the server is unavailable to perform the requested operation.

Note: At this point, neither Directory SDK For C nor Directory Server return this result code.

#define LDAP_UNAVAILABLE 0x34 /* 52 */


LDAP_UNAVAILABLE_CRITICAL_EXTENSION

This result code indicates that the specified control or matching rule is not supported by the server. Directory Server might send back this result code if the request includes an unsupported control or if the filter in the search request specifies an unsupported matching rule.

#define LDAP_UNAVAILABLE_CRITICAL_EXTENSION 0x0c /* 12 */


LDAP_UNDEFINED_TYPE

This result code indicates that the request specifies an undefined attribute type.

Note: Directory Server does not currently send this result code back to LDAP clients.

#define LDAP_UNDEFINED_TYPE 0x11 /* 17 */


LDAP_UNWILLING_TO_PERFORM

This result code indicates that the server is unwilling to perform the requested operation. Directory Server sends this result code back to the client in the following situations:

  • The client has logged in for the first time and needs to change its password, but the client is requesting to perform other LDAP operations. In this situation, the result code is accompanied by an expired password control.
  • The request is a modify DN request, and a superior DN is specified.
  • The database is in read-only mode, and the request attempts to write to the directory.
  • The request is a delete request that attempts to delete the root DSE.
  • The request is a modify DN request that attempts to modify the DN of the root DSE.
  • The request is a modify request to modify the schema entry, and one of the following occurs:
    • The operation is LDAP_MOD_REPLACE. (The server does not allow you to replace schema entry attributes.)
    • The request attempts to delete an object class that is the parent of another object class.
    • The request attempts to delete a read-only object class or attribute.
  • The server uses a database plug-in that does not implement the operation specified in the request. For example, if the database plug-in does not implement the add operation, sending an add request will return this result code.

#define LDAP_UNWILLING_TO_PERFORM 0x35 /* 53 */


LDAP_USER_CANCELLED

This result code indicates that the user cancelled the LDAP operation.

Note: Directory Server does not currently send this result code back to LDAP clients.

#define LDAP_USER_CANCELLED 0x58 /* 88 */