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