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