]> git.sur5r.net Git - openldap/blob - libraries/libldap/search.c
NT ldap_pvt_thread_self fix from HEAD
[openldap] / libraries / libldap / search.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2004 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
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>.
14  */
15 /* Portions Copyright (c) 1990 Regents of the University of Michigan.
16  * All rights reserved.
17  */
18
19 #include "portable.h"
20
21 #include <stdio.h>
22
23 #include <ac/stdlib.h>
24
25 #include <ac/socket.h>
26 #include <ac/string.h>
27 #include <ac/time.h>
28
29 #include "ldap-int.h"
30 #include "ldap_log.h"
31
32 /*
33  * ldap_search_ext - initiate an ldap search operation.
34  *
35  * Parameters:
36  *
37  *      ld              LDAP descriptor
38  *      base            DN of the base object
39  *      scope           the search scope - one of LDAP_SCOPE_BASE,
40  *                          LDAP_SCOPE_ONELEVEL, LDAP_SCOPE_SUBTREE
41  *      filter          a string containing the search filter
42  *                      (e.g., "(|(cn=bob)(sn=bob))")
43  *      attrs           list of attribute types to return for matches
44  *      attrsonly       1 => attributes only 0 => attributes and values
45  *
46  * Example:
47  *      char    *attrs[] = { "mail", "title", 0 };
48  *      ldap_search_ext( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, "cn~=bob",
49  *          attrs, attrsonly, sctrls, ctrls, timeout, sizelimit,
50  *              &msgid );
51  */
52 int
53 ldap_search_ext(
54         LDAP *ld,
55         LDAP_CONST char *base,
56         int scope,
57         LDAP_CONST char *filter,
58         char **attrs,
59         int attrsonly,
60         LDAPControl **sctrls,
61         LDAPControl **cctrls,
62         struct timeval *timeout,
63         int sizelimit,
64         int *msgidp )
65 {
66         int rc;
67         BerElement      *ber;
68         int timelimit;
69         ber_int_t id;
70
71 #ifdef NEW_LOGGING
72         LDAP_LOG ( OPERATION, ENTRY, "ldap_search_ext\n", 0, 0, 0 );
73 #else
74         Debug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 );
75 #endif
76
77         assert( ld != NULL );
78         assert( LDAP_VALID( ld ) );
79
80         /* check client controls */
81         rc = ldap_int_client_controls( ld, cctrls );
82         if( rc != LDAP_SUCCESS ) return rc;
83
84         /*
85          * if timeout is provided, both tv_sec and tv_usec must
86          * not be zero
87          */
88         if( timeout != NULL ) {
89                 if( timeout->tv_sec == 0 && timeout->tv_usec == 0 ) {
90                         return LDAP_PARAM_ERROR;
91                 }
92
93                 /* timelimit must be non-zero if timeout is provided */
94                 timelimit = timeout->tv_sec != 0 ? timeout->tv_sec : 1;
95
96         } else {
97                 /* no timeout, no timelimit */
98                 timelimit = -1;
99         }
100
101         ber = ldap_build_search_req( ld, base, scope, filter, attrs,
102             attrsonly, sctrls, cctrls, timelimit, sizelimit, &id ); 
103
104         if ( ber == NULL ) {
105                 return ld->ld_errno;
106         }
107
108
109         /* send the message */
110         *msgidp = ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id );
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_INTERMEDIATE ) {
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         ber_int_t       id;
182
183 #ifdef NEW_LOGGING
184         LDAP_LOG ( OPERATION, ENTRY, "ldap_search\n", 0, 0, 0 );
185 #else
186         Debug( LDAP_DEBUG_TRACE, "ldap_search\n", 0, 0, 0 );
187 #endif
188
189         assert( ld != NULL );
190         assert( LDAP_VALID( ld ) );
191
192         ber = ldap_build_search_req( ld, base, scope, filter, attrs,
193             attrsonly, NULL, NULL, -1, -1, &id ); 
194
195         if ( ber == NULL ) {
196                 return( -1 );
197         }
198
199
200         /* send the message */
201         return ( ldap_send_initial_request( ld, LDAP_REQ_SEARCH, base, ber, id ));
202 }
203
204
205 BerElement *
206 ldap_build_search_req(
207         LDAP *ld,
208         LDAP_CONST char *base,
209         ber_int_t scope,
210         LDAP_CONST char *filter,
211         char **attrs,
212         ber_int_t attrsonly,
213         LDAPControl **sctrls,
214         LDAPControl **cctrls,
215         ber_int_t timelimit,
216         ber_int_t sizelimit,
217         ber_int_t *idp)
218 {
219         BerElement      *ber;
220         int             err, id;
221
222         /*
223          * Create the search request.  It looks like this:
224          *      SearchRequest := [APPLICATION 3] SEQUENCE {
225          *              baseObject      DistinguishedName,
226          *              scope           ENUMERATED {
227          *                      baseObject      (0),
228          *                      singleLevel     (1),
229          *                      wholeSubtree    (2)
230          *              },
231          *              derefAliases    ENUMERATED {
232          *                      neverDerefaliases       (0),
233          *                      derefInSearching        (1),
234          *                      derefFindingBaseObj     (2),
235          *                      alwaysDerefAliases      (3)
236          *              },
237          *              sizelimit       INTEGER (0 .. 65535),
238          *              timelimit       INTEGER (0 .. 65535),
239          *              attrsOnly       BOOLEAN,
240          *              filter          Filter,
241          *              attributes      SEQUENCE OF AttributeType
242          *      }
243          * wrapped in an ldap message.
244          */
245
246         /* create a message to send */
247         if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
248                 return( NULL );
249         }
250
251         if ( base == NULL ) {
252                 /* no base provided, use session default base */
253                 base = ld->ld_options.ldo_defbase;
254
255                 if ( base == NULL ) {
256                         /* no session default base, use top */
257                         base = "";
258                 }
259         }
260
261         LDAP_NEXT_MSGID( ld, *idp );
262 #ifdef LDAP_CONNECTIONLESS
263         if ( LDAP_IS_UDP(ld) ) {
264             err = ber_write( ber, ld->ld_options.ldo_peer,
265                     sizeof(struct sockaddr), 0);
266         }
267         if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) {
268             char *dn = ld->ld_options.ldo_cldapdn;
269             if (!dn) dn = "";
270             err = ber_printf( ber, "{ist{seeiib", *idp, dn,
271                 LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
272                 (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
273                 (timelimit < 0) ? ld->ld_timelimit : timelimit,
274                 attrsonly );
275         } else
276 #endif
277         {
278             err = ber_printf( ber, "{it{seeiib", *idp,
279                 LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
280                 (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
281                 (timelimit < 0) ? ld->ld_timelimit : timelimit,
282                 attrsonly );
283         }
284
285         if ( err == -1 ) {
286                 ld->ld_errno = LDAP_ENCODING_ERROR;
287                 ber_free( ber, 1 );
288                 return( NULL );
289         }
290
291         if( filter == NULL ) {
292                 filter = "(objectclass=*)";
293         }
294
295         err = ldap_pvt_put_filter( ber, filter );
296
297         if ( err  == -1 ) {
298                 ld->ld_errno = LDAP_FILTER_ERROR;
299                 ber_free( ber, 1 );
300                 return( NULL );
301         }
302
303         if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) {
304                 ld->ld_errno = LDAP_ENCODING_ERROR;
305                 ber_free( ber, 1 );
306                 return( NULL );
307         }
308
309         /* Put Server Controls */
310         if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
311                 ber_free( ber, 1 );
312                 return( NULL );
313         }
314
315         if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
316                 ld->ld_errno = LDAP_ENCODING_ERROR;
317                 ber_free( ber, 1 );
318                 return( NULL );
319         }
320
321         return( ber );
322 }
323
324 int
325 ldap_search_st(
326         LDAP *ld, LDAP_CONST char *base, int scope,
327         LDAP_CONST char *filter, char **attrs,
328         int attrsonly, struct timeval *timeout, LDAPMessage **res )
329 {
330         int     msgid;
331
332         if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
333             == -1 )
334                 return( ld->ld_errno );
335
336         if ( ldap_result( ld, msgid, 1, timeout, res ) == -1 )
337                 return( ld->ld_errno );
338
339         if ( ld->ld_errno == LDAP_TIMEOUT ) {
340                 (void) ldap_abandon( ld, msgid );
341                 ld->ld_errno = LDAP_TIMEOUT;
342                 return( ld->ld_errno );
343         }
344
345         return( ldap_result2error( ld, *res, 0 ) );
346 }
347
348 int
349 ldap_search_s(
350         LDAP *ld,
351         LDAP_CONST char *base,
352         int scope,
353         LDAP_CONST char *filter,
354         char **attrs,
355         int attrsonly,
356         LDAPMessage **res )
357 {
358         int     msgid;
359
360         if ( (msgid = ldap_search( ld, base, scope, filter, attrs, attrsonly ))
361             == -1 )
362                 return( ld->ld_errno );
363
364         if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, res ) == -1 )
365                 return( ld->ld_errno );
366
367         return( ldap_result2error( ld, *res, 0 ) );
368 }
369