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