⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bind.c

📁 ldap服务器源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		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,		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;			}			if ( refs != NULL ) {				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 ] );			}			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 ) {		assert( refs != NULL );		ber_memvfree( (void **)refs );		op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );		rs->sr_ref = NULL;	}	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 */

⌨️ 快捷键说明

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