1 /* $NetBSD: bind.c,v 1.1.1.3 2010/12/12 15:23:09 adam Exp $ */ 2 3 /* OpenLDAP: pkg/ldap/servers/slapd/back-meta/bind.c,v 1.95.2.21 2010/04/13 20:23:30 kurt Exp */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1999-2010 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 "portable.h" 26 27 #include <stdio.h> 28 29 #include <ac/errno.h> 30 #include <ac/socket.h> 31 #include <ac/string.h> 32 33 34 #define AVL_INTERNAL 35 #include "slap.h" 36 #include "../back-ldap/back-ldap.h" 37 #include "back-meta.h" 38 #undef ldap_debug /* silence a warning in ldap-int.h */ 39 #include "../../../libraries/libldap/ldap-int.h" 40 41 #include "lutil_ldap.h" 42 43 static int 44 meta_back_proxy_authz_bind( 45 metaconn_t *mc, 46 int candidate, 47 Operation *op, 48 SlapReply *rs, 49 ldap_back_send_t sendok ); 50 51 static int 52 meta_back_single_bind( 53 Operation *op, 54 SlapReply *rs, 55 metaconn_t *mc, 56 int candidate ); 57 58 int 59 meta_back_bind( Operation *op, SlapReply *rs ) 60 { 61 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; 62 metaconn_t *mc = NULL; 63 64 int rc = LDAP_OTHER, 65 i, 66 gotit = 0, 67 isroot = 0; 68 69 SlapReply *candidates; 70 71 rs->sr_err = LDAP_SUCCESS; 72 73 Debug( LDAP_DEBUG_ARGS, "%s meta_back_bind: dn=\"%s\".\n", 74 op->o_log_prefix, op->o_req_dn.bv_val, 0 ); 75 76 /* the test on the bind method should be superfluous */ 77 switch ( be_rootdn_bind( op, rs ) ) { 78 case LDAP_SUCCESS: 79 if ( META_BACK_DEFER_ROOTDN_BIND( mi ) ) { 80 /* frontend will return success */ 81 return rs->sr_err; 82 } 83 84 isroot = 1; 85 /* fallthru */ 86 87 case SLAP_CB_CONTINUE: 88 break; 89 90 default: 91 /* be_rootdn_bind() sent result */ 92 return rs->sr_err; 93 } 94 95 /* we need meta_back_getconn() not send result even on error, 96 * because we want to intercept the error and make it 97 * invalidCredentials */ 98 mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_BIND_DONTSEND ); 99 if ( !mc ) { 100 if ( LogTest( LDAP_DEBUG_ANY ) ) { 101 char buf[ SLAP_TEXT_BUFLEN ]; 102 103 snprintf( buf, sizeof( buf ), 104 "meta_back_bind: no target " 105 "for dn \"%s\" (%d%s%s).", 106 op->o_req_dn.bv_val, rs->sr_err, 107 rs->sr_text ? ". " : "", 108 rs->sr_text ? rs->sr_text : "" ); 109 Debug( LDAP_DEBUG_ANY, 110 "%s %s\n", 111 op->o_log_prefix, buf, 0 ); 112 } 113 114 /* FIXME: there might be cases where we don't want 115 * to map the error onto invalidCredentials */ 116 switch ( rs->sr_err ) { 117 case LDAP_NO_SUCH_OBJECT: 118 case LDAP_UNWILLING_TO_PERFORM: 119 rs->sr_err = LDAP_INVALID_CREDENTIALS; 120 rs->sr_text = NULL; 121 break; 122 } 123 send_ldap_result( op, rs ); 124 return rs->sr_err; 125 } 126 127 candidates = meta_back_candidates_get( op ); 128 129 /* 130 * Each target is scanned ... 131 */ 132 mc->mc_authz_target = META_BOUND_NONE; 133 for ( i = 0; i < mi->mi_ntargets; i++ ) { 134 metatarget_t *mt = mi->mi_targets[ i ]; 135 int lerr; 136 137 /* 138 * Skip non-candidates 139 */ 140 if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) { 141 continue; 142 } 143 144 if ( gotit == 0 ) { 145 /* set rc to LDAP_SUCCESS only if at least 146 * one candidate has been tried */ 147 rc = LDAP_SUCCESS; 148 gotit = 1; 149 150 } else if ( !isroot ) { 151 /* 152 * A bind operation is expected to have 153 * ONE CANDIDATE ONLY! 154 */ 155 Debug( LDAP_DEBUG_ANY, 156 "### %s meta_back_bind: more than one" 157 " candidate selected...\n", 158 op->o_log_prefix, 0, 0 ); 159 } 160 161 if ( isroot ) { 162 if ( mt->mt_idassert_authmethod == LDAP_AUTH_NONE 163 || BER_BVISNULL( &mt->mt_idassert_authcDN ) ) 164 { 165 metasingleconn_t *msc = &mc->mc_conns[ i ]; 166 167 /* skip the target if no pseudorootdn is provided */ 168 if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) { 169 ch_free( msc->msc_bound_ndn.bv_val ); 170 BER_BVZERO( &msc->msc_bound_ndn ); 171 } 172 173 if ( !BER_BVISNULL( &msc->msc_cred ) ) { 174 /* destroy sensitive data */ 175 memset( msc->msc_cred.bv_val, 0, 176 msc->msc_cred.bv_len ); 177 ch_free( msc->msc_cred.bv_val ); 178 BER_BVZERO( &msc->msc_cred ); 179 } 180 181 continue; 182 } 183 184 185 (void)meta_back_proxy_authz_bind( mc, i, op, rs, LDAP_BACK_DONTSEND ); 186 lerr = rs->sr_err; 187 188 } else { 189 lerr = meta_back_single_bind( op, rs, mc, i ); 190 } 191 192 if ( lerr != LDAP_SUCCESS ) { 193 rc = rs->sr_err = lerr; 194 195 /* FIXME: in some cases (e.g. unavailable) 196 * do not assume it's not candidate; rather 197 * mark this as an error to be eventually 198 * reported to client */ 199 META_CANDIDATE_CLEAR( &candidates[ i ] ); 200 break; 201 } 202 } 203 204 /* must re-insert if local DN changed as result of bind */ 205 if ( rc == LDAP_SUCCESS ) { 206 if ( isroot ) { 207 mc->mc_authz_target = META_BOUND_ALL; 208 } 209 210 if ( !LDAP_BACK_PCONN_ISPRIV( mc ) 211 && !dn_match( &op->o_req_ndn, &mc->mc_local_ndn ) ) 212 { 213 int lerr; 214 215 /* wait for all other ops to release the connection */ 216 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 217 assert( mc->mc_refcnt == 1 ); 218 #if META_BACK_PRINT_CONNTREE > 0 219 meta_back_print_conntree( mi, ">>> meta_back_bind" ); 220 #endif /* META_BACK_PRINT_CONNTREE */ 221 222 /* delete all cached connections with the current connection */ 223 if ( LDAP_BACK_SINGLECONN( mi ) ) { 224 metaconn_t *tmpmc; 225 226 while ( ( tmpmc = avl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc, meta_back_conn_cmp ) ) != NULL ) 227 { 228 assert( !LDAP_BACK_PCONN_ISPRIV( mc ) ); 229 Debug( LDAP_DEBUG_TRACE, 230 "=>meta_back_bind: destroying conn %lu (refcnt=%u)\n", 231 mc->mc_conn->c_connid, mc->mc_refcnt, 0 ); 232 233 if ( tmpmc->mc_refcnt != 0 ) { 234 /* taint it */ 235 LDAP_BACK_CONN_TAINTED_SET( tmpmc ); 236 237 } else { 238 /* 239 * Needs a test because the handler may be corrupted, 240 * and calling ldap_unbind on a corrupted header results 241 * in a segmentation fault 242 */ 243 meta_back_conn_free( tmpmc ); 244 } 245 } 246 } 247 248 ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn ); 249 lerr = avl_insert( &mi->mi_conninfo.lai_tree, (caddr_t)mc, 250 meta_back_conndn_cmp, meta_back_conndn_dup ); 251 #if META_BACK_PRINT_CONNTREE > 0 252 meta_back_print_conntree( mi, "<<< meta_back_bind" ); 253 #endif /* META_BACK_PRINT_CONNTREE */ 254 if ( lerr == 0 ) { 255 #if 0 256 /* NOTE: a connection cannot be privileged 257 * and be in the avl tree at the same time 258 */ 259 if ( isroot ) { 260 LDAP_BACK_CONN_ISPRIV_SET( mc ); 261 LDAP_BACK_PCONN_SET( mc, op ); 262 } 263 #endif 264 LDAP_BACK_CONN_CACHED_SET( mc ); 265 266 } else { 267 LDAP_BACK_CONN_CACHED_CLEAR( mc ); 268 } 269 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 270 } 271 } 272 273 if ( mc != NULL ) { 274 meta_back_release_conn( mi, mc ); 275 } 276 277 /* 278 * rc is LDAP_SUCCESS if at least one bind succeeded, 279 * err is the last error that occurred during a bind; 280 * if at least (and at most?) one bind succeeds, fine. 281 */ 282 if ( rc != LDAP_SUCCESS ) { 283 284 /* 285 * deal with bind failure ... 286 */ 287 288 /* 289 * no target was found within the naming context, 290 * so bind must fail with invalid credentials 291 */ 292 if ( rs->sr_err == LDAP_SUCCESS && gotit == 0 ) { 293 rs->sr_err = LDAP_INVALID_CREDENTIALS; 294 } else { 295 rs->sr_err = slap_map_api2result( rs ); 296 } 297 send_ldap_result( op, rs ); 298 return rs->sr_err; 299 300 } 301 302 return LDAP_SUCCESS; 303 } 304 305 static int 306 meta_back_bind_op_result( 307 Operation *op, 308 SlapReply *rs, 309 metaconn_t *mc, 310 int candidate, 311 int msgid, 312 ldap_back_send_t sendok ) 313 { 314 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; 315 metatarget_t *mt = mi->mi_targets[ candidate ]; 316 metasingleconn_t *msc = &mc->mc_conns[ candidate ]; 317 LDAPMessage *res; 318 struct timeval tv; 319 int rc; 320 int nretries = mt->mt_nretries; 321 char buf[ SLAP_TEXT_BUFLEN ]; 322 323 Debug( LDAP_DEBUG_TRACE, 324 ">>> %s meta_back_bind_op_result[%d]\n", 325 op->o_log_prefix, candidate, 0 ); 326 327 /* make sure this is clean */ 328 assert( rs->sr_ctrls == NULL ); 329 330 if ( rs->sr_err == LDAP_SUCCESS ) { 331 time_t stoptime = (time_t)(-1), 332 timeout; 333 int timeout_err = op->o_protocol >= LDAP_VERSION3 ? 334 LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER; 335 const char *timeout_text = "Operation timed out"; 336 slap_op_t opidx = slap_req2op( op->o_tag ); 337 338 /* since timeout is not specified, compute and use 339 * the one specific to the ongoing operation */ 340 if ( opidx == LDAP_REQ_SEARCH ) { 341 if ( op->ors_tlimit <= 0 ) { 342 timeout = 0; 343 344 } else { 345 timeout = op->ors_tlimit; 346 timeout_err = LDAP_TIMELIMIT_EXCEEDED; 347 timeout_text = NULL; 348 } 349 350 } else { 351 timeout = mt->mt_timeout[ opidx ]; 352 } 353 354 /* better than nothing :) */ 355 if ( timeout == 0 ) { 356 if ( mi->mi_idle_timeout ) { 357 timeout = mi->mi_idle_timeout; 358 359 } else if ( mi->mi_conn_ttl ) { 360 timeout = mi->mi_conn_ttl; 361 } 362 } 363 364 if ( timeout ) { 365 stoptime = op->o_time + timeout; 366 } 367 368 LDAP_BACK_TV_SET( &tv ); 369 370 /* 371 * handle response!!! 372 */ 373 retry:; 374 rc = ldap_result( msc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res ); 375 switch ( rc ) { 376 case 0: 377 if ( nretries != META_RETRY_NEVER 378 || ( timeout && slap_get_time() <= stoptime ) ) 379 { 380 ldap_pvt_thread_yield(); 381 if ( nretries > 0 ) { 382 nretries--; 383 } 384 tv = mt->mt_bind_timeout; 385 goto retry; 386 } 387 388 /* don't let anyone else use this handler, 389 * because there's a pending bind that will not 390 * be acknowledged */ 391 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 392 assert( LDAP_BACK_CONN_BINDING( msc ) ); 393 394 #ifdef DEBUG_205 395 Debug( LDAP_DEBUG_ANY, "### %s meta_back_bind_op_result ldap_unbind_ext[%d] ld=%p\n", 396 op->o_log_prefix, candidate, (void *)msc->msc_ld ); 397 #endif /* DEBUG_205 */ 398 399 meta_clear_one_candidate( op, mc, candidate ); 400 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 401 402 rs->sr_err = timeout_err; 403 rs->sr_text = timeout_text; 404 break; 405 406 case -1: 407 ldap_get_option( msc->msc_ld, LDAP_OPT_ERROR_NUMBER, 408 &rs->sr_err ); 409 410 snprintf( buf, sizeof( buf ), 411 "err=%d (%s) nretries=%d", 412 rs->sr_err, ldap_err2string( rs->sr_err ), nretries ); 413 Debug( LDAP_DEBUG_ANY, 414 "### %s meta_back_bind_op_result[%d]: %s.\n", 415 op->o_log_prefix, candidate, buf ); 416 break; 417 418 default: 419 /* only touch when activity actually took place... */ 420 if ( mi->mi_idle_timeout != 0 && msc->msc_time < op->o_time ) { 421 msc->msc_time = op->o_time; 422 } 423 424 /* FIXME: matched? referrals? response controls? */ 425 rc = ldap_parse_result( msc->msc_ld, res, &rs->sr_err, 426 NULL, NULL, NULL, NULL, 1 ); 427 if ( rc != LDAP_SUCCESS ) { 428 rs->sr_err = rc; 429 } 430 break; 431 } 432 } 433 434 rs->sr_err = slap_map_api2result( rs ); 435 436 Debug( LDAP_DEBUG_TRACE, 437 "<<< %s meta_back_bind_op_result[%d] err=%d\n", 438 op->o_log_prefix, candidate, rs->sr_err ); 439 440 return rs->sr_err; 441 } 442 443 /* 444 * meta_back_single_bind 445 * 446 * attempts to perform a bind with creds 447 */ 448 static int 449 meta_back_single_bind( 450 Operation *op, 451 SlapReply *rs, 452 metaconn_t *mc, 453 int candidate ) 454 { 455 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; 456 metatarget_t *mt = mi->mi_targets[ candidate ]; 457 struct berval mdn = BER_BVNULL; 458 metasingleconn_t *msc = &mc->mc_conns[ candidate ]; 459 int msgid; 460 dncookie dc; 461 struct berval save_o_dn; 462 int save_o_do_not_cache; 463 LDAPControl **ctrls = NULL; 464 465 if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) { 466 ch_free( msc->msc_bound_ndn.bv_val ); 467 BER_BVZERO( &msc->msc_bound_ndn ); 468 } 469 470 if ( !BER_BVISNULL( &msc->msc_cred ) ) { 471 /* destroy sensitive data */ 472 memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len ); 473 ch_free( msc->msc_cred.bv_val ); 474 BER_BVZERO( &msc->msc_cred ); 475 } 476 477 /* 478 * Rewrite the bind dn if needed 479 */ 480 dc.target = mt; 481 dc.conn = op->o_conn; 482 dc.rs = rs; 483 dc.ctx = "bindDN"; 484 485 if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) { 486 rs->sr_text = "DN rewrite error"; 487 rs->sr_err = LDAP_OTHER; 488 return rs->sr_err; 489 } 490 491 /* don't add proxyAuthz; set the bindDN */ 492 save_o_dn = op->o_dn; 493 save_o_do_not_cache = op->o_do_not_cache; 494 op->o_do_not_cache = 1; 495 op->o_dn = op->o_req_dn; 496 497 ctrls = op->o_ctrls; 498 rs->sr_err = meta_back_controls_add( op, rs, mc, candidate, &ctrls ); 499 op->o_dn = save_o_dn; 500 op->o_do_not_cache = save_o_do_not_cache; 501 if ( rs->sr_err != LDAP_SUCCESS ) { 502 goto return_results; 503 } 504 505 /* FIXME: this fixes the bind problem right now; we need 506 * to use the asynchronous version to get the "matched" 507 * and more in case of failure ... */ 508 /* FIXME: should we check if at least some of the op->o_ctrls 509 * can/should be passed? */ 510 for (;;) { 511 rs->sr_err = ldap_sasl_bind( msc->msc_ld, mdn.bv_val, 512 LDAP_SASL_SIMPLE, &op->orb_cred, 513 ctrls, NULL, &msgid ); 514 if ( rs->sr_err != LDAP_X_CONNECTING ) { 515 break; 516 } 517 ldap_pvt_thread_yield(); 518 } 519 520 mi->mi_ldap_extra->controls_free( op, rs, &ctrls ); 521 522 meta_back_bind_op_result( op, rs, mc, candidate, msgid, LDAP_BACK_DONTSEND ); 523 if ( rs->sr_err != LDAP_SUCCESS ) { 524 goto return_results; 525 } 526 527 /* If defined, proxyAuthz will be used also when 528 * back-ldap is the authorizing backend; for this 529 * purpose, a successful bind is followed by a 530 * bind with the configured identity assertion */ 531 /* NOTE: use with care */ 532 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) { 533 meta_back_proxy_authz_bind( mc, candidate, op, rs, LDAP_BACK_SENDERR ); 534 if ( !LDAP_BACK_CONN_ISBOUND( msc ) ) { 535 goto return_results; 536 } 537 goto cache_refresh; 538 } 539 540 ber_bvreplace( &msc->msc_bound_ndn, &op->o_req_ndn ); 541 LDAP_BACK_CONN_ISBOUND_SET( msc ); 542 mc->mc_authz_target = candidate; 543 544 if ( META_BACK_TGT_SAVECRED( mt ) ) { 545 if ( !BER_BVISNULL( &msc->msc_cred ) ) { 546 memset( msc->msc_cred.bv_val, 0, 547 msc->msc_cred.bv_len ); 548 } 549 ber_bvreplace( &msc->msc_cred, &op->orb_cred ); 550 ldap_set_rebind_proc( msc->msc_ld, mt->mt_rebind_f, msc ); 551 } 552 553 cache_refresh:; 554 if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED 555 && !BER_BVISEMPTY( &op->o_req_ndn ) ) 556 { 557 ( void )meta_dncache_update_entry( &mi->mi_cache, 558 &op->o_req_ndn, candidate ); 559 } 560 561 return_results:; 562 if ( mdn.bv_val != op->o_req_dn.bv_val ) { 563 free( mdn.bv_val ); 564 } 565 566 if ( META_BACK_TGT_QUARANTINE( mt ) ) { 567 meta_back_quarantine( op, rs, candidate ); 568 } 569 570 return rs->sr_err; 571 } 572 573 /* 574 * meta_back_single_dobind 575 */ 576 int 577 meta_back_single_dobind( 578 Operation *op, 579 SlapReply *rs, 580 metaconn_t **mcp, 581 int candidate, 582 ldap_back_send_t sendok, 583 int nretries, 584 int dolock ) 585 { 586 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; 587 metatarget_t *mt = mi->mi_targets[ candidate ]; 588 metaconn_t *mc = *mcp; 589 metasingleconn_t *msc = &mc->mc_conns[ candidate ]; 590 static struct berval cred = BER_BVC( "" ); 591 int msgid; 592 593 assert( !LDAP_BACK_CONN_ISBOUND( msc ) ); 594 595 /* NOTE: this obsoletes pseudorootdn */ 596 if ( op->o_conn != NULL && 597 !op->o_do_not_cache && 598 ( BER_BVISNULL( &msc->msc_bound_ndn ) || 599 BER_BVISEMPTY( &msc->msc_bound_ndn ) || 600 ( LDAP_BACK_CONN_ISPRIV( mc ) && dn_match( &msc->msc_bound_ndn, &mt->mt_idassert_authcDN ) ) || 601 ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) ) 602 { 603 (void)meta_back_proxy_authz_bind( mc, candidate, op, rs, sendok ); 604 605 } else { 606 607 /* FIXME: should we check if at least some of the op->o_ctrls 608 * can/should be passed? */ 609 for (;;) { 610 rs->sr_err = ldap_sasl_bind( msc->msc_ld, 611 "", LDAP_SASL_SIMPLE, &cred, 612 NULL, NULL, &msgid ); 613 if ( rs->sr_err != LDAP_X_CONNECTING ) { 614 break; 615 } 616 ldap_pvt_thread_yield(); 617 } 618 619 rs->sr_err = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok ); 620 } 621 622 if ( rs->sr_err != LDAP_SUCCESS ) { 623 if ( dolock ) { 624 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 625 } 626 LDAP_BACK_CONN_BINDING_CLEAR( msc ); 627 if ( META_BACK_ONERR_STOP( mi ) ) { 628 LDAP_BACK_CONN_TAINTED_SET( mc ); 629 meta_back_release_conn_lock( mi, mc, 0 ); 630 *mcp = NULL; 631 } 632 if ( dolock ) { 633 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 634 } 635 } 636 637 if ( META_BACK_TGT_QUARANTINE( mt ) ) { 638 meta_back_quarantine( op, rs, candidate ); 639 } 640 641 return rs->sr_err; 642 } 643 644 /* 645 * meta_back_dobind 646 */ 647 int 648 meta_back_dobind( 649 Operation *op, 650 SlapReply *rs, 651 metaconn_t *mc, 652 ldap_back_send_t sendok ) 653 { 654 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; 655 656 int bound = 0, 657 i, 658 isroot = 0; 659 660 SlapReply *candidates; 661 662 if ( be_isroot( op ) ) { 663 isroot = 1; 664 } 665 666 if ( LogTest( LDAP_DEBUG_TRACE ) ) { 667 char buf[STRLENOF("4294967295U") + 1] = { 0 }; 668 mi->mi_ldap_extra->connid2str( &mc->mc_base, buf, sizeof(buf) ); 669 670 Debug( LDAP_DEBUG_TRACE, 671 "%s meta_back_dobind: conn=%s%s\n", 672 op->o_log_prefix, buf, 673 isroot ? " (isroot)" : "" ); 674 } 675 676 /* 677 * all the targets are bound as pseudoroot 678 */ 679 if ( mc->mc_authz_target == META_BOUND_ALL ) { 680 bound = 1; 681 goto done; 682 } 683 684 candidates = meta_back_candidates_get( op ); 685 686 for ( i = 0; i < mi->mi_ntargets; i++ ) { 687 metatarget_t *mt = mi->mi_targets[ i ]; 688 metasingleconn_t *msc = &mc->mc_conns[ i ]; 689 int rc; 690 691 /* 692 * Not a candidate 693 */ 694 if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) { 695 continue; 696 } 697 698 assert( msc->msc_ld != NULL ); 699 700 /* 701 * If the target is already bound it is skipped 702 */ 703 704 retry_binding:; 705 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 706 if ( LDAP_BACK_CONN_ISBOUND( msc ) 707 || ( LDAP_BACK_CONN_ISANON( msc ) 708 && mt->mt_idassert_authmethod == LDAP_AUTH_NONE ) ) 709 { 710 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 711 ++bound; 712 continue; 713 714 } else if ( META_BACK_CONN_CREATING( msc ) || LDAP_BACK_CONN_BINDING( msc ) ) 715 { 716 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 717 ldap_pvt_thread_yield(); 718 goto retry_binding; 719 720 } 721 722 LDAP_BACK_CONN_BINDING_SET( msc ); 723 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 724 725 rc = meta_back_single_dobind( op, rs, &mc, i, 726 LDAP_BACK_DONTSEND, mt->mt_nretries, 1 ); 727 /* 728 * NOTE: meta_back_single_dobind() already retries; 729 * in case of failure, it resets mc... 730 */ 731 if ( rc != LDAP_SUCCESS ) { 732 char buf[ SLAP_TEXT_BUFLEN ]; 733 734 if ( mc == NULL ) { 735 /* meta_back_single_dobind() already sent 736 * response and released connection */ 737 goto send_err; 738 } 739 740 741 if ( rc == LDAP_UNAVAILABLE ) { 742 /* FIXME: meta_back_retry() already re-calls 743 * meta_back_single_dobind() */ 744 if ( meta_back_retry( op, rs, &mc, i, sendok ) ) { 745 goto retry_ok; 746 } 747 748 if ( mc != NULL ) { 749 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 750 LDAP_BACK_CONN_BINDING_CLEAR( msc ); 751 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 752 meta_back_release_conn( mi, mc ); 753 } 754 755 return 0; 756 } 757 758 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 759 LDAP_BACK_CONN_BINDING_CLEAR( msc ); 760 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 761 762 snprintf( buf, sizeof( buf ), 763 "meta_back_dobind[%d]: (%s) err=%d (%s).", 764 i, isroot ? op->o_bd->be_rootdn.bv_val : "anonymous", 765 rc, ldap_err2string( rc ) ); 766 Debug( LDAP_DEBUG_ANY, 767 "%s %s\n", 768 op->o_log_prefix, buf, 0 ); 769 770 /* 771 * null cred bind should always succeed 772 * as anonymous, so a failure means 773 * the target is no longer candidate possibly 774 * due to technical reasons (remote host down?) 775 * so better clear the handle 776 */ 777 /* leave the target candidate, but record the error for later use */ 778 candidates[ i ].sr_err = rc; 779 if ( META_BACK_ONERR_STOP( mi ) ) { 780 bound = 0; 781 goto done; 782 } 783 784 continue; 785 } /* else */ 786 787 retry_ok:; 788 Debug( LDAP_DEBUG_TRACE, 789 "%s meta_back_dobind[%d]: " 790 "(%s)\n", 791 op->o_log_prefix, i, 792 isroot ? op->o_bd->be_rootdn.bv_val : "anonymous" ); 793 794 ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex ); 795 LDAP_BACK_CONN_BINDING_CLEAR( msc ); 796 if ( isroot ) { 797 LDAP_BACK_CONN_ISBOUND_SET( msc ); 798 } else { 799 LDAP_BACK_CONN_ISANON_SET( msc ); 800 } 801 ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex ); 802 ++bound; 803 } 804 805 done:; 806 if ( LogTest( LDAP_DEBUG_TRACE ) ) { 807 char buf[STRLENOF("4294967295U") + 1] = { 0 }; 808 mi->mi_ldap_extra->connid2str( &mc->mc_base, buf, sizeof(buf) ); 809 810 Debug( LDAP_DEBUG_TRACE, 811 "%s meta_back_dobind: conn=%s bound=%d\n", 812 op->o_log_prefix, buf, bound ); 813 } 814 815 if ( bound == 0 ) { 816 meta_back_release_conn( mi, mc ); 817 818 send_err:; 819 if ( sendok & LDAP_BACK_SENDERR ) { 820 if ( rs->sr_err == LDAP_SUCCESS ) { 821 rs->sr_err = LDAP_BUSY; 822 } 823 send_ldap_result( op, rs ); 824 } 825 826 return 0; 827 } 828 829 return ( bound > 0 ); 830 } 831 832 /* 833 * meta_back_default_rebind 834 * 835 * This is a callback used for chasing referrals using the same 836 * credentials as the original user on this session. 837 */ 838 int 839 meta_back_default_rebind( 840 LDAP *ld, 841 LDAP_CONST char *url, 842 ber_tag_t request, 843 ber_int_t msgid, 844 void *params ) 845 { 846 metasingleconn_t *msc = ( metasingleconn_t * )params; 847 848 return ldap_sasl_bind_s( ld, msc->msc_bound_ndn.bv_val, 849 LDAP_SASL_SIMPLE, &msc->msc_cred, 850 NULL, NULL, NULL ); 851 } 852 853 /* 854 * meta_back_default_urllist 855 * 856 * This is a callback used for mucking with the urllist 857 */ 858 int 859 meta_back_default_urllist( 860 LDAP *ld, 861 LDAPURLDesc **urllist, 862 LDAPURLDesc **url, 863 void *params ) 864 { 865 metatarget_t *mt = (metatarget_t *)params; 866 LDAPURLDesc **urltail; 867 868 if ( urllist == url ) { 869 return LDAP_SUCCESS; 870 } 871 872 for ( urltail = &(*url)->lud_next; *urltail; urltail = &(*urltail)->lud_next ) 873 /* count */ ; 874 875 *urltail = *urllist; 876 *urllist = *url; 877 *url = NULL; 878 879 ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex ); 880 if ( mt->mt_uri ) { 881 ch_free( mt->mt_uri ); 882 } 883 884 ldap_get_option( ld, LDAP_OPT_URI, (void *)&mt->mt_uri ); 885 ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex ); 886 887 return LDAP_SUCCESS; 888 } 889 890 int 891 meta_back_cancel( 892 metaconn_t *mc, 893 Operation *op, 894 SlapReply *rs, 895 ber_int_t msgid, 896 int candidate, 897 ldap_back_send_t sendok ) 898 { 899 metainfo_t *mi = (metainfo_t *)op->o_bd->be_private; 900 901 metatarget_t *mt = mi->mi_targets[ candidate ]; 902 metasingleconn_t *msc = &mc->mc_conns[ candidate ]; 903 904 int rc = LDAP_OTHER; 905 906 Debug( LDAP_DEBUG_TRACE, ">>> %s meta_back_cancel[%d] msgid=%d\n", 907 op->o_log_prefix, candidate, msgid ); 908 909 /* default behavior */ 910 if ( META_BACK_TGT_ABANDON( mt ) ) { 911 rc = ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL ); 912 913 } else if ( META_BACK_TGT_IGNORE( mt ) ) { 914 rc = ldap_pvt_discard( msc->msc_ld, msgid ); 915 916 } else if ( META_BACK_TGT_CANCEL( mt ) ) { 917 rc = ldap_cancel_s( msc->msc_ld, msgid, NULL, NULL ); 918 919 } else { 920 assert( 0 ); 921 } 922 923 Debug( LDAP_DEBUG_TRACE, "<<< %s meta_back_cancel[%d] err=%d\n", 924 op->o_log_prefix, candidate, rc ); 925 926 return rc; 927 } 928 929 930 931 /* 932 * FIXME: error return must be handled in a cleaner way ... 933 */ 934 int 935 meta_back_op_result( 936 metaconn_t *mc, 937 Operation *op, 938 SlapReply *rs, 939 int candidate, 940 ber_int_t msgid, 941 time_t timeout, 942 ldap_back_send_t sendok ) 943 { 944 metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; 945 946 const char *save_text = rs->sr_text, 947 *save_matched = rs->sr_matched; 948 BerVarray save_ref = rs->sr_ref; 949 LDAPControl **save_ctrls = rs->sr_ctrls; 950 void *matched_ctx = NULL; 951 952 char *matched = NULL; 953 char *text = NULL; 954 char **refs = NULL; 955 LDAPControl **ctrls = NULL; 956 957 assert( mc != NULL ); 958 959 rs->sr_text = NULL; 960 rs->sr_matched = NULL; 961 rs->sr_ref = NULL; 962 rs->sr_ctrls = NULL; 963 964 if ( candidate != META_TARGET_NONE ) { 965 metatarget_t *mt = mi->mi_targets[ candidate ]; 966 metasingleconn_t *msc = &mc->mc_conns[ candidate ]; 967 968 if ( LDAP_ERR_OK( rs->sr_err ) ) { 969 int rc; 970 struct timeval tv; 971 LDAPMessage *res = NULL; 972 time_t stoptime = (time_t)(-1); 973 int timeout_err = op->o_protocol >= LDAP_VERSION3 ? 974 LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER; 975 const char *timeout_text = "Operation timed out"; 976 977 /* if timeout is not specified, compute and use 978 * the one specific to the ongoing operation */ 979 if ( timeout == (time_t)(-1) ) { 980 slap_op_t opidx = slap_req2op( op->o_tag ); 981 982 if ( opidx == SLAP_OP_SEARCH ) { 983 if ( op->ors_tlimit <= 0 ) { 984 timeout = 0; 985 986 } else { 987 timeout = op->ors_tlimit; 988 timeout_err = LDAP_TIMELIMIT_EXCEEDED; 989 timeout_text = NULL; 990 } 991 992 } else { 993 timeout = mt->mt_timeout[ opidx ]; 994 } 995 } 996 997 /* better than nothing :) */ 998 if ( timeout == 0 ) { 999 if ( mi->mi_idle_timeout ) { 1000 timeout = mi->mi_idle_timeout; 1001 1002 } else if ( mi->mi_conn_ttl ) { 1003 timeout = mi->mi_conn_ttl; 1004 } 1005 } 1006 1007 if ( timeout ) { 1008 stoptime = op->o_time + timeout; 1009 } 1010 1011 LDAP_BACK_TV_SET( &tv ); 1012 1013 retry:; 1014 rc = ldap_result( msc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res ); 1015 switch ( rc ) { 1016 case 0: 1017 if ( timeout && slap_get_time() > stoptime ) { 1018 (void)meta_back_cancel( mc, op, rs, msgid, candidate, sendok ); 1019 rs->sr_err = timeout_err; 1020 rs->sr_text = timeout_text; 1021 break; 1022 } 1023 1024 LDAP_BACK_TV_SET( &tv ); 1025 ldap_pvt_thread_yield(); 1026 goto retry; 1027 1028 case -1: 1029 ldap_get_option( msc->msc_ld, LDAP_OPT_RESULT_CODE, 1030 &rs->sr_err ); 1031 break; 1032 1033 1034 /* otherwise get the result; if it is not 1035 * LDAP_SUCCESS, record it in the reply 1036 * structure (this includes 1037 * LDAP_COMPARE_{TRUE|FALSE}) */ 1038 default: 1039 /* only touch when activity actually took place... */ 1040 if ( mi->mi_idle_timeout != 0 && msc->msc_time < op->o_time ) { 1041 msc->msc_time = op->o_time; 1042 } 1043 1044 rc = ldap_parse_result( msc->msc_ld, res, &rs->sr_err, 1045 &matched, &text, &refs, &ctrls, 1 ); 1046 res = NULL; 1047 rs->sr_text = text; 1048 if ( rc != LDAP_SUCCESS ) { 1049 rs->sr_err = rc; 1050 } 1051 1052 /* RFC 4511: referrals can only appear 1053 * if result code is LDAP_REFERRAL */ 1054 if ( refs != NULL 1055 && refs[ 0 ] != NULL 1056 && refs[ 0 ][ 0 ] != '\0' ) 1057 { 1058 if ( rs->sr_err != LDAP_REFERRAL ) { 1059 Debug( LDAP_DEBUG_ANY, 1060 "%s meta_back_op_result[%d]: " 1061 "got referrals with err=%d\n", 1062 op->o_log_prefix, 1063 candidate, rs->sr_err ); 1064 1065 } else { 1066 int i; 1067 1068 for ( i = 0; refs[ i ] != NULL; i++ ) 1069 /* count */ ; 1070 rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ), 1071 op->o_tmpmemctx ); 1072 for ( i = 0; refs[ i ] != NULL; i++ ) { 1073 ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] ); 1074 } 1075 BER_BVZERO( &rs->sr_ref[ i ] ); 1076 } 1077 1078 } else if ( rs->sr_err == LDAP_REFERRAL ) { 1079 Debug( LDAP_DEBUG_ANY, 1080 "%s meta_back_op_result[%d]: " 1081 "got err=%d with null " 1082 "or empty referrals\n", 1083 op->o_log_prefix, 1084 candidate, rs->sr_err ); 1085 1086 rs->sr_err = LDAP_NO_SUCH_OBJECT; 1087 } 1088 1089 if ( ctrls != NULL ) { 1090 rs->sr_ctrls = ctrls; 1091 } 1092 } 1093 1094 assert( res == NULL ); 1095 } 1096 1097 /* if the error in the reply structure is not 1098 * LDAP_SUCCESS, try to map it from client 1099 * to server error */ 1100 if ( !LDAP_ERR_OK( rs->sr_err ) ) { 1101 rs->sr_err = slap_map_api2result( rs ); 1102 1103 /* internal ops ( op->o_conn == NULL ) 1104 * must not reply to client */ 1105 if ( op->o_conn && !op->o_do_not_cache && matched ) { 1106 1107 /* record the (massaged) matched 1108 * DN into the reply structure */ 1109 rs->sr_matched = matched; 1110 } 1111 } 1112 1113 if ( META_BACK_TGT_QUARANTINE( mt ) ) { 1114 meta_back_quarantine( op, rs, candidate ); 1115 } 1116 1117 } else { 1118 int i, 1119 err = rs->sr_err; 1120 1121 for ( i = 0; i < mi->mi_ntargets; i++ ) { 1122 metasingleconn_t *msc = &mc->mc_conns[ i ]; 1123 char *xtext = NULL; 1124 char *xmatched = NULL; 1125 1126 rs->sr_err = LDAP_SUCCESS; 1127 1128 ldap_get_option( msc->msc_ld, LDAP_OPT_RESULT_CODE, &rs->sr_err ); 1129 if ( rs->sr_err != LDAP_SUCCESS ) { 1130 /* 1131 * better check the type of error. In some cases 1132 * (search ?) it might be better to return a 1133 * success if at least one of the targets gave 1134 * positive result ... 1135 */ 1136 ldap_get_option( msc->msc_ld, 1137 LDAP_OPT_DIAGNOSTIC_MESSAGE, &xtext ); 1138 if ( xtext != NULL && xtext [ 0 ] == '\0' ) { 1139 ldap_memfree( xtext ); 1140 xtext = NULL; 1141 } 1142 1143 ldap_get_option( msc->msc_ld, 1144 LDAP_OPT_MATCHED_DN, &xmatched ); 1145 if ( xmatched != NULL && xmatched[ 0 ] == '\0' ) { 1146 ldap_memfree( xmatched ); 1147 xmatched = NULL; 1148 } 1149 1150 rs->sr_err = slap_map_api2result( rs ); 1151 1152 if ( LogTest( LDAP_DEBUG_ANY ) ) { 1153 char buf[ SLAP_TEXT_BUFLEN ]; 1154 1155 snprintf( buf, sizeof( buf ), 1156 "meta_back_op_result[%d] " 1157 "err=%d text=\"%s\" matched=\"%s\"", 1158 i, rs->sr_err, 1159 ( xtext ? xtext : "" ), 1160 ( xmatched ? xmatched : "" ) ); 1161 Debug( LDAP_DEBUG_ANY, "%s %s.\n", 1162 op->o_log_prefix, buf, 0 ); 1163 } 1164 1165 /* 1166 * FIXME: need to rewrite "match" (need rwinfo) 1167 */ 1168 switch ( rs->sr_err ) { 1169 default: 1170 err = rs->sr_err; 1171 if ( xtext != NULL ) { 1172 if ( text ) { 1173 ldap_memfree( text ); 1174 } 1175 text = xtext; 1176 xtext = NULL; 1177 } 1178 if ( xmatched != NULL ) { 1179 if ( matched ) { 1180 ldap_memfree( matched ); 1181 } 1182 matched = xmatched; 1183 xmatched = NULL; 1184 } 1185 break; 1186 } 1187 1188 if ( xtext ) { 1189 ldap_memfree( xtext ); 1190 } 1191 1192 if ( xmatched ) { 1193 ldap_memfree( xmatched ); 1194 } 1195 } 1196 1197 if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ i ] ) ) { 1198 meta_back_quarantine( op, rs, i ); 1199 } 1200 } 1201 1202 if ( err != LDAP_SUCCESS ) { 1203 rs->sr_err = err; 1204 } 1205 } 1206 1207 if ( matched != NULL ) { 1208 struct berval dn, pdn; 1209 1210 ber_str2bv( matched, 0, 0, &dn ); 1211 if ( dnPretty( NULL, &dn, &pdn, op->o_tmpmemctx ) == LDAP_SUCCESS ) { 1212 ldap_memfree( matched ); 1213 matched_ctx = op->o_tmpmemctx; 1214 matched = pdn.bv_val; 1215 } 1216 rs->sr_matched = matched; 1217 } 1218 1219 if ( rs->sr_err == LDAP_UNAVAILABLE ) { 1220 if ( !( sendok & LDAP_BACK_RETRYING ) ) { 1221 if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) { 1222 if ( rs->sr_text == NULL ) rs->sr_text = "Proxy operation retry failed"; 1223 send_ldap_result( op, rs ); 1224 } 1225 } 1226 1227 } else if ( op->o_conn && 1228 ( ( ( sendok & LDAP_BACK_SENDOK ) && LDAP_ERR_OK( rs->sr_err ) ) 1229 || ( ( sendok & LDAP_BACK_SENDERR ) && !LDAP_ERR_OK( rs->sr_err ) ) ) ) 1230 { 1231 send_ldap_result( op, rs ); 1232 } 1233 if ( matched ) { 1234 op->o_tmpfree( (char *)rs->sr_matched, matched_ctx ); 1235 } 1236 if ( text ) { 1237 ldap_memfree( text ); 1238 } 1239 if ( rs->sr_ref ) { 1240 op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx ); 1241 rs->sr_ref = NULL; 1242 } 1243 if ( refs ) { 1244 ber_memvfree( (void **)refs ); 1245 } 1246 if ( ctrls ) { 1247 assert( rs->sr_ctrls != NULL ); 1248 ldap_controls_free( ctrls ); 1249 } 1250 1251 rs->sr_text = save_text; 1252 rs->sr_matched = save_matched; 1253 rs->sr_ref = save_ref; 1254 rs->sr_ctrls = save_ctrls; 1255 1256 return( LDAP_ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err ); 1257 } 1258 1259 /* 1260 * meta_back_proxy_authz_cred() 1261 * 1262 * prepares credentials & method for meta_back_proxy_authz_bind(); 1263 * or, if method is SASL, performs the SASL bind directly. 1264 */ 1265 int 1266 meta_back_proxy_authz_cred( 1267 metaconn_t *mc, 1268 int candidate, 1269 Operation *op, 1270 SlapReply *rs, 1271 ldap_back_send_t sendok, 1272 struct berval *binddn, 1273 struct berval *bindcred, 1274 int *method ) 1275 { 1276 metainfo_t *mi = (metainfo_t *)op->o_bd->be_private; 1277 metatarget_t *mt = mi->mi_targets[ candidate ]; 1278 metasingleconn_t *msc = &mc->mc_conns[ candidate ]; 1279 struct berval ndn; 1280 int dobind = 0; 1281 1282 /* don't proxyAuthz if protocol is not LDAPv3 */ 1283 switch ( mt->mt_version ) { 1284 case LDAP_VERSION3: 1285 break; 1286 1287 case 0: 1288 if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) { 1289 break; 1290 } 1291 /* fall thru */ 1292 1293 default: 1294 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 1295 if ( sendok & LDAP_BACK_SENDERR ) { 1296 send_ldap_result( op, rs ); 1297 } 1298 LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); 1299 goto done; 1300 } 1301 1302 if ( op->o_tag == LDAP_REQ_BIND ) { 1303 ndn = op->o_req_ndn; 1304 1305 } else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) { 1306 ndn = op->o_conn->c_ndn; 1307 1308 } else { 1309 ndn = op->o_ndn; 1310 } 1311 1312 /* 1313 * FIXME: we need to let clients use proxyAuthz 1314 * otherwise we cannot do symmetric pools of servers; 1315 * we have to live with the fact that a user can 1316 * authorize itself as any ID that is allowed 1317 * by the authzTo directive of the "proxyauthzdn". 1318 */ 1319 /* 1320 * NOTE: current Proxy Authorization specification 1321 * and implementation do not allow proxy authorization 1322 * control to be provided with Bind requests 1323 */ 1324 /* 1325 * if no bind took place yet, but the connection is bound 1326 * and the "proxyauthzdn" is set, then bind as 1327 * "proxyauthzdn" and explicitly add the proxyAuthz 1328 * control to every operation with the dn bound 1329 * to the connection as control value. 1330 */ 1331 1332 /* bind as proxyauthzdn only if no idassert mode 1333 * is requested, or if the client's identity 1334 * is authorized */ 1335 switch ( mt->mt_idassert_mode ) { 1336 case LDAP_BACK_IDASSERT_LEGACY: 1337 if ( !BER_BVISNULL( &ndn ) && !BER_BVISEMPTY( &ndn ) ) { 1338 if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) && !BER_BVISEMPTY( &mt->mt_idassert_authcDN ) ) 1339 { 1340 *binddn = mt->mt_idassert_authcDN; 1341 *bindcred = mt->mt_idassert_passwd; 1342 dobind = 1; 1343 } 1344 } 1345 break; 1346 1347 default: 1348 /* NOTE: rootdn can always idassert */ 1349 if ( BER_BVISNULL( &ndn ) 1350 && mt->mt_idassert_authz == NULL 1351 && !( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) 1352 { 1353 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { 1354 rs->sr_err = LDAP_INAPPROPRIATE_AUTH; 1355 if ( sendok & LDAP_BACK_SENDERR ) { 1356 send_ldap_result( op, rs ); 1357 } 1358 LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); 1359 goto done; 1360 1361 } 1362 1363 rs->sr_err = LDAP_SUCCESS; 1364 *binddn = slap_empty_bv; 1365 *bindcred = slap_empty_bv; 1366 break; 1367 1368 } else if ( mt->mt_idassert_authz && !be_isroot( op ) ) { 1369 struct berval authcDN; 1370 1371 if ( BER_BVISNULL( &ndn ) ) { 1372 authcDN = slap_empty_bv; 1373 1374 } else { 1375 authcDN = ndn; 1376 } 1377 rs->sr_err = slap_sasl_matches( op, mt->mt_idassert_authz, 1378 &authcDN, &authcDN ); 1379 if ( rs->sr_err != LDAP_SUCCESS ) { 1380 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { 1381 if ( sendok & LDAP_BACK_SENDERR ) { 1382 send_ldap_result( op, rs ); 1383 } 1384 LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); 1385 goto done; 1386 } 1387 1388 rs->sr_err = LDAP_SUCCESS; 1389 *binddn = slap_empty_bv; 1390 *bindcred = slap_empty_bv; 1391 break; 1392 } 1393 } 1394 1395 *binddn = mt->mt_idassert_authcDN; 1396 *bindcred = mt->mt_idassert_passwd; 1397 dobind = 1; 1398 break; 1399 } 1400 1401 if ( dobind && mt->mt_idassert_authmethod == LDAP_AUTH_SASL ) { 1402 #ifdef HAVE_CYRUS_SASL 1403 void *defaults = NULL; 1404 struct berval authzID = BER_BVNULL; 1405 int freeauthz = 0; 1406 1407 /* if SASL supports native authz, prepare for it */ 1408 if ( ( !op->o_do_not_cache || !op->o_is_auth_check ) && 1409 ( mt->mt_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) ) 1410 { 1411 switch ( mt->mt_idassert_mode ) { 1412 case LDAP_BACK_IDASSERT_OTHERID: 1413 case LDAP_BACK_IDASSERT_OTHERDN: 1414 authzID = mt->mt_idassert_authzID; 1415 break; 1416 1417 case LDAP_BACK_IDASSERT_ANONYMOUS: 1418 BER_BVSTR( &authzID, "dn:" ); 1419 break; 1420 1421 case LDAP_BACK_IDASSERT_SELF: 1422 if ( BER_BVISNULL( &ndn ) ) { 1423 /* connection is not authc'd, so don't idassert */ 1424 BER_BVSTR( &authzID, "dn:" ); 1425 break; 1426 } 1427 authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len; 1428 authzID.bv_val = slap_sl_malloc( authzID.bv_len + 1, op->o_tmpmemctx ); 1429 AC_MEMCPY( authzID.bv_val, "dn:", STRLENOF( "dn:" ) ); 1430 AC_MEMCPY( authzID.bv_val + STRLENOF( "dn:" ), 1431 ndn.bv_val, ndn.bv_len + 1 ); 1432 freeauthz = 1; 1433 break; 1434 1435 default: 1436 break; 1437 } 1438 } 1439 1440 if ( mt->mt_idassert_secprops != NULL ) { 1441 rs->sr_err = ldap_set_option( msc->msc_ld, 1442 LDAP_OPT_X_SASL_SECPROPS, 1443 (void *)mt->mt_idassert_secprops ); 1444 1445 if ( rs->sr_err != LDAP_OPT_SUCCESS ) { 1446 rs->sr_err = LDAP_OTHER; 1447 if ( sendok & LDAP_BACK_SENDERR ) { 1448 send_ldap_result( op, rs ); 1449 } 1450 LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); 1451 goto done; 1452 } 1453 } 1454 1455 defaults = lutil_sasl_defaults( msc->msc_ld, 1456 mt->mt_idassert_sasl_mech.bv_val, 1457 mt->mt_idassert_sasl_realm.bv_val, 1458 mt->mt_idassert_authcID.bv_val, 1459 mt->mt_idassert_passwd.bv_val, 1460 authzID.bv_val ); 1461 if ( defaults == NULL ) { 1462 rs->sr_err = LDAP_OTHER; 1463 LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); 1464 if ( sendok & LDAP_BACK_SENDERR ) { 1465 send_ldap_result( op, rs ); 1466 } 1467 goto done; 1468 } 1469 1470 rs->sr_err = ldap_sasl_interactive_bind_s( msc->msc_ld, binddn->bv_val, 1471 mt->mt_idassert_sasl_mech.bv_val, NULL, NULL, 1472 LDAP_SASL_QUIET, lutil_sasl_interact, 1473 defaults ); 1474 1475 rs->sr_err = slap_map_api2result( rs ); 1476 if ( rs->sr_err != LDAP_SUCCESS ) { 1477 LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); 1478 if ( sendok & LDAP_BACK_SENDERR ) { 1479 send_ldap_result( op, rs ); 1480 } 1481 1482 } else { 1483 LDAP_BACK_CONN_ISBOUND_SET( msc ); 1484 } 1485 1486 lutil_sasl_freedefs( defaults ); 1487 if ( freeauthz ) { 1488 slap_sl_free( authzID.bv_val, op->o_tmpmemctx ); 1489 } 1490 1491 goto done; 1492 #endif /* HAVE_CYRUS_SASL */ 1493 } 1494 1495 *method = mt->mt_idassert_authmethod; 1496 switch ( mt->mt_idassert_authmethod ) { 1497 case LDAP_AUTH_NONE: 1498 BER_BVSTR( binddn, "" ); 1499 BER_BVSTR( bindcred, "" ); 1500 /* fallthru */ 1501 1502 case LDAP_AUTH_SIMPLE: 1503 break; 1504 1505 default: 1506 /* unsupported! */ 1507 LDAP_BACK_CONN_ISBOUND_CLEAR( msc ); 1508 rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED; 1509 if ( sendok & LDAP_BACK_SENDERR ) { 1510 send_ldap_result( op, rs ); 1511 } 1512 break; 1513 } 1514 1515 done:; 1516 return rs->sr_err; 1517 } 1518 1519 static int 1520 meta_back_proxy_authz_bind( metaconn_t *mc, int candidate, Operation *op, SlapReply *rs, ldap_back_send_t sendok ) 1521 { 1522 metainfo_t *mi = (metainfo_t *)op->o_bd->be_private; 1523 metatarget_t *mt = mi->mi_targets[ candidate ]; 1524 metasingleconn_t *msc = &mc->mc_conns[ candidate ]; 1525 struct berval binddn = BER_BVC( "" ), 1526 cred = BER_BVC( "" ); 1527 int method = LDAP_AUTH_NONE, 1528 rc; 1529 1530 rc = meta_back_proxy_authz_cred( mc, candidate, op, rs, sendok, &binddn, &cred, &method ); 1531 if ( rc == LDAP_SUCCESS && !LDAP_BACK_CONN_ISBOUND( msc ) ) { 1532 int msgid; 1533 1534 switch ( method ) { 1535 case LDAP_AUTH_NONE: 1536 case LDAP_AUTH_SIMPLE: 1537 for (;;) { 1538 rs->sr_err = ldap_sasl_bind( msc->msc_ld, 1539 binddn.bv_val, LDAP_SASL_SIMPLE, 1540 &cred, NULL, NULL, &msgid ); 1541 if ( rs->sr_err != LDAP_X_CONNECTING ) { 1542 break; 1543 } 1544 ldap_pvt_thread_yield(); 1545 } 1546 rc = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok ); 1547 if ( rc == LDAP_SUCCESS ) { 1548 /* set rebind stuff in case of successful proxyAuthz bind, 1549 * so that referral chasing is attempted using the right 1550 * identity */ 1551 LDAP_BACK_CONN_ISBOUND_SET( msc ); 1552 ber_bvreplace( &msc->msc_bound_ndn, &binddn ); 1553 1554 if ( META_BACK_TGT_SAVECRED( mt ) ) { 1555 if ( !BER_BVISNULL( &msc->msc_cred ) ) { 1556 memset( msc->msc_cred.bv_val, 0, 1557 msc->msc_cred.bv_len ); 1558 } 1559 ber_bvreplace( &msc->msc_cred, &cred ); 1560 ldap_set_rebind_proc( msc->msc_ld, mt->mt_rebind_f, msc ); 1561 } 1562 } 1563 break; 1564 1565 default: 1566 assert( 0 ); 1567 break; 1568 } 1569 } 1570 1571 return LDAP_BACK_CONN_ISBOUND( msc ); 1572 } 1573 1574 /* 1575 * Add controls; 1576 * 1577 * if any needs to be added, it is prepended to existing ones, 1578 * in a newly allocated array. The companion function 1579 * mi->mi_ldap_extra->controls_free() must be used to restore the original 1580 * status of op->o_ctrls. 1581 */ 1582 int 1583 meta_back_controls_add( 1584 Operation *op, 1585 SlapReply *rs, 1586 metaconn_t *mc, 1587 int candidate, 1588 LDAPControl ***pctrls ) 1589 { 1590 metainfo_t *mi = (metainfo_t *)op->o_bd->be_private; 1591 metatarget_t *mt = mi->mi_targets[ candidate ]; 1592 metasingleconn_t *msc = &mc->mc_conns[ candidate ]; 1593 1594 LDAPControl **ctrls = NULL; 1595 /* set to the maximum number of controls this backend can add */ 1596 LDAPControl c[ 2 ] = {{ 0 }}; 1597 int n = 0, i, j1 = 0, j2 = 0; 1598 1599 *pctrls = NULL; 1600 1601 rs->sr_err = LDAP_SUCCESS; 1602 1603 /* don't add controls if protocol is not LDAPv3 */ 1604 switch ( mt->mt_version ) { 1605 case LDAP_VERSION3: 1606 break; 1607 1608 case 0: 1609 if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) { 1610 break; 1611 } 1612 /* fall thru */ 1613 1614 default: 1615 goto done; 1616 } 1617 1618 /* put controls that go __before__ existing ones here */ 1619 1620 /* proxyAuthz for identity assertion */ 1621 switch ( mi->mi_ldap_extra->proxy_authz_ctrl( op, rs, &msc->msc_bound_ndn, 1622 mt->mt_version, &mt->mt_idassert, &c[ j1 ] ) ) 1623 { 1624 case SLAP_CB_CONTINUE: 1625 break; 1626 1627 case LDAP_SUCCESS: 1628 j1++; 1629 break; 1630 1631 default: 1632 goto done; 1633 } 1634 1635 /* put controls that go __after__ existing ones here */ 1636 1637 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 1638 /* session tracking */ 1639 if ( META_BACK_TGT_ST_REQUEST( mt ) ) { 1640 switch ( slap_ctrl_session_tracking_request_add( op, rs, &c[ j1 + j2 ] ) ) { 1641 case SLAP_CB_CONTINUE: 1642 break; 1643 1644 case LDAP_SUCCESS: 1645 j2++; 1646 break; 1647 1648 default: 1649 goto done; 1650 } 1651 } 1652 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 1653 1654 if ( rs->sr_err == SLAP_CB_CONTINUE ) { 1655 rs->sr_err = LDAP_SUCCESS; 1656 } 1657 1658 /* if nothing to do, just bail out */ 1659 if ( j1 == 0 && j2 == 0 ) { 1660 goto done; 1661 } 1662 1663 assert( j1 + j2 <= (int) (sizeof( c )/sizeof( c[0] )) ); 1664 1665 if ( op->o_ctrls ) { 1666 for ( n = 0; op->o_ctrls[ n ]; n++ ) 1667 /* just count ctrls */ ; 1668 } 1669 1670 ctrls = op->o_tmpalloc( (n + j1 + j2 + 1) * sizeof( LDAPControl * ) + ( j1 + j2 ) * sizeof( LDAPControl ), 1671 op->o_tmpmemctx ); 1672 if ( j1 ) { 1673 ctrls[ 0 ] = (LDAPControl *)&ctrls[ n + j1 + j2 + 1 ]; 1674 *ctrls[ 0 ] = c[ 0 ]; 1675 for ( i = 1; i < j1; i++ ) { 1676 ctrls[ i ] = &ctrls[ 0 ][ i ]; 1677 *ctrls[ i ] = c[ i ]; 1678 } 1679 } 1680 1681 i = 0; 1682 if ( op->o_ctrls ) { 1683 for ( i = 0; op->o_ctrls[ i ]; i++ ) { 1684 ctrls[ i + j1 ] = op->o_ctrls[ i ]; 1685 } 1686 } 1687 1688 n += j1; 1689 if ( j2 ) { 1690 ctrls[ n ] = (LDAPControl *)&ctrls[ n + j2 + 1 ] + j1; 1691 *ctrls[ n ] = c[ j1 ]; 1692 for ( i = 1; i < j2; i++ ) { 1693 ctrls[ n + i ] = &ctrls[ n ][ i ]; 1694 *ctrls[ n + i ] = c[ i ]; 1695 } 1696 } 1697 1698 ctrls[ n + j2 ] = NULL; 1699 1700 done:; 1701 if ( ctrls == NULL ) { 1702 ctrls = op->o_ctrls; 1703 } 1704 1705 *pctrls = ctrls; 1706 1707 return rs->sr_err; 1708 } 1709 1710