1.2 Using the LDAP Functions

The following sections discuss some general concepts for using the functions to accomplish a task and some principles for selecting the appropriate function for the task. It covers the following topics:

1.2.1 Using Dynamic Memory with LDAP Functions

If your application allocates any memory for use with LDAP functions, that memory must be freed by your application. Do not free this memory using an LDAP function, for example ldap_memfree.

All memory allocated by LDAP functions must be freed by LDAP functions. The following table lists the LDAP functions which allocate memory and the LDAP function you should use to free the memory.

Table 1-3 Dynamic Memory with LDAP Functions

Functions That Allocate Memory

Parameter/Structure Member

Memory Free Functions

ber_alloc_t

return(BerElement *)

ber_free

ber_bvdup

return(struct berval *)

ber_bvfree

ber_flatten

bvptr

ber_bvfree

ber_init

return(BerElement *)

ber_free

ber_scanf

"a" format option

ldap_memfree

ber_scanf

"B" format option

ldap_memfree

ber_scanf

"O" format option

ber_bvfree

ber_scanf

"V" format option

ber_bvecfree

ber_scanf

"v" format option

ldap_memfree

ldap_create_sort_control

ctrlp

ldap_control_free

ldap_create_sort_keylist

sortKeyList

ldap_free_sort_keylist

ldap_create_vlv_control

ctrlp

ldap_control_free

ldap_dn2ufn

return(char *)

ldap_memfree

ldap_explode_dn

return(char **)

ldap_value_free

ldap_explode_rdn

return(char **)

ldap_value_free

ldap_extended_operation_s

retdatap

ber_bvfree

ldap_extended_operation_s

retoidp

ldap_memfree

ldap_first_attribute

return (char *)

ldap_memfree

ldap_first_attribute

BerElement

ber_free ( xxx, 0)

ldap_get_context_identity_name

identity

ldapx_memfree

ldap_get_dn

return (char *)

ldap_memfree

ldap_get_entry_controls

LDAPControl

ldap_controls_free

ldap_get_option

LDAP_OPT_API_INFO / ldapai_extensions

ldap_value_free

ldap_get_option

LDAP_OPT_API_INFO/ ldapai_vendor_name

ldap_memfree

ldap_get_option

LDAP_OPT_MATCHED_DN / outvalue

ldap_memfree | ldap_controls_free

ldap_get_values

return (char **)

ldap_value_free

ldap_get_values_len

return(struct berval **)

ldap_value_free_len

ldap_init

return(LDAP *)

ldap_unbind, ldap_unbind_s

ldap_list_replicas

replicaList

ldapx_memfree

ldap_nds_to_ldap_name

ldapName

ldapx_memfree

ldap_next_attribute

return (char *)

ldap_memfree

ldap_next_attribute

BerElement

ber_free ( xxx, 0)

ldap_parse_extended_result

retdatap

ber_bvfree

ldap_parse_extended_result

retoidp

ldap_memfree

ldap_parse_reference

referralsp

ldap_value_free

ldap_parse_reference

serverctrlsp

ldap_controls_free

ldap_parse_result

errormsgp

ldap_memfree

ldap_parse_result

matcheddnp

ldap_memfree

ldap_parse_result

referralsp

ldap_value_free

ldap_parse_result

serverctrlsp

ldap_controls_free

ldap_parse_sasl_bind_result

servercredp

ber_bvfree

ldap_parse_sort_control

attribute

ldap_memfree

ldap_parse_vlv_control

contextp

ber_bvfree

ldap_result

res

ldap_msgfree

ldap_sasl_bind_s

servercredp

ber_bvfree

ldap_search_ext_s

res

ldap_msgfree

ldap_search_s

res

ldap_msgfree

ldap_search_st

res

ldap_msgfree

ldap_ssl_client_init

 

ldap_ssl_client_deinit

ldap_ssl_init

return(LDAP *)

ldap_unbind

ldap_url_parse

ludpp

ldap_free_urldesc

ldap_url_parse_ext

ludpp

ldap_free_urldesc

ldap_url_search_s

res

ldap_msgfree

ldap_url_search_st

res

ldap_msgfree

ldap_url_desc2str

return(char *)

ldap_memfree

The following functions free the memory allocated to the res parameter if the freeit parameter is set to true:

1.2.2 Selecting a Function for an LDAP Operation

Most LDAP functions that perform operations (such as add, delete, modify) have four variations:

  • LDAP v2 asynchronous. These take the format of ldap_operation, for example, ldap_search.

  • LDAP v3 asynchronous. These take the format of ldap_operation_ext, for example, ldap_search_ext.

  • LDAP v2 synchronous. These take the format of ldap_operation_s, for example, ldap_search_s.

  • LDAP v3 synchronous. These take the format of ldap_operation_ext_s, for example, ldap_search_ext_s.

