2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2003 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
15 /* Portions Copyright (c) 1990 Regents of the University of Michigan.
16 * All rights reserved.
23 #include <ac/stdlib.h>
25 #include <ac/socket.h>
26 #include <ac/string.h>
33 * ldap_search_ext - initiate an ldap search operation.
38 * base DN of the base object
39 * scope the search scope - one of
40 * LDAP_SCOPE_BASE (baseObject),
41 * LDAP_SCOPE_ONELEVEL (oneLevel),
42 * LDAP_SCOPE_SUBTREE (subtree), or
43 * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension
44 * filter a string containing the search filter
45 * (e.g., "(|(cn=bob)(sn=bob))")
46 * attrs list of attribute types to return for matches
47 * attrsonly 1 => attributes only 0 => attributes and values
50 * char *attrs[] = { "mail", "title", 0 };
51 * ldap_search_ext( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob",
52 * attrs, attrsonly, sctrls, ctrls, timeout, sizelimit,
58 LDAP_CONST char *base,
60 LDAP_CONST char *filter,
65 struct timeval *timeout,
75 LDAP_LOG ( OPERATION, ENTRY, "ldap_search_ext\n", 0, 0, 0 );
77 Debug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 );
81 assert( LDAP_VALID( ld ) );
83 /* check client controls */
84 rc = ldap_int_client_controls( ld, cctrls );
85 if( rc != LDAP_SUCCESS ) return rc;
88 * if timeout is provided, both tv_sec and tv_usec must
91 if( timeout != NULL ) {
92 if( timeout->tv_sec == 0 && timeout->tv_usec == 0 ) {
93 return LDAP_PARAM_ERROR;
96 /* timelimit must be non-zero if timeout is provided */
97 timelimit = timeout->tv_sec != 0 ? timeout->tv_sec : 1;
100 /* no timeout, no timelimit */
104 ber = ldap_build_search_req( ld, base, scope, filter, attrs,
105 attrsonly, sctrls, cctrls, timelimit, sizelimit, &id );
112 /* send the message */
113 *msgidp = ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id );
124 LDAP_CONST char *base,
126 LDAP_CONST char *filter,
129 LDAPControl **sctrls,
130 LDAPControl **cctrls,
131 struct timeval *timeout,
138 rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
139 sctrls, cctrls, timeout, sizelimit, &msgid );
141 if ( rc != LDAP_SUCCESS ) {
145 rc = ldap_result( ld, msgid, 1, timeout, res );
148 /* error(-1) or timeout(0) */
149 return( ld->ld_errno );
152 if( rc == LDAP_RES_SEARCH_REFERENCE || rc == LDAP_RES_INTERMEDIATE ) {
153 return( ld->ld_errno );
156 return( ldap_result2error( ld, *res, 0 ) );
160 * ldap_search - initiate an ldap search operation.
165 * base DN of the base object
166 * scope the search scope - one of
167 * LDAP_SCOPE_BASE (baseObject),
168 * LDAP_SCOPE_ONELEVEL (oneLevel),
169 * LDAP_SCOPE_SUBTREE (subtree), or
170 * LDAP_SCOPE_SUBORDINATE (children) -- OpenLDAP extension
171 * filter a string containing the search filter
172 * (e.g., "(|(cn=bob)(sn=bob))")
173 * attrs list of attribute types to return for matches
174 * attrsonly 1 => attributes only 0 => attributes and values
177 * char *attrs[] = { "mail", "title", 0 };
178 * msgid = ldap_search( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob",
179 * attrs, attrsonly );
183 LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter,
184 char **attrs, int attrsonly )
190 LDAP_LOG ( OPERATION, ENTRY, "ldap_search\n", 0, 0, 0 );
192 Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 );
195 assert( ld != NULL );
196 assert( LDAP_VALID( ld ) );
198 ber = ldap_build_search_req( ld, base, scope, filter, attrs,
199 attrsonly, NULL, NULL, -1, -1, &id );
206 /* send the message */
207 return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id ));
212 ldap_build_search_req(
214 LDAP_CONST char *base,
216 LDAP_CONST char *filter,
219 LDAPControl **sctrls,
220 LDAPControl **cctrls,
229 * Create the search request. It looks like this:
230 * SearchRequest := [APPLICATION 3] SEQUENCE {
231 * baseObject DistinguishedName,
237 * derefAliases ENUMERATED {
238 * neverDerefaliases (0),
239 * derefInSearching (1),
240 * derefFindingBaseObj (2),
241 * alwaysDerefAliases (3)
243 * sizelimit INTEGER (0 .. 65535),
244 * timelimit INTEGER (0 .. 65535),
247 * attributes SEQUENCE OF AttributeType
249 * wrapped in an ldap message.
252 /* create a message to send */
253 if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
257 if ( base == NULL ) {
258 /* no base provided, use session default base */
259 base = ld->ld_options.ldo_defbase;
261 if ( base == NULL ) {
262 /* no session default base, use top */
267 LDAP_NEXT_MSGID( ld, *idp );
268 #ifdef LDAP_CONNECTIONLESS
269 if ( LDAP_IS_UDP(ld) ) {
270 err = ber_write( ber, ld->ld_options.ldo_peer,
271 sizeof(struct sockaddr), 0);
273 if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) {
274 char *dn = ld->ld_options.ldo_cldapdn;
276 err = ber_printf( ber, "{ist{seeiib", *idp, dn,
277 LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
278 (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
279 (timelimit < 0) ? ld->ld_timelimit : timelimit,
284 err = ber_printf( ber, "{it{seeiib", *idp,
285 LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
286 (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
287 (timelimit < 0) ? ld->ld_timelimit : timelimit,
292 ld->ld_errno = LDAP_ENCODING_ERROR;
297 if( filter == NULL ) {
298 filter = "(objectclass=*)";
301 err = ldap_pvt_put_filter( ber, filter );
304 ld->ld_errno = LDAP_FILTER_ERROR;
309 if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) {
310 ld->ld_errno = LDAP_ENCODING_ERROR;
315 /* Put Server Controls */
316 if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
321 if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
322 ld->ld_errno = LDAP_ENCODING_ERROR;
332 LDAP *ld, LDAP_CONST char *base, int scope,
333 LDAP_CONST char *filter, char **attrs,
334 int attrsonly, struct timeval *timeout, LDAPMessage **res )
338 if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
340 return( ld->ld_errno );
342 if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 )
343 return( ld->ld_errno );
345 if ( ld->ld_errno == LDAP_TIMEOUT ) {
346 (void) ldap_abandon( ld, msgid );
347 ld->ld_errno = LDAP_TIMEOUT;
348 return( ld->ld_errno );
351 return( ldap_result2error( ld, *res, 0 ) );
357 LDAP_CONST char *base,
359 LDAP_CONST char *filter,
366 if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
368 return( ld->ld_errno );
370 if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, res ) == -1 )
371 return( ld->ld_errno );
373 return( ldap_result2error( ld, *res, 0 ) );