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

📄 bind.c

📁 ldap服务器源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	int		is_tls = op->o_conn->c_is_tls;	time_t		lc_time = (time_t)(-1);#endif /* HAVE_TLS */	ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );	rs->sr_err = ldap_initialize( &ld, li->li_uri );	ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex );	if ( rs->sr_err != LDAP_SUCCESS ) {		goto error_return;	}	/* Set LDAP version. This will always succeed: If the client	 * bound with a particular version, then so can we.	 */	if ( li->li_version != 0 ) {		version = li->li_version;	} else if ( op->o_protocol != 0 ) {		version = op->o_protocol;	} else {		/* assume it's an internal op; set to LDAPv3 */		version = LDAP_VERSION3;	}	ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (const void *)&version );	/* automatically chase referrals ("chase-referrals [{yes|no}]" statement) */	ldap_set_option( ld, LDAP_OPT_REFERRALS,		LDAP_BACK_CHASE_REFERRALS( li ) ? LDAP_OPT_ON : LDAP_OPT_OFF );	if ( li->li_network_timeout > 0 ) {		struct timeval		tv;		tv.tv_sec = li->li_network_timeout;		tv.tv_usec = 0;		ldap_set_option( ld, LDAP_OPT_NETWORK_TIMEOUT, (const void *)&tv );	}#ifdef HAVE_TLS	ldap_pvt_thread_mutex_lock( &li->li_uri_mutex );	rs->sr_err = ldap_back_start_tls( ld, op->o_protocol, &is_tls,			li->li_uri, li->li_flags, li->li_nretries, &rs->sr_text );	ldap_pvt_thread_mutex_unlock( &li->li_uri_mutex );	if ( rs->sr_err != LDAP_SUCCESS ) {		ldap_unbind_ext( ld, NULL, NULL );		rs->sr_text = "Start TLS failed";		goto error_return;	} else if ( li->li_idle_timeout ) {		/* only touch when activity actually took place... */		lc_time = op->o_time;	}#endif /* HAVE_TLS */	lc->lc_ld = ld;	lc->lc_refcnt = 1;#ifdef HAVE_TLS	if ( is_tls ) {		LDAP_BACK_CONN_ISTLS_SET( lc );	} else {		LDAP_BACK_CONN_ISTLS_CLEAR( lc );	}	if ( lc_time != (time_t)(-1) ) {		lc->lc_time = lc_time;	}#endif /* HAVE_TLS */error_return:;	if ( rs->sr_err != LDAP_SUCCESS ) {		rs->sr_err = slap_map_api2result( rs );		if ( sendok & LDAP_BACK_SENDERR ) {			if ( rs->sr_text == NULL ) {				rs->sr_text = "Proxy connection initialization failed";			}			send_ldap_result( op, rs );		}	} else {		if ( li->li_conn_ttl > 0 ) {			lc->lc_create_time = op->o_time;		}	}	return rs->sr_err;}static ldapconn_t *ldap_back_getconn(	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;	ldapconn_t	*lc = NULL,			lc_curr = { 0 };	int		refcnt = 1,			lookupconn = !( sendok & LDAP_BACK_BINDING );	/* if the server is quarantined, and	 * - the current interval did not expire yet, or	 * - no more retries should occur,	 * don't return the connection */	if ( li->li_isquarantined ) {		slap_retry_info_t	*ri = &li->li_quarantine;		int			dont_retry = 1;		if ( li->li_quarantine.ri_interval ) {			ldap_pvt_thread_mutex_lock( &li->li_quarantine_mutex );			if ( li->li_isquarantined == LDAP_BACK_FQ_YES ) {				dont_retry = ( ri->ri_num[ ri->ri_idx ] == SLAP_RETRYNUM_TAIL					|| slap_get_time() < ri->ri_last + ri->ri_interval[ ri->ri_idx ] );				if ( !dont_retry ) {					Debug( LDAP_DEBUG_ANY,						"%s: ldap_back_getconn quarantine "						"retry block #%d try #%d.\n",						op->o_log_prefix, ri->ri_idx, ri->ri_count );					li->li_isquarantined = LDAP_BACK_FQ_RETRYING;				}			}			ldap_pvt_thread_mutex_unlock( &li->li_quarantine_mutex );		}		if ( dont_retry ) {			rs->sr_err = LDAP_UNAVAILABLE;			if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {				rs->sr_text = "Target is quarantined";				send_ldap_result( op, rs );			}			return NULL;		}	}	/* Internal searches are privileged and shared. So is root. */	if ( op->o_do_not_cache || be_isroot( op ) ) {		LDAP_BACK_CONN_ISPRIV_SET( &lc_curr );		lc_curr.lc_local_ndn = op->o_bd->be_rootndn;		LDAP_BACK_PCONN_ROOTDN_SET( &lc_curr, op );	} else {		struct berval	tmpbinddn,				tmpbindcred,				save_o_dn,				save_o_ndn;		int		isproxyauthz;		/* need cleanup */		if ( binddn == NULL ) {			binddn = &tmpbinddn;		}			if ( bindcred == NULL ) {			bindcred = &tmpbindcred;		}		if ( op->o_tag == LDAP_REQ_BIND ) {			save_o_dn = op->o_dn;			save_o_ndn = op->o_ndn;			op->o_dn = op->o_req_dn;			op->o_ndn = op->o_req_ndn;		}		isproxyauthz = ldap_back_is_proxy_authz( op, rs, sendok, binddn, bindcred );		if ( isproxyauthz == -1 ) {			return NULL;		}		if ( op->o_tag == LDAP_REQ_BIND ) {			op->o_dn = save_o_dn;			op->o_ndn = save_o_ndn;		}		lc_curr.lc_local_ndn = op->o_ndn;		/* Explicit binds must not be shared;		 * however, explicit binds are piped in a special connection		 * when idassert is to occur with "override" set */		if ( op->o_tag == LDAP_REQ_BIND && !isproxyauthz ) {			lc_curr.lc_conn = op->o_conn;		} else {			if ( isproxyauthz && !( sendok & LDAP_BACK_BINDING ) ) {				lc_curr.lc_local_ndn = *binddn;				LDAP_BACK_PCONN_ROOTDN_SET( &lc_curr, op );				LDAP_BACK_CONN_ISIDASSERT_SET( &lc_curr );			} else if ( isproxyauthz && ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) {				lc_curr.lc_local_ndn = slap_empty_bv;				LDAP_BACK_PCONN_BIND_SET( &lc_curr, op );				LDAP_BACK_CONN_ISIDASSERT_SET( &lc_curr );				lookupconn = 1;			} else if ( SLAP_IS_AUTHZ_BACKEND( op ) ) {				lc_curr.lc_conn = op->o_conn;			} else {				LDAP_BACK_PCONN_ANON_SET( &lc_curr, op );			}		}	}	/* Explicit Bind requests always get their own conn */	if ( lookupconn ) {retry_lock:		ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );		if ( LDAP_BACK_PCONN_ISPRIV( &lc_curr ) ) {			/* lookup a conn that's not binding */			LDAP_TAILQ_FOREACH( lc,				&li->li_conn_priv[ LDAP_BACK_CONN2PRIV( &lc_curr ) ].lic_priv,				lc_q )			{				if ( !LDAP_BACK_CONN_BINDING( lc ) && lc->lc_refcnt == 0 ) {					break;				}			}			if ( lc != NULL ) {				if ( lc != LDAP_TAILQ_LAST( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv,					ldapconn_t, lc_q ) )				{					LDAP_TAILQ_REMOVE( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv,						lc, lc_q );					LDAP_TAILQ_ENTRY_INIT( lc, lc_q );					LDAP_TAILQ_INSERT_TAIL( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv,						lc, lc_q );				}			} else if ( !LDAP_BACK_USE_TEMPORARIES( li )				&& li->li_conn_priv[ LDAP_BACK_CONN2PRIV( &lc_curr ) ].lic_num == li->li_conn_priv_max )			{				lc = LDAP_TAILQ_FIRST( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( &lc_curr ) ].lic_priv );			}					} else {			/* Searches for a ldapconn in the avl tree */			lc = (ldapconn_t *)avl_find( li->li_conninfo.lai_tree, 					(caddr_t)&lc_curr, ldap_back_conndn_cmp );		}		if ( lc != NULL ) {			/* Don't reuse connections while they're still binding */			if ( LDAP_BACK_CONN_BINDING( lc ) ) {				if ( !LDAP_BACK_USE_TEMPORARIES( li ) ) {					ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );					ldap_pvt_thread_yield();					goto retry_lock;				}				lc = NULL;			}			if ( lc != NULL ) {				if ( op->o_tag == LDAP_REQ_BIND ) {					/* right now, this is the only possible case */					assert( ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) );					LDAP_BACK_CONN_BINDING_SET( lc );				}				refcnt = ++lc->lc_refcnt;			}		}		ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );	}	/* Looks like we didn't get a bind. Open a new session... */	if ( lc == NULL ) {		lc = (ldapconn_t *)ch_calloc( 1, sizeof( ldapconn_t ) );		lc->lc_flags = li->li_flags;		lc->lc_lcflags = lc_curr.lc_lcflags;		if ( ldap_back_prepare_conn( lc, op, rs, sendok ) != LDAP_SUCCESS ) {			ch_free( lc );			return NULL;		}		if ( sendok & LDAP_BACK_BINDING ) {			LDAP_BACK_CONN_BINDING_SET( lc );		}		lc->lc_conn = lc_curr.lc_conn;		ber_dupbv( &lc->lc_local_ndn, &lc_curr.lc_local_ndn );		/*		 * the rationale is: connections as the rootdn are privileged,		 * so acl_authcDN is to be used; however, in some cases		 * one already configured identity assertion with a highly		 * privileged idassert_authcDN, so if acl_authcDN is NULL		 * and idassert_authcDN is not, use the second instead.		 *		 * might change in the future, because it's preferable		 * to make clear what identity is being used, since		 * the only drawback is that one risks to configure		 * the same identity twice...		 */		if ( LDAP_BACK_CONN_ISPRIV( &lc_curr ) ) {			if ( BER_BVISNULL( &li->li_acl_authcDN ) && !BER_BVISNULL( &li->li_idassert_authcDN ) ) {				ber_dupbv( &lc->lc_bound_ndn, &li->li_idassert_authcDN );				ber_dupbv( &lc->lc_cred, &li->li_idassert_passwd );			} else {				ber_dupbv( &lc->lc_bound_ndn, &li->li_acl_authcDN );				ber_dupbv( &lc->lc_cred, &li->li_acl_passwd );			}			LDAP_BACK_CONN_ISPRIV_SET( lc );		} else if ( LDAP_BACK_CONN_ISIDASSERT( &lc_curr ) ) {			if ( !LDAP_BACK_PCONN_ISBIND( &lc_curr ) ) {				ber_dupbv( &lc->lc_bound_ndn, &li->li_idassert_authcDN );				ber_dupbv( &lc->lc_cred, &li->li_idassert_passwd );			}			LDAP_BACK_CONN_ISIDASSERT_SET( lc );		} else {			BER_BVZERO( &lc->lc_cred );			BER_BVZERO( &lc->lc_bound_ndn );			if ( !BER_BVISEMPTY( &op->o_ndn )				&& SLAP_IS_AUTHZ_BACKEND( op ) )			{				ber_dupbv( &lc->lc_bound_ndn, &op->o_ndn );			}		}#ifdef HAVE_TLS		/* if start TLS failed but it was not mandatory,		 * check if the non-TLS connection was already		 * in cache; in case, destroy the newly created		 * connection and use the existing one */		if ( LDAP_BACK_PCONN_ISTLS( lc ) 				&& !ldap_tls_inplace( lc->lc_ld ) )		{			ldapconn_t	*tmplc = NULL;			int		idx = LDAP_BACK_CONN2PRIV( &lc_curr ) - 1;						ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );			LDAP_TAILQ_FOREACH( tmplc,				&li->li_conn_priv[ idx ].lic_priv,				lc_q )			{				if ( !LDAP_BACK_CONN_BINDING( tmplc ) ) {					break;				}			}			if ( tmplc != NULL ) {				refcnt = ++tmplc->lc_refcnt;				ldap_back_conn_free( lc );				lc = tmplc;			}			ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );			if ( tmplc != NULL ) {				goto done;			}		}#endif /* HAVE_TLS */		/* Inserts the newly created ldapconn in the avl tree */		ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );		LDAP_BACK_CONN_ISBOUND_CLEAR( lc );		assert( lc->lc_refcnt == 1 );#if LDAP_BACK_PRINT_CONNTREE > 0		ldap_back_print_conntree( li, ">>> ldap_back_getconn(insert)" );#endif /* LDAP_BACK_PRINT_CONNTREE */			if ( LDAP_BACK_PCONN_ISPRIV( lc ) ) {			if ( li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num < li->li_conn_priv_max ) {				LDAP_TAILQ_INSERT_TAIL( &li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_priv, lc, lc_q );				li->li_conn_priv[ LDAP_BACK_CONN2PRIV( lc ) ].lic_num++;				LDAP_BACK_CONN_CACHED_SET( lc );			} else {				LDAP_BACK_CONN_TAINTED_SET( lc );			}			rs->sr_err = 0;		} 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 );

⌨️ 快捷键说明

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