If you are developing a new application, you should use the LDAP v3 version of the functions. The LDAP library supports the LDAP v2 versions for backwards compatibility with earlier releases.

1.2.3 Using Asynchronous or Synchronous Functions

Blocking versus Non-Blocking. Synchronous functions block and do not return until the LDAP server has serviced the request and returned a result. Asynchronous functions return as soon as the LDAP client processes the request, and the application is then free to do other work. However, the application is responsible to use the returned message ID to check on the status of the operation.

Return Values. The synchronous functions return both client and server error codes. The asynchronous ldap_*_ext functions return only the client error codes. The subsequent results must be parsed for the server error codes. The asynchronous ldap_* functions return a -1 for the client error codes, and the ldap_get_option function must be used to retrieve the client error codes from the LDAP session handle.

1.2.4 Initializing a Session with LDAP v3

By default, the LDAP v2 functions set up an LDAP v2 session because the session handle is configured for an LDAP v2 session. To ensure that your application sets up an LDAP v3 session, call the following functions in the order specified. The following example uses ldap_simple_bind.

  1. Call the ldap_set_option function with the ld parameter set to NULL and the option parameter set to LDAP_OPT_PROTOCOL_VERSION, and the invalue parameter set to LDAP_VERSION3.

    This sets the value in the global session handle to LDAP v3 and all subsequent session handles assume these values.

  2. Call the ldap_init function.

  3. Call the ldap_simple_bind or ldap_simple_bind_s function.

NOTE:This example uses clear text passwords. When you are ready to set up a secure connection, see Authentication.

1.2.5 Setting Initial Connection Timeout

Setting an initial connection timeout enables you to control the amount of time your application will wait for an initial connection to succeed. If a server does not respond and no initial connection timeout option is specified, timeout depends upon the underlying socket timeout setting of the operating system.

By setting an initial connection timeout, you can control how long your application will wait for an initial connection, then possibly attempt a connection to another server or wait and attempt a connection at another time.

An initial connection timeout is set using the LDAP_OPT_NETWORK_TIMEOUT option (set by calling ldap_set_option). The initial connection usually happens on the Bind command, whether it’s synchronous or asynchronous; simple, SASL, NMAS, or digest-md5. If no bind command is given, the initial connection happens on the first LDAP operation. An initial connection may also occur during a referral or rebind operation.

The following example sets an initial connection timeout of 10 seconds:

  struct timeval timeOut = {10, 0};
  ldap_set_option( NULL, LDAP_OPT_NETWORK_TIMEOUT, &timeOut);
  
  

Passing NULL for the ld parameter to ldap_set_option will set this as the default connection timeout for subsequent session handles created with ldap_init() or ldapssl_init(). To clear the timeout, pass NULL for the timeout argument to ldap_set_option.

A connection timeout will cause an LDAP_SERVER_DOWN error (81) "Can't contact LDAP server".

Using the connection timeout, you can specify multiple hosts separated by spaces in a bind call, and use this timeout to determine how long your application waits for an initial response before attempting a connection to the next host in the list. The following example sets an initial connection timeout of 5 seconds and multiple hosts in the bind call:

  struct timeval timeOut = {5,0};
  ldap_set_option( NULL, LDAP_OPT_NETWORK_TIMEOUT, &timeOut);
  ld = ldap_init("www.acme.com 129.233.80.5 127.0.0.1", 389);
  

1.2.6 Setting and Getting the Cipher Level

There are four possible combinations of cipher that can be set. The following table provides the details:

Table 1-4 Details of the Cipher Level

Cipher Value

Key Strength

Algorithm

LDAP_TLS_CIPHER_LOW

56

Single DES

LDAP_TLS_CIPHER_MEDIUM

128

RSA

LDAP_TLS_CIPHER_HIGH

168

Triple DES

LDAP_TLS_CIPHER_EXPORT

56

SHA

By default, the cipher is set to high (triple DES). If the you want to set any of the above mentioned cipher value, call the following functions in the order specified. The following example uses ldap_simple_bind.

  1. Call the ldap_set_option function with the ld parameter set to NULL and the option parameter set to LDAP_OPT_TLS_CIPHER_LEVEL, and the invalue parameter set to LDAP_TLS_CIPHER_MEDIUM.

    This sets the value in the global session handle to key strength 128, algorithm RSA, and all subsequent session handles assume these values.

  2. Call the ldapssl_init function.

  3. Call the ldap_simple_bind or ldap_simple_bind_s function.

    NOTE:After the bind operation is complete, the application can retrieve the cipher settings used during SSL connection by using the ldap_get_option.

1.2.7 LDAP URLs

