1 /* $NetBSD: search.c,v 1.4 2025/09/05 21:16:28 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1999-2024 The OpenLDAP Foundation. 7 * Portions Copyright 2001-2003 Pierangelo Masarati. 8 * Portions Copyright 1999-2003 Howard Chu. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 /* ACKNOWLEDGEMENTS: 20 * This work was initially developed by the Howard Chu for inclusion 21 * in OpenLDAP Software and subsequently enhanced by Pierangelo 22 * Masarati. 23 */ 24 25 #include <sys/cdefs.h> 26 __RCSID("$NetBSD: search.c,v 1.4 2025/09/05 21:16:28 christos Exp $"); 27 28 #include "portable.h" 29 30 #include <stdio.h> 31 32 #include <ac/socket.h> 33 #include <ac/string.h> 34 #include <ac/time.h> 35 36 #include "lutil.h" 37 #include "slap.h" 38 #include "../back-ldap/back-ldap.h" 39 #include "back-meta.h" 40 #include "../../../libraries/liblber/lber-int.h" 41 42 /* IGNORE means that target does not (no longer) participate 43 * in the search; 44 * NOTREADY means the search on that target has not been initialized yet 45 */ 46 #define META_MSGID_IGNORE (-1) 47 #define META_MSGID_NEED_BIND (-2) 48 #define META_MSGID_CONNECTING (-3) 49 50 static int 51 meta_send_entry( 52 Operation *op, 53 SlapReply *rs, 54 metaconn_t *mc, 55 int i, 56 LDAPMessage *e ); 57 58 typedef enum meta_search_candidate_t { 59 META_SEARCH_UNDEFINED = -2, 60 META_SEARCH_ERR = -1, 61 META_SEARCH_NOT_CANDIDATE, 62 META_SEARCH_CANDIDATE, 63 META_SEARCH_BINDING, 64 META_SEARCH_NEED_BIND, 65 META_SEARCH_CONNECTING 66 } meta_search_candidate_t; 67 68 /* 69 * meta_search_dobind_init() 70 * 71 * initiates bind for a candidate target of a search. 72 */ 73 static meta_search_candidate_t 74 meta_search_dobind_init( 75 Operation *op, 76 SlapReply *rs, 77 metaconn_t **mcp, 78 int candidate, 79 SlapReply *candidates ) 80 { 81 metaconn_t *mc = *mcp; 82 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; 83 metatarget_t *mt = mi->mi_targets[ candidate ]; 84 metasingleconn_t *msc = &mc->mc_conns[ candidate ]; 85 86 struct berval binddn = msc->msc_bound_ndn, 87 cred = msc->msc_cred; 88 int method; 89 90 int rc; 91 92 meta_search_candidate_t retcode; 93 94 Debug( LDAP_DEBUG_TRACE, "%s >>> meta_search_dobind_init[%d]\n", 95 op->o_log_prefix, candidate ); 96 97 /* 98 * all the targets are already bound as pseudoroot 99 */ 100 if ( mc->mc_authz_target == META_BOUND_ALL ) { 101 return META_SEARCH_CANDIDATE; 102 } 103 104 retcode = META_SEARCH_BINDING; 105 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 106 if ( LDAP_BACK_CONN_ISBOUND( msc ) || LDAP_BACK_CONN_ISANON( msc ) ) { 107 /* already bound (or anonymous) */ 108 109 #ifdef DEBUG_205 110 int bound = 0; 111 112 if ( LDAP_BACK_CONN_ISBOUND( msc ) ) { 113 bound = 1; 114 } 115 116 Debug(LDAP_DEBUG_ANY, 117 "### %s meta_search_dobind_init[%d] mc=%p ld=%p%s DN=\"%s\"\n", 118 op->o_log_prefix, candidate, (void *)mc, 119 (void *)msc->msc_ld, bound ? " bound" : " anonymous", 120 bound == 0 ? "" : msc->msc_bound_ndn.bv_val ); 121 #endif /* DEBUG_205 */ 122 123 retcode = META_SEARCH_CANDIDATE; 124 125 } else if ( META_BACK_CONN_CREATING( msc ) || LDAP_BACK_CONN_BINDING( msc ) ) { 126 /* another thread is binding the target for this conn; wait */ 127 128 #ifdef DEBUG_205 129 Debug(LDAP_DEBUG_ANY, 130 "### %s meta_search_dobind_init[%d] mc=%p ld=%p needbind\n", 131 op->o_log_prefix, candidate, (void *)mc, 132 (void *)msc->msc_ld ); 133 #endif /* DEBUG_205 */ 134 135 candidates[ candidate ].sr_msgid = META_MSGID_NEED_BIND; 136 retcode = META_SEARCH_NEED_BIND; 137 138 } else { 139 /* we'll need to bind the target for this conn */ 140 141 #ifdef DEBUG_205 142 Debug(LDAP_DEBUG_ANY, 143 "### %s meta_search_dobind_init[%d] mc=%p ld=%p binding\n", 144 op->o_log_prefix, candidate, (void *)mc, 145 (void *)msc->msc_ld ); 146 #endif /* DEBUG_205 */ 147 148 if ( msc->msc_ld == NULL ) { 149 /* for some reason (e.g. because formerly in "binding" 150 * state, with eventual connection expiration or invalidation) 151 * it was not initialized as expected */ 152 153 Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] mc=%p ld=NULL\n", 154 op->o_log_prefix, candidate, (void *)mc ); 155 156 rc = meta_back_init_one_conn( op, rs, *mcp, candidate, 157 LDAP_BACK_CONN_ISPRIV( *mcp ), LDAP_BACK_DONTSEND, 0 ); 158 switch ( rc ) { 159 case LDAP_SUCCESS: 160 assert( msc->msc_ld != NULL ); 161 break; 162 163 case LDAP_SERVER_DOWN: 164 case LDAP_UNAVAILABLE: 165 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 166 goto down; 167 168 default: 169 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 170 goto other; 171 } 172 } 173 174 LDAP_BACK_CONN_BINDING_SET( msc ); 175 } 176 177 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 178 179 if ( retcode != META_SEARCH_BINDING ) { 180 return retcode; 181 } 182 183 /* NOTE: this obsoletes pseudorootdn */ 184 if ( op->o_conn != NULL && 185 ( BER_BVISNULL( &msc->msc_bound_ndn ) || 186 BER_BVISEMPTY( &msc->msc_bound_ndn ) || 187 ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) ) 188 { 189 rc = meta_back_proxy_authz_cred( mc, candidate, op, rs, LDAP_BACK_DONTSEND, &binddn, &cred, &method ); 190 switch ( rc ) { 191 case LDAP_SUCCESS: 192 break; 193 case LDAP_UNAVAILABLE: 194 goto down; 195 default: 196 goto other; 197 } 198 199 /* NOTE: we copy things here, even if bind didn't succeed yet, 200 * because the connection is not shared until bind is over */ 201 if ( !BER_BVISNULL( &binddn ) ) { 202 ber_bvreplace( &msc->msc_bound_ndn, &binddn ); 203 if ( META_BACK_TGT_SAVECRED( mt ) && !BER_BVISNULL( &cred ) ) { 204 if ( !BER_BVISNULL( &msc->msc_cred ) ) { 205 memset( msc->msc_cred.bv_val, 0, 206 msc->msc_cred.bv_len ); 207 } 208 ber_bvreplace( &msc->msc_cred, &cred ); 209 } 210 } 211 212 if ( LDAP_BACK_CONN_ISBOUND( msc ) ) { 213 /* apparently, idassert was configured with SASL bind, 214 * so bind occurred inside meta_back_proxy_authz_cred() */ 215 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 216 LDAP_BACK_CONN_BINDING_CLEAR( msc ); 217 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 218 return META_SEARCH_CANDIDATE; 219 } 220 221 /* paranoid */ 222 switch ( method ) { 223 case LDAP_AUTH_NONE: 224 case LDAP_AUTH_SIMPLE: 225 /* do a simple bind with binddn, cred */ 226 break; 227 228 default: 229 assert( 0 ); 230 break; 231 } 232 } 233 234 assert( msc->msc_ld != NULL ); 235 236 /* connect must be async only the first time... */ 237 ldap_set_option( msc->msc_ld, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_ON ); 238 239 retry:; 240 if ( !BER_BVISEMPTY( &binddn ) && BER_BVISEMPTY( &cred ) ) { 241 /* bind anonymously? */ 242 Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] mc=%p: " 243 "non-empty dn with empty cred; binding anonymously\n", 244 op->o_log_prefix, candidate, (void *)mc ); 245 cred = slap_empty_bv; 246 247 } else if ( BER_BVISEMPTY( &binddn ) && !BER_BVISEMPTY( &cred ) ) { 248 /* error */ 249 Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] mc=%p: " 250 "empty dn with non-empty cred: error\n", 251 op->o_log_prefix, candidate, (void *)mc ); 252 rc = LDAP_OTHER; 253 goto other; 254 } 255 256 rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred, 257 NULL, NULL, &candidates[ candidate ].sr_msgid ); 258 259 #ifdef DEBUG_205 260 Debug(LDAP_DEBUG_ANY, 261 "### %s meta_search_dobind_init[%d] mc=%p ld=%p rc=%d\n", 262 op->o_log_prefix, candidate, (void *)mc, 263 (void *)mc->mc_conns[candidate].msc_ld, rc ); 264 #endif /* DEBUG_205 */ 265 266 switch ( rc ) { 267 case LDAP_SUCCESS: 268 assert( candidates[ candidate ].sr_msgid >= 0 ); 269 META_BINDING_SET( &candidates[ candidate ] ); 270 return META_SEARCH_BINDING; 271 272 case LDAP_X_CONNECTING: 273 /* must retry, same conn */ 274 candidates[ candidate ].sr_msgid = META_MSGID_CONNECTING; 275 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 276 LDAP_BACK_CONN_BINDING_CLEAR( msc ); 277 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 278 return META_SEARCH_CONNECTING; 279 280 case LDAP_SERVER_DOWN: 281 down:; 282 /* This is the worst thing that could happen: 283 * the search will wait until the retry is over. */ 284 if ( !META_IS_RETRYING( &candidates[ candidate ] ) ) { 285 META_RETRYING_SET( &candidates[ candidate ] ); 286 287 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 288 289 assert( mc->mc_refcnt > 0 ); 290 if ( LogTest( LDAP_DEBUG_ANY ) ) { 291 /* this lock is required; however, 292 * it's invoked only when logging is on */ 293 ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex ); 294 Debug(LDAP_DEBUG_ANY, 295 "%s meta_search_dobind_init[%d]: retrying URI=\"%s\" DN=\"%s\".\n", 296 op->o_log_prefix, candidate, mt->mt_uri, 297 BER_BVISNULL(&msc->msc_bound_ndn) ? "" : msc->msc_bound_ndn.bv_val ); 298 ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex ); 299 } 300 301 meta_clear_one_candidate( op, mc, candidate ); 302 LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); 303 304 ( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn ); 305 306 /* mc here must be the regular mc, reset and ready for init */ 307 rc = meta_back_init_one_conn( op, rs, mc, candidate, 308 LDAP_BACK_CONN_ISPRIV( mc ), LDAP_BACK_DONTSEND, 0 ); 309 310 if ( rc == LDAP_SUCCESS ) { 311 LDAP_BACK_CONN_BINDING_SET( msc ); 312 } 313 314 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 315 316 if ( rc == LDAP_SUCCESS ) { 317 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; 318 binddn = msc->msc_bound_ndn; 319 cred = msc->msc_cred; 320 goto retry; 321 } 322 } 323 324 if ( *mcp == NULL ) { 325 retcode = META_SEARCH_ERR; 326 rc = LDAP_UNAVAILABLE; 327 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; 328 break; 329 } 330 /* fall thru */ 331 332 default: 333 other:; 334 /* convert rc to the correct LDAP error and send it back to the client: 335 assign the error to rs, so we can use it as argument to slap_map_api2result 336 and then assign the output back to rs->sr_err */ 337 rs->sr_err = rc; 338 rs->sr_err = slap_map_api2result( rs ); 339 340 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 341 meta_clear_one_candidate( op, mc, candidate ); 342 candidates[ candidate ].sr_err = rs->sr_err; 343 if ( META_BACK_ONERR_STOP( mi ) ) { 344 LDAP_BACK_CONN_TAINTED_SET( mc ); 345 meta_back_release_conn_lock( mi, mc, 0 ); 346 *mcp = NULL; 347 348 retcode = META_SEARCH_ERR; 349 350 } else { 351 retcode = META_SEARCH_NOT_CANDIDATE; 352 } 353 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; 354 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 355 break; 356 } 357 358 return retcode; 359 } 360 361 static meta_search_candidate_t 362 meta_search_dobind_result( 363 Operation *op, 364 SlapReply *rs, 365 metaconn_t **mcp, 366 int candidate, 367 SlapReply *candidates, 368 LDAPMessage *res ) 369 { 370 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; 371 metatarget_t *mt = mi->mi_targets[ candidate ]; 372 metaconn_t *mc = *mcp; 373 metasingleconn_t *msc = &mc->mc_conns[ candidate ]; 374 375 meta_search_candidate_t retcode = META_SEARCH_NOT_CANDIDATE; 376 int rc; 377 378 assert( msc->msc_ld != NULL ); 379 380 /* FIXME: matched? referrals? response controls? */ 381 rc = ldap_parse_result( msc->msc_ld, res, 382 &candidates[ candidate ].sr_err, 383 NULL, NULL, NULL, NULL, 0 ); 384 if ( rc != LDAP_SUCCESS ) { 385 candidates[ candidate ].sr_err = rc; 386 } 387 rc = slap_map_api2result( &candidates[ candidate ] ); 388 389 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 390 LDAP_BACK_CONN_BINDING_CLEAR( msc ); 391 if ( rc != LDAP_SUCCESS ) { 392 meta_clear_one_candidate( op, mc, candidate ); 393 candidates[ candidate ].sr_err = rc; 394 if ( META_BACK_ONERR_STOP( mi ) ) { 395 LDAP_BACK_CONN_TAINTED_SET( mc ); 396 meta_back_release_conn_lock( mi, mc, 0 ); 397 *mcp = NULL; 398 retcode = META_SEARCH_ERR; 399 rs->sr_err = rc; 400 } 401 402 } else { 403 /* FIXME: check if bound as idassert authcDN! */ 404 if ( BER_BVISNULL( &msc->msc_bound_ndn ) 405 || BER_BVISEMPTY( &msc->msc_bound_ndn ) ) 406 { 407 LDAP_BACK_CONN_ISANON_SET( msc ); 408 409 } else { 410 if ( META_BACK_TGT_SAVECRED( mt ) && 411 !BER_BVISNULL( &msc->msc_cred ) && 412 !BER_BVISEMPTY( &msc->msc_cred ) ) 413 { 414 ldap_set_rebind_proc( msc->msc_ld, mt->mt_rebind_f, msc ); 415 } 416 LDAP_BACK_CONN_ISBOUND_SET( msc ); 417 } 418 retcode = META_SEARCH_CANDIDATE; 419 420 /* connect must be async */ 421 ldap_set_option( msc->msc_ld, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_OFF ); 422 } 423 424 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; 425 META_BINDING_CLEAR( &candidates[ candidate ] ); 426 427 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 428 429 return retcode; 430 } 431 432 static meta_search_candidate_t 433 meta_back_search_start( 434 Operation *op, 435 SlapReply *rs, 436 dncookie *dc, 437 metaconn_t **mcp, 438 int candidate, 439 SlapReply *candidates, 440 struct berval *prcookie, 441 ber_int_t prsize ) 442 { 443 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; 444 metatarget_t *mt = mi->mi_targets[ candidate ]; 445 metasingleconn_t *msc = &(*mcp)->mc_conns[ candidate ]; 446 struct berval realbase = op->o_req_dn; 447 int realscope = op->ors_scope; 448 struct berval mbase = BER_BVNULL; 449 struct berval mfilter = BER_BVNULL; 450 char **mapped_attrs = NULL; 451 int rc; 452 meta_search_candidate_t retcode; 453 struct timeval tv, *tvp = NULL; 454 int nretries = 1; 455 LDAPControl **ctrls = NULL; 456 #ifdef SLAPD_META_CLIENT_PR 457 LDAPControl **save_ctrls = NULL; 458 #endif /* SLAPD_META_CLIENT_PR */ 459 460 /* this should not happen; just in case... */ 461 if ( msc->msc_ld == NULL ) { 462 Debug( LDAP_DEBUG_ANY, 463 "%s: meta_back_search_start candidate=%d ld=NULL%s.\n", 464 op->o_log_prefix, candidate, 465 META_BACK_ONERR_STOP( mi ) ? "" : " (ignored)" ); 466 candidates[ candidate ].sr_err = LDAP_OTHER; 467 if ( META_BACK_ONERR_STOP( mi ) ) { 468 return META_SEARCH_ERR; 469 } 470 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; 471 return META_SEARCH_NOT_CANDIDATE; 472 } 473 474 Debug( LDAP_DEBUG_TRACE, "%s >>> meta_back_search_start[%d]\n", op->o_log_prefix, candidate ); 475 476 /* 477 * modifies the base according to the scope, if required 478 */ 479 if ( mt->mt_nsuffix.bv_len > op->o_req_ndn.bv_len ) { 480 switch ( op->ors_scope ) { 481 case LDAP_SCOPE_SUBTREE: 482 /* 483 * make the target suffix the new base 484 * FIXME: this is very forgiving, because 485 * "illegal" searchBases may be turned 486 * into the suffix of the target; however, 487 * the requested searchBase already passed 488 * thru the candidate analyzer... 489 */ 490 if ( dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) { 491 realbase = mt->mt_nsuffix; 492 if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) { 493 realscope = LDAP_SCOPE_SUBORDINATE; 494 } 495 496 } else { 497 /* 498 * this target is no longer candidate 499 */ 500 retcode = META_SEARCH_NOT_CANDIDATE; 501 goto doreturn; 502 } 503 break; 504 505 case LDAP_SCOPE_SUBORDINATE: 506 case LDAP_SCOPE_ONELEVEL: 507 { 508 struct berval rdn = mt->mt_nsuffix; 509 rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," ); 510 if ( dnIsOneLevelRDN( &rdn ) 511 && dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) 512 { 513 /* 514 * if there is exactly one level, 515 * make the target suffix the new 516 * base, and make scope "base" 517 */ 518 realbase = mt->mt_nsuffix; 519 if ( op->ors_scope == LDAP_SCOPE_SUBORDINATE ) { 520 if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) { 521 realscope = LDAP_SCOPE_SUBORDINATE; 522 } else { 523 realscope = LDAP_SCOPE_SUBTREE; 524 } 525 } else { 526 realscope = LDAP_SCOPE_BASE; 527 } 528 break; 529 } /* else continue with the next case */ 530 } 531 532 case LDAP_SCOPE_BASE: 533 /* 534 * this target is no longer candidate 535 */ 536 retcode = META_SEARCH_NOT_CANDIDATE; 537 goto doreturn; 538 } 539 } 540 541 /* check filter expression */ 542 if ( mt->mt_filter ) { 543 metafilter_t *mf; 544 for ( mf = mt->mt_filter; mf; mf = mf->mf_next ) { 545 if ( regexec( &mf->mf_regex, op->ors_filterstr.bv_val, 0, NULL, 0 ) == 0 ) 546 break; 547 } 548 /* nothing matched, this target is no longer a candidate */ 549 if ( !mf ) { 550 retcode = META_SEARCH_NOT_CANDIDATE; 551 goto doreturn; 552 } 553 } 554 555 /* initiate dobind */ 556 retcode = meta_search_dobind_init( op, rs, mcp, candidate, candidates ); 557 558 Debug( LDAP_DEBUG_TRACE, "%s <<< meta_search_dobind_init[%d]=%d\n", op->o_log_prefix, candidate, retcode ); 559 560 if ( retcode != META_SEARCH_CANDIDATE ) { 561 goto doreturn; 562 } 563 564 /* 565 * Rewrite the search base, if required 566 */ 567 dc->target = mt; 568 dc->ctx = "searchBase"; 569 switch ( ldap_back_dn_massage( dc, &realbase, &mbase ) ) { 570 case LDAP_SUCCESS: 571 break; 572 573 case LDAP_UNWILLING_TO_PERFORM: 574 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 575 rs->sr_text = "Operation not allowed"; 576 send_ldap_result( op, rs ); 577 retcode = META_SEARCH_ERR; 578 goto doreturn; 579 580 default: 581 582 /* 583 * this target is no longer candidate 584 */ 585 retcode = META_SEARCH_NOT_CANDIDATE; 586 goto doreturn; 587 } 588 589 /* 590 * Maps filter 591 */ 592 rc = ldap_back_filter_map_rewrite( dc, op->ors_filter, 593 &mfilter, BACKLDAP_MAP, op->o_tmpmemctx ); 594 switch ( rc ) { 595 case LDAP_SUCCESS: 596 break; 597 598 case LDAP_COMPARE_FALSE: 599 default: 600 /* 601 * this target is no longer candidate 602 */ 603 retcode = META_SEARCH_NOT_CANDIDATE; 604 goto done; 605 } 606 607 /* 608 * Maps required attributes 609 */ 610 rc = ldap_back_map_attrs( op, &mt->mt_rwmap.rwm_at, 611 op->ors_attrs, BACKLDAP_MAP, &mapped_attrs ); 612 if ( rc != LDAP_SUCCESS ) { 613 /* 614 * this target is no longer candidate 615 */ 616 retcode = META_SEARCH_NOT_CANDIDATE; 617 goto done; 618 } 619 620 if ( op->ors_tlimit != SLAP_NO_LIMIT ) { 621 tv.tv_sec = op->ors_tlimit > 0 ? op->ors_tlimit : 1; 622 tv.tv_usec = 0; 623 tvp = &tv; 624 } 625 626 #ifdef SLAPD_META_CLIENT_PR 627 save_ctrls = op->o_ctrls; 628 { 629 LDAPControl *pr_c = NULL; 630 int i = 0, nc = 0; 631 632 if ( save_ctrls ) { 633 for ( ; save_ctrls[i] != NULL; i++ ); 634 nc = i; 635 pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, save_ctrls, NULL ); 636 } 637 638 if ( pr_c != NULL ) nc--; 639 if ( mt->mt_ps > 0 || prcookie != NULL ) nc++; 640 641 if ( mt->mt_ps > 0 || prcookie != NULL || pr_c != NULL ) { 642 int src = 0, dst = 0; 643 BerElementBuffer berbuf; 644 BerElement *ber = (BerElement *)&berbuf; 645 struct berval val = BER_BVNULL; 646 ber_len_t len; 647 648 len = sizeof( LDAPControl * )*( nc + 1 ) + sizeof( LDAPControl ); 649 650 if ( mt->mt_ps > 0 || prcookie != NULL ) { 651 struct berval nullcookie = BER_BVNULL; 652 ber_tag_t tag; 653 654 if ( prsize == 0 && mt->mt_ps > 0 ) prsize = mt->mt_ps; 655 if ( prcookie == NULL ) prcookie = &nullcookie; 656 657 ber_init2( ber, NULL, LBER_USE_DER ); 658 tag = ber_printf( ber, "{iO}", prsize, prcookie ); 659 if ( tag == LBER_ERROR ) { 660 /* error */ 661 (void) ber_free_buf( ber ); 662 goto done_pr; 663 } 664 665 tag = ber_flatten2( ber, &val, 0 ); 666 if ( tag == LBER_ERROR ) { 667 /* error */ 668 (void) ber_free_buf( ber ); 669 goto done_pr; 670 } 671 672 len += val.bv_len + 1; 673 } 674 675 op->o_ctrls = op->o_tmpalloc( len, op->o_tmpmemctx ); 676 if ( save_ctrls ) { 677 for ( ; save_ctrls[ src ] != NULL; src++ ) { 678 if ( save_ctrls[ src ] != pr_c ) { 679 op->o_ctrls[ dst ] = save_ctrls[ src ]; 680 dst++; 681 } 682 } 683 } 684 685 if ( mt->mt_ps > 0 || prcookie != NULL ) { 686 op->o_ctrls[ dst ] = (LDAPControl *)&op->o_ctrls[ nc + 1 ]; 687 688 op->o_ctrls[ dst ]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; 689 op->o_ctrls[ dst ]->ldctl_iscritical = 1; 690 691 op->o_ctrls[ dst ]->ldctl_value.bv_val = (char *)&op->o_ctrls[ dst ][ 1 ]; 692 AC_MEMCPY( op->o_ctrls[ dst ]->ldctl_value.bv_val, val.bv_val, val.bv_len + 1 ); 693 op->o_ctrls[ dst ]->ldctl_value.bv_len = val.bv_len; 694 dst++; 695 696 (void)ber_free_buf( ber ); 697 } 698 699 op->o_ctrls[ dst ] = NULL; 700 } 701 done_pr:; 702 } 703 #endif /* SLAPD_META_CLIENT_PR */ 704 705 retry:; 706 ctrls = op->o_ctrls; 707 if ( meta_back_controls_add( op, rs, *mcp, candidate, &ctrls ) 708 != LDAP_SUCCESS ) 709 { 710 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; 711 retcode = META_SEARCH_NOT_CANDIDATE; 712 goto done; 713 } 714 715 /* 716 * Starts the search 717 */ 718 assert( msc->msc_ld != NULL ); 719 rc = ldap_pvt_search( msc->msc_ld, 720 mbase.bv_val, realscope, mfilter.bv_val, 721 mapped_attrs, op->ors_attrsonly, 722 ctrls, NULL, tvp, op->ors_slimit, op->ors_deref, 723 &candidates[ candidate ].sr_msgid ); 724 switch ( rc ) { 725 case LDAP_SUCCESS: 726 retcode = META_SEARCH_CANDIDATE; 727 break; 728 729 case LDAP_SERVER_DOWN: 730 if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND, candidates ) ) { 731 nretries = 0; 732 /* if the identity changed, there might be need to re-authz */ 733 (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls ); 734 goto retry; 735 } 736 737 if ( *mcp == NULL ) { 738 retcode = META_SEARCH_ERR; 739 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; 740 break; 741 } 742 /* fall thru */ 743 744 default: 745 candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; 746 retcode = META_SEARCH_NOT_CANDIDATE; 747 } 748 749 done:; 750 (void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls ); 751 #ifdef SLAPD_META_CLIENT_PR 752 if ( save_ctrls != op->o_ctrls ) { 753 op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx ); 754 op->o_ctrls = save_ctrls; 755 } 756 #endif /* SLAPD_META_CLIENT_PR */ 757 758 if ( mapped_attrs ) { 759 ber_memfree_x( mapped_attrs, op->o_tmpmemctx ); 760 } 761 if ( mfilter.bv_val != op->ors_filterstr.bv_val ) { 762 ber_memfree_x( mfilter.bv_val, op->o_tmpmemctx ); 763 } 764 if ( mbase.bv_val != realbase.bv_val ) { 765 free( mbase.bv_val ); 766 } 767 768 doreturn:; 769 Debug( LDAP_DEBUG_TRACE, "%s <<< meta_back_search_start[%d]=%d\n", op->o_log_prefix, candidate, retcode ); 770 771 return retcode; 772 } 773 774 int 775 meta_back_search( Operation *op, SlapReply *rs ) 776 { 777 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; 778 metaconn_t *mc; 779 struct timeval save_tv = { 0, 0 }, 780 tv; 781 time_t stoptime = (time_t)(-1), 782 lastres_time = slap_get_time(), 783 timeout = 0; 784 int rc = 0, sres = LDAP_SUCCESS; 785 char *matched = NULL; 786 int last = 0, ncandidates = 0, 787 initial_candidates = 0, candidate_match = 0, 788 needbind = 0; 789 ldap_back_send_t sendok = LDAP_BACK_SENDERR; 790 long i; 791 dncookie dc; 792 int is_ok = 0; 793 void *savepriv; 794 SlapReply *candidates = NULL; 795 int do_taint = 0; 796 797 rs_assert_ready( rs ); 798 rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia, we can set rs = non-entry */ 799 800 /* 801 * controls are set in ldap_back_dobind() 802 * 803 * FIXME: in case of values return filter, we might want 804 * to map attrs and maybe rewrite value 805 */ 806 candidates = meta_back_candidates_get( op ); 807 getconn:; 808 mc = meta_back_getconn( op, rs, NULL, sendok, candidates ); 809 if ( !mc ) { 810 return rs->sr_err; 811 } 812 813 dc.conn = op->o_conn; 814 dc.rs = rs; 815 816 /* 817 * Inits searches 818 */ 819 for ( i = 0; i < mi->mi_ntargets; i++ ) { 820 /* reset sr_msgid; it is used in most loops 821 * to check if that target is still to be considered */ 822 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 823 824 /* a target is marked as candidate by meta_back_getconn(); 825 * if for any reason (an error, it's over or so) it is 826 * no longer active, sr_msgid is set to META_MSGID_IGNORE 827 * but it remains candidate, which means it has been active 828 * at some point during the operation. This allows to 829 * use its response code and more to compute the final 830 * response */ 831 if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) { 832 continue; 833 } 834 835 candidates[ i ].sr_matched = NULL; 836 candidates[ i ].sr_text = NULL; 837 candidates[ i ].sr_ref = NULL; 838 candidates[ i ].sr_ctrls = NULL; 839 candidates[ i ].sr_nentries = 0; 840 841 /* get largest timeout among candidates */ 842 if ( mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ] 843 && mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ] > timeout ) 844 { 845 timeout = mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ]; 846 } 847 } 848 849 for ( i = 0; i < mi->mi_ntargets; i++ ) { 850 if ( !META_IS_CANDIDATE( &candidates[ i ] ) 851 || candidates[ i ].sr_err != LDAP_SUCCESS ) 852 { 853 continue; 854 } 855 856 switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ) ) 857 { 858 case META_SEARCH_NOT_CANDIDATE: 859 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 860 break; 861 862 case META_SEARCH_NEED_BIND: 863 ++needbind; 864 /* fallthru */ 865 866 case META_SEARCH_CONNECTING: 867 case META_SEARCH_CANDIDATE: 868 case META_SEARCH_BINDING: 869 candidates[ i ].sr_type = REP_INTERMEDIATE; 870 ++ncandidates; 871 break; 872 873 case META_SEARCH_ERR: 874 savepriv = op->o_private; 875 op->o_private = (void *)i; 876 send_ldap_result( op, rs ); 877 op->o_private = savepriv; 878 rc = -1; 879 goto finish; 880 881 default: 882 assert( 0 ); 883 break; 884 } 885 } 886 887 if ( ncandidates > 0 && needbind == ncandidates ) { 888 /* 889 * give up the second time... 890 * 891 * NOTE: this should not occur the second time, since a fresh 892 * connection has ben created; however, targets may also 893 * need bind because the bind timed out or so. 894 */ 895 if ( sendok & LDAP_BACK_BINDING ) { 896 Debug( LDAP_DEBUG_ANY, 897 "%s meta_back_search: unable to initialize conn\n", 898 op->o_log_prefix ); 899 rs->sr_err = LDAP_UNAVAILABLE; 900 rs->sr_text = "unable to initialize connection to remote targets"; 901 send_ldap_result( op, rs ); 902 rc = -1; 903 goto finish; 904 } 905 906 /* FIXME: better create a separate connection? */ 907 sendok |= LDAP_BACK_BINDING; 908 909 #ifdef DEBUG_205 910 Debug( LDAP_DEBUG_ANY, "*** %s drop mc=%p create new connection\n", 911 op->o_log_prefix, (void *)mc ); 912 #endif /* DEBUG_205 */ 913 914 meta_back_release_conn( mi, mc ); 915 mc = NULL; 916 917 needbind = 0; 918 ncandidates = 0; 919 920 goto getconn; 921 } 922 923 initial_candidates = ncandidates; 924 925 if ( LogTest( LDAP_DEBUG_TRACE ) ) { 926 char cnd[ SLAP_TEXT_BUFLEN ]; 927 int c; 928 929 for ( c = 0; c < mi->mi_ntargets; c++ ) { 930 if ( META_IS_CANDIDATE( &candidates[ c ] ) ) { 931 cnd[ c ] = '*'; 932 } else { 933 cnd[ c ] = ' '; 934 } 935 } 936 cnd[ c ] = '\0'; 937 938 Debug( LDAP_DEBUG_TRACE, "%s meta_back_search: ncandidates=%d " 939 "cnd=\"%s\"\n", op->o_log_prefix, ncandidates, cnd ); 940 } 941 942 if ( initial_candidates == 0 ) { 943 /* NOTE: here we are not sending any matchedDN; 944 * this is intended, because if the back-meta 945 * is serving this search request, but no valid 946 * candidate could be looked up, it means that 947 * there is a hole in the mapping of the targets 948 * and thus no knowledge of any remote superior 949 * is available */ 950 Debug( LDAP_DEBUG_ANY, "%s meta_back_search: " 951 "base=\"%s\" scope=%d: " 952 "no candidate could be selected\n", 953 op->o_log_prefix, op->o_req_dn.bv_val, 954 op->ors_scope ); 955 956 /* FIXME: we're sending the first error we encounter; 957 * maybe we should pick the worst... */ 958 rc = LDAP_NO_SUCH_OBJECT; 959 for ( i = 0; i < mi->mi_ntargets; i++ ) { 960 if ( META_IS_CANDIDATE( &candidates[ i ] ) 961 && candidates[ i ].sr_err != LDAP_SUCCESS ) 962 { 963 rc = candidates[ i ].sr_err; 964 break; 965 } 966 } 967 968 send_ldap_error( op, rs, rc, NULL ); 969 970 goto finish; 971 } 972 973 /* We pull apart the ber result, stuff it into a slapd entry, and 974 * let send_search_entry stuff it back into ber format. Slow & ugly, 975 * but this is necessary for version matching, and for ACL processing. 976 */ 977 978 if ( op->ors_tlimit != SLAP_NO_LIMIT ) { 979 stoptime = op->o_time + op->ors_tlimit; 980 } 981 982 /* 983 * In case there are no candidates, no cycle takes place... 984 * 985 * FIXME: we might use a queue, to better balance the load 986 * among the candidates 987 */ 988 for ( rc = 0; ncandidates > 0; ) { 989 int gotit = 0, 990 doabandon = 0, 991 alreadybound = ncandidates; 992 993 /* check timeout */ 994 if ( timeout && lastres_time > 0 995 && ( slap_get_time() - lastres_time ) > timeout ) 996 { 997 doabandon = 1; 998 rs->sr_text = "Operation timed out"; 999 rc = rs->sr_err = op->o_protocol >= LDAP_VERSION3 ? 1000 LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER; 1001 savepriv = op->o_private; 1002 op->o_private = (void *)i; 1003 send_ldap_result( op, rs ); 1004 op->o_private = savepriv; 1005 goto finish; 1006 } 1007 1008 /* check time limit */ 1009 if ( op->ors_tlimit != SLAP_NO_LIMIT 1010 && slap_get_time() > stoptime ) 1011 { 1012 doabandon = 1; 1013 rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED; 1014 savepriv = op->o_private; 1015 op->o_private = (void *)i; 1016 send_ldap_result( op, rs ); 1017 op->o_private = savepriv; 1018 goto finish; 1019 } 1020 1021 for ( i = 0; i < mi->mi_ntargets; i++ ) { 1022 meta_search_candidate_t retcode = META_SEARCH_UNDEFINED; 1023 metasingleconn_t *msc = &mc->mc_conns[ i ]; 1024 LDAPMessage *res = NULL, *msg; 1025 1026 /* if msgid is invalid, don't ldap_result() */ 1027 if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) { 1028 continue; 1029 } 1030 1031 /* if target still needs bind, retry */ 1032 if ( candidates[ i ].sr_msgid == META_MSGID_NEED_BIND 1033 || candidates[ i ].sr_msgid == META_MSGID_CONNECTING ) 1034 { 1035 /* initiate dobind */ 1036 retcode = meta_search_dobind_init( op, rs, &mc, i, candidates ); 1037 1038 Debug( LDAP_DEBUG_TRACE, "%s <<< meta_search_dobind_init[%ld]=%d\n", 1039 op->o_log_prefix, i, retcode ); 1040 1041 switch ( retcode ) { 1042 case META_SEARCH_NEED_BIND: 1043 alreadybound--; 1044 /* fallthru */ 1045 1046 case META_SEARCH_CONNECTING: 1047 case META_SEARCH_BINDING: 1048 break; 1049 1050 case META_SEARCH_ERR: 1051 candidates[ i ].sr_err = rs->sr_err; 1052 if ( META_BACK_ONERR_STOP( mi ) ) { 1053 savepriv = op->o_private; 1054 op->o_private = (void *)i; 1055 send_ldap_result( op, rs ); 1056 op->o_private = savepriv; 1057 goto finish; 1058 } 1059 /* fallthru */ 1060 1061 case META_SEARCH_NOT_CANDIDATE: 1062 /* 1063 * When no candidates are left, 1064 * the outer cycle finishes 1065 */ 1066 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1067 assert( ncandidates > 0 ); 1068 --ncandidates; 1069 break; 1070 1071 case META_SEARCH_CANDIDATE: 1072 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1073 switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ) ) 1074 { 1075 case META_SEARCH_CANDIDATE: 1076 assert( candidates[ i ].sr_msgid >= 0 ); 1077 break; 1078 1079 case META_SEARCH_ERR: 1080 candidates[ i ].sr_err = rs->sr_err; 1081 if ( META_BACK_ONERR_STOP( mi ) ) { 1082 savepriv = op->o_private; 1083 op->o_private = (void *)i; 1084 send_ldap_result( op, rs ); 1085 op->o_private = savepriv; 1086 goto finish; 1087 } 1088 /* fallthru */ 1089 1090 case META_SEARCH_NOT_CANDIDATE: 1091 /* means that meta_back_search_start() 1092 * failed but onerr == continue */ 1093 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1094 assert( ncandidates > 0 ); 1095 --ncandidates; 1096 break; 1097 1098 default: 1099 /* impossible */ 1100 assert( 0 ); 1101 break; 1102 } 1103 break; 1104 1105 default: 1106 /* impossible */ 1107 assert( 0 ); 1108 break; 1109 } 1110 continue; 1111 } 1112 1113 /* check for abandon */ 1114 if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) { 1115 break; 1116 } 1117 1118 #ifdef DEBUG_205 1119 if ( msc->msc_ld == NULL ) { 1120 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 1121 Debug(LDAP_DEBUG_ANY, 1122 "!!! %s meta_back_search[%ld] mc=%p msgid=%d%s%s%s\n\n", 1123 op->o_log_prefix, (long)i, (void *)mc, 1124 candidates[i].sr_msgid, 1125 META_IS_BINDING(&candidates[i]) ? " binding" : "", 1126 LDAP_BACK_CONN_BINDING(&mc->mc_conns[i]) ? " connbinding" : "", 1127 META_BACK_CONN_CREATING(&mc->mc_conns[i]) ? " conncreating" : "" ); 1128 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 1129 } 1130 #endif /* DEBUG_205 */ 1131 1132 /* 1133 * FIXME: handle time limit as well? 1134 * Note that target servers are likely 1135 * to handle it, so at some time we'll 1136 * get a LDAP_TIMELIMIT_EXCEEDED from 1137 * one of them ... 1138 */ 1139 tv = save_tv; 1140 rc = ldap_result( msc->msc_ld, candidates[ i ].sr_msgid, 1141 LDAP_MSG_RECEIVED, &tv, &res ); 1142 switch ( rc ) { 1143 case 0: 1144 /* FIXME: res should not need to be freed */ 1145 assert( res == NULL ); 1146 continue; 1147 1148 case -1: 1149 really_bad:; 1150 /* something REALLY bad happened! */ 1151 if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { 1152 candidates[ i ].sr_type = REP_RESULT; 1153 1154 if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND, candidates ) ) { 1155 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1156 switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ) ) 1157 { 1158 /* means that failed but onerr == continue */ 1159 case META_SEARCH_NOT_CANDIDATE: 1160 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1161 1162 assert( ncandidates > 0 ); 1163 --ncandidates; 1164 1165 candidates[ i ].sr_err = rs->sr_err; 1166 if ( META_BACK_ONERR_STOP( mi ) ) { 1167 savepriv = op->o_private; 1168 op->o_private = (void *)i; 1169 send_ldap_result( op, rs ); 1170 op->o_private = savepriv; 1171 goto finish; 1172 } 1173 /* fall thru */ 1174 1175 case META_SEARCH_CANDIDATE: 1176 /* get back into business... */ 1177 continue; 1178 1179 case META_SEARCH_BINDING: 1180 case META_SEARCH_CONNECTING: 1181 case META_SEARCH_NEED_BIND: 1182 case META_SEARCH_UNDEFINED: 1183 assert( 0 ); 1184 1185 default: 1186 /* unrecoverable error */ 1187 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1188 rc = rs->sr_err = LDAP_OTHER; 1189 goto finish; 1190 } 1191 } 1192 1193 candidates[ i ].sr_err = rs->sr_err; 1194 if ( META_BACK_ONERR_STOP( mi ) ) { 1195 savepriv = op->o_private; 1196 op->o_private = (void *)i; 1197 send_ldap_result( op, rs ); 1198 op->o_private = savepriv; 1199 goto finish; 1200 } 1201 } 1202 1203 /* 1204 * When no candidates are left, 1205 * the outer cycle finishes 1206 */ 1207 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1208 assert( ncandidates > 0 ); 1209 --ncandidates; 1210 rs->sr_err = candidates[ i ].sr_err; 1211 continue; 1212 1213 default: 1214 lastres_time = slap_get_time(); 1215 1216 /* only touch when activity actually took place... */ 1217 if ( mi->mi_idle_timeout != 0 && msc->msc_time < lastres_time ) { 1218 msc->msc_time = lastres_time; 1219 } 1220 break; 1221 } 1222 1223 for ( msg = ldap_first_message( msc->msc_ld, res ); 1224 msg != NULL; 1225 msg = ldap_next_message( msc->msc_ld, msg ) ) 1226 { 1227 rc = ldap_msgtype( msg ); 1228 if ( rc == LDAP_RES_SEARCH_ENTRY ) { 1229 LDAPMessage *e; 1230 1231 if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { 1232 /* don't retry any more... */ 1233 candidates[ i ].sr_type = REP_RESULT; 1234 } 1235 1236 /* count entries returned by target */ 1237 candidates[ i ].sr_nentries++; 1238 1239 is_ok++; 1240 1241 e = ldap_first_entry( msc->msc_ld, msg ); 1242 savepriv = op->o_private; 1243 op->o_private = (void *)i; 1244 rs->sr_err = meta_send_entry( op, rs, mc, i, e ); 1245 1246 switch ( rs->sr_err ) { 1247 case LDAP_SIZELIMIT_EXCEEDED: 1248 savepriv = op->o_private; 1249 op->o_private = (void *)i; 1250 send_ldap_result( op, rs ); 1251 op->o_private = savepriv; 1252 rs->sr_err = LDAP_SUCCESS; 1253 ldap_msgfree( res ); 1254 res = NULL; 1255 goto finish; 1256 1257 case LDAP_UNAVAILABLE: 1258 rs->sr_err = LDAP_OTHER; 1259 ldap_msgfree( res ); 1260 res = NULL; 1261 goto finish; 1262 } 1263 op->o_private = savepriv; 1264 1265 /* don't wait any longer... */ 1266 gotit = 1; 1267 save_tv.tv_sec = 0; 1268 save_tv.tv_usec = 0; 1269 1270 } else if ( rc == LDAP_RES_SEARCH_REFERENCE ) { 1271 char **references = NULL; 1272 int cnt; 1273 1274 if ( META_BACK_TGT_NOREFS( mi->mi_targets[ i ] ) ) { 1275 continue; 1276 } 1277 1278 if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { 1279 /* don't retry any more... */ 1280 candidates[ i ].sr_type = REP_RESULT; 1281 } 1282 1283 is_ok++; 1284 1285 rc = ldap_parse_reference( msc->msc_ld, msg, 1286 &references, &rs->sr_ctrls, 0 ); 1287 1288 if ( rc != LDAP_SUCCESS ) { 1289 continue; 1290 } 1291 1292 if ( references == NULL ) { 1293 continue; 1294 } 1295 1296 dc.ctx = "referralDN"; 1297 1298 /* FIXME: merge all and return at the end */ 1299 1300 for ( cnt = 0; references[ cnt ]; cnt++ ) 1301 ; 1302 1303 rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( cnt + 1 ), 1304 op->o_tmpmemctx ); 1305 1306 for ( cnt = 0; references[ cnt ]; cnt++ ) { 1307 ber_str2bv_x( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ], 1308 op->o_tmpmemctx ); 1309 } 1310 BER_BVZERO( &rs->sr_ref[ cnt ] ); 1311 1312 ( void )ldap_back_referral_result_rewrite( &dc, rs->sr_ref, 1313 op->o_tmpmemctx ); 1314 1315 if ( rs->sr_ref != NULL && !BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) { 1316 /* ignore return value by now */ 1317 savepriv = op->o_private; 1318 op->o_private = (void *)i; 1319 ( void )send_search_reference( op, rs ); 1320 op->o_private = savepriv; 1321 1322 ber_bvarray_free_x( rs->sr_ref, op->o_tmpmemctx ); 1323 rs->sr_ref = NULL; 1324 } 1325 1326 /* cleanup */ 1327 if ( references ) { 1328 ber_memvfree( (void **)references ); 1329 } 1330 1331 if ( rs->sr_ctrls ) { 1332 ldap_controls_free( rs->sr_ctrls ); 1333 rs->sr_ctrls = NULL; 1334 } 1335 1336 } else if ( rc == LDAP_RES_INTERMEDIATE ) { 1337 if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { 1338 /* don't retry any more... */ 1339 candidates[ i ].sr_type = REP_RESULT; 1340 } 1341 1342 /* FIXME: response controls 1343 * are passed without checks */ 1344 rs->sr_err = ldap_parse_intermediate( msc->msc_ld, 1345 msg, 1346 (char **)&rs->sr_rspoid, 1347 &rs->sr_rspdata, 1348 &rs->sr_ctrls, 1349 0 ); 1350 if ( rs->sr_err != LDAP_SUCCESS ) { 1351 candidates[ i ].sr_type = REP_RESULT; 1352 ldap_msgfree( res ); 1353 res = NULL; 1354 goto really_bad; 1355 } 1356 1357 slap_send_ldap_intermediate( op, rs ); 1358 1359 if ( rs->sr_rspoid != NULL ) { 1360 ber_memfree( (char *)rs->sr_rspoid ); 1361 rs->sr_rspoid = NULL; 1362 } 1363 1364 if ( rs->sr_rspdata != NULL ) { 1365 ber_bvfree( rs->sr_rspdata ); 1366 rs->sr_rspdata = NULL; 1367 } 1368 1369 if ( rs->sr_ctrls != NULL ) { 1370 ldap_controls_free( rs->sr_ctrls ); 1371 rs->sr_ctrls = NULL; 1372 } 1373 1374 } else if ( rc == LDAP_RES_SEARCH_RESULT ) { 1375 char **references = NULL; 1376 LDAPControl **ctrls = NULL; 1377 1378 if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { 1379 /* don't retry any more... */ 1380 candidates[ i ].sr_type = REP_RESULT; 1381 } 1382 1383 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1384 1385 /* NOTE: ignores response controls 1386 * (and intermediate response controls 1387 * as well, except for those with search 1388 * references); this may not be correct, 1389 * but if they're not ignored then 1390 * back-meta would need to merge them 1391 * consistently (think of pagedResults...) 1392 */ 1393 /* FIXME: response controls? */ 1394 rs->sr_err = ldap_parse_result( msc->msc_ld, 1395 msg, 1396 &candidates[ i ].sr_err, 1397 (char **)&candidates[ i ].sr_matched, 1398 (char **)&candidates[ i ].sr_text, 1399 &references, 1400 &ctrls /* &candidates[ i ].sr_ctrls (unused) */ , 1401 0 ); 1402 if ( rs->sr_err != LDAP_SUCCESS ) { 1403 candidates[ i ].sr_err = rs->sr_err; 1404 sres = slap_map_api2result( &candidates[ i ] ); 1405 candidates[ i ].sr_type = REP_RESULT; 1406 ldap_msgfree( res ); 1407 res = NULL; 1408 goto really_bad; 1409 } 1410 1411 rs->sr_err = candidates[ i ].sr_err; 1412 1413 /* massage matchedDN if need be */ 1414 if ( candidates[ i ].sr_matched != NULL ) { 1415 struct berval match, mmatch; 1416 1417 ber_str2bv( candidates[ i ].sr_matched, 1418 0, 0, &match ); 1419 candidates[ i ].sr_matched = NULL; 1420 1421 dc.ctx = "matchedDN"; 1422 dc.target = mi->mi_targets[ i ]; 1423 if ( !ldap_back_dn_massage( &dc, &match, &mmatch ) ) { 1424 if ( mmatch.bv_val == match.bv_val ) { 1425 candidates[ i ].sr_matched 1426 = ch_strdup( mmatch.bv_val ); 1427 1428 } else { 1429 candidates[ i ].sr_matched = mmatch.bv_val; 1430 } 1431 1432 candidate_match++; 1433 } 1434 ldap_memfree( match.bv_val ); 1435 } 1436 1437 /* add references to array */ 1438 /* RFC 4511: referrals can only appear 1439 * if result code is LDAP_REFERRAL */ 1440 if ( references != NULL 1441 && references[ 0 ] != NULL 1442 && references[ 0 ][ 0 ] != '\0' ) 1443 { 1444 if ( rs->sr_err != LDAP_REFERRAL ) { 1445 Debug( LDAP_DEBUG_ANY, 1446 "%s meta_back_search[%ld]: " 1447 "got referrals with err=%d\n", 1448 op->o_log_prefix, 1449 i, rs->sr_err ); 1450 1451 } else { 1452 BerVarray sr_ref; 1453 int cnt; 1454 1455 for ( cnt = 0; references[ cnt ]; cnt++ ) 1456 ; 1457 1458 sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( cnt + 1 ), 1459 op->o_tmpmemctx ); 1460 1461 for ( cnt = 0; references[ cnt ]; cnt++ ) { 1462 ber_str2bv_x( references[ cnt ], 0, 1, &sr_ref[ cnt ], 1463 op->o_tmpmemctx ); 1464 } 1465 BER_BVZERO( &sr_ref[ cnt ] ); 1466 1467 ( void )ldap_back_referral_result_rewrite( &dc, sr_ref, 1468 op->o_tmpmemctx ); 1469 1470 if ( rs->sr_v2ref == NULL ) { 1471 rs->sr_v2ref = sr_ref; 1472 1473 } else { 1474 for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) { 1475 ber_bvarray_add_x( &rs->sr_v2ref, &sr_ref[ cnt ], 1476 op->o_tmpmemctx ); 1477 } 1478 ber_memfree_x( sr_ref, op->o_tmpmemctx ); 1479 } 1480 } 1481 1482 } else if ( rs->sr_err == LDAP_REFERRAL ) { 1483 Debug( LDAP_DEBUG_ANY, 1484 "%s meta_back_search[%ld]: " 1485 "got err=%d with null " 1486 "or empty referrals\n", 1487 op->o_log_prefix, 1488 i, rs->sr_err ); 1489 1490 rs->sr_err = LDAP_NO_SUCH_OBJECT; 1491 } 1492 1493 /* cleanup */ 1494 ber_memvfree( (void **)references ); 1495 1496 sres = slap_map_api2result( rs ); 1497 1498 if ( LogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) { 1499 char buf[ SLAP_TEXT_BUFLEN ]; 1500 snprintf( buf, sizeof( buf ), 1501 "%s meta_back_search[%ld] " 1502 "match=\"%s\" err=%ld", 1503 op->o_log_prefix, i, 1504 candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "", 1505 (long) candidates[ i ].sr_err ); 1506 if ( candidates[ i ].sr_err == LDAP_SUCCESS ) { 1507 Debug( LDAP_DEBUG_TRACE, "%s.\n", buf ); 1508 1509 } else { 1510 Debug( LDAP_DEBUG_ANY, "%s (%s) text=\"%s\".\n", 1511 buf, ldap_err2string( candidates[ i ].sr_err ), 1512 candidates[ i ].sr_text ? candidates[i].sr_text : "" ); 1513 } 1514 } 1515 1516 switch ( sres ) { 1517 case LDAP_NO_SUCH_OBJECT: 1518 /* is_ok is touched any time a valid 1519 * (even intermediate) result is 1520 * returned; as a consequence, if 1521 * a candidate returns noSuchObject 1522 * it is ignored and the candidate 1523 * is simply demoted. */ 1524 if ( is_ok ) { 1525 sres = LDAP_SUCCESS; 1526 } 1527 break; 1528 1529 case LDAP_SUCCESS: 1530 if ( ctrls != NULL && ctrls[0] != NULL ) { 1531 #ifdef SLAPD_META_CLIENT_PR 1532 LDAPControl *pr_c; 1533 1534 pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL ); 1535 if ( pr_c != NULL ) { 1536 BerElementBuffer berbuf; 1537 BerElement *ber = (BerElement *)&berbuf; 1538 ber_tag_t tag; 1539 ber_int_t prsize; 1540 struct berval prcookie; 1541 1542 /* unsolicited, do not accept */ 1543 if ( mi->mi_targets[i]->mt_ps == 0 ) { 1544 rs->sr_err = LDAP_OTHER; 1545 goto err_pr; 1546 } 1547 1548 ber_init2( ber, &pr_c->ldctl_value, LBER_USE_DER ); 1549 1550 tag = ber_scanf( ber, "{im}", &prsize, &prcookie ); 1551 if ( tag == LBER_ERROR ) { 1552 rs->sr_err = LDAP_OTHER; 1553 goto err_pr; 1554 } 1555 1556 /* more pages? new search request */ 1557 if ( !BER_BVISNULL( &prcookie ) && !BER_BVISEMPTY( &prcookie ) ) { 1558 if ( mi->mi_targets[i]->mt_ps > 0 ) { 1559 /* ignore size if specified */ 1560 prsize = 0; 1561 1562 } else if ( prsize == 0 ) { 1563 /* guess the page size from the entries returned so far */ 1564 prsize = candidates[ i ].sr_nentries; 1565 } 1566 1567 candidates[ i ].sr_nentries = 0; 1568 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1569 candidates[ i ].sr_type = REP_INTERMEDIATE; 1570 1571 assert( candidates[ i ].sr_matched == NULL ); 1572 assert( candidates[ i ].sr_text == NULL ); 1573 assert( candidates[ i ].sr_ref == NULL ); 1574 1575 switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, &prcookie, prsize ) ) 1576 { 1577 case META_SEARCH_CANDIDATE: 1578 assert( candidates[ i ].sr_msgid >= 0 ); 1579 ldap_controls_free( ctrls ); 1580 goto free_message; 1581 1582 case META_SEARCH_ERR: 1583 err_pr:; 1584 candidates[ i ].sr_err = rs->sr_err; 1585 if ( META_BACK_ONERR_STOP( mi ) ) { 1586 savepriv = op->o_private; 1587 op->o_private = (void *)i; 1588 send_ldap_result( op, rs ); 1589 op->o_private = savepriv; 1590 ldap_controls_free( ctrls ); 1591 goto finish; 1592 } 1593 /* fallthru */ 1594 1595 case META_SEARCH_NOT_CANDIDATE: 1596 /* means that meta_back_search_start() 1597 * failed but onerr == continue */ 1598 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1599 assert( ncandidates > 0 ); 1600 --ncandidates; 1601 break; 1602 1603 default: 1604 /* impossible */ 1605 assert( 0 ); 1606 break; 1607 } 1608 break; 1609 } 1610 } 1611 #endif /* SLAPD_META_CLIENT_PR */ 1612 } 1613 /* fallthru */ 1614 1615 case LDAP_REFERRAL: 1616 is_ok++; 1617 break; 1618 1619 case LDAP_SIZELIMIT_EXCEEDED: 1620 /* if a target returned sizelimitExceeded 1621 * and the entry count is equal to the 1622 * proxy's limit, the target would have 1623 * returned more, and the error must be 1624 * propagated to the client; otherwise, 1625 * the target enforced a limit lower 1626 * than what requested by the proxy; 1627 * ignore it */ 1628 candidates[ i ].sr_err = rs->sr_err; 1629 if ( rs->sr_nentries == op->ors_slimit 1630 || META_BACK_ONERR_STOP( mi ) ) 1631 { 1632 const char *save_text; 1633 got_err: 1634 save_text = rs->sr_text; 1635 savepriv = op->o_private; 1636 op->o_private = (void *)i; 1637 rs->sr_text = candidates[ i ].sr_text; 1638 send_ldap_result( op, rs ); 1639 rs->sr_text = save_text; 1640 op->o_private = savepriv; 1641 ldap_msgfree( res ); 1642 res = NULL; 1643 ldap_controls_free( ctrls ); 1644 goto finish; 1645 } 1646 break; 1647 1648 default: 1649 candidates[ i ].sr_err = rs->sr_err; 1650 if ( META_BACK_ONERR_STOP( mi ) ) 1651 goto got_err; 1652 break; 1653 } 1654 1655 ldap_controls_free( ctrls ); 1656 last = i; 1657 rc = 0; 1658 1659 /* 1660 * When no candidates are left, 1661 * the outer cycle finishes 1662 */ 1663 assert( ncandidates > 0 ); 1664 --ncandidates; 1665 1666 } else if ( rc == LDAP_RES_BIND ) { 1667 meta_search_candidate_t retcode; 1668 1669 retcode = meta_search_dobind_result( op, rs, &mc, i, candidates, msg ); 1670 if ( retcode == META_SEARCH_CANDIDATE ) { 1671 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1672 retcode = meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ); 1673 } 1674 1675 switch ( retcode ) { 1676 case META_SEARCH_CANDIDATE: 1677 break; 1678 1679 /* means that failed but onerr == continue */ 1680 case META_SEARCH_NOT_CANDIDATE: 1681 case META_SEARCH_ERR: 1682 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1683 assert( ncandidates > 0 ); 1684 --ncandidates; 1685 1686 candidates[ i ].sr_err = rs->sr_err; 1687 if ( META_BACK_ONERR_STOP( mi ) ) { 1688 savepriv = op->o_private; 1689 op->o_private = (void *)i; 1690 send_ldap_result( op, rs ); 1691 op->o_private = savepriv; 1692 ldap_msgfree( res ); 1693 res = NULL; 1694 goto finish; 1695 } 1696 goto free_message; 1697 1698 default: 1699 assert( 0 ); 1700 break; 1701 } 1702 1703 } else { 1704 Debug( LDAP_DEBUG_ANY, 1705 "%s meta_back_search[%ld]: " 1706 "unrecognized response message tag=%d\n", 1707 op->o_log_prefix, 1708 i, rc ); 1709 1710 ldap_msgfree( res ); 1711 res = NULL; 1712 goto really_bad; 1713 } 1714 } 1715 1716 free_message:; 1717 ldap_msgfree( res ); 1718 res = NULL; 1719 } 1720 1721 /* check for abandon */ 1722 if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) { 1723 for ( i = 0; i < mi->mi_ntargets; i++ ) { 1724 if ( candidates[ i ].sr_msgid >= 0 1725 || candidates[ i ].sr_msgid == META_MSGID_CONNECTING ) 1726 { 1727 if ( META_IS_BINDING( &candidates[ i ] ) 1728 || candidates[ i ].sr_msgid == META_MSGID_CONNECTING ) 1729 { 1730 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 1731 if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) 1732 || candidates[ i ].sr_msgid == META_MSGID_CONNECTING ) 1733 { 1734 /* if still binding, destroy */ 1735 1736 #ifdef DEBUG_205 1737 Debug(LDAP_DEBUG_ANY, 1738 "### %s meta_back_search(abandon) " "ldap_unbind_ext[%ld] mc=%p ld=%p\n", 1739 op->o_log_prefix, 1740 i, (void *)mc, 1741 (void *)mc->mc_conns[i].msc_ld ); 1742 #endif /* DEBUG_205 */ 1743 1744 meta_clear_one_candidate( op, mc, i ); 1745 } 1746 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 1747 META_BINDING_CLEAR( &candidates[ i ] ); 1748 1749 } else { 1750 (void)meta_back_cancel( mc, op, rs, 1751 candidates[ i ].sr_msgid, i, 1752 LDAP_BACK_DONTSEND ); 1753 } 1754 1755 candidates[ i ].sr_msgid = META_MSGID_IGNORE; 1756 assert( ncandidates > 0 ); 1757 --ncandidates; 1758 } 1759 } 1760 1761 if ( op->o_abandon ) { 1762 rc = SLAPD_ABANDON; 1763 } 1764 1765 /* let send_ldap_result play cleanup handlers (ITS#4645) */ 1766 break; 1767 } 1768 1769 /* if no entry was found during this loop, 1770 * set a minimal timeout */ 1771 if ( ncandidates > 0 && gotit == 0 ) { 1772 if ( save_tv.tv_sec == 0 && save_tv.tv_usec == 0 ) { 1773 save_tv.tv_usec = LDAP_BACK_RESULT_UTIMEOUT/initial_candidates; 1774 1775 /* arbitrarily limit to something between 1 and 2 minutes */ 1776 } else if ( ( stoptime == -1 && save_tv.tv_sec < 60 ) 1777 || save_tv.tv_sec < ( stoptime - slap_get_time() ) / ( 2 * ncandidates ) ) 1778 { 1779 /* double the timeout */ 1780 lutil_timermul( &save_tv, 2, &save_tv ); 1781 } 1782 1783 if ( alreadybound == 0 ) { 1784 tv = save_tv; 1785 (void)select( 0, NULL, NULL, NULL, &tv ); 1786 1787 } else { 1788 ldap_pvt_thread_yield(); 1789 } 1790 } 1791 } 1792 1793 if ( rc == -1 ) { 1794 /* 1795 * FIXME: need a better strategy to handle errors 1796 */ 1797 if ( mc ) { 1798 rc = meta_back_op_result( mc, op, rs, META_TARGET_NONE, 1799 -1, stoptime != -1 ? (stoptime - slap_get_time()) : 0, 1800 LDAP_BACK_SENDERR ); 1801 } else { 1802 rc = rs->sr_err; 1803 } 1804 goto finish; 1805 } 1806 1807 /* 1808 * Rewrite the matched portion of the search base, if required 1809 * 1810 * FIXME: only the last one gets caught! 1811 */ 1812 savepriv = op->o_private; 1813 op->o_private = (void *)(long)mi->mi_ntargets; 1814 if ( candidate_match > 0 ) { 1815 struct berval pmatched = BER_BVNULL; 1816 1817 /* we use the first one */ 1818 for ( i = 0; i < mi->mi_ntargets; i++ ) { 1819 if ( META_IS_CANDIDATE( &candidates[ i ] ) 1820 && candidates[ i ].sr_matched != NULL ) 1821 { 1822 struct berval bv, pbv; 1823 int rc; 1824 1825 /* if we got success, and this target 1826 * returned noSuchObject, and its suffix 1827 * is a superior of the searchBase, 1828 * ignore the matchedDN */ 1829 if ( sres == LDAP_SUCCESS 1830 && candidates[ i ].sr_err == LDAP_NO_SUCH_OBJECT 1831 && op->o_req_ndn.bv_len > mi->mi_targets[ i ]->mt_nsuffix.bv_len ) 1832 { 1833 free( (char *)candidates[ i ].sr_matched ); 1834 candidates[ i ].sr_matched = NULL; 1835 continue; 1836 } 1837 1838 ber_str2bv( candidates[ i ].sr_matched, 0, 0, &bv ); 1839 rc = dnPretty( NULL, &bv, &pbv, op->o_tmpmemctx ); 1840 1841 if ( rc == LDAP_SUCCESS ) { 1842 1843 /* NOTE: if they all are superiors 1844 * of the baseDN, the shorter is also 1845 * superior of the longer... */ 1846 if ( pbv.bv_len > pmatched.bv_len ) { 1847 if ( !BER_BVISNULL( &pmatched ) ) { 1848 op->o_tmpfree( pmatched.bv_val, op->o_tmpmemctx ); 1849 } 1850 pmatched = pbv; 1851 op->o_private = (void *)i; 1852 1853 } else { 1854 op->o_tmpfree( pbv.bv_val, op->o_tmpmemctx ); 1855 } 1856 } 1857 1858 if ( candidates[ i ].sr_matched != NULL ) { 1859 free( (char *)candidates[ i ].sr_matched ); 1860 candidates[ i ].sr_matched = NULL; 1861 } 1862 } 1863 } 1864 1865 if ( !BER_BVISNULL( &pmatched ) ) { 1866 matched = pmatched.bv_val; 1867 } 1868 1869 } else if ( sres == LDAP_NO_SUCH_OBJECT ) { 1870 matched = op->o_bd->be_suffix[ 0 ].bv_val; 1871 } 1872 1873 /* 1874 * In case we returned at least one entry, we return LDAP_SUCCESS 1875 * otherwise, the latter error code we got 1876 */ 1877 1878 if ( sres == LDAP_SUCCESS ) { 1879 if ( rs->sr_v2ref ) { 1880 sres = LDAP_REFERRAL; 1881 } 1882 1883 if ( META_BACK_ONERR_REPORT( mi ) ) { 1884 /* 1885 * Report errors, if any 1886 * 1887 * FIXME: we should handle error codes and return the more 1888 * important/reasonable 1889 */ 1890 for ( i = 0; i < mi->mi_ntargets; i++ ) { 1891 if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) { 1892 continue; 1893 } 1894 1895 if ( candidates[ i ].sr_err != LDAP_SUCCESS 1896 && candidates[ i ].sr_err != LDAP_NO_SUCH_OBJECT ) 1897 { 1898 sres = candidates[ i ].sr_err; 1899 break; 1900 } 1901 } 1902 } 1903 } 1904 1905 rs->sr_err = sres; 1906 rs->sr_matched = ( sres == LDAP_SUCCESS ? NULL : matched ); 1907 rs->sr_ref = ( sres == LDAP_REFERRAL ? rs->sr_v2ref : NULL ); 1908 send_ldap_result( op, rs ); 1909 op->o_private = savepriv; 1910 rs->sr_matched = NULL; 1911 rs->sr_ref = NULL; 1912 1913 finish:; 1914 if ( matched && matched != op->o_bd->be_suffix[ 0 ].bv_val ) { 1915 op->o_tmpfree( matched, op->o_tmpmemctx ); 1916 } 1917 1918 if ( rs->sr_v2ref ) { 1919 ber_bvarray_free_x( rs->sr_v2ref, op->o_tmpmemctx ); 1920 } 1921 1922 for ( i = 0; i < mi->mi_ntargets; i++ ) { 1923 if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) { 1924 continue; 1925 } 1926 1927 if ( mc ) { 1928 if ( META_IS_BINDING( &candidates[ i ] ) 1929 || candidates[ i ].sr_msgid == META_MSGID_CONNECTING ) 1930 { 1931 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 1932 if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) 1933 || candidates[ i ].sr_msgid == META_MSGID_CONNECTING ) 1934 { 1935 assert( candidates[ i ].sr_msgid >= 0 1936 || candidates[ i ].sr_msgid == META_MSGID_CONNECTING ); 1937 assert( mc->mc_conns[ i ].msc_ld != NULL ); 1938 1939 #ifdef DEBUG_205 1940 Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(cleanup) " 1941 "ldap_unbind_ext[%ld] ld=%p\n", 1942 op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld ); 1943 #endif /* DEBUG_205 */ 1944 1945 /* if still binding, destroy */ 1946 meta_clear_one_candidate( op, mc, i ); 1947 } 1948 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 1949 META_BINDING_CLEAR( &candidates[ i ] ); 1950 1951 } else if ( candidates[ i ].sr_msgid >= 0 ) { 1952 (void)meta_back_cancel( mc, op, rs, 1953 candidates[ i ].sr_msgid, i, 1954 LDAP_BACK_DONTSEND ); 1955 } 1956 } 1957 1958 if ( candidates[ i ].sr_matched ) { 1959 free( (char *)candidates[ i ].sr_matched ); 1960 candidates[ i ].sr_matched = NULL; 1961 } 1962 1963 if ( candidates[ i ].sr_text ) { 1964 ldap_memfree( (char *)candidates[ i ].sr_text ); 1965 candidates[ i ].sr_text = NULL; 1966 } 1967 1968 if ( candidates[ i ].sr_ref ) { 1969 ber_bvarray_free( candidates[ i ].sr_ref ); 1970 candidates[ i ].sr_ref = NULL; 1971 } 1972 1973 if ( candidates[ i ].sr_ctrls ) { 1974 ldap_controls_free( candidates[ i ].sr_ctrls ); 1975 candidates[ i ].sr_ctrls = NULL; 1976 } 1977 1978 if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ i ] ) ) { 1979 meta_back_quarantine( op, &candidates[ i ], i ); 1980 } 1981 1982 /* only in case of timelimit exceeded, if the timelimit exceeded because 1983 * one contacted target never responded, invalidate the connection 1984 * NOTE: should we quarantine the target as well? right now, the connection 1985 * is invalidated; the next time it will be recreated and the target 1986 * will be quarantined if it cannot be contacted */ 1987 if ( mi->mi_idle_timeout != 0 1988 && rs->sr_err == LDAP_TIMELIMIT_EXCEEDED 1989 && op->o_time > mc->mc_conns[ i ].msc_time ) 1990 { 1991 /* don't let anyone else use this expired connection */ 1992 do_taint++; 1993 } 1994 } 1995 1996 if ( mc ) { 1997 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 1998 if ( do_taint ) { 1999 LDAP_BACK_CONN_TAINTED_SET( mc ); 2000 } 2001 meta_back_release_conn_lock( mi, mc, 0 ); 2002 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 2003 } 2004 2005 op->o_tmpfree( candidates, op->o_tmpmemctx ); 2006 return rs->sr_err; 2007 } 2008 2009 static int 2010 meta_send_entry( 2011 Operation *op, 2012 SlapReply *rs, 2013 metaconn_t *mc, 2014 int target, 2015 LDAPMessage *e ) 2016 { 2017 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; 2018 struct berval a, mapped; 2019 int check_duplicate_attrs = 0; 2020 int check_sorted_attrs = 0; 2021 Entry ent = { 0 }; 2022 BerElement ber = *ldap_get_message_ber( e ); 2023 Attribute *attr, **attrp; 2024 struct berval bdn, 2025 dn = BER_BVNULL; 2026 const char *text; 2027 dncookie dc; 2028 ber_len_t len; 2029 int rc; 2030 2031 if ( ber_scanf( &ber, "l{", &len ) == LBER_ERROR ) { 2032 return LDAP_DECODING_ERROR; 2033 } 2034 2035 if ( ber_set_option( &ber, LBER_OPT_REMAINING_BYTES, &len ) != LBER_OPT_SUCCESS ) { 2036 return LDAP_OTHER; 2037 } 2038 2039 if ( ber_scanf( &ber, "m{", &bdn ) == LBER_ERROR ) { 2040 return LDAP_DECODING_ERROR; 2041 } 2042 2043 /* 2044 * Rewrite the dn of the result, if needed 2045 */ 2046 dc.target = mi->mi_targets[ target ]; 2047 dc.conn = op->o_conn; 2048 dc.rs = rs; 2049 dc.ctx = "searchResult"; 2050 2051 rs->sr_err = ldap_back_dn_massage( &dc, &bdn, &dn ); 2052 if ( rs->sr_err != LDAP_SUCCESS) { 2053 return rs->sr_err; 2054 } 2055 2056 /* 2057 * Note: this may fail if the target host(s) schema differs 2058 * from the one known to the meta, and a DN with unknown 2059 * attributes is returned. 2060 * 2061 * FIXME: should we log anything, or delegate to dnNormalize? 2062 */ 2063 rc = dnPrettyNormal( NULL, &dn, &ent.e_name, &ent.e_nname, 2064 op->o_tmpmemctx ); 2065 if ( dn.bv_val != bdn.bv_val ) { 2066 free( dn.bv_val ); 2067 } 2068 BER_BVZERO( &dn ); 2069 2070 if ( rc != LDAP_SUCCESS ) { 2071 Debug( LDAP_DEBUG_ANY, 2072 "%s meta_send_entry(\"%s\"): " 2073 "invalid DN syntax\n", 2074 op->o_log_prefix, ent.e_name.bv_val ); 2075 rc = LDAP_INVALID_DN_SYNTAX; 2076 goto done; 2077 } 2078 2079 /* 2080 * cache dn 2081 */ 2082 if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) { 2083 ( void )meta_dncache_update_entry( &mi->mi_cache, 2084 &ent.e_nname, target ); 2085 } 2086 2087 attrp = &ent.e_attrs; 2088 2089 dc.ctx = "searchAttrDN"; 2090 while ( ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) { 2091 int last = 0; 2092 slap_syntax_validate_func *validate; 2093 slap_syntax_transform_func *pretty; 2094 2095 if ( ber_pvt_ber_remaining( &ber ) < 0 ) { 2096 Debug( LDAP_DEBUG_ANY, 2097 "%s meta_send_entry(\"%s\"): " 2098 "unable to parse attr \"%s\".\n", 2099 op->o_log_prefix, ent.e_name.bv_val, a.bv_val ); 2100 2101 rc = LDAP_OTHER; 2102 goto done; 2103 } 2104 2105 if ( ber_pvt_ber_remaining( &ber ) == 0 ) { 2106 break; 2107 } 2108 2109 ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_at, 2110 &a, &mapped, BACKLDAP_REMAP ); 2111 if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0' ) { 2112 ( void )ber_scanf( &ber, "x" /* [W] */ ); 2113 continue; 2114 } 2115 if ( mapped.bv_val != a.bv_val ) { 2116 /* will need to check for duplicate attrs */ 2117 check_duplicate_attrs++; 2118 } 2119 attr = attr_alloc( NULL ); 2120 if ( attr == NULL ) { 2121 rc = LDAP_OTHER; 2122 goto done; 2123 } 2124 if ( slap_bv2ad( &mapped, &attr->a_desc, &text ) 2125 != LDAP_SUCCESS) { 2126 if ( slap_bv2undef_ad( &mapped, &attr->a_desc, &text, 2127 SLAP_AD_PROXIED ) != LDAP_SUCCESS ) 2128 { 2129 Debug(LDAP_DEBUG_ANY, 2130 "%s meta_send_entry(\"%s\"): " "slap_bv2undef_ad(%s): %s\n", 2131 op->o_log_prefix, ent.e_name.bv_val, 2132 mapped.bv_val, text ); 2133 ( void )ber_scanf( &ber, "x" /* [W] */ ); 2134 attr_free( attr ); 2135 continue; 2136 } 2137 } 2138 2139 if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) 2140 check_sorted_attrs = 1; 2141 2142 /* no subschemaSubentry */ 2143 if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry 2144 || attr->a_desc == slap_schema.si_ad_entryDN ) 2145 { 2146 2147 /* 2148 * We eat target's subschemaSubentry because 2149 * a search for this value is likely not 2150 * to resolve to the appropriate backend; 2151 * later, the local subschemaSubentry is 2152 * added. 2153 * 2154 * We also eat entryDN because the frontend 2155 * will reattach it without checking if already 2156 * present... 2157 */ 2158 ( void )ber_scanf( &ber, "x" /* [W] */ ); 2159 attr_free(attr); 2160 continue; 2161 } 2162 2163 if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR 2164 || attr->a_vals == NULL ) 2165 { 2166 attr->a_vals = (struct berval *)&slap_dummy_bv; 2167 2168 } else { 2169 for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); ++last ) 2170 ; 2171 } 2172 attr->a_numvals = last; 2173 2174 validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate; 2175 pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty; 2176 2177 if ( !validate && !pretty ) { 2178 attr_free( attr ); 2179 goto next_attr; 2180 } 2181 2182 if ( attr->a_desc == slap_schema.si_ad_objectClass 2183 || attr->a_desc == slap_schema.si_ad_structuralObjectClass ) 2184 { 2185 struct berval *bv; 2186 2187 for ( bv = attr->a_vals; !BER_BVISNULL( bv ); bv++ ) { 2188 ObjectClass *oc; 2189 2190 ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_oc, 2191 bv, &mapped, BACKLDAP_REMAP ); 2192 if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0') { 2193 remove_oc:; 2194 free( bv->bv_val ); 2195 BER_BVZERO( bv ); 2196 if ( --last < 0 ) { 2197 break; 2198 } 2199 *bv = attr->a_vals[ last ]; 2200 BER_BVZERO( &attr->a_vals[ last ] ); 2201 bv--; 2202 2203 } else if ( mapped.bv_val != bv->bv_val ) { 2204 int i; 2205 2206 for ( i = 0; !BER_BVISNULL( &attr->a_vals[ i ] ); i++ ) { 2207 if ( &attr->a_vals[ i ] == bv ) { 2208 continue; 2209 } 2210 2211 if ( ber_bvstrcasecmp( &mapped, &attr->a_vals[ i ] ) == 0 ) { 2212 break; 2213 } 2214 } 2215 2216 if ( !BER_BVISNULL( &attr->a_vals[ i ] ) ) { 2217 goto remove_oc; 2218 } 2219 2220 ber_bvreplace( bv, &mapped ); 2221 2222 } else if ( ( oc = oc_bvfind_undef( bv ) ) == NULL ) { 2223 goto remove_oc; 2224 2225 } else { 2226 ber_bvreplace( bv, &oc->soc_cname ); 2227 } 2228 } 2229 /* 2230 * It is necessary to try to rewrite attributes with 2231 * dn syntax because they might be used in ACLs as 2232 * members of groups; since ACLs are applied to the 2233 * rewritten stuff, no dn-based subecj clause could 2234 * be used at the ldap backend side (see 2235 * http://www.OpenLDAP.org/faq/data/cache/452.html) 2236 * The problem can be overcome by moving the dn-based 2237 * ACLs to the target directory server, and letting 2238 * everything pass thru the ldap backend. 2239 */ 2240 } else { 2241 int i; 2242 2243 if ( attr->a_desc->ad_type->sat_syntax == 2244 slap_schema.si_syn_distinguishedName ) 2245 { 2246 ldap_dnattr_result_rewrite( &dc, attr->a_vals ); 2247 2248 } else if ( attr->a_desc == slap_schema.si_ad_ref ) { 2249 ldap_back_referral_result_rewrite( &dc, attr->a_vals, NULL ); 2250 2251 } 2252 2253 for ( i = 0; i < last; i++ ) { 2254 struct berval pval; 2255 int rc; 2256 2257 if ( pretty ) { 2258 rc = ordered_value_pretty( attr->a_desc, 2259 &attr->a_vals[i], &pval, NULL ); 2260 2261 } else { 2262 rc = ordered_value_validate( attr->a_desc, 2263 &attr->a_vals[i], 0 ); 2264 } 2265 2266 if ( rc ) { 2267 ber_memfree( attr->a_vals[i].bv_val ); 2268 if ( --last == i ) { 2269 BER_BVZERO( &attr->a_vals[ i ] ); 2270 break; 2271 } 2272 attr->a_vals[i] = attr->a_vals[last]; 2273 BER_BVZERO( &attr->a_vals[last] ); 2274 i--; 2275 continue; 2276 } 2277 2278 if ( pretty ) { 2279 ber_memfree( attr->a_vals[i].bv_val ); 2280 attr->a_vals[i] = pval; 2281 } 2282 } 2283 2284 if ( last == 0 && attr->a_vals != &slap_dummy_bv ) { 2285 attr_free( attr ); 2286 goto next_attr; 2287 } 2288 } 2289 2290 if ( last && attr->a_desc->ad_type->sat_equality && 2291 attr->a_desc->ad_type->sat_equality->smr_normalize ) 2292 { 2293 int i; 2294 2295 attr->a_nvals = ch_malloc( ( last + 1 ) * sizeof( struct berval ) ); 2296 for ( i = 0; i<last; i++ ) { 2297 /* if normalizer fails, drop this value */ 2298 if ( ordered_value_normalize( 2299 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, 2300 attr->a_desc, 2301 attr->a_desc->ad_type->sat_equality, 2302 &attr->a_vals[i], &attr->a_nvals[i], 2303 NULL )) { 2304 ber_memfree( attr->a_vals[i].bv_val ); 2305 if ( --last == i ) { 2306 BER_BVZERO( &attr->a_vals[ i ] ); 2307 break; 2308 } 2309 attr->a_vals[i] = attr->a_vals[last]; 2310 BER_BVZERO( &attr->a_vals[last] ); 2311 i--; 2312 } 2313 } 2314 BER_BVZERO( &attr->a_nvals[i] ); 2315 if ( last == 0 ) { 2316 attr_free( attr ); 2317 goto next_attr; 2318 } 2319 2320 } else { 2321 attr->a_nvals = attr->a_vals; 2322 } 2323 2324 attr->a_numvals = last; 2325 *attrp = attr; 2326 attrp = &attr->a_next; 2327 next_attr:; 2328 } 2329 2330 /* only check if some mapping occurred */ 2331 if ( check_duplicate_attrs ) { 2332 Attribute **ap; 2333 2334 for ( ap = &ent.e_attrs; *ap != NULL; ap = &(*ap)->a_next ) { 2335 Attribute **tap; 2336 2337 for ( tap = &(*ap)->a_next; *tap != NULL; ) { 2338 if ( (*tap)->a_desc == (*ap)->a_desc ) { 2339 Entry e = { 0 }; 2340 Modification mod = { 0 }; 2341 const char *text = NULL; 2342 char textbuf[ SLAP_TEXT_BUFLEN ]; 2343 Attribute *next = (*tap)->a_next; 2344 2345 BER_BVSTR( &e.e_name, "" ); 2346 BER_BVSTR( &e.e_nname, "" ); 2347 e.e_attrs = *ap; 2348 mod.sm_op = LDAP_MOD_ADD; 2349 mod.sm_desc = (*ap)->a_desc; 2350 mod.sm_type = mod.sm_desc->ad_cname; 2351 mod.sm_numvals = (*ap)->a_numvals; 2352 mod.sm_values = (*tap)->a_vals; 2353 if ( (*tap)->a_nvals != (*tap)->a_vals ) { 2354 mod.sm_nvalues = (*tap)->a_nvals; 2355 } 2356 2357 (void)modify_add_values( &e, &mod, 2358 /* permissive */ 1, 2359 &text, textbuf, sizeof( textbuf ) ); 2360 2361 /* should not insert new attrs! */ 2362 assert( e.e_attrs == *ap ); 2363 2364 attr_free( *tap ); 2365 *tap = next; 2366 2367 } else { 2368 tap = &(*tap)->a_next; 2369 } 2370 } 2371 } 2372 } 2373 2374 /* Check for sorted attributes */ 2375 if ( check_sorted_attrs ) { 2376 for ( attr = ent.e_attrs; attr; attr = attr->a_next ) { 2377 if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) { 2378 while ( attr->a_numvals > 1 ) { 2379 int i; 2380 int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx ); 2381 if ( rc != LDAP_TYPE_OR_VALUE_EXISTS ) 2382 break; 2383 2384 /* Strip duplicate values */ 2385 if ( attr->a_nvals != attr->a_vals ) 2386 ber_memfree( attr->a_nvals[i].bv_val ); 2387 ber_memfree( attr->a_vals[i].bv_val ); 2388 attr->a_numvals--; 2389 if ( (unsigned)i < attr->a_numvals ) { 2390 attr->a_vals[i] = attr->a_vals[attr->a_numvals]; 2391 if ( attr->a_nvals != attr->a_vals ) 2392 attr->a_nvals[i] = attr->a_nvals[attr->a_numvals]; 2393 } 2394 BER_BVZERO(&attr->a_vals[attr->a_numvals]); 2395 if ( attr->a_nvals != attr->a_vals ) 2396 BER_BVZERO(&attr->a_nvals[attr->a_numvals]); 2397 } 2398 attr->a_flags |= SLAP_ATTR_SORTED_VALS; 2399 } 2400 } 2401 } 2402 2403 ldap_get_entry_controls( mc->mc_conns[target].msc_ld, 2404 e, &rs->sr_ctrls ); 2405 rs->sr_entry = &ent; 2406 rs->sr_attrs = op->ors_attrs; 2407 rs->sr_operational_attrs = NULL; 2408 rs->sr_flags = mi->mi_targets[ target ]->mt_rep_flags; 2409 rs->sr_err = LDAP_SUCCESS; 2410 rc = send_search_entry( op, rs ); 2411 switch ( rc ) { 2412 case LDAP_UNAVAILABLE: 2413 rc = LDAP_OTHER; 2414 break; 2415 } 2416 2417 done:; 2418 rs->sr_entry = NULL; 2419 rs->sr_attrs = NULL; 2420 if ( rs->sr_ctrls != NULL ) { 2421 ldap_controls_free( rs->sr_ctrls ); 2422 rs->sr_ctrls = NULL; 2423 } 2424 if ( !BER_BVISNULL( &ent.e_name ) ) { 2425 free( ent.e_name.bv_val ); 2426 BER_BVZERO( &ent.e_name ); 2427 } 2428 if ( !BER_BVISNULL( &ent.e_nname ) ) { 2429 free( ent.e_nname.bv_val ); 2430 BER_BVZERO( &ent.e_nname ); 2431 } 2432 entry_clean( &ent ); 2433 2434 return rc; 2435 } 2436 2437