]> git.sur5r.net Git - openldap/blob - libraries/libldap/search.c
Update copyright statements
[openldap] / libraries / libldap / search.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6 /*  Portions
7  *  Copyright (c) 1990 Regents of the University of Michigan.
8  *  All rights reserved.
9  *
10  *  search.c
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16
17 #include <ac/stdlib.h>
18
19 #include <ac/socket.h>
20 #include <ac/string.h>
21 #include <ac/time.h>
22
23 #include "ldap-int.h"
24
25
26 /*
27  * ldap_search_ext - initiate an ldap search operation.
28  *
29  * Parameters:
30  *
31  *      ld              LDAP descriptor
32  *      base            DN of the base object
33  *      scope           the search scope - one of LDAP_SCOPE_BASE,
34  *                          LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
35  *      filter          a string containing the search filter
36  *                      (e.g., "(|(cn=bob)(sn=bob))")
37  *      attrs           list of attribute types to return for matches
38  *      attrsonly       1 => attributes only 0 => attributes and values
39  *
40  * Example:
41  *      char    *attrs[] = { "mail", "title", 0 };
42  *      ldap_search_ext( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob",
43  *          attrs, attrsonly, sctrls, ctrls, timeout, sizelimit,
44  *              &msgid );
45  */
46 int
47 ldap_search_ext(
48         LDAP *ld,
49         LDAP_CONST char *base,
50         int scope,
51         LDAP_CONST char *filter,
52         char **attrs,
53         int attrsonly,
54         LDAPControl **sctrls,
55         LDAPControl **cctrls,
56         struct timeval *timeout,
57         int sizelimit,
58         int *msgidp )
59 {
60         int rc;
61         BerElement      *ber;
62         int timelimit;
63
64         Debug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 );
65
66         assert( ld != NULL );
67         assert( LDAP_VALID( ld ) );
68
69         /* check client controls */
70         rc = ldap_int_client_controls( ld, cctrls );
71         if( rc != LDAP_SUCCESS ) return rc;
72
73         /*
74          * if timeout is provided, both tv_sec and tv_usec must
75          * be non-zero
76          */
77         if( timeout != NULL ) {
78                 if( timeout->tv_sec == 0 && timeout->tv_usec == 0 ) {
79                         return LDAP_PARAM_ERROR;
80                 }
81
82                 /* timelimit must be non-zero if timeout is provided */
83                 timelimit = timeout->tv_sec != 0 ? timeout->tv_sec : 1;
84
85         } else {
86                 /* no timeout, no timelimit */
87                 timelimit = -1;
88         }
89
90         ber = ldap_build_search_req( ld, base, scope, filter, attrs,
91             attrsonly, sctrls, cctrls, timelimit, sizelimit ); 
92
93         if ( ber == NULL ) {
94                 return ld->ld_errno;
95         }
96
97 #ifndef LDAP_NOCACHE
98         if ( ld->ld_cache != NULL ) {
99                 if ( ldap_check_cache( ld, LDAP_REQ_SEARCH, ber ) == 0 ) {
100                         ber_free( ber, 1 );
101                         ld->ld_errno = LDAP_SUCCESS;
102                         *msgidp = ld->ld_msgid;
103                         return ld->ld_errno;
104                 }
105                 ldap_add_request_to_cache( ld, LDAP_REQ_SEARCH, ber );
106         }
107 #endif /* LDAP_NOCACHE */
108
109         /* send the message */
110         *msgidp = ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber );
111
112         if( *msgidp < 0 )
113                 return ld->ld_errno;
114
115         return LDAP_SUCCESS;
116 }
117
118 int
119 ldap_search_ext_s(
120         LDAP *ld,
121         LDAP_CONST char *base,
122         int scope,
123         LDAP_CONST char *filter,
124         char **attrs,
125         int attrsonly,
126         LDAPControl **sctrls,
127         LDAPControl **cctrls,
128         struct timeval *timeout,
129         int sizelimit,
130         LDAPMessage **res )
131 {
132         int rc;
133         int     msgid;
134
135         rc = ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
136                 sctrls, cctrls, timeout, sizelimit, &msgid );
137
138         if ( rc != LDAP_SUCCESS ) {
139                 return( rc );
140         }
141
142         rc = ldap_result( ld, msgid, 1, timeout, res );
143
144         if( rc <= 0 ) {
145                 /* error(-1) or timeout(0) */
146                 return( ld->ld_errno );
147         }
148
149         if( rc == LDAP_RES_SEARCH_REFERENCE || rc == LDAP_RES_EXTENDED_PARTIAL ) {
150                 return( ld->ld_errno );
151         }
152
153         return( ldap_result2error( ld, *res, 0 ) );
154 }
155
156 /*
157  * ldap_search - initiate an ldap search operation.
158  *
159  * Parameters:
160  *
161  *      ld              LDAP descriptor
162  *      base            DN of the base object
163  *      scope           the search scope - one of LDAP_SCOPE_BASE,
164  *                          LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
165  *      filter          a string containing the search filter
166  *                      (e.g., "(|(cn=bob)(sn=bob))")
167  *      attrs           list of attribute types to return for matches
168  *      attrsonly       1 => attributes only 0 => attributes and values
169  *
170  * Example:
171  *      char    *attrs[] = { "mail", "title", 0 };
172  *      msgid = ldap_search( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob",
173  *          attrs, attrsonly );
174  */
175 int
176 ldap_search(
177         LDAP *ld, LDAP_CONST char *base, int scope, LDAP_CONST char *filter,
178         char **attrs, int attrsonly )
179 {
180         BerElement      *ber;
181
182         Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 );
183
184         assert( ld != NULL );
185         assert( LDAP_VALID( ld ) );
186
187         ber = ldap_build_search_req( ld, base, scope, filter, attrs,
188             attrsonly, NULL, NULL, -1, -1 ); 
189
190         if ( ber == NULL ) {
191                 return( -1 );
192         }
193
194 #ifndef LDAP_NOCACHE
195         if ( ld->ld_cache != NULL ) {
196                 if ( ldap_check_cache( ld, LDAP_REQ_SEARCH, ber ) == 0 ) {
197                         ber_free( ber, 1 );
198                         ld->ld_errno = LDAP_SUCCESS;
199                         return( ld->ld_msgid );
200                 }
201                 ldap_add_request_to_cache( ld, LDAP_REQ_SEARCH, ber );
202         }
203 #endif /* LDAP_NOCACHE */
204
205         /* send the message */
206         return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber ));
207 }
208
209
210 BerElement *
211 ldap_build_search_req(
212         LDAP *ld,
213         LDAP_CONST char *base,
214         ber_int_t scope,
215         LDAP_CONST char *filter,
216         char **attrs,
217         ber_int_t attrsonly,
218         LDAPControl **sctrls,
219         LDAPControl **cctrls,
220         ber_int_t timelimit,
221         ber_int_t sizelimit )
222 {
223         BerElement      *ber;
224         int             err;
225
226         /*
227          * Create the search request.  It looks like this:
228          *      SearchRequest := [APPLICATION 3] SEQUENCE {
229          *              baseObject      DistinguishedName,
230          *              scope           ENUMERATED {
231          *                      baseObject      (0),
232          *                      singleLevel     (1),
233          *                      wholeSubtree    (2)
234          *              },
235          *              derefAliases    ENUMERATED {
236          *                      neverDerefaliases       (0),
237          *                      derefInSearching        (1),
238          *                      derefFindingBaseObj     (2),
239          *                      alwaysDerefAliases      (3)
240          *              },
241          *              sizelimit       INTEGER (0 .. 65535),
242          *              timelimit       INTEGER (0 .. 65535),
243          *              attrsOnly       BOOLEAN,
244          *              filter          Filter,
245          *              attributes      SEQUENCE OF AttributeType
246          *      }
247          * wrapped in an ldap message.
248          */
249
250         /* create a message to send */
251         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
252                 return( NULL );
253         }
254
255         if ( base == NULL ) {
256                 /* no base provided, use session default base */
257                 base = ld->ld_options.ldo_defbase;
258
259                 if ( base == NULL ) {
260                         /* no session default base, use top */
261                         base = "";
262                 }
263         }
264
265 #ifdef LDAP_CONNECTIONLESS
266         if ( LDAP_IS_UDP(ld) ) {
267             err = ber_write( ber, ld->ld_options.ldo_peer,
268                     sizeof(struct sockaddr), 0);
269         }
270         if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) {
271             char *dn = ld->ld_options.ldo_cldapdn;
272             if (!dn) dn = "";
273             err = ber_printf( ber, "{ist{seeiib", ++ld->ld_msgid, dn,
274                 LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
275                 (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
276                 (timelimit < 0) ? ld->ld_timelimit : timelimit,
277                 attrsonly );
278         } else
279 #endif
280         {
281             err = ber_printf( ber, "{it{seeiib", ++ld->ld_msgid,
282                 LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
283                 (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
284                 (timelimit < 0) ? ld->ld_timelimit : timelimit,
285                 attrsonly );
286         }
287
288         if ( err == -1 ) {
289                 ld->ld_errno = LDAP_ENCODING_ERROR;
290                 ber_free( ber, 1 );
291                 return( NULL );
292         }
293
294         if( filter == NULL ) {
295                 filter = "(objectclass=*)";
296         }
297
298         err = ldap_int_put_filter( ber, filter );
299
300         if ( err  == -1 ) {
301                 ld->ld_errno = LDAP_FILTER_ERROR;
302                 ber_free( ber, 1 );
303                 return( NULL );
304         }
305
306         if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) {
307                 ld->ld_errno = LDAP_ENCODING_ERROR;
308                 ber_free( ber, 1 );
309                 return( NULL );
310         }
311
312         /* Put Server Controls */
313         if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
314                 ber_free( ber, 1 );
315                 return( NULL );
316         }
317
318         if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
319                 ld->ld_errno = LDAP_ENCODING_ERROR;
320                 ber_free( ber, 1 );
321                 return( NULL );
322         }
323
324         return( ber );
325 }
326
327 int
328 ldap_search_st(
329         LDAP *ld, LDAP_CONST char *base, int scope,
330         LDAP_CONST char *filter, char **attrs,
331         int attrsonly, struct timeval *timeout, LDAPMessage **res )
332 {
333         int     msgid;
334
335         if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
336             == -1 )
337                 return( ld->ld_errno );
338
339         if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 )
340                 return( ld->ld_errno );
341
342         if ( ld->ld_errno == LDAP_TIMEOUT ) {
343                 (void) ldap_abandon( ld, msgid );
344                 ld->ld_errno = LDAP_TIMEOUT;
345                 return( ld->ld_errno );
346         }
347
348         return( ldap_result2error( ld, *res, 0 ) );
349 }
350
351 int
352 ldap_search_s(
353         LDAP *ld,
354         LDAP_CONST char *base,
355         int scope,
356         LDAP_CONST char *filter,
357         char **attrs,
358         int attrsonly,
359         LDAPMessage **res )
360 {
361         int     msgid;
362
363         if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
364             == -1 )
365                 return( ld->ld_errno );
366
367         if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, res ) == -1 )
368                 return( ld->ld_errno );
369
370         return( ldap_result2error( ld, *res, 0 ) );
371 }
372