bind.c

来自「ldap服务器源码」· C语言 代码 · 共 1,440 行 · 第 1/3 页

C
1,440
字号
	if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {		rs->sr_text = "DN rewrite error";		rs->sr_err = LDAP_OTHER;		return rs->sr_err;	}	/* FIXME: this fixes the bind problem right now; we need	 * to use the asynchronous version to get the "matched"	 * and more in case of failure ... */	/* FIXME: should we check if at least some of the op->o_ctrls	 * can/should be passed? */	rs->sr_err = ldap_sasl_bind( msc->msc_ld, mdn.bv_val,			LDAP_SASL_SIMPLE, &op->orb_cred,			op->o_ctrls, NULL, &msgid );	meta_back_bind_op_result( op, rs, mc, candidate, msgid, LDAP_BACK_DONTSEND );	if ( rs->sr_err != LDAP_SUCCESS ) {		goto return_results;	}	/* If defined, proxyAuthz will be used also when	 * back-ldap is the authorizing backend; for this	 * purpose, a successful bind is followed by a	 * bind with the configured identity assertion */	/* NOTE: use with care */	if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {		meta_back_proxy_authz_bind( mc, candidate, op, rs, LDAP_BACK_SENDERR );		if ( !LDAP_BACK_CONN_ISBOUND( msc ) ) {			goto return_results;		}		goto cache_refresh;	}	ber_bvreplace( &msc->msc_bound_ndn, &op->o_req_ndn );	LDAP_BACK_CONN_ISBOUND_SET( msc );	mc->mc_authz_target = candidate;	if ( LDAP_BACK_SAVECRED( mi ) ) {		if ( !BER_BVISNULL( &msc->msc_cred ) ) {			memset( msc->msc_cred.bv_val, 0,				msc->msc_cred.bv_len );		}		ber_bvreplace( &msc->msc_cred, &op->orb_cred );		ldap_set_rebind_proc( msc->msc_ld, mt->mt_rebind_f, msc );	}cache_refresh:;	if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED			&& !BER_BVISEMPTY( &op->o_req_ndn ) )	{		( void )meta_dncache_update_entry( &mi->mi_cache,				&op->o_req_ndn, candidate );	}return_results:;	if ( mdn.bv_val != op->o_req_dn.bv_val ) {		free( mdn.bv_val );	}	if ( META_BACK_TGT_QUARANTINE( mt ) ) {		meta_back_quarantine( op, rs, candidate );	}	return rs->sr_err;}/* * meta_back_single_dobind */intmeta_back_single_dobind(	Operation		*op,	SlapReply		*rs,	metaconn_t		**mcp,	int			candidate,	ldap_back_send_t	sendok,	int			nretries,	int			dolock ){	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;	metatarget_t		*mt = mi->mi_targets[ candidate ];	metaconn_t		*mc = *mcp;	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];	static struct berval	cred = BER_BVC( "" );	int			msgid;	assert( !LDAP_BACK_CONN_ISBOUND( msc ) );	/* NOTE: this obsoletes pseudorootdn */	if ( op->o_conn != NULL &&		!op->o_do_not_cache &&		( BER_BVISNULL( &msc->msc_bound_ndn ) ||			BER_BVISEMPTY( &msc->msc_bound_ndn ) ||			( LDAP_BACK_CONN_ISPRIV( mc ) && dn_match( &msc->msc_bound_ndn, &mt->mt_idassert_authcDN ) ) ||			( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )	{		(void)meta_back_proxy_authz_bind( mc, candidate, op, rs, sendok );	} else {		/* FIXME: should we check if at least some of the op->o_ctrls		 * can/should be passed? */		rs->sr_err = ldap_sasl_bind( msc->msc_ld,			"", LDAP_SASL_SIMPLE, &cred,			NULL, NULL, &msgid );		rs->sr_err = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok );	}	if ( rs->sr_err != LDAP_SUCCESS ) {		if ( dolock ) {			ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );		}	        LDAP_BACK_CONN_BINDING_CLEAR( msc );		if ( META_BACK_ONERR_STOP( mi ) ) {	        	LDAP_BACK_CONN_TAINTED_SET( mc );			meta_back_release_conn_lock( mi, mc, 0 );			*mcp = NULL;		}		if ( dolock ) {			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );		}	}	if ( META_BACK_TGT_QUARANTINE( mt ) ) {		meta_back_quarantine( op, rs, candidate );	}	return rs->sr_err;}/* * meta_back_dobind */intmeta_back_dobind(	Operation		*op,	SlapReply		*rs,	metaconn_t		*mc,	ldap_back_send_t	sendok ){	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;	int			bound = 0,				i,				isroot = 0;	SlapReply		*candidates = meta_back_candidates_get( op );	if ( be_isroot( op ) ) {		isroot = 1;	}	Debug( LDAP_DEBUG_TRACE,		"%s meta_back_dobind: conn=%ld%s\n",		op->o_log_prefix,		LDAP_BACK_PCONN_ID( mc ),		isroot ? " (isroot)" : "" );	/*	 * all the targets are bound as pseudoroot	 */	if ( mc->mc_authz_target == META_BOUND_ALL ) {		bound = 1;		goto done;	}	for ( i = 0; i < mi->mi_ntargets; i++ ) {		metatarget_t		*mt = mi->mi_targets[ i ];		metasingleconn_t	*msc = &mc->mc_conns[ i ];		int			rc;		/*		 * Not a candidate		 */		if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {			continue;		}		assert( msc->msc_ld != NULL );		/*		 * If the target is already bound it is skipped		 */retry_binding:;		ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );		if ( LDAP_BACK_CONN_ISBOUND( msc )			|| ( LDAP_BACK_CONN_ISANON( msc )				&& mt->mt_idassert_authmethod == LDAP_AUTH_NONE ) )		{			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );			++bound;			continue;		} else if ( META_BACK_CONN_CREATING( msc ) || LDAP_BACK_CONN_BINDING( msc ) )		{			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );			ldap_pvt_thread_yield();			goto retry_binding;		}		LDAP_BACK_CONN_BINDING_SET( msc );		ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );		rc = meta_back_single_dobind( op, rs, &mc, i,			LDAP_BACK_DONTSEND, mt->mt_nretries, 1 );		/*		 * NOTE: meta_back_single_dobind() already retries;		 * in case of failure, it resets mc...		 */		if ( rc != LDAP_SUCCESS ) {			char		buf[ SLAP_TEXT_BUFLEN ];			if ( mc == NULL ) {				/* meta_back_single_dobind() already sent 				 * response and released connection */				goto send_err;			}			if ( rc == LDAP_UNAVAILABLE ) {				/* FIXME: meta_back_retry() already re-calls				 * meta_back_single_dobind() */				if ( meta_back_retry( op, rs, &mc, i, sendok ) ) {					goto retry_ok;				}				if ( mc != NULL ) {					ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );					LDAP_BACK_CONN_BINDING_CLEAR( msc );					ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );					meta_back_release_conn( mi, mc );				}				return 0;			}			ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );			LDAP_BACK_CONN_BINDING_CLEAR( msc );			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );			snprintf( buf, sizeof( buf ),				"meta_back_dobind[%d]: (%s) err=%d (%s).",				i, isroot ? op->o_bd->be_rootdn.bv_val : "anonymous",				rc, ldap_err2string( rc ) );			Debug( LDAP_DEBUG_ANY,				"%s %s\n",				op->o_log_prefix, buf, 0 );			/*			 * null cred bind should always succeed			 * as anonymous, so a failure means			 * the target is no longer candidate possibly			 * due to technical reasons (remote host down?)			 * so better clear the handle			 */			/* leave the target candidate, but record the error for later use */			candidates[ i ].sr_err = rc;			if ( META_BACK_ONERR_STOP( mi ) ) {				bound = 0;				goto done;			}			continue;		} /* else */retry_ok:;		Debug( LDAP_DEBUG_TRACE,			"%s meta_back_dobind[%d]: "			"(%s)\n",			op->o_log_prefix, i,			isroot ? op->o_bd->be_rootdn.bv_val : "anonymous" );		ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );		LDAP_BACK_CONN_BINDING_CLEAR( msc );		if ( isroot ) {			LDAP_BACK_CONN_ISBOUND_SET( msc );		} else {			LDAP_BACK_CONN_ISANON_SET( msc );		}		ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );		++bound;	}done:;	Debug( LDAP_DEBUG_TRACE,		"%s meta_back_dobind: conn=%ld bound=%d\n",		op->o_log_prefix, LDAP_BACK_PCONN_ID( mc ), bound );	if ( bound == 0 ) {		meta_back_release_conn( mi, mc );send_err:;		if ( sendok & LDAP_BACK_SENDERR ) {			if ( rs->sr_err == LDAP_SUCCESS ) {				rs->sr_err = LDAP_BUSY;			}			send_ldap_result( op, rs );		}		return 0;	}	return ( bound > 0 );}/* * meta_back_default_rebind * * This is a callback used for chasing referrals using the same * credentials as the original user on this session. */int meta_back_default_rebind(	LDAP			*ld,	LDAP_CONST char		*url,	ber_tag_t		request,	ber_int_t		msgid,	void			*params ){	metasingleconn_t	*msc = ( metasingleconn_t * )params;	return ldap_sasl_bind_s( ld, msc->msc_bound_ndn.bv_val,			LDAP_SASL_SIMPLE, &msc->msc_cred,			NULL, NULL, NULL );}intmeta_back_cancel(	metaconn_t		*mc,	Operation		*op,	SlapReply		*rs,	ber_int_t		msgid,	int			candidate,	ldap_back_send_t	sendok ){	metainfo_t		*mi = (metainfo_t *)op->o_bd->be_private;	metatarget_t		*mt = mi->mi_targets[ candidate ];	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];	int			rc = LDAP_OTHER;	Debug( LDAP_DEBUG_TRACE, ">>> %s meta_back_cancel[%d] msgid=%d\n",		op->o_log_prefix, candidate, msgid );	/* default behavior */	if ( META_BACK_TGT_ABANDON( mt ) ) {		rc = ldap_abandon_ext( msc->msc_ld, msgid, NULL, NULL );	} else if ( META_BACK_TGT_CANCEL( mt ) ) {		rc = ldap_cancel_s( msc->msc_ld, msgid, NULL, NULL );	} else {		assert( 0 );	}	Debug( LDAP_DEBUG_TRACE, "<<< %s meta_back_cancel[%d] err=%d\n",		op->o_log_prefix, candidate, rc );	return rc;}/* * FIXME: error return must be handled in a cleaner way ... */intmeta_back_op_result(	metaconn_t		*mc,	Operation		*op,	SlapReply		*rs,	int			candidate,	ber_int_t		msgid,	time_t			timeout,	ldap_back_send_t	sendok ){	metainfo_t	*mi = ( metainfo_t * )op->o_bd->be_private;	const char	*save_text = rs->sr_text,			*save_matched = rs->sr_matched;	BerVarray	save_ref = rs->sr_ref;	LDAPControl	**save_ctrls = rs->sr_ctrls;	void		*matched_ctx = NULL;	char		*matched = NULL;	char		*text = NULL;	char		**refs = NULL;	LDAPControl	**ctrls = NULL;	assert( mc != NULL );	rs->sr_text = NULL;	rs->sr_matched = NULL;	rs->sr_ref = NULL;	rs->sr_ctrls = NULL;	if ( candidate != META_TARGET_NONE ) {		metatarget_t		*mt = mi->mi_targets[ candidate ];		metasingleconn_t	*msc = &mc->mc_conns[ candidate ];#define	ERR_OK(err) ((err) == LDAP_SUCCESS || (err) == LDAP_COMPARE_FALSE || (err) == LDAP_COMPARE_TRUE)		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 = mt->mt_timeout[ opidx ];				}			}			/* better than nothing :) */			if ( timeout == 0 ) {				if ( mi->mi_idle_timeout ) {					timeout = mi->mi_idle_timeout;				} else if ( mi->mi_conn_ttl ) {					timeout = mi->mi_conn_ttl;				}			}			if ( timeout ) {				stoptime = op->o_time + timeout;			}			LDAP_BACK_TV_SET( &tv );retry:;			rc = ldap_result( msc->msc_ld, msgid, LDAP_MSG_ALL, &tv, &res );			switch ( rc ) {			case 0:				if ( timeout && slap_get_time() > stoptime ) {					(void)meta_back_cancel( mc, op, rs, msgid, candidate, sendok );					rs->sr_err = timeout_err;					rs->sr_text = timeout_text;					break;				}				LDAP_BACK_TV_SET( &tv );				ldap_pvt_thread_yield();				goto retry;			case -1:				ldap_get_option( msc->msc_ld, LDAP_OPT_RESULT_CODE,						&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 ( mi->mi_idle_timeout != 0 && msc->msc_time < op->o_time ) {					msc->msc_time = op->o_time;				}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?