You are currently viewing a snapshot of www.mozilla.org taken on April 21, 2008. Most of this content is
highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If
there are any pages on this archive site that you think should be added back to www.mozilla.org, please file a bug.
This chapter explains how to call the LDAP
API functions to search the directory, retrieve search results, and
get attributes and values from each entry in the search results.
The chapter also provides examples of calling synchronous and
asynchronous functions to search the directory.
This chapter contains the following sections, which explain how
to create and execute a search of the directory:
In the LDAPv3 protocol, a server can send
three different types of results back to the client:
Directory entries found by the search.
Any search references found within the scope of the search (a
search reference is a reference to another LDAP server).
An LDAP result code specifying the result of the search operation.
Results are represented by
LDAPMessage structures.
Note that in order to receive search
references from LDAPv3 servers you must identify your client as an
LDAPv3 client. If you do not, the server will return the LDAP error
code LDAP_PARTIAL_RESULTS and a set of referrals. See
"Specifying the LDAP Version of Your Client" for details.
The Mozilla LDAP C SDK provides functions
that allow you to search the directory and retrieve results from
the server:
You can send a search request by calling the synchronous function
ldap_search_ext_s() or the asynchronous function
ldap_search_ext().
(For more information about the difference between synchronous and
asynchronous functions, see "Calling Synchronous and Asynchronous
Functions.")
The server sends back matching entries or search references to
your client.
If you are retrieving the results one at a time, you can call
ldap_result() to get each result (an
LDAPMessage structure) and determine what type of
result (entry or search reference) was sent from the server.
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_first_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().
To search the directory, call ldap_search_ext_s()
or ldap_search_ext():
ldap_search_ext_s() is a synchronous function. This
function blocks until all results have been received from the
server.
ldap_search_ext() is an asynchronous function. This
function sends an LDAP search request to the server. You can do
other work while periodically checking to see if the server has
returned any results.
These two functions are declared as follows:
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 );
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 );
For either function, you specify the search
criteria using the following parameters:
base specifies the starting point in the directory,
or the base DN (an entry where to start searching).
To search entries under "dc=example,dc=com", the
base DN is "dc=example,dc=com". See "Specifying the
Base DN and Scope" for details.
scope specifies the scope of the search (which
entries you want to search).
You can narrow the scope of the search to search only the base DN,
entries at one level under the base DN, or entries at all levels
under the base DN. See
Specifying the Base
DN and Scope for details.
filter specifies a search filter (what to search for).
A search filter can be as simple as "find entries where the last
name is 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 for details.
attrs and attrsonly specify the type of
information that you want return (which attributes you want to
retrieve) and whether you want to retrieve only the attribute type
or the attribute type and its values
timeoutp and sizelimit specify the
search constraints that you want applied to this search.
For example, you can specify a different time-out period or
maximum number of results that differ from the values of these
options for the current session. See
Setting Search
Preferences for details.
Figure 6-1 illustrates how search criteria works.
Figure 6-1 - Search criteria for an LDAP search operation
Specifying the Base DN and Scope
When sending a search request, you need to specify the base DN and
scope of the search to identify the entries that you want searched.
The base DN (the base argument) is the DN of the
entry that serves as the starting point of the search.
To specify the scope of the search, you pass
one of the following values as the scope parameter:
LDAP_SCOPE_SUBTREE searches the base
entry and all entries at all levels below the base
entry (as illustrated in Figure 6-2).
Figure 6-2 - Example of a search with the scope LDAP_SCOPE_SUBTREE
LDAP_SCOPE_ONELEVEL searches all entries at one level
below the base entry (as illustrated in Figure 6-3).
The base entry is not included in the search. Use
this setting if you just want a list of the entries under a given
entry. (See "Listing Subentries" for an example.)
Figure 6-3 - Example of a search with the scope LDAP_SCOPE_ONELEVEL
LDAP_SCOPE_BASE searches only the base
entry. Use this setting if you just want to read the attributes of
the base entry (as illustrated in Figure 6-4). (See
Reading an Entry for an example.)
Figure 6-4 - Example of a search with the scope LDAP_SCOPE_BASE
Specifying a Search Filter
When you search the directory, you use a search filter to define
the search. Here is the basic syntax for a search filter:
(attribute operator value)
Here is a simple example of a search filter:
(cn=Barbara Jensen)
In this example, cn is the
attribute, = is the operator, and
Barbara Jensen is the value. The filter finds
entries with the common name Barbara Jensen.
For a listing of valid attributes that you can use in your search
filter, see the documentation for the LDAP server you are using.
Table 6-1 lists the valid operators you can use.
Table 6-1 - Basic operators for search filters
Operator
Description
Example
=
Returns entries whose attribute is equal to the value.
(cn=Barbara Jensen)
finds the entry "cn=Barbara Jensen"
=
Returns entries whose attribute is greater than or equal to the value.
(sn >= jensen)
finds all entries from "sn=jensen" to
"sn=z..."
<=
Returns entries whose attribute is less than or equal to the value.
(sn <= jensen)
finds all entries from "sn=a..." to
"sn=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, this is an algorithm that matches
words that sound alike.
(sn ~= jensen)
finds the entry "sn = jansen"
Note that when comparing values containing letters, 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)
Using Boolean operators and parentheses, you can combine different
sets of conditions. Here is the syntax for combining search filters:
( boolean_operator (filter1)(filter2)(filter3) )
Table 6-2 lists the valid Boolean operators you can use.
Table 6-2 - Boolean operators for search filters
Boolean Operator
Description
&
Returns entries matching all specified filter criteria.
|
Returns entries matching 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)
but not: (!(filter1)(filter2))
For example, you can use this filter to
search for all entries with the last name Jensen or the
last name Johnson:
(|(sn=Jensen)(sn=Johnson))
You can also include wildcards 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*)
Specifying the Attributes to Retrieve
Using the attrs argument, you
can either retrieve all attributes in entries returned by the
search, or you can specify the attributes that you want returned in
the search results. For example, you can specify that you want to
return the following attributes:
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 (by passing 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 none of the attributes from an entry, pass
LDAP_NO_ATTRS as the attrs argument.
Note that if you plan to sort the results on your client (see
Sorting the Search Results),
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.
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, if you pass NULL for the
attrs argument to retrieve all of the attributes in
entries found by the search, the operational attribute
creatorsName will not be returned to your client. You
need to explicitly specify the creatorsName attribute
in the attrs argument.
To return all attributes in an entry and
selected operational attributes, pass a NULL-terminated array
containing LDAP_ALL_USER_ATTRS and the names of the
operational attributes as the attrs argument.
The following table lists some of the
operational attributes and the information they contain.
Table 6-3 - Information available in operational attributes
Attribute Name
Description of Values
createTimestamp
The time the entry was added to the directory.
modifyTimestamp
The time the entry was last modified.
creatorsName
Distinguished name (DN) of the user who
added the entry to the directory.
modifiersName
Distinguished name (DN) of the user who last modified the entry.
subschemaSubentry
Distinguished name (DN) of the subschema entry, which controls
the schema for this entry. (See "Getting Schema Information" for
details.)
Setting Search Preferences
For a given search, you can specify the maximum number of results
to be returned or the maximum amount of time to wait for a search.
Use the timeoutp and sizelimit arguments
of the ldap_search_ext_s() or
ldap_search_ext() functions.
Note the following:
To specify an infinite time limit (basically, no limit), create a
timeval structure with
tv_sec = tv_usec = 0, and pass a pointer to this as
the timeoutp argument.
To use the time limit specified by the LDAP_OPT_TIMELIMIT
preference for this connection, pass NULL as the
timeoutp argument.
To specify an infinite size limit (basically, no limit), pass
LDAP_NO_LIMIT as the sizelimit argument.
To specify these 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 (basically, no limit), set the value of the option
to LDAP_NO_LIMIT.
Note that the LDAP server may already have
time and size constraints set up 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.
Code Example 6-1 - Setting session search preferences
#include "ldap.h"
...
LDAP *ld;
int max_ret, max_tim;
char *host = "localhost";
...
/* Initialize a session with the LDAP server ldap.example.com:389. */
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 );
...
Example of Sending a Search Request
The following example sends a search request to the server
for all entries with the last name (or surname)
"Jensen" in the example.com organization.
In the LDAPv3 protocol, a server can return
the following types of results to your client:
Directory entries found by the search (those entries matching 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 specifying the result of the search operation.
The server returns the search results as a
chain of LDAPMessage structures. Each structure
contains an entry, a search reference, or an LDAP result code.
Because the results are represented as a chain, you should not free
individual LDAPMessage structures within the chain.
(When you are done working with the results, you can free the chain
itself, rather than individual structures within the chain.)
To access data from entries found by the
search, you need to follow this general process:
Get each entry in the results.
Get the attributes from each entry.
Get the values from each attribute.
Figure 6-5 illustrates the relationship
between entries, attributes, values, and search results.