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