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

📄 search.c

📁 OpenLdap是LDAP的开源项目
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $OpenLDAP: pkg/ldap/servers/slapd/back-meta/search.c,v 1.84.2.33 2007/08/14 09:59:44 ando Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 1999-2007 The OpenLDAP Foundation. * Portions Copyright 2001-2003 Pierangelo Masarati. * Portions Copyright 1999-2003 Howard Chu. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * <http://www.OpenLDAP.org/license.html>. *//* ACKNOWLEDGEMENTS: * This work was initially developed by the Howard Chu for inclusion * in OpenLDAP Software and subsequently enhanced by Pierangelo * Masarati. */#include "portable.h"#include <stdio.h>#include <ac/socket.h>#include <ac/string.h>#include <ac/time.h>#include "lutil.h"#include "slap.h"#include "../back-ldap/back-ldap.h"#include "back-meta.h"#undef ldap_debug	/* silence a warning in ldap-int.h */#include "ldap_log.h"#include "../../../libraries/libldap/ldap-int.h"/* IGNORE means that target does not (no longer) participate * in the search; * NOTREADY means the search on that target has not been initialized yet */#define	META_MSGID_IGNORE	(-1)#define	META_MSGID_NEED_BIND	(-2)static intmeta_send_entry(	Operation 	*op,	SlapReply	*rs,	metaconn_t	*mc,	int 		i,	LDAPMessage 	*e );typedef enum meta_search_candidate_t {	META_SEARCH_UNDEFINED = -2,	META_SEARCH_ERR = -1,	META_SEARCH_NOT_CANDIDATE,	META_SEARCH_CANDIDATE,	META_SEARCH_BINDING,	META_SEARCH_NEED_BIND} meta_search_candidate_t;/* * meta_search_dobind_init() * * initiates bind for a candidate target of a search. */static meta_search_candidate_tmeta_search_dobind_init(	Operation		*op,	SlapReply		*rs,	metaconn_t		**mcp,	int			candidate,	SlapReply		*candidates ){	metaconn_t		*mc = *mcp;	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;	metatarget_t		*mt = mi->mi_targets[ candidate ];	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];	struct berval		binddn = msc->msc_bound_ndn,				cred = msc->msc_cred;	int			method;	int			rc;	meta_search_candidate_t	retcode;	Debug( LDAP_DEBUG_TRACE, "%s >>> meta_search_dobind_init[%d]\n",		op->o_log_prefix, candidate, 0 );	/*	 * all the targets are already bound as pseudoroot	 */	if ( mc->mc_authz_target == META_BOUND_ALL ) {		return META_SEARCH_CANDIDATE;	}	retcode = META_SEARCH_BINDING;	ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );	if ( LDAP_BACK_CONN_ISBOUND( msc ) || LDAP_BACK_CONN_ISANON( msc ) ) {		/* already bound (or anonymous) */#ifdef DEBUG_205		char	buf[ SLAP_TEXT_BUFLEN ] = { '\0' };		int	bound = 0;		if ( LDAP_BACK_CONN_ISBOUND( msc ) ) {			bound = 1;		}		snprintf( buf, sizeof( buf ), " mc=%p ld=%p%s DN=\"%s\"",			(void *)mc, (void *)msc->msc_ld,			bound ? " bound" : " anonymous",			bound == 0 ? "" : msc->msc_bound_ndn.bv_val );		Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",			op->o_log_prefix, candidate, buf );#endif /* DEBUG_205 */		retcode = META_SEARCH_CANDIDATE;	} else if ( META_BACK_CONN_CREATING( msc ) || LDAP_BACK_CONN_BINDING( msc ) ) {		/* another thread is binding the target for this conn; wait */#ifdef DEBUG_205		char	buf[ SLAP_TEXT_BUFLEN ] = { '\0' };		snprintf( buf, sizeof( buf ), " mc=%p ld=%p needbind",			(void *)mc, (void *)msc->msc_ld );		Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",			op->o_log_prefix, candidate, buf );#endif /* DEBUG_205 */		candidates[ candidate ].sr_msgid = META_MSGID_NEED_BIND;		retcode = META_SEARCH_NEED_BIND;	} else {		/* we'll need to bind the target for this conn */#ifdef DEBUG_205		char buf[ SLAP_TEXT_BUFLEN ];		snprintf( buf, sizeof( buf ), " mc=%p ld=%p binding",			(void *)mc, (void *)msc->msc_ld );		Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",			op->o_log_prefix, candidate, buf );#endif /* DEBUG_205 */		if ( msc->msc_ld == NULL ) {			/* for some reason (e.g. because formerly in "binding"			 * state, with eventual connection expiration or invalidation)			 * it was not initialized as expected */			Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] mc=%p ld=NULL\n",				op->o_log_prefix, candidate, (void *)mc );			rc = meta_back_init_one_conn( op, rs, *mcp, candidate,				LDAP_BACK_CONN_ISPRIV( *mcp ), LDAP_BACK_DONTSEND, 0 );			switch ( rc ) {			case LDAP_SUCCESS:				assert( msc->msc_ld != NULL );				break;			case LDAP_SERVER_DOWN:			case LDAP_UNAVAILABLE:				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );				goto down;				default:				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );				goto other;			}		}		LDAP_BACK_CONN_BINDING_SET( msc );	}	ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );	if ( retcode != META_SEARCH_BINDING ) {		return retcode;	}	/* 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 ) ||			( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )	{		rc = meta_back_proxy_authz_cred( mc, candidate, op, rs, LDAP_BACK_DONTSEND, &binddn, &cred, &method );		if ( rc != LDAP_SUCCESS ) {			goto down;		}		/* NOTE: we copy things here, even if bind didn't succeed yet,		 * because the connection is not shared until bind is over */		if ( !BER_BVISNULL( &binddn ) ) {			ber_bvreplace( &msc->msc_bound_ndn, &binddn );			if ( LDAP_BACK_SAVECRED( mi ) && !BER_BVISNULL( &cred ) ) {				if ( !BER_BVISNULL( &msc->msc_cred ) ) {					memset( msc->msc_cred.bv_val, 0,						msc->msc_cred.bv_len );				}				ber_bvreplace( &msc->msc_cred, &cred );			}		}		if ( LDAP_BACK_CONN_ISBOUND( msc ) ) {			/* apparently, idassert was configured with SASL bind,			 * so bind occurred inside meta_back_proxy_authz_cred() */			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 );			return META_SEARCH_CANDIDATE;		}		/* paranoid */		switch ( method ) {		case LDAP_AUTH_NONE:		case LDAP_AUTH_SIMPLE:			/* do a simple bind with binddn, cred */			break;		default:			assert( 0 );			break;		}	}	assert( msc->msc_ld != NULL );retry:;	rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,			NULL, NULL, &candidates[ candidate ].sr_msgid );#ifdef DEBUG_205	{		char buf[ SLAP_TEXT_BUFLEN ];		snprintf( buf, sizeof( buf ), "meta_search_dobind_init[%d] mc=%p ld=%p rc=%d",			candidate, (void *)mc, (void *)mc->mc_conns[ candidate ].msc_ld, rc );		Debug( LDAP_DEBUG_ANY, "### %s %s\n",			op->o_log_prefix, buf, 0 );	}#endif /* DEBUG_205 */	switch ( rc ) {	case LDAP_SUCCESS:		assert( candidates[ candidate ].sr_msgid >= 0 );		META_BINDING_SET( &candidates[ candidate ] );		return META_SEARCH_BINDING;	case LDAP_SERVER_DOWN:down:;		/* This is the worst thing that could happen:		 * the search will wait until the retry is over. */		if ( !META_IS_RETRYING( &candidates[ candidate ] ) ) {			META_RETRYING_SET( &candidates[ candidate ] );			ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );			assert( mc->mc_refcnt > 0 );			if ( StatslogTest( LDAP_DEBUG_ANY ) ) {				char	buf[ SLAP_TEXT_BUFLEN ];				/* this lock is required; however,				 * it's invoked only when logging is on */				ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );				snprintf( buf, sizeof( buf ),					"retrying URI=\"%s\" DN=\"%s\"",					mt->mt_uri,					BER_BVISNULL( &msc->msc_bound_ndn ) ?						"" : msc->msc_bound_ndn.bv_val );				ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );				Debug( LDAP_DEBUG_ANY,					"%s meta_search_dobind_init[%d]: %s.\n",					op->o_log_prefix, candidate, buf );			}			meta_clear_one_candidate( op, mc, candidate );			LDAP_BACK_CONN_ISBOUND_CLEAR( msc );			( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );			/* mc here must be the regular mc, reset and ready for init */			rc = meta_back_init_one_conn( op, rs, mc, candidate,				LDAP_BACK_CONN_ISPRIV( mc ), LDAP_BACK_DONTSEND, 0 );			if ( rc == LDAP_SUCCESS ) {				LDAP_BACK_CONN_BINDING_SET( msc );			}			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );			if ( rc == LDAP_SUCCESS ) {				candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;				goto retry;			}		}		if ( *mcp == NULL ) {			retcode = META_SEARCH_ERR;			rs->sr_err = LDAP_UNAVAILABLE;			candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;			break;		}		/* fall thru */	default:other:;		rs->sr_err = rc;		rc = slap_map_api2result( rs );		ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );		meta_clear_one_candidate( op, mc, candidate );		candidates[ candidate ].sr_err = rc;		if ( META_BACK_ONERR_STOP( mi ) ) {			LDAP_BACK_CONN_TAINTED_SET( mc );			meta_back_release_conn_lock( mi, mc, 0 );			*mcp = NULL;			rs->sr_err = rc;			retcode = META_SEARCH_ERR;		} else {			retcode = META_SEARCH_NOT_CANDIDATE;		}		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;		ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );		break;	}	return retcode;}static meta_search_candidate_tmeta_search_dobind_result(	Operation		*op,	SlapReply		*rs,	metaconn_t		**mcp,	int			candidate,	SlapReply		*candidates,	LDAPMessage		*res ){	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;	metaconn_t		*mc = *mcp;	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];	meta_search_candidate_t	retcode = META_SEARCH_NOT_CANDIDATE;	int			rc;	assert( msc->msc_ld != NULL );	/* FIXME: matched? referrals? response controls? */	rc = ldap_parse_result( msc->msc_ld, res,		&candidates[ candidate ].sr_err,		NULL, NULL, NULL, NULL, 0 );	if ( rc != LDAP_SUCCESS ) {		candidates[ candidate ].sr_err = rc;	} else {		rc = slap_map_api2result( &candidates[ candidate ] );	}	ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );	LDAP_BACK_CONN_BINDING_CLEAR( msc );	if ( rc != LDAP_SUCCESS ) {		meta_clear_one_candidate( op, mc, candidate );		candidates[ candidate ].sr_err = rc;		if ( META_BACK_ONERR_STOP( mi ) ) {	        	LDAP_BACK_CONN_TAINTED_SET( mc );			meta_back_release_conn_lock( mi, mc, 0 );			*mcp = NULL;			retcode = META_SEARCH_ERR;			rs->sr_err = rc;		}	} else {		/* FIXME: check if bound as idassert authcDN! */		if ( BER_BVISNULL( &msc->msc_bound_ndn )			|| BER_BVISEMPTY( &msc->msc_bound_ndn ) )		{			LDAP_BACK_CONN_ISANON_SET( msc );		} else {			LDAP_BACK_CONN_ISBOUND_SET( msc );		}		retcode = META_SEARCH_CANDIDATE;	}	candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;	META_BINDING_CLEAR( &candidates[ candidate ] );	ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );	return retcode;}static meta_search_candidate_tmeta_back_search_start(	Operation		*op,	SlapReply		*rs,	dncookie		*dc,	metaconn_t		**mcp,	int			candidate,	SlapReply		*candidates ){	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;	metatarget_t		*mt = mi->mi_targets[ candidate ];	metasingleconn_t	*msc = &(*mcp)->mc_conns[ candidate ];	struct berval		realbase = op->o_req_dn;	int			realscope = op->ors_scope;	struct berval		mbase = BER_BVNULL; 	struct berval		mfilter = BER_BVNULL;	char			**mapped_attrs = NULL;	int			rc;	meta_search_candidate_t	retcode;	struct timeval		tv, *tvp = NULL;	int			nretries = 1;	LDAPControl		**ctrls = NULL;	/* this should not happen; just in case... */	if ( msc->msc_ld == NULL ) {		Debug( LDAP_DEBUG_ANY,			"%s: meta_back_search_start candidate=%d ld=NULL%s.\n",			op->o_log_prefix, candidate,			META_BACK_ONERR_STOP( mi ) ? "" : " (ignored)" );		candidates[ candidate ].sr_err = LDAP_OTHER;		if ( META_BACK_ONERR_STOP( mi ) ) {			return META_SEARCH_ERR;		}		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;		return META_SEARCH_NOT_CANDIDATE;	}	Debug( LDAP_DEBUG_TRACE, "%s >>> meta_back_search_start[%d]\n", op->o_log_prefix, candidate, 0 );	/*	 * modifies the base according to the scope, if required	 */	if ( mt->mt_nsuffix.bv_len > op->o_req_ndn.bv_len ) {		switch ( op->ors_scope ) {		case LDAP_SCOPE_SUBTREE:			/*			 * make the target suffix the new base			 * FIXME: this is very forgiving, because			 * "illegal" searchBases may be turned			 * into the suffix of the target; however,			 * the requested searchBase already passed			 * thru the candidate analyzer...			 */			if ( dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) {				realbase = mt->mt_nsuffix;				if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {					realscope = LDAP_SCOPE_SUBORDINATE;				}			} else {				/*				 * this target is no longer candidate				 */				retcode = META_SEARCH_NOT_CANDIDATE;				goto doreturn;			}			break;		case LDAP_SCOPE_SUBORDINATE:		case LDAP_SCOPE_ONELEVEL:		{			struct berval	rdn = mt->mt_nsuffix;			rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," );			if ( dnIsOneLevelRDN( &rdn )					&& dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) )			{				/*				 * if there is exactly one level,				 * make the target suffix the new				 * base, and make scope "base"				 */				realbase = mt->mt_nsuffix;				if ( op->ors_scope == LDAP_SCOPE_SUBORDINATE ) {					if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {						realscope = LDAP_SCOPE_SUBORDINATE;					} else {						realscope = LDAP_SCOPE_SUBTREE;					}				} else {					realscope = LDAP_SCOPE_BASE;				}				break;			} /* else continue with the next case */		}		case LDAP_SCOPE_BASE:			/*			 * this target is no longer candidate			 */			retcode = META_SEARCH_NOT_CANDIDATE;			goto doreturn;		}	}	/* initiate dobind */	retcode = meta_search_dobind_init( op, rs, mcp, candidate, candidates );	Debug( LDAP_DEBUG_TRACE, "%s <<< meta_search_dobind_init[%d]=%d\n", op->o_log_prefix, candidate, retcode );	if ( retcode != META_SEARCH_CANDIDATE ) {		goto doreturn;	}

⌨️ 快捷键说明

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