Mozilla LDAP C SDK Programmer's Guide
Chapter 9 - Comparing Values in Entries
This chapter explains how to use the API functions to compare data in entries in the directory. The LDAP API includes functions that you can call to compare the value of an attribute in an entry against a specified value.
The chapter includes the following sections:
- Comparing the Value of an Attribute
- Performing a Synchronous Comparison Operation
- Performing an Asynchronous Comparison Operation
Comparing the Value of an Attribute
To determine if an attribute contains a certain value, call one of the following functions:
-
The synchronous
ldap_compare_ext_s()
function (see "Performing a Synchronous Comparison Operation"). -
The asynchronous
ldap_compare_ext()
function (see "Performing an Asynchronous Comparison Operation").
For more information about the difference between synchronous and asynchronous functions, see "Calling Synchronous and Asynchronous Functions."
Note that both of these functions compare values that are in
berval
structures; this
allows you to compare binary values. If you just want to compare
string values, you can call the
ldap_compare()
or
ldap_compare_s()
function.
Performing a Synchronous Comparison Operation
If you want to wait for the results of the compare
operation to complete before continuing, call the synchronous
ldap_compare_ext_s()
function to compare berval structures
or wait for the results of the compare operation to complete before
continuing, call the synchronous
ldap_compare_s()
function
to compare string values. These functions send an LDAP compare request
to the server and block until the server sends the results of the
operation back to your client.
Both the ldap_compare_ext_s()
function and the ldap_compare_s()
function return one of
the following values after the LDAP compare operation completes:
-
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.
See the documentation on the
ldap_compare_ext_s()
function for a list of the possible result codes.
The following section of code uses the synchronous
ldap_compare_s()
function to determine if an entry
has the value "bjensen@example.com" in the mail attribute.
Code Example 9-1 - Applying the ldap_compare_s() function
#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 ); ...
Performing an Asynchronous Comparison Operation
If you want to 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 an LDAP 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 the ldap_compare_ext()
function and the ldap_compare()
function 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 this message ID. The ldap_result()
function
uses the message ID to determine if the server sent the results of the
compare operation. The 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 result code should be
one of the following:
-
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. (For a list of possible result codes for an
LDAP compare operation, see the result code documentation for the
ldap_compare_ext_s()
function.)
The following section of code calls
ldap_compare()
to determine if an entry has the value
"bjensen@example.com" in the mail attribute.
Code Example 9-2 - Applying the ldap_compare() function
#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; } } } ...
Example: Comparing a Value in an Entry (Synchronous)
The following sample program calls the synchronous
ldap_compare_s()
function to determine if a user's entry has the value
"bjensen@example.com" in the mail attribute.
Code Example 9-3 - Comparing entry values using ldap_compare_s()
#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. */ 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; }
Example: Comparing a Value in an Entry (Asynchronous)
The following sample program calls the asynchronous
ldap_compare()
function
to determine if a user's entry has the value "bjensen@example.com" in
the mail attribute.
Code Example 9-4 - Comparing entry values using ldap_compare()
#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. */ 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++; }