...
#include <stdio.h>
#include "ldap.h"
/* Specify the search criteria here. */
#define HOSTNAME "localhost"
#define PORTNUMBER 389
#define BASEDN "o=Airius.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. */
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 LDAP v3 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 );
}
...The rest of this chapter explains how to initialize a session, authenticate your client, perform LDAP operations, and disconnect from the LDAP server.
LDAP structure, which contains information about the LDAP server and the LDAP session. You need to pass this structure to all subsequent LDAP API functions to identify the LDAP server that you are working with.
The following sections explain how to initialize an LDAP session with a server and how to specify session preferences:
An example of initializing an LDAP session is also provided. See "Examples of Initializing an LDAP Session."
NOTE: If you plan to connect to the LDAP server over a Secure Sockets Layer (SSL), the procedure for initializing an LDAP session differs. For details, see Chapter 12, "Connecting Over SSL".
ldap_init() function. Pass the host name and port number of your LDAP server as arguments to this function.
If the server is using the default port for the LDAP protocol (port 389), you can pass LDAP_PORT as the value of the port parameter. For example:
...
LDAP *ld
...
ld = ldap_init( "directory.netscape.com", LDAP_PORT );If successful, the
ldap_init() function returns a connection handle, which is a pointer to an LDAP structure containing information about the connection to the LDAP server. You need to pass this pointer to the LDAP API functions for connecting, authenticating, and performing LDAP operations on a server.
For example, when you call a function to search the directory, you need to pass the connection handle as a parameter. The connection handle provides context for the connection.
ldap_init() function. For example:
...
LDAP *ld
...
ld = ldap_init( "ld1.netscape.com ld2.netscape.com ld3.netscape.com",
LDAP_PORT );In the example above, the LDAP client will attempt to connect to the LDAP server on ld1.netscape.com, port 389. If that server does not respond, the client will attempt to connect to the LDAP server on ld2.netscape.com, port 389. If that server does not respond, the client will use the server on ld3.netscape.com, port 389. If any of the servers do not use the default port specified as the second argument to
ldap_init(), use the host:port format to specify the server name. For example:
...
LDAP *ld
...
ld = ldap_init( "ld1.netscape.com ld2.netscape.com:38900", LDAP_PORT );In the example above, the LDAP client will attempt to connect to the LDAP server on ld1.netscape.com, port 389. If that server does not respond, the client will attempt to connect to the LDAP server on ld2.netscape.com, port 38900.
ldap_get_option() function or the ldap_set_option() function.
Both functions pass two parameters (in addition to the ld parameter, which represents the connection to the server):
option parameter that identifies the option that you want to get or set value parameter that is either a pointer to a place to put the value that you are getting or a pointer to the value that you are settingLDAP structure as the first argument.
For a complete list of the options and values you can get and set, see the documentation on the ldap_get_option() function and the ldap_set_option() function.
Some of these preferences are described in the sections below:
LDAP_SERVER_DOWN is returned by your client. If you want your client to continue to attempt to communicate with the server, you can set the LDAP_OPT_RESTART preference for the session.
Call the ldap_set_option() function and pass LDAP_OPT_RESTART as the value of the option parameter.
optdata parameter to LDAP_OPT_ON. optdata parameter to LDAP_OPT_OFF. LDAP_OPT_OFF. Both LDAP_OPT_OFF and LDAP_OPT_ON are cast to (void *). You can pass these parameters directly to the function. For example:
...
ldap_set_option( ld, LDAP_OPT_RESTART, LDAP_OPT_ON );
...Note that this option is not available on Macintosh clients.
ldap_set_option() function and set the LDAP_OPT_PROTOCOL_VERSION option to the value 3. For example:
...
version = LDAP_VERSION3;
ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
...After setting this option, your client can authenticate or bind to the server (see "Binding and Authenticating to an LDAP Server" for details). As part of the process of binding to the server, your client sends the supported LDAP version number to the server. This allows the server to determine whether or not to enable use of LDAP v3 features. Note that the LDAP v3 protocol allows you to perform LDAP operations without binding to the server first. If you perform LDAP operations without binding, the server may assume that your client is an LDAP v3 client. (For example, the Netscape Directory Server 3.0 assumes that if your client supports LDAP v3 if it performs an LDAP operation without binding first.)
ldap.netscape.com:389 and directory.netscape.com:3890. The example also sets a session preference that identifies the client as an LDAP v3 client.
#include <stdio.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.netscape.com directory.netscape.com:3890";
/* 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 ( ( ld1 = ldap_init( ldap_host, ldap_default_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 API calls pass ld as an argument to identify the LDAP
* server. */
...After you initialize a session with an LDAP server, you can set session options and connect and authenticate to the LDAP server. (Note that the
ldap_init() function does not connect to the LDAP server right away.)
NULL values as the user's distinguished name and password (as described in "Binding Anonymously"). ldap_simple_bind_s() function if you want to wait for the bind operation to complete before the function returns. (See "Performing a Synchronous Authentication Operation.") ldap_simple_bind() function if you do not want to wait for the bind operation to complete. You can perform other work while periodically checking for the results of the bind operation. (See "Performing an Asynchronous Authentication Operation.")ldap_simple_bind() or ldap_simple_bind_s() function.
If you are binding to the Netscape Directory Server 3.0, the server may send back special controls to indicate that your password has expired or will expire in the near future. For more information on these controls, see "Using Password Policy Controls."
For more information about the difference between synchronous and asynchronous functions, see "Calling Synchronous and Asynchronous Functions."
ldap_simple_bind_s() function. This function returns LDAP_SUCCESS if the operation successfully completed or an LDAP result code if a problem occurred. (See the documentation for this function for a list of possible result codes returned.)
If you specify a DN but no password, your client will bind to the server anonymously. If you want a NULL password to be rejected as an incorrect password, you need to write code to perform the check before you call the ldap_simple_bind_s() function.
The following section of code uses the synchronous ldap_simple_bind_s() function to authenticate the user Barbara Jensen to the LDAP server. (For an example of binding anonymously, see "Binding Anonymously.")
...
#include <stdio.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BIND_DN "uid=bjensen,ou=People,o=Airius.com"
#define BIND_PW "hifalutin"
LDAP *ld;
int rc;
/* Get a handle to an LDAP connection. */
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 );
...
ldap_simple_bind() function. This function sends an LDAP bind request to the server and returns a message ID identifying the bind operation.
If you specify a DN but no password, your client will bind to the server anonymously. If you want a NULL password to be rejected as an incorrect password, you need to write code to perform the check before you call the ldap_simple_bind() function.
You can check to see if your client has received the results of the bind operation from the server by calling the ldap_result() function and passing it the message ID.
If your client has received the results, the ldap_result() function passes back the results of the bind operation in an LDAPMessage structure. To get error information from this structure, you can pass it to the ldap_parse_result() function.
The ldap_parse_result() function 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 from the server.
(The Netscape Directory Server 3.0 may return a control if the user's password has expired or will expire in the near future. For more information, see "Using Password Policy Controls.")
The following section of code uses the asynchronous ldap_simple_bind() function to authenticate the user Barbara Jensen to the LDAP server. (For an example of binding anonymously, see "Binding Anonymously.")
...
#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,o=Airius.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. */
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.
(See "Receiving the Portion of the DN Matching an Entry"
for an explanation.) */
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++;
}
...
ldap_simple_bind() or ldap_simple_bind_s(), and pass NULL values for the who and passwd parameters. For example:
...
rc = ldap_simple_bind_s( ld, NULL, NULL );
...
ldap_search_ext() or ldap_search_ext_s(). (See "Searching the Directory" for details.) ldap_compare_ext() or ldap_compare_ext_s(). (See "Comparing the Value of an Attribute" for details.) ldap_add_ext() or ldap_add_ext_s(). (See "Adding a New Entry" for details.) ldap_modify_ext() or ldap_modify_ext_s(). (See "Modifying an Entry" for details.) ldap_delete_ext() or ldap_delete_ext_s(). (See "Deleting an Entry" for details.)ldap_rename() or ldap_rename_s(). (See "Changing the DN of an Entry" for details.) _s are synchronous functions, and the remaining functions are asynchronous functions. (For more information on the distinction between calling synchronous and asynchronous functions, see "Calling Synchronous and Asynchronous Functions.")
Note that the Netscape Directory SDK 3.0 for C still supports the older versions of these functions for backward-compatibility. For more information, see "Backward Compatibility with Earlier Releases."
ldap_unbind() function ldap_unbind_s() function ldap_unbind() and ldap_unbind_s() are both synchronous functions. These functions are identical; they use different names so that each authentication function (ldap_simple_bind() and ldap_simple_bind_s()) has a corresponding function for closing the server connection.
After you close the connection, you can no longer use the LDAP structure. Calling ldap_unbind() or ldap_unbind_s() frees the LDAP structure from memory.
The following code 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 ) );
}
...
Last Updated: 10/01/98 17:03:11