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

📄 search.c

📁 ldap服务器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* search.c - search operation *//* $OpenLDAP: pkg/ldap/servers/slapd/back-bdb/search.c,v 1.221.2.15 2007/01/02 21:44:00 kurt Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 2000-2007 The OpenLDAP Foundation. * 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>. */#include "portable.h"#include <stdio.h>#include <ac/string.h>#include "back-bdb.h"#include "idl.h"static int base_candidate(	BackendDB	*be,	Entry	*e,	ID		*ids );static int search_candidates(	Operation *op,	SlapReply *rs,	Entry *e,	u_int32_t locker,	ID	*ids,	ID	*scopes );static int parse_paged_cookie( Operation *op, SlapReply *rs );static void send_paged_response( 	Operation *op,	SlapReply *rs,	ID  *lastid,	int tentries );/* Dereference aliases for a single alias entry. Return the final * dereferenced entry on success, NULL on any failure. */static Entry * deref_base (	Operation *op,	SlapReply *rs,	Entry *e,	Entry **matched,	u_int32_t locker,	DB_LOCK *lock,	ID	*tmp,	ID	*visited ){	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;	struct berval ndn;	EntryInfo *ei;	DB_LOCK lockr;	rs->sr_err = LDAP_ALIAS_DEREF_PROBLEM;	rs->sr_text = "maximum deref depth exceeded";	for (;;) {		/* Remember the last entry we looked at, so we can		 * report broken links		 */		*matched = e;		if (BDB_IDL_N(tmp) >= op->o_bd->be_max_deref_depth) {			e = NULL;			break;		}		/* If this is part of a subtree or onelevel search,		 * have we seen this ID before? If so, quit.		 */		if ( visited && bdb_idl_insert( visited, e->e_id ) ) {			e = NULL;			break;		}		/* If we've seen this ID during this deref iteration,		 * we've hit a loop.		 */		if ( bdb_idl_insert( tmp, e->e_id ) ) {			rs->sr_err = LDAP_ALIAS_PROBLEM;			rs->sr_text = "circular alias";			e = NULL;			break;		}		/* If there was a problem getting the aliasedObjectName,		 * get_alias_dn will have set the error status.		 */		if ( get_alias_dn(e, &ndn, &rs->sr_err, &rs->sr_text) ) {			e = NULL;			break;		}		rs->sr_err = bdb_dn2entry( op, NULL, &ndn, &ei,			0, locker, &lockr );		if ( ei ) {			e = ei->bei_e;		} else {			e = NULL;		}		if (!e) {			rs->sr_err = LDAP_ALIAS_PROBLEM;			rs->sr_text = "aliasedObject not found";			break;		}		/* Free the previous entry, continue to work with the		 * one we just retrieved.		 */		bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache,			*matched, lock);		*lock = lockr;		/* We found a regular entry. Return this to the caller. The		 * entry is still locked for Read.		 */		if (!is_entry_alias(e)) {			rs->sr_err = LDAP_SUCCESS;			rs->sr_text = NULL;			break;		}	}	return e;}/* Look for and dereference all aliases within the search scope. Adds * the dereferenced entries to the "ids" list. Requires "stack" to be * able to hold 8 levels of DB_SIZE IDLs. Of course we're hardcoded to * require a minimum of 8 UM_SIZE IDLs so this is never a problem. */static int search_aliases(	Operation *op,	SlapReply *rs,	Entry *e,	u_int32_t locker,	ID *ids,	ID *scopes,	ID *stack ){	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;	ID *aliases, *curscop, *subscop, *visited, *newsubs, *oldsubs, *tmp;	ID cursora, ida, cursoro, ido, *subscop2;	Entry *matched, *a;	EntryInfo *ei;	struct berval bv_alias = BER_BVC( "alias" );#ifdef LDAP_COMP_MATCH	AttributeAssertion aa_alias = { NULL, BER_BVNULL, NULL };#else	AttributeAssertion aa_alias = { NULL, BER_BVNULL };#endif	Filter	af;	DB_LOCK locka, lockr;	int first = 1;	aliases = stack;	/* IDL of all aliases in the database */	curscop = aliases + BDB_IDL_DB_SIZE;	/* Aliases in the current scope */	subscop = curscop + BDB_IDL_DB_SIZE;	/* The current scope */	visited = subscop + BDB_IDL_DB_SIZE;	/* IDs we've seen in this search */	newsubs = visited + BDB_IDL_DB_SIZE;	/* New subtrees we've added */	oldsubs = newsubs + BDB_IDL_DB_SIZE;	/* Subtrees added previously */	tmp = oldsubs + BDB_IDL_DB_SIZE;	/* Scratch space for deref_base() */	/* A copy of subscop, because subscop gets clobbered by	 * the bdb_idl_union/intersection routines	 */	subscop2 = tmp + BDB_IDL_DB_SIZE;	af.f_choice = LDAP_FILTER_EQUALITY;	af.f_ava = &aa_alias;	af.f_av_desc = slap_schema.si_ad_objectClass;	af.f_av_value = bv_alias;	af.f_next = NULL;	/* Find all aliases in database */	BDB_IDL_ZERO( aliases );	rs->sr_err = bdb_filter_candidates( op, &af, aliases,		curscop, visited );	if (rs->sr_err != LDAP_SUCCESS) {		return rs->sr_err;	}	oldsubs[0] = 1;	oldsubs[1] = e->e_id;	BDB_IDL_ZERO( ids );	BDB_IDL_ZERO( visited );	BDB_IDL_ZERO( newsubs );	cursoro = 0;	ido = bdb_idl_first( oldsubs, &cursoro );	for (;;) {		/* Set curscop to only the aliases in the current scope. Start with		 * all the aliases, obtain the IDL for the current scope, and then		 * get the intersection of these two IDLs. Add the current scope		 * to the cumulative list of candidates.		 */		BDB_IDL_CPY( curscop, aliases );		rs->sr_err = bdb_dn2idl( op, e, subscop,			subscop2+BDB_IDL_DB_SIZE );		if (first) {			first = 0;		} else {			bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, e, &locka);		}		BDB_IDL_CPY(subscop2, subscop);		rs->sr_err = bdb_idl_intersection(curscop, subscop);		bdb_idl_union( ids, subscop2 );		/* Dereference all of the aliases in the current scope. */		cursora = 0;		for (ida = bdb_idl_first(curscop, &cursora); ida != NOID;			ida = bdb_idl_next(curscop, &cursora))		{			ei = NULL;retry1:			rs->sr_err = bdb_cache_find_id(op, NULL,				ida, &ei, 0, locker, &lockr );			if (rs->sr_err != LDAP_SUCCESS) {				if ( rs->sr_err == DB_LOCK_DEADLOCK ||					rs->sr_err == DB_LOCK_NOTGRANTED ) goto retry1;				continue;			}			a = ei->bei_e;			/* This should only happen if the curscop IDL has maxed out and			 * turned into a range that spans IDs indiscriminately			 */			if (!is_entry_alias(a)) {				bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache,					a, &lockr);				continue;			}			/* Actually dereference the alias */			BDB_IDL_ZERO(tmp);			a = deref_base( op, rs, a, &matched, locker, &lockr,				tmp, visited );			if (a) {				/* If the target was not already in our current candidates,				 * make note of it in the newsubs list. Also				 * set it in the scopes list so that bdb_search				 * can check it.				 */				if (bdb_idl_insert(ids, a->e_id) == 0) {					bdb_idl_insert(newsubs, a->e_id);					bdb_idl_insert(scopes, a->e_id);				}				bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache,					a, &lockr);			} else if (matched) {				/* Alias could not be dereferenced, or it deref'd to				 * an ID we've already seen. Ignore it.				 */				bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache,					matched, &lockr );				rs->sr_text = NULL;			}		}		/* If this is a OneLevel search, we're done; oldsubs only had one		 * ID in it. For a Subtree search, oldsubs may be a list of scope IDs.		 */		if ( op->ors_scope == LDAP_SCOPE_ONELEVEL ) break;nextido:		ido = bdb_idl_next( oldsubs, &cursoro );				/* If we're done processing the old scopes, did we add any new		 * scopes in this iteration? If so, go back and do those now.		 */		if (ido == NOID) {			if (BDB_IDL_IS_ZERO(newsubs)) break;			BDB_IDL_CPY(oldsubs, newsubs);			BDB_IDL_ZERO(newsubs);			cursoro = 0;			ido = bdb_idl_first( oldsubs, &cursoro );		}		/* Find the entry corresponding to the next scope. If it can't		 * be found, ignore it and move on. This should never happen;		 * we should never see the ID of an entry that doesn't exist.		 * Set the name so that the scope's IDL can be retrieved.		 */		ei = NULL;sameido:		rs->sr_err = bdb_cache_find_id(op, NULL, ido, &ei,			0, locker, &locka );		if ( rs->sr_err != LDAP_SUCCESS ) {			if ( rs->sr_err == DB_LOCK_DEADLOCK ||				rs->sr_err == DB_LOCK_NOTGRANTED )				goto sameido;			goto nextido;		}		e = ei->bei_e;	}	return rs->sr_err;}intbdb_search( Operation *op, SlapReply *rs ){	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;	time_t		stoptime;	ID		id, cursor;	ID		candidates[BDB_IDL_UM_SIZE];	ID		scopes[BDB_IDL_DB_SIZE];	Entry		*e = NULL, base, e_root = {0};	Entry		*matched = NULL;	EntryInfo	*ei, ei_root = {0};	struct berval	realbase = BER_BVNULL;#ifdef SLAP_ACL_HONOR_DISCLOSE	slap_mask_t	mask;#endif	int		manageDSAit;	int		tentries = 0;	ID		lastid = NOID;	AttributeName	*attrs;	u_int32_t	locker = 0;	DB_LOCK		lock;	struct	bdb_op_info	*opinfo = NULL;	DB_TXN			*ltid = NULL;	Debug( LDAP_DEBUG_TRACE, "=> " LDAP_XSTRING(bdb_search) "\n", 0, 0, 0);	attrs = op->oq_search.rs_attrs;	opinfo = (struct bdb_op_info *) op->o_private;	manageDSAit = get_manageDSAit( op );	if ( opinfo && opinfo->boi_txn ) {		ltid = opinfo->boi_txn;		locker = TXN_ID( ltid );	} else {		rs->sr_err = LOCK_ID( bdb->bi_dbenv, &locker );		switch(rs->sr_err) {		case 0:			break;		default:			send_ldap_error( op, rs, LDAP_OTHER, "internal error" );			return rs->sr_err;		}	}	if ( op->o_req_ndn.bv_len == 0 ) {		/* DIT root special case */		ei_root.bei_e = &e_root;		ei_root.bei_parent = &ei_root;		e_root.e_private = &ei_root;		e_root.e_id = 0;		BER_BVSTR( &e_root.e_nname, "" );		BER_BVSTR( &e_root.e_name, "" );		ei = &ei_root;		rs->sr_err = LDAP_SUCCESS;	} else {		if ( op->ors_deref & LDAP_DEREF_FINDING ) {			BDB_IDL_ZERO(candidates);		}dn2entry_retry:		/* get entry with reader lock */		rs->sr_err = bdb_dn2entry( op, ltid, &op->o_req_ndn, &ei,			1, locker, &lock );	}	switch(rs->sr_err) {	case DB_NOTFOUND:		matched = ei->bei_e;		break;	case 0:		e = ei->bei_e;		break;	case LDAP_BUSY:		send_ldap_error( op, rs, LDAP_BUSY, "ldap server busy" );		if ( !opinfo )			LOCK_ID_FREE (bdb->bi_dbenv, locker );		return LDAP_BUSY;	case DB_LOCK_DEADLOCK:	case DB_LOCK_NOTGRANTED:		goto dn2entry_retry;	default:		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );		if ( !opinfo )			LOCK_ID_FREE (bdb->bi_dbenv, locker );		return rs->sr_err;	}	if ( op->ors_deref & LDAP_DEREF_FINDING ) {		if ( matched && is_entry_alias( matched )) {			struct berval stub;			stub.bv_val = op->o_req_ndn.bv_val;			stub.bv_len = op->o_req_ndn.bv_len - matched->e_nname.bv_len - 1;			e = deref_base( op, rs, matched, &matched, locker, &lock,				candidates, NULL );			if ( e ) {				build_new_dn( &op->o_req_ndn, &e->e_nname, &stub,					op->o_tmpmemctx );				bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache,					e, &lock);				matched = NULL;				goto dn2entry_retry;			}		} else if ( e && is_entry_alias( e )) {			e = deref_base( op, rs, e, &matched, locker, &lock,				candidates, NULL );		}	}	if ( e == NULL ) {		struct berval matched_dn = BER_BVNULL;		if ( matched != NULL ) {			BerVarray erefs = NULL;#ifdef SLAP_ACL_HONOR_DISCLOSE			/* return referral only if "disclose"			 * is granted on the object */			if ( ! access_allowed( op, matched,						slap_schema.si_ad_entry,						NULL, ACL_DISCLOSE, NULL ) )			{				rs->sr_err = LDAP_NO_SUCH_OBJECT;

⌨️ 快捷键说明

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