LDAP URLs provide a uniform method to access information on an LDAP server. Defined in RFC 2255, LDAP URLs begin with the prefix ldap:// or ldaps://. The following provides the syntax and descriptions of an LDAP URL.

  ldap[s]://<hostname>:<port>/<base_dn>?<attributes>?<scope>?<filter>?<extension>
  

HINT:ldaps is a common enhancement used to denote SSL, and is not defined in an RFC.

In the LDAP Libraries for C, LDAP URLs are used to:

  • Return referrals or search references from a server

  • Perform searches (ldap_url_search)

Table 1-5 Field descriptions for an LDAP URL

URL Element

Default Value

Description

hostname

none

DNS name or IP address of the LDAP server.

port

389

Port of the LDAP server.

base_dn

root

Base DN for the LDAP operation.

attributes

all attributes

A comma-delimited list of attributes to return.

scope

base

Search scope: base, one, sub.

filter

objectClass=*

Search filter.

extension

none

LDAP extended operations.

NOTE:An attribute list is required if you want to provide a scope (even if the attribute list is blank). To return all attributes within a specific scope you must include <base_dn>??<scope>.

Determining if a URL is an LDAP URL

To determine if a URL is a valid ldap:// or ldaps:// URL use one of the following functions:

Both functions take a URL as the parameter and return 1 if the URL is a valid LDAP URL, and 0 if it is not valid.

Parsing an LDAP URL

The ldap_url_parse function parses an LDAP URL and returns an LDAPURLDesc structure to your application. You can then retrieve the individual parameters from the URL, or you can pass this URL to a search function.

Searching with an LDAP URL

The ldap_url_search functions allow you to pass an LDAPURLDesc structure to perform an LDAP search.

1.2.8 Threads

The LDAP libraries for C APIs are operation thread safe. This allows different threads within an application to concurrently use the same LDAP session handle for different operations.

Applications using this feature need to duplicate the session handle using the ldap_dup function. The returned session handle may be used concurrently with the original session handle. To destroy the session handle use the ldap_destroy function.

The following example uses ldap_dup and ldap_destory.

  1. Call the ldap_init function.

  2. Call the ldap_simple_bind or ldap_simple_bind_s function.

  3. Duplicate the session handle using ldap_dup.

  4. Use the duplicated session handle in a separated thread to do any LDAP operation like add, search, or modify.

  5. Close the duplicated session handle using ldap_destroy in the same thread.

  6. Use the original LDAP handle in the main thread to do any LDAP operation like add, search, or modify.

  7. Use the LDAP_OPT_SESSION_REFCNT to get reference count associated with the supplied session handle.

  8. Call the ldap_unbind function.

For more information, refer to the theadSafe.c sample program.

1.2.9 Internationalization

The LDAP libraries have been enabled for internationalization. However, the messages are currently available only in English. For cross-platform support, the English messages have been placed in the following files:

Table 1-6 Internationalization File Name on Different Platforms

File Name

Platform

ldapsdk.msg

NetWare

ldapsdkmsg.dll

Windows (NT, 95, 98, 2000)

ldapsdk.mo

Solaris (2.6, 2.7, 2.8), Linux (RedHat 7.2), AIX and HP-UX (11.11)

Depending upon the platform, the message file is installed in the following locations:

  • On a NetWare server in the sys:\system\nls\4 directory.

  • On an eDirectory for NT server in the winnt\system32\nls\english directory.

  • On a Windows client in the Novell\ndk\cldapsdk\bin\win32\nls\english directory.

  • On a Unix platform (Solaris, Linux, or HP-UX) in the [install directory]/cldapsdk/lib/locale/C/LC_MESSAGES directory.

NetWare NLMs

If you wish to translate the messages to another language for the NetWare platform, you will need to use the internationalization tools included in the NLM User Interface Developer Components. Use the ldapmsg.h file and the tools to create an errormsg.mdb file. Use the tools to translate the errormsg.mdb file. Use the translated file and the tools to create an ldapsdk.msg file.

Windows

If you wish to translate the messages to another language for the Windows platform, translate the errormsg.rc file. When you save the file, the resource.h file is created. Build the code to convert the errormsg.rc and resource.h files to an errormsg.dll file.

Unix

If you wish to translate the messages to another language for a Unix platform, complete the following steps:

  1. Translate the messages in the ldapsdk.po file to the target language. This file is located in the <install directory>/cldapsdk/lib/locale/C/LC_MESSAGES directory. The following steps assume that French is the target language.

  2. Use the msgfmt command to convert the ldapsdk.po file to an ldapsdk.mo file.

  3. Create the directory for the messages. For French, the directory would be the following:

      <install directory>/cldapsdk/lib/locale/fr/LC_MESSAGES
      
  4. Copy the ldapsdk.mo file to the directory created in Step 3.

  5. Export the following:

      NLDAPSDK_ROOT=<install directory>