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