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