📄 bind.c
字号:
} else { rs->sr_err = avl_insert( &li->li_conninfo.lai_tree, (caddr_t)lc, ldap_back_conndn_cmp, ldap_back_conndn_dup ); LDAP_BACK_CONN_CACHED_SET( lc ); }#if LDAP_BACK_PRINT_CONNTREE > 0 ldap_back_print_conntree( li, "<<< ldap_back_getconn(insert)" );#endif /* LDAP_BACK_PRINT_CONNTREE */ ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); if ( StatslogTest( LDAP_DEBUG_TRACE ) ) { char buf[ SLAP_TEXT_BUFLEN ]; snprintf( buf, sizeof( buf ), "lc=%p inserted refcnt=%u rc=%d", (void *)lc, refcnt, rs->sr_err ); Debug( LDAP_DEBUG_TRACE, "=>ldap_back_getconn: %s: %s\n", op->o_log_prefix, buf, 0 ); } if ( !LDAP_BACK_PCONN_ISPRIV( lc ) ) { /* Err could be -1 in case a duplicate ldapconn is inserted */ switch ( rs->sr_err ) { case 0: break; case -1: LDAP_BACK_CONN_CACHED_CLEAR( lc ); if ( !( sendok & LDAP_BACK_BINDING ) && !LDAP_BACK_USE_TEMPORARIES( li ) ) { /* duplicate: free and try to get the newly created one */ ldap_back_conn_free( lc ); lc = NULL; goto retry_lock; } /* taint connection, so that it'll be freed when released */ LDAP_BACK_CONN_TAINTED_SET( lc ); break; default: LDAP_BACK_CONN_CACHED_CLEAR( lc ); ldap_back_conn_free( lc ); rs->sr_err = LDAP_OTHER; rs->sr_text = "Proxy bind collision"; if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) { send_ldap_result( op, rs ); } return NULL; } } } else { int expiring = 0; if ( ( li->li_idle_timeout != 0 && op->o_time > lc->lc_time + li->li_idle_timeout ) || ( li->li_conn_ttl != 0 && op->o_time > lc->lc_create_time + li->li_conn_ttl ) ) { expiring = 1; /* let it be used, but taint/delete it so that * no-one else can look it up any further */ ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );#if LDAP_BACK_PRINT_CONNTREE > 0 ldap_back_print_conntree( li, ">>> ldap_back_getconn(timeout)" );#endif /* LDAP_BACK_PRINT_CONNTREE */ (void)ldap_back_conn_delete( li, lc ); LDAP_BACK_CONN_TAINTED_SET( lc );#if LDAP_BACK_PRINT_CONNTREE > 0 ldap_back_print_conntree( li, "<<< ldap_back_getconn(timeout)" );#endif /* LDAP_BACK_PRINT_CONNTREE */ ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); } if ( StatslogTest( LDAP_DEBUG_TRACE ) ) { char buf[ SLAP_TEXT_BUFLEN ]; snprintf( buf, sizeof( buf ), "conn %p fetched refcnt=%u%s", (void *)lc, refcnt, expiring ? " expiring" : "" ); Debug( LDAP_DEBUG_TRACE, "=>ldap_back_getconn: %s.\n", buf, 0, 0 ); } }#ifdef HAVE_TLSdone:;#endif /* HAVE_TLS */ return lc;}voidldap_back_release_conn_lock( ldapinfo_t *li, ldapconn_t **lcp, int dolock ){ ldapconn_t *lc = *lcp; if ( dolock ) { ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); } assert( lc->lc_refcnt > 0 ); LDAP_BACK_CONN_BINDING_CLEAR( lc ); lc->lc_refcnt--; if ( LDAP_BACK_CONN_TAINTED( lc ) ) { ldap_back_freeconn( li, lc, 0 ); *lcp = NULL; } if ( dolock ) { ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); }}voidldap_back_quarantine( Operation *op, SlapReply *rs ){ ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; slap_retry_info_t *ri = &li->li_quarantine; ldap_pvt_thread_mutex_lock( &li->li_quarantine_mutex ); if ( rs->sr_err == LDAP_UNAVAILABLE ) { time_t new_last = slap_get_time(); switch ( li->li_isquarantined ) { case LDAP_BACK_FQ_NO: if ( ri->ri_last == new_last ) { goto done; } Debug( LDAP_DEBUG_ANY, "%s: ldap_back_quarantine enter.\n", op->o_log_prefix, 0, 0 ); ri->ri_idx = 0; ri->ri_count = 0; break; case LDAP_BACK_FQ_RETRYING: Debug( LDAP_DEBUG_ANY, "%s: ldap_back_quarantine block #%d try #%d failed.\n", op->o_log_prefix, ri->ri_idx, ri->ri_count ); ++ri->ri_count; if ( ri->ri_num[ ri->ri_idx ] != SLAP_RETRYNUM_FOREVER && ri->ri_count == ri->ri_num[ ri->ri_idx ] ) { ri->ri_count = 0; ++ri->ri_idx; } break; default: break; } li->li_isquarantined = LDAP_BACK_FQ_YES; ri->ri_last = new_last; } else if ( li->li_isquarantined != LDAP_BACK_FQ_NO ) { if ( ri->ri_last == slap_get_time() ) { goto done; } Debug( LDAP_DEBUG_ANY, "%s: ldap_back_quarantine exit (%d) err=%d.\n", op->o_log_prefix, li->li_isquarantined, rs->sr_err ); if ( li->li_quarantine_f ) { (void)li->li_quarantine_f( li, li->li_quarantine_p ); } ri->ri_count = 0; ri->ri_idx = 0; li->li_isquarantined = LDAP_BACK_FQ_NO; }done:; ldap_pvt_thread_mutex_unlock( &li->li_quarantine_mutex );}/* * ldap_back_dobind_int * * Note: dolock indicates whether li->li_conninfo.lai_mutex must be locked or not */static intldap_back_dobind_int( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok, int retries, int dolock ){ ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; ldapconn_t *lc; struct berval binddn = slap_empty_bv, bindcred = slap_empty_bv; int rc = 0, isbound, binding = 0; ber_int_t msgid; assert( lcp != NULL ); assert( retries >= 0 ); if ( sendok & LDAP_BACK_GETCONN ) { assert( *lcp == NULL ); lc = ldap_back_getconn( op, rs, sendok, &binddn, &bindcred ); if ( lc == NULL ) { return 0; } *lcp = lc; } else { lc = *lcp; } assert( lc != NULL );retry_lock:; if ( dolock ) { ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); } if ( binding == 0 ) { /* check if already bound */ rc = isbound = LDAP_BACK_CONN_ISBOUND( lc ); if ( isbound ) { if ( dolock ) { ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); } return rc; } if ( LDAP_BACK_CONN_BINDING( lc ) ) { /* if someone else is about to bind it, give up and retry */ if ( dolock ) { ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); } ldap_pvt_thread_yield(); goto retry_lock; } else { /* otherwise this thread will bind it */ LDAP_BACK_CONN_BINDING_SET( lc ); binding = 1; } } if ( dolock ) { ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); } /* * FIXME: we need to let clients use proxyAuthz * otherwise we cannot do symmetric pools of servers; * we have to live with the fact that a user can * authorize itself as any ID that is allowed * by the authzTo directive of the "proxyauthzdn". */ /* * NOTE: current Proxy Authorization specification * and implementation do not allow proxy authorization * control to be provided with Bind requests */ /* * if no bind took place yet, but the connection is bound * and the "idassert-authcDN" (or other ID) is set, * then bind as the asserting identity and explicitly * add the proxyAuthz control to every operation with the * dn bound to the connection as control value. * This is done also if this is the authrizing backend, * but the "override" flag is given to idassert. * It allows to use SASL bind and yet proxyAuthz users */ if ( LDAP_BACK_CONN_ISIDASSERT( lc ) ) { if ( BER_BVISEMPTY( &binddn ) && BER_BVISEMPTY( &bindcred ) ) { /* if we got here, it shouldn't return result */ rc = ldap_back_is_proxy_authz( op, rs, LDAP_BACK_DONTSEND, &binddn, &bindcred ); assert( rc == 1 ); } rc = ldap_back_proxy_authz_bind( lc, op, rs, sendok, &binddn, &bindcred ); goto done; }#ifdef HAVE_CYRUS_SASL if ( LDAP_BACK_CONN_ISPRIV( lc ) && li->li_acl_authmethod == LDAP_AUTH_SASL ) { void *defaults = NULL; if ( li->li_acl_secprops != NULL ) { rc = ldap_set_option( lc->lc_ld, LDAP_OPT_X_SASL_SECPROPS, li->li_acl_secprops ); if ( rc != LDAP_OPT_SUCCESS ) { Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option " "(SECPROPS,\"%s\") failed!\n", li->li_acl_secprops, 0, 0 ); goto done; } } defaults = lutil_sasl_defaults( lc->lc_ld, li->li_acl_sasl_mech.bv_val, li->li_acl_sasl_realm.bv_val, li->li_acl_authcID.bv_val, li->li_acl_passwd.bv_val, NULL ); rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld, li->li_acl_authcDN.bv_val, li->li_acl_sasl_mech.bv_val, NULL, NULL, LDAP_SASL_QUIET, lutil_sasl_interact, defaults ); lutil_sasl_freedefs( defaults ); rs->sr_err = slap_map_api2result( rs ); if ( rs->sr_err != LDAP_SUCCESS ) { LDAP_BACK_CONN_ISBOUND_CLEAR( lc ); if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); } } else { LDAP_BACK_CONN_ISBOUND_SET( lc ); } if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } goto done; }#endif /* HAVE_CYRUS_SASL */retry:; rs->sr_err = ldap_sasl_bind( lc->lc_ld, BER_BVISNULL( &lc->lc_cred ) ? "" : lc->lc_bound_ndn.bv_val, LDAP_SASL_SIMPLE, &lc->lc_cred, NULL, NULL, &msgid ); if ( rs->sr_err == LDAP_SERVER_DOWN ) { if ( retries != LDAP_BACK_RETRY_NEVER ) { if ( dolock ) { ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); } assert( lc->lc_refcnt > 0 ); if ( lc->lc_refcnt == 1 ) { ldap_unbind_ext( lc->lc_ld, NULL, NULL ); lc->lc_ld = NULL; /* lc here must be the regular lc, reset and ready for init */ rs->sr_err = ldap_back_prepare_conn( lc, op, rs, sendok ); if ( rs->sr_err != LDAP_SUCCESS ) { sendok &= ~LDAP_BACK_SENDERR; lc->lc_refcnt = 0; } } if ( dolock ) { ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); } if ( rs->sr_err == LDAP_SUCCESS ) { if ( retries > 0 ) { retries--; } goto retry; } } assert( lc->lc_refcnt == 1 ); lc->lc_refcnt = 0; ldap_back_freeconn( li, lc, dolock ); *lcp = NULL; rs->sr_err = slap_map_api2result( rs ); if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } if ( rs->sr_err != LDAP_SUCCESS && ( sendok & LDAP_BACK_SENDERR ) ) { rs->sr_text = "Internal proxy bind failure"; send_ldap_result( op, rs ); } return 0; } rc = ldap_back_op_result( lc, op, rs, msgid, -1, ( sendok | LDAP_BACK_BINDING ) ); if ( rc == LDAP_SUCCESS ) { LDAP_BACK_CONN_ISBOUND_SET( lc ); }done:; LDAP_BACK_CONN_BINDING_CLEAR( lc ); rc = LDAP_BACK_CONN_ISBOUND( lc ); if ( !rc ) { ldap_back_release_conn_lock( li, lcp, dolock ); } else if ( LDAP_BACK_SAVECRED( li ) ) { ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc ); } return rc;}/* * ldap_back_dobind * * Note: dolock indicates whether li->li_conninfo.lai_mutex must be locked or not */intldap_back_dobind( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok ){ ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; return ldap_back_dobind_int( lcp, op, rs, ( sendok | LDAP_BACK_GETCONN ), li->li_nretries, 1 );}/* * ldap_back_default_rebind * * This is a callback used for chasing referrals using the same * credentials as the original user on this session. */int ldap_back_default_rebind( LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params ){ ldapconn_t *lc = (ldapconn_t *)params;#ifdef HAVE_TLS /* ... otherwise we couldn't get here */ assert( lc != NULL ); if ( !ldap_tls_inplace( ld ) ) { int is_tls = LDAP_BACK_CONN_ISTLS( lc ), rc; const char *text = NULL; rc = ldap_back_start_tls( ld, 0, &is_tls, url, lc->lc_flags, LDAP_BACK_RETRY_DEFAULT, &text ); if ( rc != LDAP_SUCCESS ) { return rc; } }#endif /* HAVE_TLS */ /* FIXME: add checks on the URL/identity? */ return ldap_sasl_bind_s( ld, BER_BVISNULL( &lc->lc_cred ) ? "" : lc->lc_bound_ndn.bv_val, LDAP_SASL_SIMPLE, &lc->lc_cred, NULL, NULL, NULL );}intldap_back_cancel( ldapconn_t *lc,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -