3 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
7 * Copyright (c) 1995 Regents of the University of Michigan.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that this notice is preserved and that due credit is given
12 * to the University of Michigan at Ann Arbor. The name of the University
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission. This software
15 * is provided ``as is'' without express or implied warranty.
22 #include <ac/string.h>
23 #include <ac/socket.h>
30 Connection *conn, /* where to send results */
31 Operation *op /* info about the op to which we're responding */
34 ber_int_t scope, deref, attrsonly;
35 ber_int_t sizelimit, timelimit;
36 struct berval base = { 0, NULL };
37 struct berval *pbase = NULL;
38 struct berval *nbase = NULL;
39 struct berval fstr = { 0, NULL };
40 Filter *filter = NULL;
41 struct berval **attrs = NULL;
48 LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
49 "do_search: conn %d\n", conn->c_connid ));
51 Debug( LDAP_DEBUG_TRACE, "do_search\n", 0, 0, 0 );
55 * Parse the search request. It looks like this:
57 * SearchRequest := [APPLICATION 3] SEQUENCE {
58 * baseObject DistinguishedName,
64 * derefAliases ENUMERATED {
65 * neverDerefaliases (0),
66 * derefInSearching (1),
67 * derefFindingBaseObj (2),
68 * alwaysDerefAliases (3)
70 * sizelimit INTEGER (0 .. 65535),
71 * timelimit INTEGER (0 .. 65535),
74 * attributes SEQUENCE OF AttributeType
78 /* baseObject, scope, derefAliases, sizelimit, timelimit, attrsOnly */
79 if ( ber_scanf( op->o_ber, "{oiiiib" /*}*/,
80 &base, &scope, &deref, &sizelimit,
81 &timelimit, &attrsonly ) == LBER_ERROR )
83 send_ldap_disconnect( conn, op,
84 LDAP_PROTOCOL_ERROR, "decoding error" );
85 rc = SLAPD_DISCONNECT;
91 case LDAP_SCOPE_ONELEVEL:
92 case LDAP_SCOPE_SUBTREE:
95 send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
96 NULL, "invalid scope", NULL, NULL );
101 case LDAP_DEREF_NEVER:
102 case LDAP_DEREF_FINDING:
103 case LDAP_DEREF_SEARCHING:
104 case LDAP_DEREF_ALWAYS:
107 send_ldap_result( conn, op, rc = LDAP_PROTOCOL_ERROR,
108 NULL, "invalid deref", NULL, NULL );
112 rc = dnPretty( NULL, &base, &pbase );
113 if( rc != LDAP_SUCCESS ) {
115 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
116 "do_search: conn %d invalid dn (%s)\n",
117 conn->c_connid, base.bv_val ));
119 Debug( LDAP_DEBUG_ANY,
120 "do_search: invalid dn (%s)\n", base.bv_val, 0, 0 );
122 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
123 "invalid DN", NULL, NULL );
127 rc = dnNormalize( NULL, &base, &nbase );
128 if( rc != LDAP_SUCCESS ) {
130 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
131 "do_searc: conn %d invalid dn (%s)\n",
132 conn->c_connid, base.bv_val ));
134 Debug( LDAP_DEBUG_ANY,
135 "do_search: invalid dn (%s)\n", base.bv_val, 0, 0 );
137 send_ldap_result( conn, op, rc = LDAP_INVALID_DN_SYNTAX, NULL,
138 "invalid DN", NULL, NULL );
144 LDAP_LOG(( "operation", LDAP_LEVEL_ARGS,
145 "do_search \"%s\" %d %d %d %d %d\n", base.bv_val, scope,
146 deref, sizelimit, timelimit, attrsonly ));
148 Debug( LDAP_DEBUG_ARGS, "SRCH \"%s\" %d %d", base.bv_val, scope, deref );
149 Debug( LDAP_DEBUG_ARGS, " %d %d %d\n", sizelimit, timelimit,
153 /* filter - returns a "normalized" version */
154 rc = get_filter( conn, op->o_ber, &filter, &fstr, &text );
155 if( rc != LDAP_SUCCESS ) {
156 if( rc == SLAPD_DISCONNECT ) {
157 send_ldap_disconnect( conn, op,
158 LDAP_PROTOCOL_ERROR, text );
160 send_ldap_result( conn, op, rc,
161 NULL, text, NULL, NULL );
167 LDAP_LOG(( "operation", LDAP_LEVEL_ARGS,
168 "do_search: conn %d filter: %s\n", conn->c_connid, fstr.bv_val ));
170 Debug( LDAP_DEBUG_ARGS, " filter: %s\n", fstr.bv_val, 0, 0 );
175 if ( ber_scanf( op->o_ber, /*{*/ "{V}}", &attrs ) == LBER_ERROR ) {
176 send_ldap_disconnect( conn, op,
177 LDAP_PROTOCOL_ERROR, "decoding attrs error" );
178 rc = SLAPD_DISCONNECT;
182 if( (rc = get_ctrls( conn, op, 1 )) != LDAP_SUCCESS ) {
184 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
185 "do_search: conn %d get_ctrls failed (%d)\n",
186 conn->c_connid, rc ));
188 Debug( LDAP_DEBUG_ANY, "do_search: get_ctrls failed\n", 0, 0, 0 );
197 LDAP_LOG(( "operation", LDAP_LEVEL_ARGS,
198 "do_search: conn %d attrs:", conn->c_connid ));
200 Debug( LDAP_DEBUG_ARGS, " attrs:", 0, 0, 0 );
204 if ( attrs != NULL ) {
205 for ( i = 0; attrs[i] != NULL; i++ ) {
207 LDAP_LOG(( "operation", LDAP_LEVEL_ARGS,
208 "do_search: %s", attrs[i]->bv_val ));
210 Debug( LDAP_DEBUG_ARGS, " %s", attrs[i]->bv_val, 0, 0 );
217 LDAP_LOG(( "operation", LDAP_LEVEL_ARGS, "\n" ));
219 Debug( LDAP_DEBUG_ARGS, "\n", 0, 0, 0 );
222 Statslog( LDAP_DEBUG_STATS,
223 "conn=%ld op=%d SRCH base=\"%s\" scope=%d filter=\"%s\"\n",
224 op->o_connid, op->o_opid, pbase->bv_val, scope, fstr.bv_val );
226 manageDSAit = get_manageDSAit( op );
228 if ( scope == LDAP_SCOPE_BASE ) {
231 if ( strcasecmp( nbase->bv_val, LDAP_ROOT_DSE ) == 0 ) {
232 #ifdef LDAP_CONNECTIONLESS
233 /* Ignore LDAPv2 CLDAP DSE queries */
234 if (op->o_protocol==LDAP_VERSION2 && conn->c_is_udp) {
238 /* check restrictions */
239 rc = backend_check_restrictions( NULL, conn, op, NULL, &text ) ;
240 if( rc != LDAP_SUCCESS ) {
241 send_ldap_result( conn, op, rc,
242 NULL, text, NULL, NULL );
246 rc = root_dse_info( conn, &entry, &text );
249 #if defined( SLAPD_SCHEMA_DN )
250 else if ( strcasecmp( nbase->bv_val, SLAPD_SCHEMA_DN ) == 0 ) {
251 /* check restrictions */
252 rc = backend_check_restrictions( NULL, conn, op, NULL, &text ) ;
253 if( rc != LDAP_SUCCESS ) {
254 send_ldap_result( conn, op, rc,
255 NULL, text, NULL, NULL );
259 rc = schema_info( &entry, &text );
263 if( rc != LDAP_SUCCESS ) {
264 send_ldap_result( conn, op, rc,
265 NULL, text, NULL, NULL );
268 } else if ( entry != NULL ) {
269 rc = test_filter( NULL, conn, op,
272 if( rc == LDAP_COMPARE_TRUE ) {
273 send_search_entry( NULL, conn, op,
274 entry, attrs, attrsonly, NULL );
278 send_ldap_result( conn, op, LDAP_SUCCESS,
279 NULL, NULL, NULL, NULL );
285 if( !nbase->bv_len && default_search_nbase.bv_len ) {
286 ch_free( base.bv_val );
287 ch_free( nbase->bv_val );
289 base.bv_val = ch_strdup( default_search_base.bv_val );
290 base.bv_len = default_search_base.bv_len;
291 nbase->bv_val = ch_strdup( default_search_nbase.bv_val );
292 nbase->bv_len = default_search_nbase.bv_len;
296 * We could be serving multiple database backends. Select the
297 * appropriate one, or send a referral to our "referral server"
298 * if we don't hold it.
300 if ( (be = select_backend( nbase, manageDSAit, 1 )) == NULL ) {
301 struct berval **ref = referral_rewrite( default_referral,
302 NULL, pbase->bv_val, scope );
304 send_ldap_result( conn, op, rc = LDAP_REFERRAL,
305 NULL, NULL, ref ? ref : default_referral, NULL );
311 /* check restrictions */
312 rc = backend_check_restrictions( be, conn, op, NULL, &text ) ;
313 if( rc != LDAP_SUCCESS ) {
314 send_ldap_result( conn, op, rc,
315 NULL, text, NULL, NULL );
319 /* check for referrals */
320 rc = backend_check_referrals( be, conn, op, pbase, nbase );
321 if ( rc != LDAP_SUCCESS ) {
325 /* deref the base if needed */
326 suffix_alias( be, nbase );
328 /* actually do the search and send the result(s) */
329 if ( be->be_search ) {
330 (*be->be_search)( be, conn, op, pbase, nbase,
331 scope, deref, sizelimit,
332 timelimit, filter, fstr.bv_val, attrs, attrsonly );
334 send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
335 NULL, "operation not supported within namingContext", NULL, NULL );
340 if( pbase != NULL) ber_bvfree( pbase );
341 if( nbase != NULL) ber_bvfree( nbase );
343 if( fstr.bv_val != NULL) free( fstr.bv_val );
344 if( filter != NULL) filter_free( filter );
345 if ( attrs != NULL ) {
346 ber_bvecfree( attrs );