1 /* $NetBSD: bind.c,v 1.1.1.3 2010/12/12 15:23:03 adam Exp $ */ 2 3 /* bind.c - ldap backend bind function */ 4 /* OpenLDAP: pkg/ldap/servers/slapd/back-ldap/bind.c,v 1.162.2.29 2010/06/10 19:38:49 quanah Exp */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1999-2010 The OpenLDAP Foundation. 8 * Portions Copyright 2000-2003 Pierangelo Masarati. 9 * Portions Copyright 1999-2003 Howard Chu. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted only as authorized by the OpenLDAP 14 * Public License. 15 * 16 * A copy of this license is available in the file LICENSE in the 17 * top-level directory of the distribution or, alternatively, at 18 * <http://www.OpenLDAP.org/license.html>. 19 */ 20 /* ACKNOWLEDGEMENTS: 21 * This work was initially developed by Howard Chu for inclusion 22 * in OpenLDAP Software and subsequently enhanced by Pierangelo 23 * Masarati. 24 */ 25 26 #include "portable.h" 27 28 #include <stdio.h> 29 30 #include <ac/errno.h> 31 #include <ac/socket.h> 32 #include <ac/string.h> 33 34 #define AVL_INTERNAL 35 #include "slap.h" 36 #include "back-ldap.h" 37 #include "lutil.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 #define LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ "2.16.840.1.113730.3.4.12" 44 45 #if LDAP_BACK_PRINT_CONNTREE > 0 46 47 static const struct { 48 slap_mask_t f; 49 char c; 50 } flagsmap[] = { 51 { LDAP_BACK_FCONN_ISBOUND, 'B' }, 52 { LDAP_BACK_FCONN_ISANON, 'A' }, 53 { LDAP_BACK_FCONN_ISPRIV, 'P' }, 54 { LDAP_BACK_FCONN_ISTLS, 'T' }, 55 { LDAP_BACK_FCONN_BINDING, 'X' }, 56 { LDAP_BACK_FCONN_TAINTED, 'E' }, 57 { LDAP_BACK_FCONN_ABANDON, 'N' }, 58 { LDAP_BACK_FCONN_ISIDASR, 'S' }, 59 { LDAP_BACK_FCONN_CACHED, 'C' }, 60 { 0, '\0' } 61 }; 62 63 static void 64 ldap_back_conn_print( ldapconn_t *lc, const char *avlstr ) 65 { 66 char buf[ SLAP_TEXT_BUFLEN ]; 67 char fbuf[ sizeof("BAPTIENSC") ]; 68 int i; 69 70 ldap_back_conn2str( &lc->lc_base, buf, sizeof( buf ) ); 71 for ( i = 0; flagsmap[ i ].c != '\0'; i++ ) { 72 if ( lc->lc_lcflags & flagsmap[i].f ) { 73 fbuf[i] = flagsmap[i].c; 74 75 } else { 76 fbuf[i] = '.'; 77 } 78 } 79 fbuf[i] = '\0'; 80 81 fprintf( stderr, "lc=%p %s %s flags=0x%08x (%s)\n", 82 (void *)lc, buf, avlstr, lc->lc_lcflags, fbuf ); 83 } 84 85 static void 86 ldap_back_ravl_print( Avlnode *root, int depth ) 87 { 88 int i; 89 ldapconn_t *lc; 90 91 if ( root == 0 ) { 92 return; 93 } 94 95 ldap_back_ravl_print( root->avl_right, depth+1 ); 96 97 for ( i = 0; i < depth; i++ ) { 98 fprintf( stderr, "-" ); 99 } 100 101 lc = root->avl_data; 102 ldap_back_conn_print( lc, avl_bf2str( root->avl_bf ) ); 103 104 ldap_back_ravl_print( root->avl_left, depth + 1 ); 105 } 106 107 static char* priv2str[] = { 108 "privileged", 109 "privileged/TLS", 110 "anonymous", 111 "anonymous/TLS", 112 "bind", 113 "bind/TLS", 114 NULL 115 }; 116 117 void 118 ldap_back_print_conntree( ldapinfo_t *li, char *msg ) 119 { 120 int c; 121 122 fprintf( stderr, "========> %s\n", msg ); 123 124 for ( c = LDAP_BACK_PCONN_FIRST; c < LDAP_BACK_PCONN_LAST; c++ ) { 125 int i = 0; 126 ldapconn_t *lc; 127 128 fprintf( stderr, " %s[%d]\n", priv2str[ c ], li->li_conn_priv[ c ].lic_num ); 129 130 LDAP_TAILQ_FOREACH( lc, &li->li_conn_priv[ c ].lic_priv, lc_q ) 131 { 132 fprintf( stderr, " [%d] ", i ); 133 ldap_back_conn_print( lc, "" ); 134 i++; 135 } 136 } 137 138 if ( li->li_conninfo.lai_tree == 0 ) { 139 fprintf( stderr, "\t(empty)\n" ); 140 141 } else { 142 ldap_back_ravl_print( li->li_conninfo.lai_tree, 0 ); 143 } 144 145 fprintf( stderr, "<======== %s\n", msg ); 146 } 147 #endif /* LDAP_BACK_PRINT_CONNTREE */ 148 149 static int 150 ldap_back_freeconn( ldapinfo_t *li, ldapconn_t *lc, int dolock ); 151 152 static ldapconn_t * 153 ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok, 154 struct berval *binddn, struct berval *bindcred ); 155 156 static int 157 ldap_back_is_proxy_authz( Operation *op, SlapReply *rs, ldap_back_send_t sendok, 158 struct berval *binddn, struct berval *bindcred ); 159 160 static int 161 ldap_back_proxy_authz_bind( ldapconn_t *lc, Operation *op, SlapReply *rs, 162 ldap_back_send_t sendok, struct berval *binddn, struct berval *bindcred ); 163 164 static int 165 ldap_back_prepare_conn( ldapconn_t *lc, Operation *op, SlapReply *rs, 166 ldap_back_send_t sendok ); 167 168 static int 169 ldap_back_conndnlc_cmp( const void *c1, const void *c2 ); 170 171 ldapconn_t * 172 ldap_back_conn_delete( ldapinfo_t *li, ldapconn_t *lc ) 173 { 174 if ( LDAP_BACK_PCONN_ISPRIV( lc ) ) { 175 if ( LDAP_BACK_CONN_CACHED( lc ) ) { 176 assert( lc->lc_q.tqe_prev != NULL ); 177 assert( li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num > 0 ); 178 li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num--; 179 LDAP_TAILQ_REMOVE( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv, lc, lc_q ); 180 LDAP_TAILQ_ENTRY_INIT( lc, lc_q ); 181 LDAP_BACK_CONN_CACHED_CLEAR( lc ); 182 183 } else { 184 assert( LDAP_BACK_CONN_TAINTED( lc ) ); 185 assert( lc->lc_q.tqe_prev == NULL ); 186 } 187 188 } else { 189 ldapconn_t *tmplc = NULL; 190 191 if ( LDAP_BACK_CONN_CACHED( lc ) ) { 192 assert( !LDAP_BACK_CONN_TAINTED( lc ) ); 193 tmplc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc, 194 ldap_back_conndnlc_cmp ); 195 assert( tmplc == lc ); 196 LDAP_BACK_CONN_CACHED_CLEAR( lc ); 197 } 198 199 assert( LDAP_BACK_CONN_TAINTED( lc ) || tmplc == lc ); 200 } 201 202 return lc; 203 } 204 205 int 206 ldap_back_bind( Operation *op, SlapReply *rs ) 207 { 208 ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; 209 ldapconn_t *lc; 210 211 LDAPControl **ctrls = NULL; 212 struct berval save_o_dn; 213 int save_o_do_not_cache, 214 rc = 0; 215 ber_int_t msgid; 216 ldap_back_send_t retrying = LDAP_BACK_RETRYING; 217 218 /* allow rootdn as a means to auth without the need to actually 219 * contact the proxied DSA */ 220 switch ( be_rootdn_bind( op, rs ) ) { 221 case SLAP_CB_CONTINUE: 222 break; 223 224 default: 225 return rs->sr_err; 226 } 227 228 lc = ldap_back_getconn( op, rs, LDAP_BACK_BIND_SERR, NULL, NULL ); 229 if ( !lc ) { 230 return rs->sr_err; 231 } 232 233 /* we can do (almost) whatever we want with this conn, 234 * because either it's temporary, or it's marked as binding */ 235 if ( !BER_BVISNULL( &lc->lc_bound_ndn ) ) { 236 ch_free( lc->lc_bound_ndn.bv_val ); 237 BER_BVZERO( &lc->lc_bound_ndn ); 238 } 239 if ( !BER_BVISNULL( &lc->lc_cred ) ) { 240 memset( lc->lc_cred.bv_val, 0, lc->lc_cred.bv_len ); 241 ch_free( lc->lc_cred.bv_val ); 242 BER_BVZERO( &lc->lc_cred ); 243 } 244 LDAP_BACK_CONN_ISBOUND_CLEAR( lc ); 245 246 /* don't add proxyAuthz; set the bindDN */ 247 save_o_dn = op->o_dn; 248 save_o_do_not_cache = op->o_do_not_cache; 249 op->o_dn = op->o_req_dn; 250 op->o_do_not_cache = 1; 251 252 ctrls = op->o_ctrls; 253 rc = ldap_back_controls_add( op, rs, lc, &ctrls ); 254 op->o_dn = save_o_dn; 255 op->o_do_not_cache = save_o_do_not_cache; 256 if ( rc != LDAP_SUCCESS ) { 257 send_ldap_result( op, rs ); 258 ldap_back_release_conn( li, lc ); 259 return( rc ); 260 } 261 262 retry:; 263 /* method is always LDAP_AUTH_SIMPLE if we got here */ 264 rs->sr_err = ldap_sasl_bind( lc->lc_ld, op->o_req_dn.bv_val, 265 LDAP_SASL_SIMPLE, 266 &op->orb_cred, ctrls, NULL, &msgid ); 267 /* FIXME: should we always retry, or only when piping the bind 268 * in the "override" connection pool? */ 269 rc = ldap_back_op_result( lc, op, rs, msgid, 270 li->li_timeout[ SLAP_OP_BIND ], 271 LDAP_BACK_BIND_SERR | retrying ); 272 if ( rc == LDAP_UNAVAILABLE && retrying ) { 273 retrying &= ~LDAP_BACK_RETRYING; 274 if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_BIND_SERR ) ) { 275 goto retry; 276 } 277 } 278 279 ldap_back_controls_free( op, rs, &ctrls ); 280 281 if ( rc == LDAP_SUCCESS ) { 282 op->o_conn->c_authz_cookie = op->o_bd->be_private; 283 284 /* If defined, proxyAuthz will be used also when 285 * back-ldap is the authorizing backend; for this 286 * purpose, after a successful bind the connection 287 * is left for further binds, and further operations 288 * on this client connection will use a default 289 * connection with identity assertion */ 290 /* NOTE: use with care */ 291 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) { 292 ldap_back_release_conn( li, lc ); 293 return( rc ); 294 } 295 296 /* rebind is now done inside ldap_back_proxy_authz_bind() 297 * in case of success */ 298 LDAP_BACK_CONN_ISBOUND_SET( lc ); 299 ber_dupbv( &lc->lc_bound_ndn, &op->o_req_ndn ); 300 301 if ( !BER_BVISNULL( &lc->lc_cred ) ) { 302 memset( lc->lc_cred.bv_val, 0, 303 lc->lc_cred.bv_len ); 304 } 305 306 if ( LDAP_BACK_SAVECRED( li ) ) { 307 ber_bvreplace( &lc->lc_cred, &op->orb_cred ); 308 ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc ); 309 310 } else { 311 lc->lc_cred.bv_len = 0; 312 } 313 } 314 315 /* must re-insert if local DN changed as result of bind */ 316 if ( !LDAP_BACK_CONN_ISBOUND( lc ) 317 || ( !dn_match( &op->o_req_ndn, &lc->lc_local_ndn ) 318 && !LDAP_BACK_PCONN_ISPRIV( lc ) ) ) 319 { 320 int lerr = -1; 321 ldapconn_t *tmplc; 322 323 /* wait for all other ops to release the connection */ 324 retry_lock:; 325 ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); 326 if ( lc->lc_refcnt > 1 ) { 327 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 328 ldap_pvt_thread_yield(); 329 goto retry_lock; 330 } 331 332 #if LDAP_BACK_PRINT_CONNTREE > 0 333 ldap_back_print_conntree( li, ">>> ldap_back_bind" ); 334 #endif /* LDAP_BACK_PRINT_CONNTREE */ 335 336 assert( lc->lc_refcnt == 1 ); 337 ldap_back_conn_delete( li, lc ); 338 339 /* delete all cached connections with the current connection */ 340 if ( LDAP_BACK_SINGLECONN( li ) ) { 341 while ( ( tmplc = avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc, ldap_back_conn_cmp ) ) != NULL ) 342 { 343 assert( !LDAP_BACK_PCONN_ISPRIV( lc ) ); 344 Debug( LDAP_DEBUG_TRACE, 345 "=>ldap_back_bind: destroying conn %lu (refcnt=%u)\n", 346 lc->lc_conn->c_connid, lc->lc_refcnt, 0 ); 347 348 if ( tmplc->lc_refcnt != 0 ) { 349 /* taint it */ 350 LDAP_BACK_CONN_TAINTED_SET( tmplc ); 351 LDAP_BACK_CONN_CACHED_CLEAR( tmplc ); 352 353 } else { 354 /* 355 * Needs a test because the handler may be corrupted, 356 * and calling ldap_unbind on a corrupted header results 357 * in a segmentation fault 358 */ 359 ldap_back_conn_free( tmplc ); 360 } 361 } 362 } 363 364 if ( LDAP_BACK_CONN_ISBOUND( lc ) ) { 365 ber_bvreplace( &lc->lc_local_ndn, &op->o_req_ndn ); 366 if ( be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) { 367 LDAP_BACK_PCONN_ROOTDN_SET( lc, op ); 368 } 369 lerr = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc, 370 ldap_back_conndn_cmp, ldap_back_conndn_dup ); 371 } 372 373 #if LDAP_BACK_PRINT_CONNTREE > 0 374 ldap_back_print_conntree( li, "<<< ldap_back_bind" ); 375 #endif /* LDAP_BACK_PRINT_CONNTREE */ 376 377 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 378 switch ( lerr ) { 379 case 0: 380 LDAP_BACK_CONN_CACHED_SET( lc ); 381 break; 382 383 case -1: 384 /* duplicate; someone else successfully bound 385 * on the same connection with the same identity; 386 * we can do this because lc_refcnt == 1 */ 387 ldap_back_conn_free( lc ); 388 lc = NULL; 389 } 390 } 391 392 if ( lc != NULL ) { 393 ldap_back_release_conn( li, lc ); 394 } 395 396 return( rc ); 397 } 398 399 /* 400 * ldap_back_conndn_cmp 401 * 402 * compares two ldapconn_t based on the value of the conn pointer 403 * and of the local DN; used by avl stuff for insert, lookup 404 * and direct delete 405 */ 406 int 407 ldap_back_conndn_cmp( const void *c1, const void *c2 ) 408 { 409 const ldapconn_t *lc1 = (const ldapconn_t *)c1; 410 const ldapconn_t *lc2 = (const ldapconn_t *)c2; 411 int rc; 412 413 /* If local DNs don't match, it is definitely not a match */ 414 /* For shared sessions, conn is NULL. Only explicitly 415 * bound sessions will have non-NULL conn. 416 */ 417 rc = SLAP_PTRCMP( lc1->lc_conn, lc2->lc_conn ); 418 if ( rc == 0 ) { 419 rc = ber_bvcmp( &lc1->lc_local_ndn, &lc2->lc_local_ndn ); 420 } 421 422 return rc; 423 } 424 425 /* 426 * ldap_back_conndnlc_cmp 427 * 428 * compares two ldapconn_t based on the value of the conn pointer, 429 * the local DN and the lc pointer; used by avl stuff for insert, lookup 430 * and direct delete 431 */ 432 static int 433 ldap_back_conndnlc_cmp( const void *c1, const void *c2 ) 434 { 435 const ldapconn_t *lc1 = (const ldapconn_t *)c1; 436 const ldapconn_t *lc2 = (const ldapconn_t *)c2; 437 int rc; 438 439 /* If local DNs don't match, it is definitely not a match */ 440 /* For shared sessions, conn is NULL. Only explicitly 441 * bound sessions will have non-NULL conn. 442 */ 443 rc = SLAP_PTRCMP( lc1->lc_conn, lc2->lc_conn ); 444 if ( rc == 0 ) { 445 rc = ber_bvcmp( &lc1->lc_local_ndn, &lc2->lc_local_ndn ); 446 if ( rc == 0 ) { 447 rc = SLAP_PTRCMP( lc1, lc2 ); 448 } 449 } 450 451 return rc; 452 } 453 454 /* 455 * ldap_back_conn_cmp 456 * 457 * compares two ldapconn_t based on the value of the conn pointer; 458 * used by avl stuff for delete of all conns with the same connid 459 */ 460 int 461 ldap_back_conn_cmp( const void *c1, const void *c2 ) 462 { 463 const ldapconn_t *lc1 = (const ldapconn_t *)c1; 464 const ldapconn_t *lc2 = (const ldapconn_t *)c2; 465 466 /* For shared sessions, conn is NULL. Only explicitly 467 * bound sessions will have non-NULL conn. 468 */ 469 return SLAP_PTRCMP( lc1->lc_conn, lc2->lc_conn ); 470 } 471 472 /* 473 * ldap_back_conndn_dup 474 * 475 * returns -1 in case a duplicate ldapconn_t has been inserted; 476 * used by avl stuff 477 */ 478 int 479 ldap_back_conndn_dup( void *c1, void *c2 ) 480 { 481 ldapconn_t *lc1 = (ldapconn_t *)c1; 482 ldapconn_t *lc2 = (ldapconn_t *)c2; 483 484 /* Cannot have more than one shared session with same DN */ 485 if ( lc1->lc_conn == lc2->lc_conn && 486 dn_match( &lc1->lc_local_ndn, &lc2->lc_local_ndn ) ) 487 { 488 return -1; 489 } 490 491 return 0; 492 } 493 494 static int 495 ldap_back_freeconn( ldapinfo_t *li, ldapconn_t *lc, int dolock ) 496 { 497 if ( dolock ) { 498 ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); 499 } 500 501 #if LDAP_BACK_PRINT_CONNTREE > 0 502 ldap_back_print_conntree( li, ">>> ldap_back_freeconn" ); 503 #endif /* LDAP_BACK_PRINT_CONNTREE */ 504 505 (void)ldap_back_conn_delete( li, lc ); 506 507 if ( lc->lc_refcnt == 0 ) { 508 ldap_back_conn_free( (void *)lc ); 509 } 510 511 #if LDAP_BACK_PRINT_CONNTREE > 0 512 ldap_back_print_conntree( li, "<<< ldap_back_freeconn" ); 513 #endif /* LDAP_BACK_PRINT_CONNTREE */ 514 515 if ( dolock ) { 516 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 517 } 518 519 return 0; 520 } 521 522 #ifdef HAVE_TLS 523 static int 524 ldap_back_start_tls( 525 LDAP *ld, 526 int protocol, 527 int *is_tls, 528 const char *url, 529 unsigned flags, 530 int retries, 531 const char **text ) 532 { 533 int rc = LDAP_SUCCESS; 534 535 /* start TLS ("tls-[try-]{start,propagate}" statements) */ 536 if ( ( LDAP_BACK_USE_TLS_F( flags ) || ( *is_tls && LDAP_BACK_PROPAGATE_TLS_F( flags ) ) ) 537 && !ldap_is_ldaps_url( url ) ) 538 { 539 #ifdef SLAP_STARTTLS_ASYNCHRONOUS 540 /* 541 * use asynchronous StartTLS 542 * in case, chase referral (not implemented yet) 543 */ 544 int msgid; 545 546 if ( protocol == 0 ) { 547 ldap_get_option( ld, LDAP_OPT_PROTOCOL_VERSION, 548 (void *)&protocol ); 549 } 550 551 if ( protocol < LDAP_VERSION3 ) { 552 /* we should rather bail out... */ 553 rc = LDAP_UNWILLING_TO_PERFORM; 554 *text = "invalid protocol version"; 555 } 556 557 if ( rc == LDAP_SUCCESS ) { 558 rc = ldap_start_tls( ld, NULL, NULL, &msgid ); 559 } 560 561 if ( rc == LDAP_SUCCESS ) { 562 LDAPMessage *res = NULL; 563 struct timeval tv; 564 565 LDAP_BACK_TV_SET( &tv ); 566 567 retry:; 568 rc = ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res ); 569 if ( rc < 0 ) { 570 rc = LDAP_UNAVAILABLE; 571 572 } else if ( rc == 0 ) { 573 if ( retries != LDAP_BACK_RETRY_NEVER ) { 574 ldap_pvt_thread_yield(); 575 if ( retries > 0 ) { 576 retries--; 577 } 578 LDAP_BACK_TV_SET( &tv ); 579 goto retry; 580 } 581 rc = LDAP_UNAVAILABLE; 582 583 } else if ( rc == LDAP_RES_EXTENDED ) { 584 struct berval *data = NULL; 585 586 rc = ldap_parse_extended_result( ld, res, 587 NULL, &data, 0 ); 588 if ( rc == LDAP_SUCCESS ) { 589 int err; 590 rc = ldap_parse_result( ld, res, &err, 591 NULL, NULL, NULL, NULL, 1 ); 592 if ( rc == LDAP_SUCCESS ) { 593 rc = err; 594 } 595 res = NULL; 596 597 /* FIXME: in case a referral 598 * is returned, should we try 599 * using it instead of the 600 * configured URI? */ 601 if ( rc == LDAP_SUCCESS ) { 602 rc = ldap_install_tls( ld ); 603 604 } else if ( rc == LDAP_REFERRAL ) { 605 rc = LDAP_UNWILLING_TO_PERFORM; 606 *text = "unwilling to chase referral returned by Start TLS exop"; 607 } 608 609 if ( data ) { 610 if ( data->bv_val ) { 611 ber_memfree( data->bv_val ); 612 } 613 ber_memfree( data ); 614 } 615 } 616 617 } else { 618 rc = LDAP_OTHER; 619 } 620 621 if ( res != NULL ) { 622 ldap_msgfree( res ); 623 } 624 } 625 #else /* ! SLAP_STARTTLS_ASYNCHRONOUS */ 626 /* 627 * use synchronous StartTLS 628 */ 629 rc = ldap_start_tls_s( ld, NULL, NULL ); 630 #endif /* ! SLAP_STARTTLS_ASYNCHRONOUS */ 631 632 /* if StartTLS is requested, only attempt it if the URL 633 * is not "ldaps://"; this may occur not only in case 634 * of misconfiguration, but also when used in the chain 635 * overlay, where the "uri" can be parsed out of a referral */ 636 switch ( rc ) { 637 case LDAP_SUCCESS: 638 *is_tls = 1; 639 break; 640 641 case LDAP_SERVER_DOWN: 642 break; 643 644 default: 645 if ( LDAP_BACK_TLS_CRITICAL_F( flags ) ) { 646 *text = "could not start TLS"; 647 break; 648 } 649 650 /* in case Start TLS is not critical */ 651 *is_tls = 0; 652 rc = LDAP_SUCCESS; 653 break; 654 } 655 656 } else { 657 *is_tls = 0; 658 } 659 660 return rc; 661 } 662 #endif /* HAVE_TLS */ 663 664 static int 665 ldap_back_prepare_conn( ldapconn_t *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok ) 666 { 667 ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; 668 int version; 669 LDAP *ld = NULL; 670 #ifdef HAVE_TLS 671 int is_tls = op->o_conn->c_is_tls; 672 time_t lctime = (time_t)(-1); 673 slap_bindconf *sb; 674 #endif /* HAVE_TLS */ 675 676 ldap_pvt_thread_mutex_lock( &li->li_uri_mutex ); 677 rs->sr_err = ldap_initialize( &ld, li->li_uri ); 678 ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex ); 679 if ( rs->sr_err != LDAP_SUCCESS ) { 680 goto error_return; 681 } 682 683 if ( li->li_urllist_f ) { 684 ldap_set_urllist_proc( ld, li->li_urllist_f, li->li_urllist_p ); 685 } 686 687 /* Set LDAP version. This will always succeed: If the client 688 * bound with a particular version, then so can we. 689 */ 690 if ( li->li_version != 0 ) { 691 version = li->li_version; 692 693 } else if ( op->o_protocol != 0 ) { 694 version = op->o_protocol; 695 696 } else { 697 /* assume it's an internal op; set to LDAPv3 */ 698 version = LDAP_VERSION3; 699 } 700 ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&version ); 701 702 /* automatically chase referrals ("chase-referrals [{yes|no}]" statement) */ 703 ldap_set_option( ld, LDAP_OPT_REFERRALS, 704 LDAP_BACK_CHASE_REFERRALS( li ) ? LDAP_OPT_ON : LDAP_OPT_OFF ); 705 706 if ( li->li_network_timeout > 0 ) { 707 struct timeval tv; 708 709 tv.tv_sec = li->li_network_timeout; 710 tv.tv_usec = 0; 711 ldap_set_option( ld, LDAP_OPT_NETWORK_TIMEOUT, (const void *)&tv ); 712 } 713 714 #ifdef HAVE_TLS 715 if ( LDAP_BACK_CONN_ISPRIV( lc ) ) { 716 sb = &li->li_acl; 717 718 } else if ( LDAP_BACK_CONN_ISIDASSERT( lc ) ) { 719 sb = &li->li_idassert.si_bc; 720 721 } else { 722 sb = &li->li_tls; 723 } 724 725 if ( sb->sb_tls_do_init ) { 726 bindconf_tls_set( sb, ld ); 727 } else if ( sb->sb_tls_ctx ) { 728 ldap_set_option( ld, LDAP_OPT_X_TLS_CTX, sb->sb_tls_ctx ); 729 } 730 731 ldap_pvt_thread_mutex_lock( &li->li_uri_mutex ); 732 assert( li->li_uri_mutex_do_not_lock == 0 ); 733 li->li_uri_mutex_do_not_lock = 1; 734 rs->sr_err = ldap_back_start_tls( ld, op->o_protocol, &is_tls, 735 li->li_uri, li->li_flags, li->li_nretries, &rs->sr_text ); 736 li->li_uri_mutex_do_not_lock = 0; 737 ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex ); 738 if ( rs->sr_err != LDAP_SUCCESS ) { 739 ldap_unbind_ext( ld, NULL, NULL ); 740 rs->sr_text = "Start TLS failed"; 741 goto error_return; 742 743 } else if ( li->li_idle_timeout ) { 744 /* only touch when activity actually took place... */ 745 lctime = op->o_time; 746 } 747 #endif /* HAVE_TLS */ 748 749 lc->lc_ld = ld; 750 lc->lc_refcnt = 1; 751 #ifdef HAVE_TLS 752 if ( is_tls ) { 753 LDAP_BACK_CONN_ISTLS_SET( lc ); 754 } else { 755 LDAP_BACK_CONN_ISTLS_CLEAR( lc ); 756 } 757 if ( lctime != (time_t)(-1) ) { 758 lc->lc_time = lctime; 759 } 760 #endif /* HAVE_TLS */ 761 762 error_return:; 763 if ( rs->sr_err != LDAP_SUCCESS ) { 764 rs->sr_err = slap_map_api2result( rs ); 765 if ( sendok & LDAP_BACK_SENDERR ) { 766 if ( rs->sr_text == NULL ) { 767 rs->sr_text = "Proxy connection initialization failed"; 768 } 769 send_ldap_result( op, rs ); 770 } 771 772 } else { 773 if ( li->li_conn_ttl > 0 ) { 774 lc->lc_create_time = op->o_time; 775 } 776 } 777 778 return rs->sr_err; 779 } 780 781 static ldapconn_t * 782 ldap_back_getconn( 783 Operation *op, 784 SlapReply *rs, 785 ldap_back_send_t sendok, 786 struct berval *binddn, 787 struct berval *bindcred ) 788 { 789 ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; 790 ldapconn_t *lc = NULL, 791 lc_curr = {{ 0 }}; 792 int refcnt = 1, 793 lookupconn = !( sendok & LDAP_BACK_BINDING ); 794 795 /* if the server is quarantined, and 796 * - the current interval did not expire yet, or 797 * - no more retries should occur, 798 * don't return the connection */ 799 if ( li->li_isquarantined ) { 800 slap_retry_info_t *ri = &li->li_quarantine; 801 int dont_retry = 1; 802 803 if ( li->li_quarantine.ri_interval ) { 804 ldap_pvt_thread_mutex_lock( &li->li_quarantine_mutex ); 805 if ( li->li_isquarantined == LDAP_BACK_FQ_YES ) { 806 dont_retry = ( ri->ri_num[ ri->ri_idx ] == SLAP_RETRYNUM_TAIL 807 || slap_get_time() < ri->ri_last + ri->ri_interval[ ri->ri_idx ] ); 808 if ( !dont_retry ) { 809 Debug( LDAP_DEBUG_ANY, 810 "%s: ldap_back_getconn quarantine " 811 "retry block #%d try #%d.\n", 812 op->o_log_prefix, ri->ri_idx, ri->ri_count ); 813 li->li_isquarantined = LDAP_BACK_FQ_RETRYING; 814 } 815 } 816 ldap_pvt_thread_mutex_unlock( &li->li_quarantine_mutex ); 817 } 818 819 if ( dont_retry ) { 820 rs->sr_err = LDAP_UNAVAILABLE; 821 if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) { 822 rs->sr_text = "Target is quarantined"; 823 send_ldap_result( op, rs ); 824 } 825 return NULL; 826 } 827 } 828 829 /* Internal searches are privileged and shared. So is root. */ 830 if ( op->o_do_not_cache || be_isroot( op ) ) { 831 LDAP_BACK_CONN_ISPRIV_SET( &lc_curr ); 832 lc_curr.lc_local_ndn = op->o_bd->be_rootndn; 833 LDAP_BACK_PCONN_ROOTDN_SET( &lc_curr, op ); 834 835 } else { 836 struct berval tmpbinddn, 837 tmpbindcred, 838 save_o_dn, 839 save_o_ndn; 840 int isproxyauthz; 841 842 /* need cleanup */ 843 if ( binddn == NULL ) { 844 binddn = &tmpbinddn; 845 } 846 if ( bindcred == NULL ) { 847 bindcred = &tmpbindcred; 848 } 849 if ( op->o_tag == LDAP_REQ_BIND ) { 850 save_o_dn = op->o_dn; 851 save_o_ndn = op->o_ndn; 852 op->o_dn = op->o_req_dn; 853 op->o_ndn = op->o_req_ndn; 854 } 855 isproxyauthz = ldap_back_is_proxy_authz( op, rs, sendok, binddn, bindcred ); 856 if ( op->o_tag == LDAP_REQ_BIND ) { 857 op->o_dn = save_o_dn; 858 op->o_ndn = save_o_ndn; 859 } 860 if ( isproxyauthz == -1 ) { 861 return NULL; 862 } 863 864 lc_curr.lc_local_ndn = op->o_ndn; 865 /* Explicit binds must not be shared; 866 * however, explicit binds are piped in a special connection 867 * when idassert is to occur with "override" set */ 868 if ( op->o_tag == LDAP_REQ_BIND && !isproxyauthz ) { 869 lc_curr.lc_conn = op->o_conn; 870 871 } else { 872 if ( isproxyauthz && !( sendok & LDAP_BACK_BINDING ) ) { 873 lc_curr.lc_local_ndn = *binddn; 874 LDAP_BACK_PCONN_ROOTDN_SET( &lc_curr, op ); 875 LDAP_BACK_CONN_ISIDASSERT_SET( &lc_curr ); 876 877 } else if ( isproxyauthz && ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) { 878 lc_curr.lc_local_ndn = slap_empty_bv; 879 LDAP_BACK_PCONN_BIND_SET( &lc_curr, op ); 880 LDAP_BACK_CONN_ISIDASSERT_SET( &lc_curr ); 881 lookupconn = 1; 882 883 } else if ( SLAP_IS_AUTHZ_BACKEND( op ) ) { 884 lc_curr.lc_conn = op->o_conn; 885 886 } else { 887 LDAP_BACK_PCONN_ANON_SET( &lc_curr, op ); 888 } 889 } 890 } 891 892 /* Explicit Bind requests always get their own conn */ 893 if ( lookupconn ) { 894 retry_lock: 895 ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); 896 if ( LDAP_BACK_PCONN_ISPRIV( &lc_curr ) ) { 897 /* lookup a conn that's not binding */ 898 LDAP_TAILQ_FOREACH( lc, 899 &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( &lc_curr ) ].lic_priv, 900 lc_q ) 901 { 902 if ( !LDAP_BACK_CONN_BINDING( lc ) && lc->lc_refcnt == 0 ) { 903 break; 904 } 905 } 906 907 if ( lc != NULL ) { 908 if ( lc != LDAP_TAILQ_LAST( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv, 909 ldapconn_t, lc_q ) ) 910 { 911 LDAP_TAILQ_REMOVE( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv, 912 lc, lc_q ); 913 LDAP_TAILQ_ENTRY_INIT( lc, lc_q ); 914 LDAP_TAILQ_INSERT_TAIL( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv, 915 lc, lc_q ); 916 } 917 918 } else if ( !LDAP_BACK_USE_TEMPORARIES( li ) 919 && li->li_conn_priv[ LDAP_BACK_CONN2PRIV( &lc_curr ) ].lic_num == li->li_conn_priv_max ) 920 { 921 lc = LDAP_TAILQ_FIRST( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( &lc_curr ) ].lic_priv ); 922 } 923 924 } else { 925 926 /* Searches for a ldapconn in the avl tree */ 927 lc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree, 928 (caddr_t)&lc_curr, ldap_back_conndn_cmp ); 929 } 930 931 if ( lc != NULL ) { 932 /* Don't reuse connections while they're still binding */ 933 if ( LDAP_BACK_CONN_BINDING( lc ) ) { 934 if ( !LDAP_BACK_USE_TEMPORARIES( li ) ) { 935 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 936 937 ldap_pvt_thread_yield(); 938 goto retry_lock; 939 } 940 lc = NULL; 941 } 942 943 if ( lc != NULL ) { 944 if ( op->o_tag == LDAP_REQ_BIND ) { 945 /* right now, this is the only possible case */ 946 assert( ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ); 947 LDAP_BACK_CONN_BINDING_SET( lc ); 948 } 949 950 refcnt = ++lc->lc_refcnt; 951 } 952 } 953 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 954 } 955 956 /* Looks like we didn't get a bind. Open a new session... */ 957 if ( lc == NULL ) { 958 lc = (ldapconn_t *)ch_calloc( 1, sizeof( ldapconn_t ) ); 959 lc->lc_flags = li->li_flags; 960 lc->lc_lcflags = lc_curr.lc_lcflags; 961 if ( ldap_back_prepare_conn( lc, op, rs, sendok ) != LDAP_SUCCESS ) { 962 ch_free( lc ); 963 return NULL; 964 } 965 966 if ( sendok & LDAP_BACK_BINDING ) { 967 LDAP_BACK_CONN_BINDING_SET( lc ); 968 } 969 970 lc->lc_conn = lc_curr.lc_conn; 971 ber_dupbv( &lc->lc_local_ndn, &lc_curr.lc_local_ndn ); 972 973 /* 974 * the rationale is: connections as the rootdn are privileged, 975 * so acl_authcDN is to be used; however, in some cases 976 * one already configured identity assertion with a highly 977 * privileged idassert_authcDN, so if acl_authcDN is NULL 978 * and idassert_authcDN is not, use the second instead. 979 * 980 * might change in the future, because it's preferable 981 * to make clear what identity is being used, since 982 * the only drawback is that one risks to configure 983 * the same identity twice... 984 */ 985 if ( LDAP_BACK_CONN_ISPRIV( &lc_curr ) ) { 986 if ( BER_BVISNULL( &li->li_acl_authcDN ) && !BER_BVISNULL( &li->li_idassert_authcDN ) ) { 987 ber_dupbv( &lc->lc_bound_ndn, &li->li_idassert_authcDN ); 988 ber_dupbv( &lc->lc_cred, &li->li_idassert_passwd ); 989 990 } else { 991 ber_dupbv( &lc->lc_bound_ndn, &li->li_acl_authcDN ); 992 ber_dupbv( &lc->lc_cred, &li->li_acl_passwd ); 993 } 994 LDAP_BACK_CONN_ISPRIV_SET( lc ); 995 996 } else if ( LDAP_BACK_CONN_ISIDASSERT( &lc_curr ) ) { 997 if ( !LDAP_BACK_PCONN_ISBIND( &lc_curr ) ) { 998 ber_dupbv( &lc->lc_bound_ndn, &li->li_idassert_authcDN ); 999 ber_dupbv( &lc->lc_cred, &li->li_idassert_passwd ); 1000 } 1001 LDAP_BACK_CONN_ISIDASSERT_SET( lc ); 1002 1003 } else { 1004 BER_BVZERO( &lc->lc_cred ); 1005 BER_BVZERO( &lc->lc_bound_ndn ); 1006 if ( !BER_BVISEMPTY( &op->o_ndn ) 1007 && SLAP_IS_AUTHZ_BACKEND( op ) ) 1008 { 1009 ber_dupbv( &lc->lc_bound_ndn, &op->o_ndn ); 1010 } 1011 } 1012 1013 #ifdef HAVE_TLS 1014 /* if start TLS failed but it was not mandatory, 1015 * check if the non-TLS connection was already 1016 * in cache; in case, destroy the newly created 1017 * connection and use the existing one */ 1018 if ( LDAP_BACK_PCONN_ISTLS( lc ) 1019 && !ldap_tls_inplace( lc->lc_ld ) ) 1020 { 1021 ldapconn_t *tmplc = NULL; 1022 int idx = LDAP_BACK_CONN2PRIV( &lc_curr ) - 1; 1023 1024 ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); 1025 LDAP_TAILQ_FOREACH( tmplc, 1026 &li->li_conn_priv[ idx ].lic_priv, 1027 lc_q ) 1028 { 1029 if ( !LDAP_BACK_CONN_BINDING( tmplc ) ) { 1030 break; 1031 } 1032 } 1033 1034 if ( tmplc != NULL ) { 1035 refcnt = ++tmplc->lc_refcnt; 1036 ldap_back_conn_free( lc ); 1037 lc = tmplc; 1038 } 1039 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 1040 1041 if ( tmplc != NULL ) { 1042 goto done; 1043 } 1044 } 1045 #endif /* HAVE_TLS */ 1046 1047 /* Inserts the newly created ldapconn in the avl tree */ 1048 ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); 1049 1050 LDAP_BACK_CONN_ISBOUND_CLEAR( lc ); 1051 1052 assert( lc->lc_refcnt == 1 ); 1053 1054 #if LDAP_BACK_PRINT_CONNTREE > 0 1055 ldap_back_print_conntree( li, ">>> ldap_back_getconn(insert)" ); 1056 #endif /* LDAP_BACK_PRINT_CONNTREE */ 1057 1058 if ( LDAP_BACK_PCONN_ISPRIV( lc ) ) { 1059 if ( li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num < li->li_conn_priv_max ) { 1060 LDAP_TAILQ_INSERT_TAIL( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv, lc, lc_q ); 1061 li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num++; 1062 LDAP_BACK_CONN_CACHED_SET( lc ); 1063 1064 } else { 1065 LDAP_BACK_CONN_TAINTED_SET( lc ); 1066 } 1067 rs->sr_err = 0; 1068 1069 } else { 1070 rs->sr_err = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc, 1071 ldap_back_conndn_cmp, ldap_back_conndn_dup ); 1072 LDAP_BACK_CONN_CACHED_SET( lc ); 1073 } 1074 1075 #if LDAP_BACK_PRINT_CONNTREE > 0 1076 ldap_back_print_conntree( li, "<<< ldap_back_getconn(insert)" ); 1077 #endif /* LDAP_BACK_PRINT_CONNTREE */ 1078 1079 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 1080 1081 if ( LogTest( LDAP_DEBUG_TRACE ) ) { 1082 char buf[ SLAP_TEXT_BUFLEN ]; 1083 1084 snprintf( buf, sizeof( buf ), 1085 "lc=%p inserted refcnt=%u rc=%d", 1086 (void *)lc, refcnt, rs->sr_err ); 1087 1088 Debug( LDAP_DEBUG_TRACE, 1089 "=>ldap_back_getconn: %s: %s\n", 1090 op->o_log_prefix, buf, 0 ); 1091 } 1092 1093 if ( !LDAP_BACK_PCONN_ISPRIV( lc ) ) { 1094 /* Err could be -1 in case a duplicate ldapconn is inserted */ 1095 switch ( rs->sr_err ) { 1096 case 0: 1097 break; 1098 1099 case -1: 1100 LDAP_BACK_CONN_CACHED_CLEAR( lc ); 1101 if ( !( sendok & LDAP_BACK_BINDING ) && !LDAP_BACK_USE_TEMPORARIES( li ) ) { 1102 /* duplicate: free and try to get the newly created one */ 1103 ldap_back_conn_free( lc ); 1104 lc = NULL; 1105 goto retry_lock; 1106 } 1107 1108 /* taint connection, so that it'll be freed when released */ 1109 LDAP_BACK_CONN_TAINTED_SET( lc ); 1110 break; 1111 1112 default: 1113 LDAP_BACK_CONN_CACHED_CLEAR( lc ); 1114 ldap_back_conn_free( lc ); 1115 rs->sr_err = LDAP_OTHER; 1116 rs->sr_text = "Proxy bind collision"; 1117 if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) { 1118 send_ldap_result( op, rs ); 1119 } 1120 return NULL; 1121 } 1122 } 1123 1124 } else { 1125 int expiring = 0; 1126 1127 if ( ( li->li_idle_timeout != 0 && op->o_time > lc->lc_time + li->li_idle_timeout ) 1128 || ( li->li_conn_ttl != 0 && op->o_time > lc->lc_create_time + li->li_conn_ttl ) ) 1129 { 1130 expiring = 1; 1131 1132 /* let it be used, but taint/delete it so that 1133 * no-one else can look it up any further */ 1134 ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); 1135 1136 #if LDAP_BACK_PRINT_CONNTREE > 0 1137 ldap_back_print_conntree( li, ">>> ldap_back_getconn(timeout)" ); 1138 #endif /* LDAP_BACK_PRINT_CONNTREE */ 1139 1140 (void)ldap_back_conn_delete( li, lc ); 1141 LDAP_BACK_CONN_TAINTED_SET( lc ); 1142 1143 #if LDAP_BACK_PRINT_CONNTREE > 0 1144 ldap_back_print_conntree( li, "<<< ldap_back_getconn(timeout)" ); 1145 #endif /* LDAP_BACK_PRINT_CONNTREE */ 1146 1147 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 1148 } 1149 1150 if ( LogTest( LDAP_DEBUG_TRACE ) ) { 1151 char buf[ SLAP_TEXT_BUFLEN ]; 1152 1153 snprintf( buf, sizeof( buf ), 1154 "conn %p fetched refcnt=%u%s", 1155 (void *)lc, refcnt, 1156 expiring ? " expiring" : "" ); 1157 Debug( LDAP_DEBUG_TRACE, 1158 "=>ldap_back_getconn: %s.\n", buf, 0, 0 ); 1159 } 1160 } 1161 1162 #ifdef HAVE_TLS 1163 done:; 1164 #endif /* HAVE_TLS */ 1165 1166 return lc; 1167 } 1168 1169 void 1170 ldap_back_release_conn_lock( 1171 ldapinfo_t *li, 1172 ldapconn_t **lcp, 1173 int dolock ) 1174 { 1175 1176 ldapconn_t *lc = *lcp; 1177 1178 if ( dolock ) { 1179 ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); 1180 } 1181 assert( lc->lc_refcnt > 0 ); 1182 LDAP_BACK_CONN_BINDING_CLEAR( lc ); 1183 lc->lc_refcnt--; 1184 if ( LDAP_BACK_CONN_TAINTED( lc ) ) { 1185 ldap_back_freeconn( li, lc, 0 ); 1186 *lcp = NULL; 1187 } 1188 if ( dolock ) { 1189 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 1190 } 1191 } 1192 1193 void 1194 ldap_back_quarantine( 1195 Operation *op, 1196 SlapReply *rs ) 1197 { 1198 ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; 1199 1200 slap_retry_info_t *ri = &li->li_quarantine; 1201 1202 ldap_pvt_thread_mutex_lock( &li->li_quarantine_mutex ); 1203 1204 if ( rs->sr_err == LDAP_UNAVAILABLE ) { 1205 time_t new_last = slap_get_time(); 1206 1207 switch ( li->li_isquarantined ) { 1208 case LDAP_BACK_FQ_NO: 1209 if ( ri->ri_last == new_last ) { 1210 goto done; 1211 } 1212 1213 Debug( LDAP_DEBUG_ANY, 1214 "%s: ldap_back_quarantine enter.\n", 1215 op->o_log_prefix, 0, 0 ); 1216 1217 ri->ri_idx = 0; 1218 ri->ri_count = 0; 1219 break; 1220 1221 case LDAP_BACK_FQ_RETRYING: 1222 Debug( LDAP_DEBUG_ANY, 1223 "%s: ldap_back_quarantine block #%d try #%d failed.\n", 1224 op->o_log_prefix, ri->ri_idx, ri->ri_count ); 1225 1226 ++ri->ri_count; 1227 if ( ri->ri_num[ ri->ri_idx ] != SLAP_RETRYNUM_FOREVER 1228 && ri->ri_count == ri->ri_num[ ri->ri_idx ] ) 1229 { 1230 ri->ri_count = 0; 1231 ++ri->ri_idx; 1232 } 1233 break; 1234 1235 default: 1236 break; 1237 } 1238 1239 li->li_isquarantined = LDAP_BACK_FQ_YES; 1240 ri->ri_last = new_last; 1241 1242 } else if ( li->li_isquarantined != LDAP_BACK_FQ_NO ) { 1243 if ( ri->ri_last == slap_get_time() ) { 1244 goto done; 1245 } 1246 1247 Debug( LDAP_DEBUG_ANY, 1248 "%s: ldap_back_quarantine exit (%d) err=%d.\n", 1249 op->o_log_prefix, li->li_isquarantined, rs->sr_err ); 1250 1251 if ( li->li_quarantine_f ) { 1252 (void)li->li_quarantine_f( li, li->li_quarantine_p ); 1253 } 1254 1255 ri->ri_count = 0; 1256 ri->ri_idx = 0; 1257 li->li_isquarantined = LDAP_BACK_FQ_NO; 1258 } 1259 1260 done:; 1261 ldap_pvt_thread_mutex_unlock( &li->li_quarantine_mutex ); 1262 } 1263 1264 static int 1265 ldap_back_dobind_cb( 1266 Operation *op, 1267 SlapReply *rs 1268 ) 1269 { 1270 ber_tag_t *tptr = op->o_callback->sc_private; 1271 op->o_tag = *tptr; 1272 rs->sr_tag = slap_req2res( op->o_tag ); 1273 1274 return SLAP_CB_CONTINUE; 1275 } 1276 1277 /* 1278 * ldap_back_dobind_int 1279 * 1280 * Note: dolock indicates whether li->li_conninfo.lai_mutex must be locked or not 1281 */ 1282 static int 1283 ldap_back_dobind_int( 1284 ldapconn_t **lcp, 1285 Operation *op, 1286 SlapReply *rs, 1287 ldap_back_send_t sendok, 1288 int retries, 1289 int dolock ) 1290 { 1291 ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; 1292 1293 ldapconn_t *lc; 1294 struct berval binddn = slap_empty_bv, 1295 bindcred = slap_empty_bv; 1296 1297 int rc = 0, 1298 isbound, 1299 binding = 0; 1300 ber_int_t msgid; 1301 ber_tag_t o_tag = op->o_tag; 1302 slap_callback cb = {0}; 1303 char *tmp_dn; 1304 1305 assert( lcp != NULL ); 1306 assert( retries >= 0 ); 1307 1308 if ( sendok & LDAP_BACK_GETCONN ) { 1309 assert( *lcp == NULL ); 1310 1311 lc = ldap_back_getconn( op, rs, sendok, &binddn, &bindcred ); 1312 if ( lc == NULL ) { 1313 return 0; 1314 } 1315 *lcp = lc; 1316 1317 } else { 1318 lc = *lcp; 1319 } 1320 1321 assert( lc != NULL ); 1322 1323 retry_lock:; 1324 if ( dolock ) { 1325 ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); 1326 } 1327 1328 if ( binding == 0 ) { 1329 /* check if already bound */ 1330 rc = isbound = LDAP_BACK_CONN_ISBOUND( lc ); 1331 if ( isbound ) { 1332 if ( dolock ) { 1333 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 1334 } 1335 return rc; 1336 } 1337 1338 if ( LDAP_BACK_CONN_BINDING( lc ) ) { 1339 /* if someone else is about to bind it, give up and retry */ 1340 if ( dolock ) { 1341 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 1342 } 1343 ldap_pvt_thread_yield(); 1344 goto retry_lock; 1345 1346 } else { 1347 /* otherwise this thread will bind it */ 1348 LDAP_BACK_CONN_BINDING_SET( lc ); 1349 binding = 1; 1350 } 1351 } 1352 1353 if ( dolock ) { 1354 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 1355 } 1356 1357 /* 1358 * FIXME: we need to let clients use proxyAuthz 1359 * otherwise we cannot do symmetric pools of servers; 1360 * we have to live with the fact that a user can 1361 * authorize itself as any ID that is allowed 1362 * by the authzTo directive of the "proxyauthzdn". 1363 */ 1364 /* 1365 * NOTE: current Proxy Authorization specification 1366 * and implementation do not allow proxy authorization 1367 * control to be provided with Bind requests 1368 */ 1369 /* 1370 * if no bind took place yet, but the connection is bound 1371 * and the "idassert-authcDN" (or other ID) is set, 1372 * then bind as the asserting identity and explicitly 1373 * add the proxyAuthz control to every operation with the 1374 * dn bound to the connection as control value. 1375 * This is done also if this is the authorizing backend, 1376 * but the "override" flag is given to idassert. 1377 * It allows to use SASL bind and yet proxyAuthz users 1378 */ 1379 op->o_tag = LDAP_REQ_BIND; 1380 cb.sc_next = op->o_callback; 1381 cb.sc_private = &o_tag; 1382 cb.sc_response = ldap_back_dobind_cb; 1383 op->o_callback = &cb; 1384 1385 if ( LDAP_BACK_CONN_ISIDASSERT( lc ) ) { 1386 if ( BER_BVISEMPTY( &binddn ) && BER_BVISEMPTY( &bindcred ) ) { 1387 /* if we got here, it shouldn't return result */ 1388 rc = ldap_back_is_proxy_authz( op, rs, 1389 LDAP_BACK_DONTSEND, &binddn, &bindcred ); 1390 assert( rc == 1 ); 1391 } 1392 rc = ldap_back_proxy_authz_bind( lc, op, rs, sendok, &binddn, &bindcred ); 1393 goto done; 1394 } 1395 1396 #ifdef HAVE_CYRUS_SASL 1397 if ( LDAP_BACK_CONN_ISPRIV( lc ) 1398 && li->li_acl_authmethod == LDAP_AUTH_SASL ) 1399 { 1400 void *defaults = NULL; 1401 1402 if ( li->li_acl_secprops != NULL ) { 1403 rc = ldap_set_option( lc->lc_ld, 1404 LDAP_OPT_X_SASL_SECPROPS, li->li_acl_secprops ); 1405 1406 if ( rc != LDAP_OPT_SUCCESS ) { 1407 Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option " 1408 "(SECPROPS,\"%s\") failed!\n", 1409 li->li_acl_secprops, 0, 0 ); 1410 goto done; 1411 } 1412 } 1413 1414 defaults = lutil_sasl_defaults( lc->lc_ld, 1415 li->li_acl_sasl_mech.bv_val, 1416 li->li_acl_sasl_realm.bv_val, 1417 li->li_acl_authcID.bv_val, 1418 li->li_acl_passwd.bv_val, 1419 NULL ); 1420 if ( defaults == NULL ) { 1421 rs->sr_err = LDAP_OTHER; 1422 LDAP_BACK_CONN_ISBOUND_CLEAR( lc ); 1423 if ( sendok & LDAP_BACK_SENDERR ) { 1424 send_ldap_result( op, rs ); 1425 } 1426 goto done; 1427 } 1428 1429 rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld, 1430 li->li_acl_authcDN.bv_val, 1431 li->li_acl_sasl_mech.bv_val, NULL, NULL, 1432 LDAP_SASL_QUIET, lutil_sasl_interact, 1433 defaults ); 1434 1435 lutil_sasl_freedefs( defaults ); 1436 1437 switch ( rs->sr_err ) { 1438 case LDAP_SUCCESS: 1439 LDAP_BACK_CONN_ISBOUND_SET( lc ); 1440 break; 1441 1442 case LDAP_LOCAL_ERROR: 1443 /* list client API error codes that require 1444 * to taint the connection */ 1445 /* FIXME: should actually retry? */ 1446 LDAP_BACK_CONN_TAINTED_SET( lc ); 1447 1448 /* fallthru */ 1449 1450 default: 1451 LDAP_BACK_CONN_ISBOUND_CLEAR( lc ); 1452 rs->sr_err = slap_map_api2result( rs ); 1453 if ( sendok & LDAP_BACK_SENDERR ) { 1454 send_ldap_result( op, rs ); 1455 } 1456 break; 1457 } 1458 1459 if ( LDAP_BACK_QUARANTINE( li ) ) { 1460 ldap_back_quarantine( op, rs ); 1461 } 1462 1463 goto done; 1464 } 1465 #endif /* HAVE_CYRUS_SASL */ 1466 1467 retry:; 1468 if ( BER_BVISNULL( &lc->lc_cred ) ) { 1469 tmp_dn = ""; 1470 if ( !BER_BVISNULL( &lc->lc_bound_ndn ) && !BER_BVISEMPTY( &lc->lc_bound_ndn ) ) { 1471 Debug( LDAP_DEBUG_ANY, "%s ldap_back_dobind_int: DN=\"%s\" without creds, binding anonymously", 1472 op->o_log_prefix, lc->lc_bound_ndn.bv_val, 0 ); 1473 } 1474 1475 } else { 1476 tmp_dn = lc->lc_bound_ndn.bv_val; 1477 } 1478 rs->sr_err = ldap_sasl_bind( lc->lc_ld, 1479 tmp_dn, 1480 LDAP_SASL_SIMPLE, &lc->lc_cred, 1481 NULL, NULL, &msgid ); 1482 1483 if ( rs->sr_err == LDAP_SERVER_DOWN ) { 1484 if ( retries != LDAP_BACK_RETRY_NEVER ) { 1485 if ( dolock ) { 1486 ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); 1487 } 1488 1489 assert( lc->lc_refcnt > 0 ); 1490 if ( lc->lc_refcnt == 1 ) { 1491 ldap_unbind_ext( lc->lc_ld, NULL, NULL ); 1492 lc->lc_ld = NULL; 1493 1494 /* lc here must be the regular lc, reset and ready for init */ 1495 rs->sr_err = ldap_back_prepare_conn( lc, op, rs, sendok ); 1496 if ( rs->sr_err != LDAP_SUCCESS ) { 1497 sendok &= ~LDAP_BACK_SENDERR; 1498 lc->lc_refcnt = 0; 1499 } 1500 } 1501 1502 if ( dolock ) { 1503 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 1504 } 1505 1506 if ( rs->sr_err == LDAP_SUCCESS ) { 1507 if ( retries > 0 ) { 1508 retries--; 1509 } 1510 goto retry; 1511 } 1512 } 1513 1514 assert( lc->lc_refcnt == 1 ); 1515 lc->lc_refcnt = 0; 1516 ldap_back_freeconn( li, lc, dolock ); 1517 *lcp = NULL; 1518 rs->sr_err = slap_map_api2result( rs ); 1519 1520 if ( LDAP_BACK_QUARANTINE( li ) ) { 1521 ldap_back_quarantine( op, rs ); 1522 } 1523 1524 if ( rs->sr_err != LDAP_SUCCESS && 1525 ( sendok & LDAP_BACK_SENDERR ) ) 1526 { 1527 if ( op->o_callback == &cb ) 1528 op->o_callback = cb.sc_next; 1529 op->o_tag = o_tag; 1530 rs->sr_text = "Proxy can't contact remote server"; 1531 send_ldap_result( op, rs ); 1532 } 1533 1534 rc = 0; 1535 goto func_leave; 1536 } 1537 1538 rc = ldap_back_op_result( lc, op, rs, msgid, 1539 -1, ( sendok | LDAP_BACK_BINDING ) ); 1540 if ( rc == LDAP_SUCCESS ) { 1541 op->o_conn->c_authz_cookie = op->o_bd->be_private; 1542 LDAP_BACK_CONN_ISBOUND_SET( lc ); 1543 } 1544 1545 done:; 1546 LDAP_BACK_CONN_BINDING_CLEAR( lc ); 1547 rc = LDAP_BACK_CONN_ISBOUND( lc ); 1548 if ( !rc ) { 1549 ldap_back_release_conn_lock( li, lcp, dolock ); 1550 1551 } else if ( LDAP_BACK_SAVECRED( li ) ) { 1552 ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc ); 1553 } 1554 1555 func_leave:; 1556 if ( op->o_callback == &cb ) 1557 op->o_callback = cb.sc_next; 1558 op->o_tag = o_tag; 1559 1560 return rc; 1561 } 1562 1563 /* 1564 * ldap_back_dobind 1565 * 1566 * Note: dolock indicates whether li->li_conninfo.lai_mutex must be locked or not 1567 */ 1568 int 1569 ldap_back_dobind( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok ) 1570 { 1571 ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; 1572 1573 return ldap_back_dobind_int( lcp, op, rs, 1574 ( sendok | LDAP_BACK_GETCONN ), li->li_nretries, 1 ); 1575 } 1576 1577 /* 1578 * ldap_back_default_rebind 1579 * 1580 * This is a callback used for chasing referrals using the same 1581 * credentials as the original user on this session. 1582 */ 1583 int 1584 ldap_back_default_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request, 1585 ber_int_t msgid, void *params ) 1586 { 1587 ldapconn_t *lc = (ldapconn_t *)params; 1588 1589 #ifdef HAVE_TLS 1590 /* ... otherwise we couldn't get here */ 1591 assert( lc != NULL ); 1592 1593 if ( !ldap_tls_inplace( ld ) ) { 1594 int is_tls = LDAP_BACK_CONN_ISTLS( lc ), 1595 rc; 1596 const char *text = NULL; 1597 1598 rc = ldap_back_start_tls( ld, 0, &is_tls, url, lc->lc_flags, 1599 LDAP_BACK_RETRY_DEFAULT, &text ); 1600 if ( rc != LDAP_SUCCESS ) { 1601 return rc; 1602 } 1603 } 1604 #endif /* HAVE_TLS */ 1605 1606 /* FIXME: add checks on the URL/identity? */ 1607 1608 return ldap_sasl_bind_s( ld, 1609 BER_BVISNULL( &lc->lc_cred ) ? "" : lc->lc_bound_ndn.bv_val, 1610 LDAP_SASL_SIMPLE, &lc->lc_cred, NULL, NULL, NULL ); 1611 } 1612 1613 /* 1614 * ldap_back_default_urllist 1615 */ 1616 int 1617 ldap_back_default_urllist( 1618 LDAP *ld, 1619 LDAPURLDesc **urllist, 1620 LDAPURLDesc **url, 1621 void *params ) 1622 { 1623 ldapinfo_t *li = (ldapinfo_t *)params; 1624 LDAPURLDesc **urltail; 1625 1626 if ( urllist == url ) { 1627 return LDAP_SUCCESS; 1628 } 1629 1630 for ( urltail = &(*url)->lud_next; *urltail; urltail = &(*urltail)->lud_next ) 1631 /* count */ ; 1632 1633 *urltail = *urllist; 1634 *urllist = *url; 1635 *url = NULL; 1636 1637 if ( !li->li_uri_mutex_do_not_lock ) { 1638 ldap_pvt_thread_mutex_lock( &li->li_uri_mutex ); 1639 } 1640 1641 if ( li->li_uri ) { 1642 ch_free( li->li_uri ); 1643 } 1644 1645 ldap_get_option( ld, LDAP_OPT_URI, (void *)&li->li_uri ); 1646 1647 if ( !li->li_uri_mutex_do_not_lock ) { 1648 ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex ); 1649 } 1650 1651 return LDAP_SUCCESS; 1652 } 1653 1654 int 1655 ldap_back_cancel( 1656 ldapconn_t *lc, 1657 Operation *op, 1658 SlapReply *rs, 1659 ber_int_t msgid, 1660 ldap_back_send_t sendok ) 1661 { 1662 ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; 1663 1664 /* default behavior */ 1665 if ( LDAP_BACK_ABANDON( li ) ) { 1666 return ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL ); 1667 } 1668 1669 if ( LDAP_BACK_IGNORE( li ) ) { 1670 return ldap_pvt_discard( lc->lc_ld, msgid ); 1671 } 1672 1673 if ( LDAP_BACK_CANCEL( li ) ) { 1674 /* FIXME: asynchronous? */ 1675 return ldap_cancel_s( lc->lc_ld, msgid, NULL, NULL ); 1676 } 1677 1678 assert( 0 ); 1679 1680 return LDAP_OTHER; 1681 } 1682 1683 int 1684 ldap_back_op_result( 1685 ldapconn_t *lc, 1686 Operation *op, 1687 SlapReply *rs, 1688 ber_int_t msgid, 1689 time_t timeout, 1690 ldap_back_send_t sendok ) 1691 { 1692 ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; 1693 1694 char *match = NULL; 1695 char *text = NULL; 1696 char **refs = NULL; 1697 LDAPControl **ctrls = NULL; 1698 1699 rs->sr_text = NULL; 1700 rs->sr_matched = NULL; 1701 rs->sr_ref = NULL; 1702 rs->sr_ctrls = NULL; 1703 1704 /* if the error recorded in the reply corresponds 1705 * to a successful state, get the error from the 1706 * remote server response */ 1707 if ( LDAP_ERR_OK( rs->sr_err ) ) { 1708 int rc; 1709 struct timeval tv; 1710 LDAPMessage *res = NULL; 1711 time_t stoptime = (time_t)(-1); 1712 int timeout_err = op->o_protocol >= LDAP_VERSION3 ? 1713 LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER; 1714 const char *timeout_text = "Operation timed out"; 1715 1716 /* if timeout is not specified, compute and use 1717 * the one specific to the ongoing operation */ 1718 if ( timeout == (time_t)(-1) ) { 1719 slap_op_t opidx = slap_req2op( op->o_tag ); 1720 1721 if ( opidx == SLAP_OP_SEARCH ) { 1722 if ( op->ors_tlimit <= 0 ) { 1723 timeout = 0; 1724 1725 } else { 1726 timeout = op->ors_tlimit; 1727 timeout_err = LDAP_TIMELIMIT_EXCEEDED; 1728 timeout_text = NULL; 1729 } 1730 1731 } else { 1732 timeout = li->li_timeout[ opidx ]; 1733 } 1734 } 1735 1736 /* better than nothing :) */ 1737 if ( timeout == 0 ) { 1738 if ( li->li_idle_timeout ) { 1739 timeout = li->li_idle_timeout; 1740 1741 } else if ( li->li_conn_ttl ) { 1742 timeout = li->li_conn_ttl; 1743 } 1744 } 1745 1746 if ( timeout ) { 1747 stoptime = op->o_time + timeout; 1748 } 1749 1750 LDAP_BACK_TV_SET( &tv ); 1751 1752 retry:; 1753 /* if result parsing fails, note the failure reason */ 1754 rc = ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res ); 1755 switch ( rc ) { 1756 case 0: 1757 if ( timeout && slap_get_time() > stoptime ) { 1758 if ( sendok & LDAP_BACK_BINDING ) { 1759 ldap_unbind_ext( lc->lc_ld, NULL, NULL ); 1760 lc->lc_ld = NULL; 1761 1762 /* let it be used, but taint/delete it so that 1763 * no-one else can look it up any further */ 1764 ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); 1765 1766 #if LDAP_BACK_PRINT_CONNTREE > 0 1767 ldap_back_print_conntree( li, ">>> ldap_back_getconn(timeout)" ); 1768 #endif /* LDAP_BACK_PRINT_CONNTREE */ 1769 1770 (void)ldap_back_conn_delete( li, lc ); 1771 LDAP_BACK_CONN_TAINTED_SET( lc ); 1772 1773 #if LDAP_BACK_PRINT_CONNTREE > 0 1774 ldap_back_print_conntree( li, "<<< ldap_back_getconn(timeout)" ); 1775 #endif /* LDAP_BACK_PRINT_CONNTREE */ 1776 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 1777 1778 } else { 1779 (void)ldap_back_cancel( lc, op, rs, msgid, sendok ); 1780 } 1781 rs->sr_err = timeout_err; 1782 rs->sr_text = timeout_text; 1783 break; 1784 } 1785 1786 /* timeout == 0 */ 1787 LDAP_BACK_TV_SET( &tv ); 1788 ldap_pvt_thread_yield(); 1789 goto retry; 1790 1791 case -1: 1792 ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, 1793 &rs->sr_err ); 1794 break; 1795 1796 1797 /* otherwise get the result; if it is not 1798 * LDAP_SUCCESS, record it in the reply 1799 * structure (this includes 1800 * LDAP_COMPARE_{TRUE|FALSE}) */ 1801 default: 1802 /* only touch when activity actually took place... */ 1803 if ( li->li_idle_timeout && lc ) { 1804 lc->lc_time = op->o_time; 1805 } 1806 1807 rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, 1808 &match, &text, &refs, &ctrls, 1 ); 1809 rs->sr_text = text; 1810 if ( rc != LDAP_SUCCESS ) { 1811 rs->sr_err = rc; 1812 } 1813 1814 /* RFC 4511: referrals can only appear 1815 * if result code is LDAP_REFERRAL */ 1816 if ( refs != NULL 1817 && refs[ 0 ] != NULL 1818 && refs[ 0 ][ 0 ] != '\0' ) 1819 { 1820 if ( rs->sr_err != LDAP_REFERRAL ) { 1821 Debug( LDAP_DEBUG_ANY, 1822 "%s ldap_back_op_result: " 1823 "got referrals with err=%d\n", 1824 op->o_log_prefix, 1825 rs->sr_err, 0 ); 1826 1827 } else { 1828 int i; 1829 1830 for ( i = 0; refs[ i ] != NULL; i++ ) 1831 /* count */ ; 1832 rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ), 1833 op->o_tmpmemctx ); 1834 for ( i = 0; refs[ i ] != NULL; i++ ) { 1835 ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] ); 1836 } 1837 BER_BVZERO( &rs->sr_ref[ i ] ); 1838 } 1839 1840 } else if ( rs->sr_err == LDAP_REFERRAL ) { 1841 Debug( LDAP_DEBUG_ANY, 1842 "%s ldap_back_op_result: " 1843 "got err=%d with null " 1844 "or empty referrals\n", 1845 op->o_log_prefix, 1846 rs->sr_err, 0 ); 1847 1848 rs->sr_err = LDAP_NO_SUCH_OBJECT; 1849 } 1850 1851 if ( ctrls != NULL ) { 1852 rs->sr_ctrls = ctrls; 1853 } 1854 } 1855 } 1856 1857 /* if the error in the reply structure is not 1858 * LDAP_SUCCESS, try to map it from client 1859 * to server error */ 1860 if ( !LDAP_ERR_OK( rs->sr_err ) ) { 1861 rs->sr_err = slap_map_api2result( rs ); 1862 1863 /* internal ops ( op->o_conn == NULL ) 1864 * must not reply to client */ 1865 if ( op->o_conn && !op->o_do_not_cache && match ) { 1866 1867 /* record the (massaged) matched 1868 * DN into the reply structure */ 1869 rs->sr_matched = match; 1870 } 1871 } 1872 1873 if ( rs->sr_err == LDAP_UNAVAILABLE ) { 1874 if ( !( sendok & LDAP_BACK_RETRYING ) ) { 1875 if ( LDAP_BACK_QUARANTINE( li ) ) { 1876 ldap_back_quarantine( op, rs ); 1877 } 1878 if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) { 1879 if ( rs->sr_text == NULL ) rs->sr_text = "Proxy operation retry failed"; 1880 send_ldap_result( op, rs ); 1881 } 1882 } 1883 1884 } else if ( op->o_conn && 1885 ( ( ( sendok & LDAP_BACK_SENDOK ) && LDAP_ERR_OK( rs->sr_err ) ) 1886 || ( ( sendok & LDAP_BACK_SENDERR ) && !LDAP_ERR_OK( rs->sr_err ) ) ) ) 1887 { 1888 send_ldap_result( op, rs ); 1889 } 1890 1891 if ( text ) { 1892 ldap_memfree( text ); 1893 } 1894 rs->sr_text = NULL; 1895 1896 /* there can't be refs with a (successful) bind */ 1897 if ( rs->sr_ref ) { 1898 op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx ); 1899 rs->sr_ref = NULL; 1900 } 1901 1902 if ( refs ) { 1903 ber_memvfree( (void **)refs ); 1904 } 1905 1906 /* match should not be possible with a successful bind */ 1907 if ( match ) { 1908 if ( rs->sr_matched != match ) { 1909 free( (char *)rs->sr_matched ); 1910 } 1911 rs->sr_matched = NULL; 1912 ldap_memfree( match ); 1913 } 1914 1915 if ( ctrls != NULL ) { 1916 if ( op->o_tag == LDAP_REQ_BIND && rs->sr_err == LDAP_SUCCESS ) { 1917 int i; 1918 1919 for ( i = 0; ctrls[i] != NULL; i++ ); 1920 1921 rs->sr_ctrls = op->o_tmpalloc( sizeof( LDAPControl * )*( i + 1 ), 1922 op->o_tmpmemctx ); 1923 for ( i = 0; ctrls[ i ] != NULL; i++ ) { 1924 char *ptr; 1925 ber_len_t oidlen = strlen( ctrls[i]->ldctl_oid ); 1926 ber_len_t size = sizeof( LDAPControl ) 1927 + oidlen + 1 1928 + ctrls[i]->ldctl_value.bv_len + 1; 1929 1930 rs->sr_ctrls[ i ] = op->o_tmpalloc( size, op->o_tmpmemctx ); 1931 rs->sr_ctrls[ i ]->ldctl_oid = (char *)&rs->sr_ctrls[ i ][ 1 ]; 1932 lutil_strcopy( rs->sr_ctrls[ i ]->ldctl_oid, ctrls[i]->ldctl_oid ); 1933 rs->sr_ctrls[ i ]->ldctl_value.bv_val 1934 = (char *)&rs->sr_ctrls[ i ]->ldctl_oid[oidlen + 1]; 1935 rs->sr_ctrls[ i ]->ldctl_value.bv_len 1936 = ctrls[i]->ldctl_value.bv_len; 1937 ptr = lutil_memcopy( rs->sr_ctrls[ i ]->ldctl_value.bv_val, 1938 ctrls[i]->ldctl_value.bv_val, ctrls[i]->ldctl_value.bv_len ); 1939 *ptr = '\0'; 1940 } 1941 rs->sr_ctrls[ i ] = NULL; 1942 rs->sr_flags |= REP_CTRLS_MUSTBEFREED; 1943 1944 } else { 1945 assert( rs->sr_ctrls != NULL ); 1946 rs->sr_ctrls = NULL; 1947 } 1948 1949 ldap_controls_free( ctrls ); 1950 } 1951 1952 return( LDAP_ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err ); 1953 } 1954 1955 /* return true if bound, false if failed */ 1956 int 1957 ldap_back_retry( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok ) 1958 { 1959 ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; 1960 int rc = 0; 1961 1962 assert( lcp != NULL ); 1963 assert( *lcp != NULL ); 1964 1965 ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); 1966 1967 if ( (*lcp)->lc_refcnt == 1 ) { 1968 int binding = LDAP_BACK_CONN_BINDING( *lcp ); 1969 1970 ldap_pvt_thread_mutex_lock( &li->li_uri_mutex ); 1971 Debug( LDAP_DEBUG_ANY, 1972 "%s ldap_back_retry: retrying URI=\"%s\" DN=\"%s\"\n", 1973 op->o_log_prefix, li->li_uri, 1974 BER_BVISNULL( &(*lcp)->lc_bound_ndn ) ? 1975 "" : (*lcp)->lc_bound_ndn.bv_val ); 1976 ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex ); 1977 1978 ldap_unbind_ext( (*lcp)->lc_ld, NULL, NULL ); 1979 (*lcp)->lc_ld = NULL; 1980 LDAP_BACK_CONN_ISBOUND_CLEAR( (*lcp) ); 1981 1982 /* lc here must be the regular lc, reset and ready for init */ 1983 rc = ldap_back_prepare_conn( *lcp, op, rs, sendok ); 1984 if ( rc != LDAP_SUCCESS ) { 1985 /* freeit, because lc_refcnt == 1 */ 1986 (*lcp)->lc_refcnt = 0; 1987 (void)ldap_back_freeconn( li, *lcp, 0 ); 1988 *lcp = NULL; 1989 rc = 0; 1990 1991 } else if ( ( sendok & LDAP_BACK_BINDING ) ) { 1992 if ( binding ) { 1993 LDAP_BACK_CONN_BINDING_SET( *lcp ); 1994 } 1995 rc = 1; 1996 1997 } else { 1998 rc = ldap_back_dobind_int( lcp, op, rs, sendok, 0, 0 ); 1999 if ( rc == 0 && *lcp != NULL ) { 2000 /* freeit, because lc_refcnt == 1 */ 2001 (*lcp)->lc_refcnt = 0; 2002 LDAP_BACK_CONN_TAINTED_SET( *lcp ); 2003 (void)ldap_back_freeconn( li, *lcp, 0 ); 2004 *lcp = NULL; 2005 } 2006 } 2007 2008 } else { 2009 Debug( LDAP_DEBUG_TRACE, 2010 "ldap_back_retry: conn %p refcnt=%u unable to retry.\n", 2011 (void *)(*lcp), (*lcp)->lc_refcnt, 0 ); 2012 2013 LDAP_BACK_CONN_TAINTED_SET( *lcp ); 2014 ldap_back_release_conn_lock( li, lcp, 0 ); 2015 assert( *lcp == NULL ); 2016 2017 if ( sendok & LDAP_BACK_SENDERR ) { 2018 rs->sr_err = LDAP_UNAVAILABLE; 2019 rs->sr_text = "Unable to retry"; 2020 send_ldap_result( op, rs ); 2021 } 2022 } 2023 2024 ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); 2025 2026 return rc; 2027 } 2028 2029 static int 2030 ldap_back_is_proxy_authz( Operation *op, SlapReply *rs, ldap_back_send_t sendok, 2031 struct berval *binddn, struct berval *bindcred ) 2032 { 2033 ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; 2034 struct berval ndn; 2035 int dobind = 0; 2036 2037 if ( op->o_conn == NULL || op->o_do_not_cache ) { 2038 goto done; 2039 } 2040 2041 /* don't proxyAuthz if protocol is not LDAPv3 */ 2042 switch ( li->li_version ) { 2043 case LDAP_VERSION3: 2044 break; 2045 2046 case 0: 2047 if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) { 2048 break; 2049 } 2050 /* fall thru */ 2051 2052 default: 2053 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 2054 if ( sendok & LDAP_BACK_SENDERR ) { 2055 send_ldap_result( op, rs ); 2056 dobind = -1; 2057 } 2058 goto done; 2059 } 2060 2061 /* safe default */ 2062 *binddn = slap_empty_bv; 2063 *bindcred = slap_empty_bv; 2064 2065 if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) { 2066 ndn = op->o_conn->c_ndn; 2067 2068 } else { 2069 ndn = op->o_ndn; 2070 } 2071 2072 switch ( li->li_idassert_mode ) { 2073 case LDAP_BACK_IDASSERT_LEGACY: 2074 if ( !BER_BVISNULL( &ndn ) && !BER_BVISEMPTY( &ndn ) ) { 2075 if ( !BER_BVISNULL( &li->li_idassert_authcDN ) && !BER_BVISEMPTY( &li->li_idassert_authcDN ) ) 2076 { 2077 *binddn = li->li_idassert_authcDN; 2078 *bindcred = li->li_idassert_passwd; 2079 dobind = 1; 2080 } 2081 } 2082 break; 2083 2084 default: 2085 /* NOTE: rootdn can always idassert */ 2086 if ( BER_BVISNULL( &ndn ) 2087 && li->li_idassert_authz == NULL 2088 && !( li->li_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) 2089 { 2090 if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { 2091 rs->sr_err = LDAP_INAPPROPRIATE_AUTH; 2092 if ( sendok & LDAP_BACK_SENDERR ) { 2093 send_ldap_result( op, rs ); 2094 dobind = -1; 2095 } 2096 2097 } else { 2098 rs->sr_err = LDAP_SUCCESS; 2099 *binddn = slap_empty_bv; 2100 *bindcred = slap_empty_bv; 2101 break; 2102 } 2103 2104 goto done; 2105 2106 } else if ( !be_isroot( op ) ) { 2107 if ( li->li_idassert_passthru ) { 2108 struct berval authcDN; 2109 2110 if ( BER_BVISNULL( &ndn ) ) { 2111 authcDN = slap_empty_bv; 2112 2113 } else { 2114 authcDN = ndn; 2115 } 2116 rs->sr_err = slap_sasl_matches( op, li->li_idassert_passthru, 2117 &authcDN, &authcDN ); 2118 if ( rs->sr_err == LDAP_SUCCESS ) { 2119 dobind = 0; 2120 break; 2121 } 2122 } 2123 2124 if ( li->li_idassert_authz ) { 2125 struct berval authcDN; 2126 2127 if ( BER_BVISNULL( &ndn ) ) { 2128 authcDN = slap_empty_bv; 2129 2130 } else { 2131 authcDN = ndn; 2132 } 2133 rs->sr_err = slap_sasl_matches( op, li->li_idassert_authz, 2134 &authcDN, &authcDN ); 2135 if ( rs->sr_err != LDAP_SUCCESS ) { 2136 if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { 2137 if ( sendok & LDAP_BACK_SENDERR ) { 2138 send_ldap_result( op, rs ); 2139 dobind = -1; 2140 } 2141 2142 } else { 2143 rs->sr_err = LDAP_SUCCESS; 2144 *binddn = slap_empty_bv; 2145 *bindcred = slap_empty_bv; 2146 break; 2147 } 2148 2149 goto done; 2150 } 2151 } 2152 } 2153 2154 *binddn = li->li_idassert_authcDN; 2155 *bindcred = li->li_idassert_passwd; 2156 dobind = 1; 2157 break; 2158 } 2159 2160 done:; 2161 return dobind; 2162 } 2163 2164 static int 2165 ldap_back_proxy_authz_bind( 2166 ldapconn_t *lc, 2167 Operation *op, 2168 SlapReply *rs, 2169 ldap_back_send_t sendok, 2170 struct berval *binddn, 2171 struct berval *bindcred ) 2172 { 2173 ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; 2174 struct berval ndn; 2175 int msgid; 2176 int rc; 2177 2178 if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) { 2179 ndn = op->o_conn->c_ndn; 2180 2181 } else { 2182 ndn = op->o_ndn; 2183 } 2184 2185 if ( li->li_idassert_authmethod == LDAP_AUTH_SASL ) { 2186 #ifdef HAVE_CYRUS_SASL 2187 void *defaults = NULL; 2188 struct berval authzID = BER_BVNULL; 2189 int freeauthz = 0; 2190 2191 /* if SASL supports native authz, prepare for it */ 2192 if ( ( !op->o_do_not_cache || !op->o_is_auth_check ) && 2193 ( li->li_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) ) 2194 { 2195 switch ( li->li_idassert_mode ) { 2196 case LDAP_BACK_IDASSERT_OTHERID: 2197 case LDAP_BACK_IDASSERT_OTHERDN: 2198 authzID = li->li_idassert_authzID; 2199 break; 2200 2201 case LDAP_BACK_IDASSERT_ANONYMOUS: 2202 BER_BVSTR( &authzID, "dn:" ); 2203 break; 2204 2205 case LDAP_BACK_IDASSERT_SELF: 2206 if ( BER_BVISNULL( &ndn ) ) { 2207 /* connection is not authc'd, so don't idassert */ 2208 BER_BVSTR( &authzID, "dn:" ); 2209 break; 2210 } 2211 authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len; 2212 authzID.bv_val = slap_sl_malloc( authzID.bv_len + 1, op->o_tmpmemctx ); 2213 AC_MEMCPY( authzID.bv_val, "dn:", STRLENOF( "dn:" ) ); 2214 AC_MEMCPY( authzID.bv_val + STRLENOF( "dn:" ), 2215 ndn.bv_val, ndn.bv_len + 1 ); 2216 freeauthz = 1; 2217 break; 2218 2219 default: 2220 break; 2221 } 2222 } 2223 2224 if ( li->li_idassert_secprops != NULL ) { 2225 rs->sr_err = ldap_set_option( lc->lc_ld, 2226 LDAP_OPT_X_SASL_SECPROPS, 2227 (void *)li->li_idassert_secprops ); 2228 2229 if ( rs->sr_err != LDAP_OPT_SUCCESS ) { 2230 rs->sr_err = LDAP_OTHER; 2231 if ( sendok & LDAP_BACK_SENDERR ) { 2232 send_ldap_result( op, rs ); 2233 } 2234 LDAP_BACK_CONN_ISBOUND_CLEAR( lc ); 2235 goto done; 2236 } 2237 } 2238 2239 defaults = lutil_sasl_defaults( lc->lc_ld, 2240 li->li_idassert_sasl_mech.bv_val, 2241 li->li_idassert_sasl_realm.bv_val, 2242 li->li_idassert_authcID.bv_val, 2243 li->li_idassert_passwd.bv_val, 2244 authzID.bv_val ); 2245 if ( defaults == NULL ) { 2246 rs->sr_err = LDAP_OTHER; 2247 LDAP_BACK_CONN_ISBOUND_CLEAR( lc ); 2248 if ( sendok & LDAP_BACK_SENDERR ) { 2249 send_ldap_result( op, rs ); 2250 } 2251 goto done; 2252 } 2253 2254 rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld, binddn->bv_val, 2255 li->li_idassert_sasl_mech.bv_val, NULL, NULL, 2256 LDAP_SASL_QUIET, lutil_sasl_interact, 2257 defaults ); 2258 2259 switch ( rs->sr_err ) { 2260 case LDAP_SUCCESS: 2261 LDAP_BACK_CONN_ISBOUND_SET( lc ); 2262 break; 2263 2264 case LDAP_LOCAL_ERROR: 2265 /* list client API error codes that require 2266 * to taint the connection */ 2267 /* FIXME: should actually retry? */ 2268 LDAP_BACK_CONN_TAINTED_SET( lc ); 2269 2270 /* fallthru */ 2271 2272 default: 2273 LDAP_BACK_CONN_ISBOUND_CLEAR( lc ); 2274 rs->sr_err = slap_map_api2result( rs ); 2275 if ( sendok & LDAP_BACK_SENDERR ) { 2276 send_ldap_result( op, rs ); 2277 } 2278 break; 2279 } 2280 2281 lutil_sasl_freedefs( defaults ); 2282 if ( freeauthz ) { 2283 slap_sl_free( authzID.bv_val, op->o_tmpmemctx ); 2284 } 2285 2286 goto done; 2287 #endif /* HAVE_CYRUS_SASL */ 2288 } 2289 2290 switch ( li->li_idassert_authmethod ) { 2291 case LDAP_AUTH_NONE: 2292 /* FIXME: do we really need this? */ 2293 BER_BVSTR( binddn, "" ); 2294 BER_BVSTR( bindcred, "" ); 2295 /* fallthru */ 2296 2297 case LDAP_AUTH_SIMPLE: 2298 rs->sr_err = ldap_sasl_bind( lc->lc_ld, 2299 binddn->bv_val, LDAP_SASL_SIMPLE, 2300 bindcred, NULL, NULL, &msgid ); 2301 rc = ldap_back_op_result( lc, op, rs, msgid, 2302 -1, ( sendok | LDAP_BACK_BINDING ) ); 2303 break; 2304 2305 default: 2306 /* unsupported! */ 2307 LDAP_BACK_CONN_ISBOUND_CLEAR( lc ); 2308 rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED; 2309 if ( sendok & LDAP_BACK_SENDERR ) { 2310 send_ldap_result( op, rs ); 2311 } 2312 goto done; 2313 } 2314 2315 if ( rc == LDAP_SUCCESS ) { 2316 /* set rebind stuff in case of successful proxyAuthz bind, 2317 * so that referral chasing is attempted using the right 2318 * identity */ 2319 LDAP_BACK_CONN_ISBOUND_SET( lc ); 2320 op->o_conn->c_authz_cookie = op->o_bd->be_private; 2321 if ( !BER_BVISNULL( binddn ) ) { 2322 ber_bvreplace( &lc->lc_bound_ndn, binddn ); 2323 } 2324 2325 if ( !BER_BVISNULL( &lc->lc_cred ) ) { 2326 memset( lc->lc_cred.bv_val, 0, 2327 lc->lc_cred.bv_len ); 2328 } 2329 2330 if ( LDAP_BACK_SAVECRED( li ) ) { 2331 if ( !BER_BVISNULL( bindcred ) ) { 2332 ber_bvreplace( &lc->lc_cred, bindcred ); 2333 ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc ); 2334 } 2335 2336 } else { 2337 lc->lc_cred.bv_len = 0; 2338 } 2339 } 2340 done:; 2341 return LDAP_BACK_CONN_ISBOUND( lc ); 2342 } 2343 2344 /* 2345 * ldap_back_proxy_authz_ctrl() prepends a proxyAuthz control 2346 * to existing server-side controls if required; if not, 2347 * the existing server-side controls are placed in *pctrls. 2348 * The caller, after using the controls in client API 2349 * operations, if ( *pctrls != op->o_ctrls ), should 2350 * free( (*pctrls)[ 0 ] ) and free( *pctrls ). 2351 * The function returns success if the control could 2352 * be added if required, or if it did nothing; in the future, 2353 * it might return some error if it failed. 2354 * 2355 * if no bind took place yet, but the connection is bound 2356 * and the "proxyauthzdn" is set, then bind as "proxyauthzdn" 2357 * and explicitly add proxyAuthz the control to every operation 2358 * with the dn bound to the connection as control value. 2359 * 2360 * If no server-side controls are defined for the operation, 2361 * simply add the proxyAuthz control; otherwise, if the 2362 * proxyAuthz control is not already set, add it as 2363 * the first one 2364 * 2365 * FIXME: is controls order significant for security? 2366 * ANSWER: controls ordering and interoperability 2367 * must be indicated by the specs of each control; if none 2368 * is specified, the order is irrelevant. 2369 */ 2370 int 2371 ldap_back_proxy_authz_ctrl( 2372 Operation *op, 2373 SlapReply *rs, 2374 struct berval *bound_ndn, 2375 int version, 2376 slap_idassert_t *si, 2377 LDAPControl *ctrl ) 2378 { 2379 slap_idassert_mode_t mode; 2380 struct berval assertedID, 2381 ndn; 2382 int isroot = 0; 2383 2384 rs->sr_err = SLAP_CB_CONTINUE; 2385 2386 /* FIXME: SASL/EXTERNAL over ldapi:// doesn't honor the authcID, 2387 * but if it is not set this test fails. We need a different 2388 * means to detect if idassert is enabled */ 2389 if ( ( BER_BVISNULL( &si->si_bc.sb_authcId ) || BER_BVISEMPTY( &si->si_bc.sb_authcId ) ) 2390 && ( BER_BVISNULL( &si->si_bc.sb_binddn ) || BER_BVISEMPTY( &si->si_bc.sb_binddn ) ) 2391 && BER_BVISNULL( &si->si_bc.sb_saslmech ) ) 2392 { 2393 goto done; 2394 } 2395 2396 if ( !op->o_conn || op->o_do_not_cache || ( isroot = be_isroot( op ) ) ) { 2397 goto done; 2398 } 2399 2400 if ( op->o_tag == LDAP_REQ_BIND ) { 2401 ndn = op->o_req_ndn; 2402 2403 } else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) { 2404 ndn = op->o_conn->c_ndn; 2405 2406 } else { 2407 ndn = op->o_ndn; 2408 } 2409 2410 if ( si->si_mode == LDAP_BACK_IDASSERT_LEGACY ) { 2411 if ( op->o_proxy_authz ) { 2412 /* 2413 * FIXME: we do not want to perform proxyAuthz 2414 * on behalf of the client, because this would 2415 * be performed with "proxyauthzdn" privileges. 2416 * 2417 * This might actually be too strict, since 2418 * the "proxyauthzdn" authzTo, and each entry's 2419 * authzFrom attributes may be crafted 2420 * to avoid unwanted proxyAuthz to take place. 2421 */ 2422 #if 0 2423 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 2424 rs->sr_text = "proxyAuthz not allowed within namingContext"; 2425 #endif 2426 goto done; 2427 } 2428 2429 if ( !BER_BVISNULL( bound_ndn ) ) { 2430 goto done; 2431 } 2432 2433 if ( BER_BVISNULL( &ndn ) ) { 2434 goto done; 2435 } 2436 2437 if ( BER_BVISNULL( &si->si_bc.sb_binddn ) ) { 2438 goto done; 2439 } 2440 2441 } else if ( si->si_bc.sb_method == LDAP_AUTH_SASL ) { 2442 if ( ( si->si_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) ) 2443 { 2444 /* already asserted in SASL via native authz */ 2445 goto done; 2446 } 2447 2448 } else if ( si->si_authz && !isroot ) { 2449 int rc; 2450 struct berval authcDN; 2451 2452 if ( BER_BVISNULL( &ndn ) ) { 2453 authcDN = slap_empty_bv; 2454 } else { 2455 authcDN = ndn; 2456 } 2457 rc = slap_sasl_matches( op, si->si_authz, 2458 &authcDN, &authcDN ); 2459 if ( rc != LDAP_SUCCESS ) { 2460 if ( si->si_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { 2461 /* ndn is not authorized 2462 * to use idassert */ 2463 rs->sr_err = rc; 2464 } 2465 goto done; 2466 } 2467 } 2468 2469 if ( op->o_proxy_authz ) { 2470 /* 2471 * FIXME: we can: 2472 * 1) ignore the already set proxyAuthz control 2473 * 2) leave it in place, and don't set ours 2474 * 3) add both 2475 * 4) reject the operation 2476 * 2477 * option (4) is very drastic 2478 * option (3) will make the remote server reject 2479 * the operation, thus being equivalent to (4) 2480 * option (2) will likely break the idassert 2481 * assumptions, so we cannot accept it; 2482 * option (1) means that we are contradicting 2483 * the client's reques. 2484 * 2485 * I think (4) is the only correct choice. 2486 */ 2487 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 2488 rs->sr_text = "proxyAuthz not allowed within namingContext"; 2489 } 2490 2491 if ( op->o_is_auth_check ) { 2492 mode = LDAP_BACK_IDASSERT_NOASSERT; 2493 2494 } else { 2495 mode = si->si_mode; 2496 } 2497 2498 switch ( mode ) { 2499 case LDAP_BACK_IDASSERT_LEGACY: 2500 /* original behavior: 2501 * assert the client's identity */ 2502 case LDAP_BACK_IDASSERT_SELF: 2503 assertedID = ndn; 2504 break; 2505 2506 case LDAP_BACK_IDASSERT_ANONYMOUS: 2507 /* assert "anonymous" */ 2508 assertedID = slap_empty_bv; 2509 break; 2510 2511 case LDAP_BACK_IDASSERT_NOASSERT: 2512 /* don't assert; bind as proxyauthzdn */ 2513 goto done; 2514 2515 case LDAP_BACK_IDASSERT_OTHERID: 2516 case LDAP_BACK_IDASSERT_OTHERDN: 2517 /* assert idassert DN */ 2518 assertedID = si->si_bc.sb_authzId; 2519 break; 2520 2521 default: 2522 assert( 0 ); 2523 } 2524 2525 /* if we got here, "" is allowed to proxyAuthz */ 2526 if ( BER_BVISNULL( &assertedID ) ) { 2527 assertedID = slap_empty_bv; 2528 } 2529 2530 /* don't idassert the bound DN (ITS#4497) */ 2531 if ( dn_match( &assertedID, bound_ndn ) ) { 2532 goto done; 2533 } 2534 2535 ctrl->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; 2536 ctrl->ldctl_iscritical = ( ( si->si_flags & LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL ) == LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL ); 2537 2538 switch ( si->si_mode ) { 2539 /* already in u:ID or dn:DN form */ 2540 case LDAP_BACK_IDASSERT_OTHERID: 2541 case LDAP_BACK_IDASSERT_OTHERDN: 2542 ber_dupbv_x( &ctrl->ldctl_value, &assertedID, op->o_tmpmemctx ); 2543 rs->sr_err = LDAP_SUCCESS; 2544 break; 2545 2546 /* needs the dn: prefix */ 2547 default: 2548 ctrl->ldctl_value.bv_len = assertedID.bv_len + STRLENOF( "dn:" ); 2549 ctrl->ldctl_value.bv_val = op->o_tmpalloc( ctrl->ldctl_value.bv_len + 1, 2550 op->o_tmpmemctx ); 2551 AC_MEMCPY( ctrl->ldctl_value.bv_val, "dn:", STRLENOF( "dn:" ) ); 2552 AC_MEMCPY( &ctrl->ldctl_value.bv_val[ STRLENOF( "dn:" ) ], 2553 assertedID.bv_val, assertedID.bv_len + 1 ); 2554 rs->sr_err = LDAP_SUCCESS; 2555 break; 2556 } 2557 2558 /* Older versions of <draft-weltman-ldapv3-proxy> required 2559 * to encode the value of the authzID (and called it proxyDN); 2560 * this hack provides compatibility with those DSAs that 2561 * implement it this way */ 2562 if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) { 2563 struct berval authzID = ctrl->ldctl_value; 2564 BerElementBuffer berbuf; 2565 BerElement *ber = (BerElement *)&berbuf; 2566 ber_tag_t tag; 2567 2568 ber_init2( ber, 0, LBER_USE_DER ); 2569 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); 2570 2571 tag = ber_printf( ber, "O", &authzID ); 2572 if ( tag == LBER_ERROR ) { 2573 rs->sr_err = LDAP_OTHER; 2574 goto free_ber; 2575 } 2576 2577 if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) { 2578 rs->sr_err = LDAP_OTHER; 2579 goto free_ber; 2580 } 2581 2582 rs->sr_err = LDAP_SUCCESS; 2583 2584 free_ber:; 2585 op->o_tmpfree( authzID.bv_val, op->o_tmpmemctx ); 2586 ber_free_buf( ber ); 2587 2588 if ( rs->sr_err != LDAP_SUCCESS ) { 2589 goto done; 2590 } 2591 2592 } else if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) { 2593 struct berval authzID = ctrl->ldctl_value, 2594 tmp; 2595 BerElementBuffer berbuf; 2596 BerElement *ber = (BerElement *)&berbuf; 2597 ber_tag_t tag; 2598 2599 if ( strncasecmp( authzID.bv_val, "dn:", STRLENOF( "dn:" ) ) != 0 ) { 2600 rs->sr_err = LDAP_PROTOCOL_ERROR; 2601 goto done; 2602 } 2603 2604 tmp = authzID; 2605 tmp.bv_val += STRLENOF( "dn:" ); 2606 tmp.bv_len -= STRLENOF( "dn:" ); 2607 2608 ber_init2( ber, 0, LBER_USE_DER ); 2609 ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); 2610 2611 /* apparently, Mozilla API encodes this 2612 * as "SEQUENCE { LDAPDN }" */ 2613 tag = ber_printf( ber, "{O}", &tmp ); 2614 if ( tag == LBER_ERROR ) { 2615 rs->sr_err = LDAP_OTHER; 2616 goto free_ber2; 2617 } 2618 2619 if ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 ) { 2620 rs->sr_err = LDAP_OTHER; 2621 goto free_ber2; 2622 } 2623 2624 ctrl->ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ; 2625 rs->sr_err = LDAP_SUCCESS; 2626 2627 free_ber2:; 2628 op->o_tmpfree( authzID.bv_val, op->o_tmpmemctx ); 2629 ber_free_buf( ber ); 2630 2631 if ( rs->sr_err != LDAP_SUCCESS ) { 2632 goto done; 2633 } 2634 } 2635 2636 done:; 2637 2638 return rs->sr_err; 2639 } 2640 2641 /* 2642 * Add controls; 2643 * 2644 * if any needs to be added, it is prepended to existing ones, 2645 * in a newly allocated array. The companion function 2646 * ldap_back_controls_free() must be used to restore the original 2647 * status of op->o_ctrls. 2648 */ 2649 int 2650 ldap_back_controls_add( 2651 Operation *op, 2652 SlapReply *rs, 2653 ldapconn_t *lc, 2654 LDAPControl ***pctrls ) 2655 { 2656 ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; 2657 2658 LDAPControl **ctrls = NULL; 2659 /* set to the maximum number of controls this backend can add */ 2660 LDAPControl c[ 2 ] = { { 0 } }; 2661 int n = 0, i, j1 = 0, j2 = 0; 2662 2663 *pctrls = NULL; 2664 2665 rs->sr_err = LDAP_SUCCESS; 2666 2667 /* don't add controls if protocol is not LDAPv3 */ 2668 switch ( li->li_version ) { 2669 case LDAP_VERSION3: 2670 break; 2671 2672 case 0: 2673 if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) { 2674 break; 2675 } 2676 /* fall thru */ 2677 2678 default: 2679 goto done; 2680 } 2681 2682 /* put controls that go __before__ existing ones here */ 2683 2684 /* proxyAuthz for identity assertion */ 2685 switch ( ldap_back_proxy_authz_ctrl( op, rs, &lc->lc_bound_ndn, 2686 li->li_version, &li->li_idassert, &c[ j1 ] ) ) 2687 { 2688 case SLAP_CB_CONTINUE: 2689 break; 2690 2691 case LDAP_SUCCESS: 2692 j1++; 2693 break; 2694 2695 default: 2696 goto done; 2697 } 2698 2699 /* put controls that go __after__ existing ones here */ 2700 2701 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 2702 /* FIXME: according to <draft-wahl-ldap-session>, 2703 * the server should check if the control can be added 2704 * based on the identity of the client and so */ 2705 2706 /* session tracking */ 2707 if ( LDAP_BACK_ST_REQUEST( li ) ) { 2708 switch ( slap_ctrl_session_tracking_request_add( op, rs, &c[ j1 + j2 ] ) ) { 2709 case SLAP_CB_CONTINUE: 2710 break; 2711 2712 case LDAP_SUCCESS: 2713 j2++; 2714 break; 2715 2716 default: 2717 goto done; 2718 } 2719 } 2720 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 2721 2722 if ( rs->sr_err == SLAP_CB_CONTINUE ) { 2723 rs->sr_err = LDAP_SUCCESS; 2724 } 2725 2726 /* if nothing to do, just bail out */ 2727 if ( j1 == 0 && j2 == 0 ) { 2728 goto done; 2729 } 2730 2731 assert( j1 + j2 <= (int) (sizeof( c )/sizeof( c[0] )) ); 2732 2733 if ( op->o_ctrls ) { 2734 for ( n = 0; op->o_ctrls[ n ]; n++ ) 2735 /* just count ctrls */ ; 2736 } 2737 2738 ctrls = op->o_tmpalloc( (n + j1 + j2 + 1) * sizeof( LDAPControl * ) + ( j1 + j2 ) * sizeof( LDAPControl ), 2739 op->o_tmpmemctx ); 2740 if ( j1 ) { 2741 ctrls[ 0 ] = (LDAPControl *)&ctrls[ n + j1 + j2 + 1 ]; 2742 *ctrls[ 0 ] = c[ 0 ]; 2743 for ( i = 1; i < j1; i++ ) { 2744 ctrls[ i ] = &ctrls[ 0 ][ i ]; 2745 *ctrls[ i ] = c[ i ]; 2746 } 2747 } 2748 2749 i = 0; 2750 if ( op->o_ctrls ) { 2751 for ( i = 0; op->o_ctrls[ i ]; i++ ) { 2752 ctrls[ i + j1 ] = op->o_ctrls[ i ]; 2753 } 2754 } 2755 2756 n += j1; 2757 if ( j2 ) { 2758 ctrls[ n ] = (LDAPControl *)&ctrls[ n + j2 + 1 ] + j1; 2759 *ctrls[ n ] = c[ j1 ]; 2760 for ( i = 1; i < j2; i++ ) { 2761 ctrls[ n + i ] = &ctrls[ n ][ i ]; 2762 *ctrls[ n + i ] = c[ i ]; 2763 } 2764 } 2765 2766 ctrls[ n + j2 ] = NULL; 2767 2768 done:; 2769 if ( ctrls == NULL ) { 2770 ctrls = op->o_ctrls; 2771 } 2772 2773 *pctrls = ctrls; 2774 2775 return rs->sr_err; 2776 } 2777 2778 int 2779 ldap_back_controls_free( Operation *op, SlapReply *rs, LDAPControl ***pctrls ) 2780 { 2781 LDAPControl **ctrls = *pctrls; 2782 2783 /* we assume that the controls added by the proxy come first, 2784 * so as soon as we find op->o_ctrls[ 0 ] we can stop */ 2785 if ( ctrls && ctrls != op->o_ctrls ) { 2786 int i = 0, n = 0, n_added; 2787 LDAPControl *lower, *upper; 2788 2789 assert( ctrls[ 0 ] != NULL ); 2790 2791 for ( n = 0; ctrls[ n ] != NULL; n++ ) 2792 /* count 'em */ ; 2793 2794 if ( op->o_ctrls ) { 2795 for ( i = 0; op->o_ctrls[ i ] != NULL; i++ ) 2796 /* count 'em */ ; 2797 } 2798 2799 n_added = n - i; 2800 lower = (LDAPControl *)&ctrls[ n ]; 2801 upper = &lower[ n_added ]; 2802 2803 for ( i = 0; ctrls[ i ] != NULL; i++ ) { 2804 if ( ctrls[ i ] < lower || ctrls[ i ] >= upper ) { 2805 /* original; don't touch */ 2806 continue; 2807 } 2808 2809 if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) { 2810 op->o_tmpfree( ctrls[ i ]->ldctl_value.bv_val, op->o_tmpmemctx ); 2811 } 2812 } 2813 2814 op->o_tmpfree( ctrls, op->o_tmpmemctx ); 2815 } 2816 2817 *pctrls = NULL; 2818 2819 return 0; 2820 } 2821 2822 int 2823 ldap_back_conn2str( const ldapconn_base_t *lc, char *buf, ber_len_t buflen ) 2824 { 2825 char tbuf[ SLAP_TEXT_BUFLEN ]; 2826 char *ptr = buf, *end = buf + buflen; 2827 int len; 2828 2829 if ( ptr + sizeof("conn=") > end ) return -1; 2830 ptr = lutil_strcopy( ptr, "conn=" ); 2831 2832 len = ldap_back_connid2str( lc, ptr, (ber_len_t)(end - ptr) ); 2833 ptr += len; 2834 if ( ptr >= end ) return -1; 2835 2836 if ( !BER_BVISNULL( &lc->lcb_local_ndn ) ) { 2837 if ( ptr + sizeof(" DN=\"\"") + lc->lcb_local_ndn.bv_len > end ) return -1; 2838 ptr = lutil_strcopy( ptr, " DN=\"" ); 2839 ptr = lutil_strncopy( ptr, lc->lcb_local_ndn.bv_val, lc->lcb_local_ndn.bv_len ); 2840 *ptr++ = '"'; 2841 } 2842 2843 if ( lc->lcb_create_time != 0 ) { 2844 len = snprintf( tbuf, sizeof(tbuf), "%ld", lc->lcb_create_time ); 2845 if ( ptr + sizeof(" created=") + len >= end ) return -1; 2846 ptr = lutil_strcopy( ptr, " created=" ); 2847 ptr = lutil_strcopy( ptr, tbuf ); 2848 } 2849 2850 if ( lc->lcb_time != 0 ) { 2851 len = snprintf( tbuf, sizeof(tbuf), "%ld", lc->lcb_time ); 2852 if ( ptr + sizeof(" modified=") + len >= end ) return -1; 2853 ptr = lutil_strcopy( ptr, " modified=" ); 2854 ptr = lutil_strcopy( ptr, tbuf ); 2855 } 2856 2857 len = snprintf( tbuf, sizeof(tbuf), "%u", lc->lcb_refcnt ); 2858 if ( ptr + sizeof(" refcnt=") + len >= end ) return -1; 2859 ptr = lutil_strcopy( ptr, " refcnt=" ); 2860 ptr = lutil_strcopy( ptr, tbuf ); 2861 2862 return ptr - buf; 2863 } 2864 2865 int 2866 ldap_back_connid2str( const ldapconn_base_t *lc, char *buf, ber_len_t buflen ) 2867 { 2868 static struct berval conns[] = { 2869 BER_BVC("ROOTDN"), 2870 BER_BVC("ROOTDN-TLS"), 2871 BER_BVC("ANON"), 2872 BER_BVC("ANON-TLS"), 2873 BER_BVC("BIND"), 2874 BER_BVC("BIND-TLS"), 2875 BER_BVNULL 2876 }; 2877 2878 int len = 0; 2879 2880 if ( LDAP_BACK_PCONN_ISPRIV( (const ldapconn_t *)lc ) ) { 2881 long cid; 2882 struct berval *bv; 2883 2884 cid = (long)lc->lcb_conn; 2885 assert( cid >= LDAP_BACK_PCONN_FIRST && cid < LDAP_BACK_PCONN_LAST ); 2886 2887 bv = &conns[ cid ]; 2888 2889 if ( bv->bv_len >= buflen ) { 2890 return bv->bv_len + 1; 2891 } 2892 2893 len = bv->bv_len; 2894 lutil_strncopy( buf, bv->bv_val, bv->bv_len + 1 ); 2895 2896 } else { 2897 len = snprintf( buf, buflen, "%lu", lc->lcb_conn->c_connid ); 2898 } 2899 2900 return len; 2901 } 2902