search.c revision 1.1.1.4 1 1.1.1.3 lukem /* $NetBSD: search.c,v 1.1.1.4 2010/12/12 15:23:07 adam Exp $ */
2 1.1.1.3 lukem
3 1.1 lukem /* search.c - ldap backend search function */
4 1.1.1.4 adam /* OpenLDAP: pkg/ldap/servers/slapd/back-ldap/search.c,v 1.201.2.26 2010/04/15 22:20:09 quanah Exp */
5 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 1.1 lukem *
7 1.1.1.4 adam * Copyright 1999-2010 The OpenLDAP Foundation.
8 1.1 lukem * Portions Copyright 1999-2003 Howard Chu.
9 1.1 lukem * Portions Copyright 2000-2003 Pierangelo Masarati.
10 1.1 lukem * All rights reserved.
11 1.1 lukem *
12 1.1 lukem * Redistribution and use in source and binary forms, with or without
13 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
14 1.1 lukem * Public License.
15 1.1 lukem *
16 1.1 lukem * A copy of this license is available in the file LICENSE in the
17 1.1 lukem * top-level directory of the distribution or, alternatively, at
18 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
19 1.1 lukem */
20 1.1 lukem /* ACKNOWLEDGEMENTS:
21 1.1 lukem * This work was initially developed by the Howard Chu for inclusion
22 1.1 lukem * in OpenLDAP Software and subsequently enhanced by Pierangelo
23 1.1 lukem * Masarati.
24 1.1 lukem */
25 1.1 lukem
26 1.1 lukem #include "portable.h"
27 1.1 lukem
28 1.1 lukem #include <stdio.h>
29 1.1 lukem
30 1.1 lukem #include <ac/socket.h>
31 1.1 lukem #include <ac/string.h>
32 1.1 lukem #include <ac/time.h>
33 1.1 lukem
34 1.1 lukem #include "slap.h"
35 1.1 lukem #include "back-ldap.h"
36 1.1 lukem #undef ldap_debug /* silence a warning in ldap-int.h */
37 1.1 lukem #include "../../../libraries/libldap/ldap-int.h"
38 1.1 lukem
39 1.1 lukem #include "lutil.h"
40 1.1 lukem
41 1.1 lukem static int
42 1.1 lukem ldap_build_entry( Operation *op, LDAPMessage *e, Entry *ent,
43 1.1 lukem struct berval *bdn );
44 1.1 lukem
45 1.1 lukem /*
46 1.1 lukem * Quick'n'dirty rewrite of filter in case of error, to deal with
47 1.1 lukem * <draft-zeilenga-ldap-t-f>.
48 1.1 lukem */
49 1.1 lukem static int
50 1.1 lukem ldap_back_munge_filter(
51 1.1 lukem Operation *op,
52 1.1.1.3 lukem struct berval *filter,
53 1.1.1.3 lukem int *freeit )
54 1.1 lukem {
55 1.1 lukem ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
56 1.1 lukem
57 1.1 lukem char *ptr;
58 1.1 lukem int gotit = 0;
59 1.1 lukem
60 1.1 lukem Debug( LDAP_DEBUG_ARGS, "=> ldap_back_munge_filter \"%s\"\n",
61 1.1 lukem filter->bv_val, 0, 0 );
62 1.1 lukem
63 1.1 lukem for ( ptr = strstr( filter->bv_val, "(?=" );
64 1.1 lukem ptr;
65 1.1 lukem ptr = strstr( ptr, "(?=" ) )
66 1.1 lukem {
67 1.1 lukem static struct berval
68 1.1 lukem bv_true = BER_BVC( "(?=true)" ),
69 1.1 lukem bv_false = BER_BVC( "(?=false)" ),
70 1.1 lukem bv_undefined = BER_BVC( "(?=undefined)" ),
71 1.1 lukem bv_t = BER_BVC( "(&)" ),
72 1.1 lukem bv_f = BER_BVC( "(|)" ),
73 1.1 lukem bv_T = BER_BVC( "(objectClass=*)" ),
74 1.1 lukem bv_F = BER_BVC( "(!(objectClass=*))" );
75 1.1 lukem struct berval *oldbv = NULL,
76 1.1 lukem *newbv = NULL,
77 1.1 lukem oldfilter = BER_BVNULL;
78 1.1 lukem
79 1.1 lukem if ( strncmp( ptr, bv_true.bv_val, bv_true.bv_len ) == 0 ) {
80 1.1 lukem oldbv = &bv_true;
81 1.1 lukem if ( LDAP_BACK_T_F( li ) ) {
82 1.1 lukem newbv = &bv_t;
83 1.1 lukem
84 1.1 lukem } else {
85 1.1 lukem newbv = &bv_T;
86 1.1 lukem }
87 1.1 lukem
88 1.1 lukem } else if ( strncmp( ptr, bv_false.bv_val, bv_false.bv_len ) == 0 )
89 1.1 lukem {
90 1.1 lukem oldbv = &bv_false;
91 1.1 lukem if ( LDAP_BACK_T_F( li ) ) {
92 1.1 lukem newbv = &bv_f;
93 1.1 lukem
94 1.1 lukem } else {
95 1.1 lukem newbv = &bv_F;
96 1.1 lukem }
97 1.1 lukem
98 1.1 lukem } else if ( strncmp( ptr, bv_undefined.bv_val, bv_undefined.bv_len ) == 0 )
99 1.1 lukem {
100 1.1.1.3 lukem /* if undef or invalid filter is not allowed,
101 1.1.1.3 lukem * don't rewrite filter */
102 1.1.1.3 lukem if ( LDAP_BACK_NOUNDEFFILTER( li ) ) {
103 1.1.1.3 lukem if ( filter->bv_val != op->ors_filterstr.bv_val ) {
104 1.1.1.3 lukem op->o_tmpfree( filter->bv_val, op->o_tmpmemctx );
105 1.1.1.3 lukem }
106 1.1.1.3 lukem BER_BVZERO( filter );
107 1.1.1.3 lukem gotit = -1;
108 1.1.1.3 lukem goto done;
109 1.1.1.3 lukem }
110 1.1.1.3 lukem
111 1.1 lukem oldbv = &bv_undefined;
112 1.1 lukem newbv = &bv_F;
113 1.1 lukem
114 1.1 lukem } else {
115 1.1 lukem gotit = 0;
116 1.1 lukem goto done;
117 1.1 lukem }
118 1.1 lukem
119 1.1 lukem oldfilter = *filter;
120 1.1.1.3 lukem filter->bv_len += newbv->bv_len - oldbv->bv_len;
121 1.1.1.3 lukem if ( filter->bv_val == op->ors_filterstr.bv_val ) {
122 1.1.1.3 lukem filter->bv_val = op->o_tmpalloc( filter->bv_len + 1,
123 1.1.1.3 lukem op->o_tmpmemctx );
124 1.1 lukem
125 1.1.1.3 lukem AC_MEMCPY( filter->bv_val, op->ors_filterstr.bv_val,
126 1.1.1.3 lukem op->ors_filterstr.bv_len + 1 );
127 1.1 lukem
128 1.1.1.3 lukem *freeit = 1;
129 1.1.1.3 lukem } else {
130 1.1.1.3 lukem filter->bv_val = op->o_tmprealloc( filter->bv_val,
131 1.1.1.3 lukem filter->bv_len + 1, op->o_tmpmemctx );
132 1.1 lukem }
133 1.1 lukem
134 1.1.1.3 lukem ptr = filter->bv_val + ( ptr - oldfilter.bv_val );
135 1.1.1.3 lukem
136 1.1 lukem AC_MEMCPY( &ptr[ newbv->bv_len ],
137 1.1 lukem &ptr[ oldbv->bv_len ],
138 1.1 lukem oldfilter.bv_len - ( ptr - filter->bv_val ) - oldbv->bv_len + 1 );
139 1.1 lukem AC_MEMCPY( ptr, newbv->bv_val, newbv->bv_len );
140 1.1 lukem
141 1.1 lukem ptr += newbv->bv_len;
142 1.1 lukem gotit = 1;
143 1.1 lukem }
144 1.1 lukem
145 1.1 lukem done:;
146 1.1 lukem Debug( LDAP_DEBUG_ARGS, "<= ldap_back_munge_filter \"%s\" (%d)\n",
147 1.1 lukem filter->bv_val, gotit, 0 );
148 1.1 lukem
149 1.1 lukem return gotit;
150 1.1 lukem }
151 1.1 lukem
152 1.1 lukem int
153 1.1 lukem ldap_back_search(
154 1.1 lukem Operation *op,
155 1.1 lukem SlapReply *rs )
156 1.1 lukem {
157 1.1 lukem ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
158 1.1 lukem
159 1.1 lukem ldapconn_t *lc = NULL;
160 1.1 lukem struct timeval tv;
161 1.1 lukem time_t stoptime = (time_t)(-1);
162 1.1 lukem LDAPMessage *res,
163 1.1 lukem *e;
164 1.1 lukem int rc = 0,
165 1.1 lukem msgid;
166 1.1 lukem struct berval match = BER_BVNULL,
167 1.1 lukem filter = BER_BVNULL;
168 1.1 lukem int i;
169 1.1 lukem char **attrs = NULL;
170 1.1.1.3 lukem int freetext = 0, freefilter = 0;
171 1.1 lukem int do_retry = 1, dont_retry = 0;
172 1.1 lukem LDAPControl **ctrls = NULL;
173 1.1 lukem char **references = NULL;
174 1.1 lukem
175 1.1 lukem /* FIXME: shouldn't this be null? */
176 1.1 lukem const char *save_matched = rs->sr_matched;
177 1.1 lukem
178 1.1 lukem if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
179 1.1 lukem return rs->sr_err;
180 1.1 lukem }
181 1.1 lukem
182 1.1 lukem /*
183 1.1 lukem * FIXME: in case of values return filter, we might want
184 1.1 lukem * to map attrs and maybe rewrite value
185 1.1 lukem */
186 1.1 lukem
187 1.1 lukem if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
188 1.1 lukem tv.tv_sec = op->ors_tlimit;
189 1.1 lukem tv.tv_usec = 0;
190 1.1 lukem stoptime = op->o_time + op->ors_tlimit;
191 1.1 lukem
192 1.1 lukem } else {
193 1.1 lukem LDAP_BACK_TV_SET( &tv );
194 1.1 lukem }
195 1.1 lukem
196 1.1 lukem if ( op->ors_attrs ) {
197 1.1 lukem for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ )
198 1.1 lukem /* just count attrs */ ;
199 1.1 lukem
200 1.1.1.4 adam attrs = op->o_tmpalloc( ( i + 1 )*sizeof( char * ),
201 1.1.1.4 adam op->o_tmpmemctx );
202 1.1 lukem if ( attrs == NULL ) {
203 1.1 lukem rs->sr_err = LDAP_NO_MEMORY;
204 1.1 lukem rc = -1;
205 1.1 lukem goto finish;
206 1.1 lukem }
207 1.1 lukem
208 1.1 lukem for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ ) {
209 1.1 lukem attrs[ i ] = op->ors_attrs[i].an_name.bv_val;
210 1.1 lukem }
211 1.1 lukem attrs[ i ] = NULL;
212 1.1 lukem }
213 1.1 lukem
214 1.1 lukem ctrls = op->o_ctrls;
215 1.1 lukem rc = ldap_back_controls_add( op, rs, lc, &ctrls );
216 1.1 lukem if ( rc != LDAP_SUCCESS ) {
217 1.1 lukem goto finish;
218 1.1 lukem }
219 1.1 lukem
220 1.1 lukem /* deal with <draft-zeilenga-ldap-t-f> filters */
221 1.1 lukem filter = op->ors_filterstr;
222 1.1 lukem retry:
223 1.1.1.3 lukem rs->sr_err = ldap_pvt_search( lc->lc_ld, op->o_req_dn.bv_val,
224 1.1 lukem op->ors_scope, filter.bv_val,
225 1.1 lukem attrs, op->ors_attrsonly, ctrls, NULL,
226 1.1 lukem tv.tv_sec ? &tv : NULL,
227 1.1.1.3 lukem op->ors_slimit, op->ors_deref, &msgid );
228 1.1 lukem
229 1.1 lukem if ( rs->sr_err != LDAP_SUCCESS ) {
230 1.1 lukem switch ( rs->sr_err ) {
231 1.1 lukem case LDAP_SERVER_DOWN:
232 1.1 lukem if ( do_retry ) {
233 1.1 lukem do_retry = 0;
234 1.1 lukem if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {
235 1.1 lukem goto retry;
236 1.1 lukem }
237 1.1 lukem }
238 1.1 lukem
239 1.1 lukem if ( lc == NULL ) {
240 1.1 lukem /* reset by ldap_back_retry ... */
241 1.1 lukem rs->sr_err = slap_map_api2result( rs );
242 1.1 lukem
243 1.1 lukem } else {
244 1.1 lukem rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_DONTSEND );
245 1.1 lukem }
246 1.1 lukem
247 1.1 lukem goto finish;
248 1.1 lukem
249 1.1 lukem case LDAP_FILTER_ERROR:
250 1.1.1.3 lukem if (ldap_back_munge_filter( op, &filter, &freefilter ) > 0 ) {
251 1.1 lukem goto retry;
252 1.1 lukem }
253 1.1 lukem
254 1.1 lukem /* invalid filters return success with no data */
255 1.1 lukem rs->sr_err = LDAP_SUCCESS;
256 1.1 lukem rs->sr_text = NULL;
257 1.1 lukem goto finish;
258 1.1 lukem
259 1.1 lukem default:
260 1.1 lukem rs->sr_err = slap_map_api2result( rs );
261 1.1 lukem rs->sr_text = NULL;
262 1.1 lukem goto finish;
263 1.1 lukem }
264 1.1 lukem }
265 1.1 lukem
266 1.1 lukem /* if needed, initialize timeout */
267 1.1 lukem if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
268 1.1 lukem if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) {
269 1.1 lukem tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ];
270 1.1 lukem tv.tv_usec = 0;
271 1.1 lukem }
272 1.1 lukem }
273 1.1 lukem
274 1.1 lukem /* We pull apart the ber result, stuff it into a slapd entry, and
275 1.1 lukem * let send_search_entry stuff it back into ber format. Slow & ugly,
276 1.1 lukem * but this is necessary for version matching, and for ACL processing.
277 1.1 lukem */
278 1.1 lukem
279 1.1 lukem for ( rc = -2; rc != -1; rc = ldap_result( lc->lc_ld, msgid, LDAP_MSG_ONE, &tv, &res ) )
280 1.1 lukem {
281 1.1 lukem /* check for abandon */
282 1.1 lukem if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( lc ) ) {
283 1.1 lukem if ( rc > 0 ) {
284 1.1 lukem ldap_msgfree( res );
285 1.1 lukem }
286 1.1 lukem (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
287 1.1 lukem rc = SLAPD_ABANDON;
288 1.1 lukem goto finish;
289 1.1 lukem }
290 1.1 lukem
291 1.1 lukem if ( rc == 0 || rc == -2 ) {
292 1.1 lukem ldap_pvt_thread_yield();
293 1.1 lukem
294 1.1 lukem /* check timeout */
295 1.1 lukem if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
296 1.1 lukem if ( rc == 0 ) {
297 1.1 lukem (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
298 1.1 lukem rs->sr_text = "Operation timed out";
299 1.1 lukem rc = rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
300 1.1 lukem LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
301 1.1 lukem goto finish;
302 1.1 lukem }
303 1.1 lukem
304 1.1 lukem } else {
305 1.1 lukem LDAP_BACK_TV_SET( &tv );
306 1.1 lukem }
307 1.1 lukem
308 1.1 lukem /* check time limit */
309 1.1 lukem if ( op->ors_tlimit != SLAP_NO_LIMIT
310 1.1 lukem && slap_get_time() > stoptime )
311 1.1 lukem {
312 1.1 lukem (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
313 1.1 lukem rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
314 1.1 lukem goto finish;
315 1.1 lukem }
316 1.1 lukem continue;
317 1.1 lukem
318 1.1 lukem } else {
319 1.1 lukem /* only touch when activity actually took place... */
320 1.1 lukem if ( li->li_idle_timeout && lc ) {
321 1.1 lukem lc->lc_time = op->o_time;
322 1.1 lukem }
323 1.1 lukem
324 1.1 lukem /* don't retry any more */
325 1.1 lukem dont_retry = 1;
326 1.1 lukem }
327 1.1 lukem
328 1.1 lukem
329 1.1 lukem if ( rc == LDAP_RES_SEARCH_ENTRY ) {
330 1.1 lukem Entry ent = { 0 };
331 1.1 lukem struct berval bdn = BER_BVNULL;
332 1.1 lukem
333 1.1 lukem do_retry = 0;
334 1.1 lukem
335 1.1 lukem e = ldap_first_entry( lc->lc_ld, res );
336 1.1 lukem rc = ldap_build_entry( op, e, &ent, &bdn );
337 1.1 lukem if ( rc == LDAP_SUCCESS ) {
338 1.1 lukem ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls );
339 1.1 lukem rs->sr_entry = &ent;
340 1.1 lukem rs->sr_attrs = op->ors_attrs;
341 1.1 lukem rs->sr_operational_attrs = NULL;
342 1.1 lukem rs->sr_flags = 0;
343 1.1 lukem rs->sr_err = LDAP_SUCCESS;
344 1.1 lukem rc = rs->sr_err = send_search_entry( op, rs );
345 1.1 lukem if ( rs->sr_ctrls ) {
346 1.1 lukem ldap_controls_free( rs->sr_ctrls );
347 1.1 lukem rs->sr_ctrls = NULL;
348 1.1 lukem }
349 1.1 lukem rs->sr_entry = NULL;
350 1.1 lukem if ( !BER_BVISNULL( &ent.e_name ) ) {
351 1.1 lukem assert( ent.e_name.bv_val != bdn.bv_val );
352 1.1 lukem op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx );
353 1.1 lukem BER_BVZERO( &ent.e_name );
354 1.1 lukem }
355 1.1 lukem if ( !BER_BVISNULL( &ent.e_nname ) ) {
356 1.1 lukem op->o_tmpfree( ent.e_nname.bv_val, op->o_tmpmemctx );
357 1.1 lukem BER_BVZERO( &ent.e_nname );
358 1.1 lukem }
359 1.1 lukem entry_clean( &ent );
360 1.1 lukem }
361 1.1 lukem ldap_msgfree( res );
362 1.1.1.3 lukem switch ( rc ) {
363 1.1.1.3 lukem case LDAP_SUCCESS:
364 1.1.1.3 lukem case LDAP_INSUFFICIENT_ACCESS:
365 1.1.1.3 lukem break;
366 1.1.1.3 lukem
367 1.1.1.3 lukem default:
368 1.1 lukem if ( rc == LDAP_UNAVAILABLE ) {
369 1.1 lukem rc = rs->sr_err = LDAP_OTHER;
370 1.1 lukem } else {
371 1.1 lukem (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND );
372 1.1 lukem }
373 1.1 lukem goto finish;
374 1.1 lukem }
375 1.1 lukem
376 1.1 lukem } else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
377 1.1.1.2 lukem if ( LDAP_BACK_NOREFS( li ) ) {
378 1.1.1.2 lukem ldap_msgfree( res );
379 1.1.1.2 lukem continue;
380 1.1.1.2 lukem }
381 1.1.1.2 lukem
382 1.1 lukem do_retry = 0;
383 1.1 lukem rc = ldap_parse_reference( lc->lc_ld, res,
384 1.1 lukem &references, &rs->sr_ctrls, 1 );
385 1.1 lukem
386 1.1 lukem if ( rc != LDAP_SUCCESS ) {
387 1.1 lukem continue;
388 1.1 lukem }
389 1.1 lukem
390 1.1 lukem /* FIXME: there MUST be at least one */
391 1.1 lukem if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) {
392 1.1 lukem int cnt;
393 1.1 lukem
394 1.1 lukem for ( cnt = 0; references[ cnt ]; cnt++ )
395 1.1 lukem /* NO OP */ ;
396 1.1 lukem
397 1.1 lukem /* FIXME: there MUST be at least one */
398 1.1 lukem rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
399 1.1 lukem op->o_tmpmemctx );
400 1.1 lukem
401 1.1 lukem for ( cnt = 0; references[ cnt ]; cnt++ ) {
402 1.1 lukem ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
403 1.1 lukem }
404 1.1 lukem BER_BVZERO( &rs->sr_ref[ cnt ] );
405 1.1 lukem
406 1.1 lukem /* ignore return value by now */
407 1.1 lukem rs->sr_entry = NULL;
408 1.1 lukem ( void )send_search_reference( op, rs );
409 1.1 lukem
410 1.1 lukem } else {
411 1.1 lukem Debug( LDAP_DEBUG_ANY,
412 1.1 lukem "%s ldap_back_search: "
413 1.1 lukem "got SEARCH_REFERENCE "
414 1.1 lukem "with no referrals\n",
415 1.1 lukem op->o_log_prefix, 0, 0 );
416 1.1 lukem }
417 1.1 lukem
418 1.1 lukem /* cleanup */
419 1.1 lukem if ( references ) {
420 1.1 lukem ber_memvfree( (void **)references );
421 1.1 lukem op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
422 1.1 lukem rs->sr_ref = NULL;
423 1.1 lukem references = NULL;
424 1.1 lukem }
425 1.1 lukem
426 1.1 lukem if ( rs->sr_ctrls ) {
427 1.1 lukem ldap_controls_free( rs->sr_ctrls );
428 1.1 lukem rs->sr_ctrls = NULL;
429 1.1 lukem }
430 1.1 lukem
431 1.1.1.3 lukem } else if ( rc == LDAP_RES_INTERMEDIATE ) {
432 1.1.1.3 lukem /* FIXME: response controls
433 1.1.1.3 lukem * are passed without checks */
434 1.1.1.3 lukem rc = ldap_parse_intermediate( lc->lc_ld,
435 1.1.1.3 lukem res,
436 1.1.1.3 lukem (char **)&rs->sr_rspoid,
437 1.1.1.3 lukem &rs->sr_rspdata,
438 1.1.1.3 lukem &rs->sr_ctrls,
439 1.1.1.3 lukem 0 );
440 1.1.1.3 lukem if ( rc != LDAP_SUCCESS ) {
441 1.1.1.3 lukem continue;
442 1.1.1.3 lukem }
443 1.1.1.3 lukem
444 1.1.1.3 lukem slap_send_ldap_intermediate( op, rs );
445 1.1.1.3 lukem
446 1.1.1.3 lukem if ( rs->sr_rspoid != NULL ) {
447 1.1.1.3 lukem ber_memfree( (char *)rs->sr_rspoid );
448 1.1.1.3 lukem rs->sr_rspoid = NULL;
449 1.1.1.3 lukem }
450 1.1.1.3 lukem
451 1.1.1.3 lukem if ( rs->sr_rspdata != NULL ) {
452 1.1.1.3 lukem ber_bvfree( rs->sr_rspdata );
453 1.1.1.3 lukem rs->sr_rspdata = NULL;
454 1.1.1.3 lukem }
455 1.1.1.3 lukem
456 1.1.1.3 lukem if ( rs->sr_ctrls != NULL ) {
457 1.1.1.3 lukem ldap_controls_free( rs->sr_ctrls );
458 1.1.1.3 lukem rs->sr_ctrls = NULL;
459 1.1.1.3 lukem }
460 1.1.1.3 lukem
461 1.1 lukem } else {
462 1.1 lukem char *err = NULL;
463 1.1 lukem
464 1.1 lukem rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err,
465 1.1 lukem &match.bv_val, &err,
466 1.1 lukem &references, &rs->sr_ctrls, 1 );
467 1.1 lukem if ( rc != LDAP_SUCCESS ) {
468 1.1 lukem rs->sr_err = rc;
469 1.1 lukem }
470 1.1 lukem rs->sr_err = slap_map_api2result( rs );
471 1.1 lukem if ( err ) {
472 1.1 lukem rs->sr_text = err;
473 1.1 lukem freetext = 1;
474 1.1 lukem }
475 1.1 lukem
476 1.1 lukem /* RFC 4511: referrals can only appear
477 1.1 lukem * if result code is LDAP_REFERRAL */
478 1.1 lukem if ( references
479 1.1 lukem && references[ 0 ]
480 1.1 lukem && references[ 0 ][ 0 ] )
481 1.1 lukem {
482 1.1 lukem if ( rs->sr_err != LDAP_REFERRAL ) {
483 1.1 lukem Debug( LDAP_DEBUG_ANY,
484 1.1 lukem "%s ldap_back_search: "
485 1.1 lukem "got referrals with err=%d\n",
486 1.1 lukem op->o_log_prefix,
487 1.1 lukem rs->sr_err, 0 );
488 1.1 lukem
489 1.1 lukem } else {
490 1.1 lukem int cnt;
491 1.1 lukem
492 1.1 lukem for ( cnt = 0; references[ cnt ]; cnt++ )
493 1.1 lukem /* NO OP */ ;
494 1.1 lukem
495 1.1 lukem rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ),
496 1.1 lukem op->o_tmpmemctx );
497 1.1 lukem
498 1.1 lukem for ( cnt = 0; references[ cnt ]; cnt++ ) {
499 1.1 lukem /* duplicating ...*/
500 1.1 lukem ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] );
501 1.1 lukem }
502 1.1 lukem BER_BVZERO( &rs->sr_ref[ cnt ] );
503 1.1 lukem }
504 1.1 lukem
505 1.1 lukem } else if ( rs->sr_err == LDAP_REFERRAL ) {
506 1.1 lukem Debug( LDAP_DEBUG_ANY,
507 1.1 lukem "%s ldap_back_search: "
508 1.1 lukem "got err=%d with null "
509 1.1 lukem "or empty referrals\n",
510 1.1 lukem op->o_log_prefix,
511 1.1 lukem rs->sr_err, 0 );
512 1.1 lukem
513 1.1 lukem rs->sr_err = LDAP_NO_SUCH_OBJECT;
514 1.1 lukem }
515 1.1 lukem
516 1.1 lukem if ( match.bv_val != NULL ) {
517 1.1 lukem match.bv_len = strlen( match.bv_val );
518 1.1 lukem }
519 1.1 lukem
520 1.1 lukem rc = 0;
521 1.1 lukem break;
522 1.1 lukem }
523 1.1 lukem
524 1.1 lukem /* if needed, restore timeout */
525 1.1 lukem if ( li->li_timeout[ SLAP_OP_SEARCH ] ) {
526 1.1 lukem if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) {
527 1.1 lukem tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ];
528 1.1 lukem tv.tv_usec = 0;
529 1.1 lukem }
530 1.1 lukem }
531 1.1 lukem }
532 1.1 lukem
533 1.1 lukem if ( rc == -1 && dont_retry == 0 ) {
534 1.1 lukem if ( do_retry ) {
535 1.1 lukem do_retry = 0;
536 1.1 lukem if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) {
537 1.1 lukem goto retry;
538 1.1 lukem }
539 1.1 lukem }
540 1.1 lukem rs->sr_err = LDAP_SERVER_DOWN;
541 1.1 lukem rs->sr_err = slap_map_api2result( rs );
542 1.1 lukem goto finish;
543 1.1 lukem }
544 1.1 lukem
545 1.1 lukem /*
546 1.1 lukem * Rewrite the matched portion of the search base, if required
547 1.1 lukem */
548 1.1 lukem if ( !BER_BVISNULL( &match ) && !BER_BVISEMPTY( &match ) ) {
549 1.1 lukem struct berval pmatch;
550 1.1 lukem
551 1.1 lukem if ( dnPretty( NULL, &match, &pmatch, op->o_tmpmemctx ) == LDAP_SUCCESS ) {
552 1.1 lukem rs->sr_matched = pmatch.bv_val;
553 1.1 lukem LDAP_FREE( match.bv_val );
554 1.1 lukem
555 1.1 lukem } else {
556 1.1 lukem rs->sr_matched = match.bv_val;
557 1.1 lukem }
558 1.1 lukem }
559 1.1 lukem
560 1.1 lukem if ( rs->sr_v2ref ) {
561 1.1 lukem rs->sr_err = LDAP_REFERRAL;
562 1.1 lukem }
563 1.1 lukem
564 1.1 lukem finish:;
565 1.1 lukem if ( LDAP_BACK_QUARANTINE( li ) ) {
566 1.1 lukem ldap_back_quarantine( op, rs );
567 1.1 lukem }
568 1.1 lukem
569 1.1.1.3 lukem if ( freefilter && filter.bv_val != op->ors_filterstr.bv_val ) {
570 1.1.1.3 lukem op->o_tmpfree( filter.bv_val, op->o_tmpmemctx );
571 1.1.1.3 lukem }
572 1.1.1.3 lukem
573 1.1 lukem #if 0
574 1.1 lukem /* let send_ldap_result play cleanup handlers (ITS#4645) */
575 1.1 lukem if ( rc != SLAPD_ABANDON )
576 1.1 lukem #endif
577 1.1 lukem {
578 1.1 lukem send_ldap_result( op, rs );
579 1.1 lukem }
580 1.1 lukem
581 1.1 lukem (void)ldap_back_controls_free( op, rs, &ctrls );
582 1.1 lukem
583 1.1 lukem if ( rs->sr_ctrls ) {
584 1.1 lukem ldap_controls_free( rs->sr_ctrls );
585 1.1 lukem rs->sr_ctrls = NULL;
586 1.1 lukem }
587 1.1 lukem
588 1.1 lukem if ( rs->sr_matched != NULL && rs->sr_matched != save_matched ) {
589 1.1 lukem if ( rs->sr_matched != match.bv_val ) {
590 1.1 lukem ber_memfree_x( (char *)rs->sr_matched, op->o_tmpmemctx );
591 1.1 lukem
592 1.1 lukem } else {
593 1.1 lukem LDAP_FREE( match.bv_val );
594 1.1 lukem }
595 1.1 lukem rs->sr_matched = save_matched;
596 1.1 lukem }
597 1.1 lukem
598 1.1 lukem if ( rs->sr_text ) {
599 1.1 lukem if ( freetext ) {
600 1.1 lukem LDAP_FREE( (char *)rs->sr_text );
601 1.1 lukem }
602 1.1 lukem rs->sr_text = NULL;
603 1.1 lukem }
604 1.1 lukem
605 1.1 lukem if ( rs->sr_ref ) {
606 1.1 lukem op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );
607 1.1 lukem rs->sr_ref = NULL;
608 1.1 lukem }
609 1.1 lukem
610 1.1 lukem if ( references ) {
611 1.1 lukem ber_memvfree( (void **)references );
612 1.1 lukem }
613 1.1 lukem
614 1.1 lukem if ( attrs ) {
615 1.1.1.4 adam op->o_tmpfree( attrs, op->o_tmpmemctx );
616 1.1 lukem }
617 1.1 lukem
618 1.1 lukem if ( lc != NULL ) {
619 1.1 lukem ldap_back_release_conn( li, lc );
620 1.1 lukem }
621 1.1 lukem
622 1.1 lukem return rs->sr_err;
623 1.1 lukem }
624 1.1 lukem
625 1.1 lukem static int
626 1.1 lukem ldap_build_entry(
627 1.1 lukem Operation *op,
628 1.1 lukem LDAPMessage *e,
629 1.1 lukem Entry *ent,
630 1.1 lukem struct berval *bdn )
631 1.1 lukem {
632 1.1 lukem struct berval a;
633 1.1 lukem BerElement ber = *e->lm_ber;
634 1.1 lukem Attribute *attr, **attrp;
635 1.1 lukem const char *text;
636 1.1 lukem int last;
637 1.1 lukem char *lastb;
638 1.1 lukem ber_len_t len;
639 1.1 lukem
640 1.1 lukem /* safe assumptions ... */
641 1.1 lukem assert( ent != NULL );
642 1.1 lukem BER_BVZERO( &ent->e_bv );
643 1.1 lukem
644 1.1 lukem if ( ber_scanf( &ber, "{m", bdn ) == LBER_ERROR ) {
645 1.1 lukem return LDAP_DECODING_ERROR;
646 1.1 lukem }
647 1.1 lukem
648 1.1 lukem /*
649 1.1 lukem * Note: this may fail if the target host(s) schema differs
650 1.1 lukem * from the one known to the meta, and a DN with unknown
651 1.1 lukem * attributes is returned.
652 1.1 lukem *
653 1.1 lukem * FIXME: should we log anything, or delegate to dnNormalize?
654 1.1 lukem */
655 1.1 lukem /* Note: if the distinguished values or the naming attributes
656 1.1 lukem * change, should we massage them as well?
657 1.1 lukem */
658 1.1 lukem if ( dnPrettyNormal( NULL, bdn, &ent->e_name, &ent->e_nname,
659 1.1 lukem op->o_tmpmemctx ) != LDAP_SUCCESS )
660 1.1 lukem {
661 1.1 lukem return LDAP_INVALID_DN_SYNTAX;
662 1.1 lukem }
663 1.1 lukem
664 1.1 lukem ent->e_attrs = NULL;
665 1.1 lukem if ( ber_first_element( &ber, &len, &lastb ) != LBER_SEQUENCE ) {
666 1.1 lukem return LDAP_SUCCESS;
667 1.1 lukem }
668 1.1 lukem
669 1.1 lukem attrp = &ent->e_attrs;
670 1.1 lukem while ( ber_next_element( &ber, &len, lastb ) == LBER_SEQUENCE &&
671 1.1 lukem ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) {
672 1.1 lukem int i;
673 1.1 lukem slap_syntax_validate_func *validate;
674 1.1 lukem slap_syntax_transform_func *pretty;
675 1.1 lukem
676 1.1 lukem attr = attr_alloc( NULL );
677 1.1 lukem if ( attr == NULL ) {
678 1.1.1.3 lukem return LDAP_OTHER;
679 1.1 lukem }
680 1.1 lukem if ( slap_bv2ad( &a, &attr->a_desc, &text )
681 1.1 lukem != LDAP_SUCCESS )
682 1.1 lukem {
683 1.1 lukem if ( slap_bv2undef_ad( &a, &attr->a_desc, &text,
684 1.1 lukem SLAP_AD_PROXIED ) != LDAP_SUCCESS )
685 1.1 lukem {
686 1.1 lukem Debug( LDAP_DEBUG_ANY,
687 1.1 lukem "%s ldap_build_entry: "
688 1.1 lukem "slap_bv2undef_ad(%s): %s\n",
689 1.1 lukem op->o_log_prefix, a.bv_val, text );
690 1.1.1.3 lukem
691 1.1.1.3 lukem ( void )ber_scanf( &ber, "x" /* [W] */ );
692 1.1 lukem attr_free( attr );
693 1.1 lukem continue;
694 1.1 lukem }
695 1.1 lukem }
696 1.1 lukem
697 1.1 lukem /* no subschemaSubentry */
698 1.1 lukem if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry
699 1.1 lukem || attr->a_desc == slap_schema.si_ad_entryDN )
700 1.1 lukem {
701 1.1 lukem
702 1.1 lukem /*
703 1.1 lukem * We eat target's subschemaSubentry because
704 1.1 lukem * a search for this value is likely not
705 1.1 lukem * to resolve to the appropriate backend;
706 1.1 lukem * later, the local subschemaSubentry is
707 1.1 lukem * added.
708 1.1 lukem *
709 1.1 lukem * We also eat entryDN because the frontend
710 1.1 lukem * will reattach it without checking if already
711 1.1 lukem * present...
712 1.1 lukem */
713 1.1 lukem ( void )ber_scanf( &ber, "x" /* [W] */ );
714 1.1 lukem attr_free( attr );
715 1.1 lukem continue;
716 1.1 lukem }
717 1.1 lukem
718 1.1 lukem if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR
719 1.1 lukem || attr->a_vals == NULL )
720 1.1 lukem {
721 1.1 lukem /*
722 1.1 lukem * Note: attr->a_vals can be null when using
723 1.1 lukem * values result filter
724 1.1 lukem */
725 1.1 lukem attr->a_vals = (struct berval *)&slap_dummy_bv;
726 1.1 lukem }
727 1.1 lukem
728 1.1 lukem validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
729 1.1 lukem pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty;
730 1.1 lukem
731 1.1 lukem if ( !validate && !pretty ) {
732 1.1 lukem attr->a_nvals = NULL;
733 1.1 lukem attr_free( attr );
734 1.1 lukem goto next_attr;
735 1.1 lukem }
736 1.1 lukem
737 1.1.1.3 lukem for ( i = 0; !BER_BVISNULL( &attr->a_vals[i] ); i++ ) ;
738 1.1.1.3 lukem last = i;
739 1.1.1.3 lukem
740 1.1.1.3 lukem /*
741 1.1.1.3 lukem * check that each value is valid per syntax
742 1.1.1.3 lukem * and pretty if appropriate
743 1.1.1.3 lukem */
744 1.1.1.3 lukem for ( i = 0; i<last; i++ ) {
745 1.1 lukem struct berval pval;
746 1.1 lukem int rc;
747 1.1 lukem
748 1.1 lukem if ( pretty ) {
749 1.1.1.4 adam rc = ordered_value_pretty( attr->a_desc,
750 1.1 lukem &attr->a_vals[i], &pval, NULL );
751 1.1 lukem
752 1.1 lukem } else {
753 1.1.1.4 adam rc = ordered_value_validate( attr->a_desc,
754 1.1.1.4 adam &attr->a_vals[i], 0 );
755 1.1 lukem }
756 1.1 lukem
757 1.1 lukem if ( rc != LDAP_SUCCESS ) {
758 1.1.1.3 lukem ObjectClass *oc;
759 1.1.1.3 lukem
760 1.1 lukem /* check if, by chance, it's an undefined objectClass */
761 1.1 lukem if ( attr->a_desc == slap_schema.si_ad_objectClass &&
762 1.1.1.3 lukem ( oc = oc_bvfind_undef( &attr->a_vals[i] ) ) != NULL )
763 1.1 lukem {
764 1.1.1.3 lukem ber_dupbv( &pval, &oc->soc_cname );
765 1.1.1.3 lukem rc = LDAP_SUCCESS;
766 1.1 lukem
767 1.1 lukem } else {
768 1.1.1.3 lukem LBER_FREE( attr->a_vals[i].bv_val );
769 1.1.1.3 lukem if ( --last == i ) {
770 1.1.1.3 lukem BER_BVZERO( &attr->a_vals[i] );
771 1.1.1.3 lukem break;
772 1.1.1.3 lukem }
773 1.1.1.3 lukem attr->a_vals[i] = attr->a_vals[last];
774 1.1.1.3 lukem BER_BVZERO( &attr->a_vals[last] );
775 1.1.1.3 lukem i--;
776 1.1 lukem }
777 1.1 lukem }
778 1.1 lukem
779 1.1.1.3 lukem if ( rc == LDAP_SUCCESS && pretty ) {
780 1.1 lukem LBER_FREE( attr->a_vals[i].bv_val );
781 1.1 lukem attr->a_vals[i] = pval;
782 1.1 lukem }
783 1.1 lukem }
784 1.1 lukem attr->a_numvals = last = i;
785 1.1.1.3 lukem if ( last == 0 && attr->a_vals != &slap_dummy_bv ) {
786 1.1.1.3 lukem attr->a_nvals = NULL;
787 1.1.1.3 lukem attr_free( attr );
788 1.1.1.3 lukem goto next_attr;
789 1.1.1.3 lukem }
790 1.1 lukem
791 1.1 lukem if ( last && attr->a_desc->ad_type->sat_equality &&
792 1.1 lukem attr->a_desc->ad_type->sat_equality->smr_normalize )
793 1.1 lukem {
794 1.1 lukem attr->a_nvals = ch_malloc( ( last + 1 )*sizeof( struct berval ) );
795 1.1 lukem for ( i = 0; i < last; i++ ) {
796 1.1 lukem int rc;
797 1.1 lukem
798 1.1.1.4 adam rc = ordered_value_normalize(
799 1.1 lukem SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
800 1.1.1.4 adam attr->a_desc,
801 1.1 lukem attr->a_desc->ad_type->sat_equality,
802 1.1 lukem &attr->a_vals[i], &attr->a_nvals[i],
803 1.1 lukem NULL );
804 1.1 lukem
805 1.1 lukem if ( rc != LDAP_SUCCESS ) {
806 1.1.1.3 lukem LBER_FREE( attr->a_vals[i].bv_val );
807 1.1.1.3 lukem if ( --last == i ) {
808 1.1.1.3 lukem BER_BVZERO( &attr->a_vals[i] );
809 1.1.1.3 lukem break;
810 1.1.1.3 lukem }
811 1.1.1.3 lukem attr->a_vals[i] = attr->a_vals[last];
812 1.1.1.3 lukem BER_BVZERO( &attr->a_vals[last] );
813 1.1.1.3 lukem i--;
814 1.1 lukem }
815 1.1 lukem }
816 1.1 lukem BER_BVZERO( &attr->a_nvals[i] );
817 1.1.1.3 lukem if ( last == 0 ) {
818 1.1.1.3 lukem attr_free( attr );
819 1.1.1.3 lukem goto next_attr;
820 1.1.1.3 lukem }
821 1.1 lukem
822 1.1 lukem } else {
823 1.1 lukem attr->a_nvals = attr->a_vals;
824 1.1 lukem }
825 1.1.1.3 lukem
826 1.1.1.3 lukem attr->a_numvals = last;
827 1.1.1.3 lukem
828 1.1.1.3 lukem /* Handle sorted vals, strip dups but keep the attr */
829 1.1.1.3 lukem if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
830 1.1.1.3 lukem while ( attr->a_numvals > 1 ) {
831 1.1.1.3 lukem int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx );
832 1.1.1.3 lukem if ( rc != LDAP_TYPE_OR_VALUE_EXISTS )
833 1.1.1.3 lukem break;
834 1.1.1.3 lukem
835 1.1.1.3 lukem /* Strip duplicate values */
836 1.1.1.3 lukem if ( attr->a_nvals != attr->a_vals )
837 1.1.1.3 lukem LBER_FREE( attr->a_nvals[i].bv_val );
838 1.1.1.3 lukem LBER_FREE( attr->a_vals[i].bv_val );
839 1.1.1.3 lukem attr->a_numvals--;
840 1.1.1.3 lukem
841 1.1.1.3 lukem assert( i >= 0 );
842 1.1.1.3 lukem if ( (unsigned)i < attr->a_numvals ) {
843 1.1.1.3 lukem attr->a_vals[i] = attr->a_vals[attr->a_numvals];
844 1.1.1.3 lukem if ( attr->a_nvals != attr->a_vals )
845 1.1.1.3 lukem attr->a_nvals[i] = attr->a_nvals[attr->a_numvals];
846 1.1.1.3 lukem }
847 1.1.1.3 lukem BER_BVZERO(&attr->a_vals[attr->a_numvals]);
848 1.1.1.3 lukem if ( attr->a_nvals != attr->a_vals )
849 1.1.1.3 lukem BER_BVZERO(&attr->a_nvals[attr->a_numvals]);
850 1.1.1.3 lukem }
851 1.1.1.3 lukem attr->a_flags |= SLAP_ATTR_SORTED_VALS;
852 1.1.1.3 lukem }
853 1.1.1.3 lukem
854 1.1 lukem *attrp = attr;
855 1.1 lukem attrp = &attr->a_next;
856 1.1 lukem
857 1.1 lukem next_attr:;
858 1.1 lukem }
859 1.1 lukem
860 1.1 lukem return LDAP_SUCCESS;
861 1.1 lukem }
862 1.1 lukem
863 1.1 lukem /* return 0 IFF we can retrieve the entry with ndn
864 1.1 lukem */
865 1.1 lukem int
866 1.1 lukem ldap_back_entry_get(
867 1.1 lukem Operation *op,
868 1.1 lukem struct berval *ndn,
869 1.1 lukem ObjectClass *oc,
870 1.1 lukem AttributeDescription *at,
871 1.1 lukem int rw,
872 1.1 lukem Entry **ent )
873 1.1 lukem {
874 1.1 lukem ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private;
875 1.1 lukem
876 1.1 lukem ldapconn_t *lc = NULL;
877 1.1.1.2 lukem int rc,
878 1.1 lukem do_not_cache;
879 1.1.1.2 lukem ber_tag_t tag;
880 1.1 lukem struct berval bdn;
881 1.1 lukem LDAPMessage *result = NULL,
882 1.1 lukem *e = NULL;
883 1.1 lukem char *attr[3], **attrp = NULL;
884 1.1 lukem char *filter = NULL;
885 1.1 lukem SlapReply rs;
886 1.1 lukem int do_retry = 1;
887 1.1 lukem LDAPControl **ctrls = NULL;
888 1.1 lukem
889 1.1 lukem *ent = NULL;
890 1.1 lukem
891 1.1 lukem /* Tell getconn this is a privileged op */
892 1.1 lukem do_not_cache = op->o_do_not_cache;
893 1.1.1.2 lukem tag = op->o_tag;
894 1.1.1.2 lukem /* do not cache */
895 1.1 lukem op->o_do_not_cache = 1;
896 1.1.1.2 lukem /* ldap_back_entry_get() is an entry lookup, so it does not need
897 1.1.1.2 lukem * to know what the entry is being looked up for */
898 1.1.1.2 lukem op->o_tag = LDAP_REQ_SEARCH;
899 1.1.1.2 lukem rc = ldap_back_dobind( &lc, op, &rs, LDAP_BACK_DONTSEND );
900 1.1.1.2 lukem op->o_do_not_cache = do_not_cache;
901 1.1.1.2 lukem op->o_tag = tag;
902 1.1.1.2 lukem if ( !rc ) {
903 1.1 lukem return rs.sr_err;
904 1.1 lukem }
905 1.1 lukem
906 1.1 lukem if ( at ) {
907 1.1 lukem attrp = attr;
908 1.1 lukem if ( oc && at != slap_schema.si_ad_objectClass ) {
909 1.1 lukem attr[0] = slap_schema.si_ad_objectClass->ad_cname.bv_val;
910 1.1 lukem attr[1] = at->ad_cname.bv_val;
911 1.1 lukem attr[2] = NULL;
912 1.1 lukem
913 1.1 lukem } else {
914 1.1 lukem attr[0] = at->ad_cname.bv_val;
915 1.1 lukem attr[1] = NULL;
916 1.1 lukem }
917 1.1 lukem }
918 1.1 lukem
919 1.1 lukem if ( oc ) {
920 1.1 lukem char *ptr;
921 1.1 lukem
922 1.1 lukem filter = op->o_tmpalloc( STRLENOF( "(objectClass=" ")" )
923 1.1 lukem + oc->soc_cname.bv_len + 1, op->o_tmpmemctx );
924 1.1 lukem ptr = lutil_strcopy( filter, "(objectClass=" );
925 1.1 lukem ptr = lutil_strcopy( ptr, oc->soc_cname.bv_val );
926 1.1 lukem *ptr++ = ')';
927 1.1 lukem *ptr++ = '\0';
928 1.1 lukem }
929 1.1 lukem
930 1.1 lukem retry:
931 1.1 lukem ctrls = op->o_ctrls;
932 1.1 lukem rc = ldap_back_controls_add( op, &rs, lc, &ctrls );
933 1.1 lukem if ( rc != LDAP_SUCCESS ) {
934 1.1 lukem goto cleanup;
935 1.1 lukem }
936 1.1 lukem
937 1.1 lukem /* TODO: timeout? */
938 1.1.1.3 lukem rc = ldap_pvt_search_s( lc->lc_ld, ndn->bv_val, LDAP_SCOPE_BASE, filter,
939 1.1.1.3 lukem attrp, LDAP_DEREF_NEVER, ctrls, NULL,
940 1.1.1.3 lukem NULL, LDAP_NO_LIMIT, 0, &result );
941 1.1 lukem if ( rc != LDAP_SUCCESS ) {
942 1.1 lukem if ( rc == LDAP_SERVER_DOWN && do_retry ) {
943 1.1 lukem do_retry = 0;
944 1.1 lukem if ( ldap_back_retry( &lc, op, &rs, LDAP_BACK_DONTSEND ) ) {
945 1.1 lukem /* if the identity changed, there might be need to re-authz */
946 1.1 lukem (void)ldap_back_controls_free( op, &rs, &ctrls );
947 1.1 lukem goto retry;
948 1.1 lukem }
949 1.1 lukem }
950 1.1 lukem goto cleanup;
951 1.1 lukem }
952 1.1 lukem
953 1.1 lukem e = ldap_first_entry( lc->lc_ld, result );
954 1.1 lukem if ( e == NULL ) {
955 1.1 lukem /* the entry exists, but it doesn't match the filter? */
956 1.1 lukem goto cleanup;
957 1.1 lukem }
958 1.1 lukem
959 1.1 lukem *ent = entry_alloc();
960 1.1 lukem if ( *ent == NULL ) {
961 1.1 lukem rc = LDAP_NO_MEMORY;
962 1.1 lukem goto cleanup;
963 1.1 lukem }
964 1.1 lukem
965 1.1 lukem rc = ldap_build_entry( op, e, *ent, &bdn );
966 1.1 lukem
967 1.1 lukem if ( rc != LDAP_SUCCESS ) {
968 1.1 lukem entry_free( *ent );
969 1.1 lukem *ent = NULL;
970 1.1 lukem }
971 1.1 lukem
972 1.1 lukem cleanup:
973 1.1 lukem (void)ldap_back_controls_free( op, &rs, &ctrls );
974 1.1 lukem
975 1.1 lukem if ( result ) {
976 1.1 lukem ldap_msgfree( result );
977 1.1 lukem }
978 1.1 lukem
979 1.1 lukem if ( filter ) {
980 1.1 lukem op->o_tmpfree( filter, op->o_tmpmemctx );
981 1.1 lukem }
982 1.1 lukem
983 1.1 lukem if ( lc != NULL ) {
984 1.1 lukem ldap_back_release_conn( li, lc );
985 1.1 lukem }
986 1.1 lukem
987 1.1 lukem return rc;
988 1.1 lukem }
989 1.1 lukem
990