📄 bind.c
字号:
Operation *op, SlapReply *rs, ber_int_t msgid, ldap_back_send_t sendok ){ ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; /* default behavior */ if ( LDAP_BACK_ABANDON( li ) ) { return ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL ); } if ( LDAP_BACK_CANCEL( li ) ) { /* FIXME: asynchronous? */ return ldap_cancel_s( lc->lc_ld, msgid, NULL, NULL ); } assert( 0 ); return LDAP_OTHER;}intldap_back_op_result( ldapconn_t *lc, Operation *op, SlapReply *rs, ber_int_t msgid, time_t timeout, ldap_back_send_t sendok ){ ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; char *match = NULL; char *text = NULL; char **refs = NULL; LDAPControl **ctrls = NULL;#define ERR_OK(err) ((err) == LDAP_SUCCESS || (err) == LDAP_COMPARE_FALSE || (err) == LDAP_COMPARE_TRUE) rs->sr_text = NULL; rs->sr_matched = NULL; rs->sr_ref = NULL; rs->sr_ctrls = NULL; /* if the error recorded in the reply corresponds * to a successful state, get the error from the * remote server response */ if ( ERR_OK( rs->sr_err ) ) { int rc; struct timeval tv; LDAPMessage *res = NULL; time_t stoptime = (time_t)(-1); int timeout_err = op->o_protocol >= LDAP_VERSION3 ? LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER; const char *timeout_text = "Operation timed out"; /* if timeout is not specified, compute and use * the one specific to the ongoing operation */ if ( timeout == (time_t)(-1) ) { slap_op_t opidx = slap_req2op( op->o_tag ); if ( opidx == SLAP_OP_SEARCH ) { if ( op->ors_tlimit <= 0 ) { timeout = 0; } else { timeout = op->ors_tlimit; timeout_err = LDAP_TIMELIMIT_EXCEEDED; timeout_text = NULL; } } else { timeout = li->li_timeout[ opidx ]; } } /* better than nothing :) */ if ( timeout == 0 ) { if ( li->li_idle_timeout ) { timeout = li->li_idle_timeout; } else if ( li->li_conn_ttl ) { timeout = li->li_conn_ttl; } } if ( timeout ) { stoptime = op->o_time + timeout; } LDAP_BACK_TV_SET( &tv );retry:; /* if result parsing fails, note the failure reason */ rc = ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res ); switch ( rc ) { case 0: if ( timeout && slap_get_time() > stoptime ) { if ( sendok & LDAP_BACK_BINDING ) { ldap_unbind_ext( lc->lc_ld, NULL, NULL ); lc->lc_ld = NULL; /* 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 ); } else { (void)ldap_back_cancel( lc, op, rs, msgid, sendok ); } rs->sr_err = timeout_err; rs->sr_text = timeout_text; break; } /* timeout == 0 */ LDAP_BACK_TV_SET( &tv ); ldap_pvt_thread_yield(); goto retry; case -1: ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rs->sr_err ); break; /* otherwise get the result; if it is not * LDAP_SUCCESS, record it in the reply * structure (this includes * LDAP_COMPARE_{TRUE|FALSE}) */ default: /* only touch when activity actually took place... */ if ( li->li_idle_timeout && lc ) { lc->lc_time = op->o_time; } rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, &match, &text, &refs, &ctrls, 1 ); rs->sr_text = text; if ( rc != LDAP_SUCCESS ) { rs->sr_err = rc; } /* RFC 4511: referrals can only appear * if result code is LDAP_REFERRAL */ if ( refs != NULL && refs[ 0 ] != NULL && refs[ 0 ][ 0 ] != '\0' ) { if ( rs->sr_err != LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s ldap_back_op_result: " "got referrals with err=%d\n", op->o_log_prefix, rs->sr_err, 0 ); } else { int i; for ( i = 0; refs[ i ] != NULL; i++ ) /* count */ ; rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ), op->o_tmpmemctx ); for ( i = 0; refs[ i ] != NULL; i++ ) { ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] ); } BER_BVZERO( &rs->sr_ref[ i ] ); } } else if ( rs->sr_err == LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s ldap_back_op_result: " "got err=%d with null " "or empty referrals\n", op->o_log_prefix, rs->sr_err, 0 ); rs->sr_err = LDAP_NO_SUCH_OBJECT; } if ( ctrls != NULL ) { rs->sr_ctrls = ctrls; } } } /* if the error in the reply structure is not * LDAP_SUCCESS, try to map it from client * to server error */ if ( !ERR_OK( rs->sr_err ) ) { rs->sr_err = slap_map_api2result( rs ); /* internal ops ( op->o_conn == NULL ) * must not reply to client */ if ( op->o_conn && !op->o_do_not_cache && match ) { /* record the (massaged) matched * DN into the reply structure */ rs->sr_matched = match; } } if ( rs->sr_err == LDAP_UNAVAILABLE ) { if ( !( sendok & LDAP_BACK_RETRYING ) ) { if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) { if ( rs->sr_text == NULL ) rs->sr_text = "Proxy operation retry failed"; send_ldap_result( op, rs ); } } } else if ( op->o_conn && ( ( ( sendok & LDAP_BACK_SENDOK ) && ERR_OK( rs->sr_err ) ) || ( ( sendok & LDAP_BACK_SENDERR ) && rs->sr_err != LDAP_SUCCESS ) ) ) { send_ldap_result( op, rs ); } if ( match ) { if ( rs->sr_matched != match ) { free( (char *)rs->sr_matched ); } rs->sr_matched = NULL; ldap_memfree( match ); } if ( text ) { ldap_memfree( text ); } rs->sr_text = NULL; if ( rs->sr_ref ) { op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx ); rs->sr_ref = NULL; } if ( refs ) { ber_memvfree( (void **)refs ); } if ( ctrls ) { assert( rs->sr_ctrls != NULL ); ldap_controls_free( ctrls ); rs->sr_ctrls = NULL; } return( ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );}/* return true if bound, false if failed */intldap_back_retry( ldapconn_t **lcp, Operation *op, SlapReply *rs, ldap_back_send_t sendok ){ ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; int rc = 0; assert( lcp != NULL ); assert( *lcp != NULL ); ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex ); if ( (*lcp)->lc_refcnt == 1 ) { int binding = LDAP_BACK_CONN_BINDING( *lcp ); ldap_pvt_thread_mutex_lock( &li->li_uri_mutex ); Debug( LDAP_DEBUG_ANY, "%s ldap_back_retry: retrying URI=\"%s\" DN=\"%s\"\n", op->o_log_prefix, li->li_uri, BER_BVISNULL( &(*lcp)->lc_bound_ndn ) ? "" : (*lcp)->lc_bound_ndn.bv_val ); ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex ); ldap_unbind_ext( (*lcp)->lc_ld, NULL, NULL ); (*lcp)->lc_ld = NULL; LDAP_BACK_CONN_ISBOUND_CLEAR( (*lcp) ); /* lc here must be the regular lc, reset and ready for init */ rc = ldap_back_prepare_conn( *lcp, op, rs, sendok ); if ( rc != LDAP_SUCCESS ) { /* freeit, because lc_refcnt == 1 */ (*lcp)->lc_refcnt = 0; (void)ldap_back_freeconn( li, *lcp, 0 ); *lcp = NULL; rc = 0; } else if ( ( sendok & LDAP_BACK_BINDING ) ) { if ( binding ) { LDAP_BACK_CONN_BINDING_SET( *lcp ); } rc = 1; } else { rc = ldap_back_dobind_int( lcp, op, rs, sendok, 0, 0 ); if ( rc == 0 && *lcp != NULL ) { /* freeit, because lc_refcnt == 1 */ (*lcp)->lc_refcnt = 0; LDAP_BACK_CONN_TAINTED_SET( *lcp ); (void)ldap_back_freeconn( li, *lcp, 0 ); *lcp = NULL; } } } else { Debug( LDAP_DEBUG_TRACE, "ldap_back_retry: conn %p refcnt=%u unable to retry.\n", (void *)(*lcp), (*lcp)->lc_refcnt, 0 ); LDAP_BACK_CONN_TAINTED_SET( *lcp ); ldap_back_release_conn_lock( li, lcp, 0 ); assert( *lcp == NULL ); if ( sendok & LDAP_BACK_SENDERR ) { rs->sr_err = LDAP_UNAVAILABLE; rs->sr_text = "Unable to retry"; send_ldap_result( op, rs ); } } ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex ); return rc;}static intldap_back_is_proxy_authz( Operation *op, SlapReply *rs, ldap_back_send_t sendok, struct berval *binddn, struct berval *bindcred ){ ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; struct berval ndn; int dobind = 0; if ( op->o_conn == NULL || op->o_do_not_cache ) { goto done; } /* don't proxyAuthz if protocol is not LDAPv3 */ switch ( li->li_version ) { case LDAP_VERSION3: break; case 0: if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) { break; } /* fall thru */ default: rs->sr_err = LDAP_UNWILLING_TO_PERFORM; if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); dobind = -1; } goto done; } /* safe default */ *binddn = slap_empty_bv; *bindcred = slap_empty_bv; if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) { ndn = op->o_conn->c_ndn; } else { ndn = op->o_ndn; } switch ( li->li_idassert_mode ) { case LDAP_BACK_IDASSERT_LEGACY: if ( !BER_BVISNULL( &ndn ) && !BER_BVISEMPTY( &ndn ) ) { if ( !BER_BVISNULL( &li->li_idassert_authcDN ) && !BER_BVISEMPTY( &li->li_idassert_authcDN ) ) { *binddn = li->li_idassert_authcDN; *bindcred = li->li_idassert_passwd; dobind = 1; } } break; default: /* NOTE: rootdn can always idassert */ if ( BER_BVISNULL( &ndn ) && li->li_idassert_authz == NULL && !( li->li_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) { if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { rs->sr_err = LDAP_INAPPROPRIATE_AUTH; if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); dobind = -1; } } else { rs->sr_err = LDAP_SUCCESS; *binddn = slap_empty_bv; *bindcred = slap_empty_bv; break; } goto done; } else if ( li->li_idassert_authz && !be_isroot( op ) ) { struct berval authcDN; if ( BER_BVISNULL( &ndn ) ) { authcDN = slap_empty_bv; } else { authcDN = ndn; } rs->sr_err = slap_sasl_matches( op, li->li_idassert_authz, &authcDN, &authcDN ); if ( rs->sr_err != LDAP_SUCCESS ) { if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { if ( sendok & LDAP_BACK_SENDERR ) { send_ldap_result( op, rs ); dobind = -1; } } else { rs->sr_err = LDAP_SUCCESS; *binddn = slap_empty_bv; *bindcred = slap_empty_bv; break; } goto done; } } *binddn = li->li_idassert_authcDN; *bindcred = li->li_idassert_passwd; dobind = 1; break; }done:; return dobind;}static intldap_back_proxy_authz_bind( ldapconn_t *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok, struct berval *binddn, struct berval *bindcred ){ ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; struct berval ndn; int msgid; int rc; if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) { ndn = op->o_conn->c_ndn; } else { ndn = op->o_ndn; } if ( li->li_idassert_authmethod == LDAP_AUTH_SASL ) {#ifdef HAVE_CYRUS_SASL void *defaults = NULL; struct berval authzID = BER_BVNULL; int freeauthz = 0; /* if SASL supports native authz, prepare for it */ if ( ( !op->o_do_not_cache || !op->o_is_auth_check ) && ( li->li_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) ) { switch ( li->li_idassert_mode ) { case LDAP_BACK_IDASSERT_OTHERID: case LDAP_BACK_IDASSERT_OTHERDN:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -