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