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