Exemple #1
0
/* Look for and dereference all aliases within the search scope.
 * Requires "stack" to be able to hold 6 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,
	ID e_id,
	IdScopes *isc,
	MDB_cursor *mci,
	ID *stack )
{
	ID *aliases, *curscop, *visited, *newsubs, *oldsubs, *tmp;
	ID cursora, ida, cursoro, ido;
	Entry *matched, *a;
	struct berval bv_alias = BER_BVC( "alias" );
	AttributeAssertion aa_alias = ATTRIBUTEASSERTION_INIT;
	Filter	af;
	int first = 1;

	aliases = stack;	/* IDL of all aliases in the database */
	curscop = aliases + MDB_IDL_DB_SIZE;	/* Aliases in the current scope */
	visited = curscop + MDB_IDL_DB_SIZE;	/* IDs we've seen in this search */
	newsubs = visited + MDB_IDL_DB_SIZE;	/* New subtrees we've added */
	oldsubs = newsubs + MDB_IDL_DB_SIZE;	/* Subtrees added previously */
	tmp = oldsubs + MDB_IDL_DB_SIZE;	/* Scratch space for deref_base() */

	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 */
	MDB_IDL_ZERO( aliases );
	rs->sr_err = mdb_filter_candidates( op, isc->mt, &af, aliases,
		curscop, visited );
	if (rs->sr_err != LDAP_SUCCESS || MDB_IDL_IS_ZERO( aliases )) {
		return rs->sr_err;
	}
	oldsubs[0] = 1;
	oldsubs[1] = e_id;

	MDB_IDL_ZERO( visited );
	MDB_IDL_ZERO( newsubs );

	cursoro = 0;
	ido = mdb_idl_first( oldsubs, &cursoro );

	for (;;) {
		/* Set curscop to only the aliases in the current scope. Start with
		 * all the aliases, then get the intersection with the scope.
		 */
		rs->sr_err = mdb_idscope( op, isc->mt, e_id, aliases, curscop );

		/* Dereference all of the aliases in the current scope. */
		cursora = 0;
		for (ida = mdb_idl_first(curscop, &cursora); ida != NOID;
			ida = mdb_idl_next(curscop, &cursora))
		{
			rs->sr_err = mdb_id2entry(op, mci, ida, &a);
			if (rs->sr_err != LDAP_SUCCESS) {
				continue;
			}

			/* 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)) {
				mdb_entry_return(op, a);
				continue;
			}

			/* Actually dereference the alias */
			MDB_IDL_ZERO(tmp);
			a = deref_base( op, rs, a, &matched, isc->mt,
				tmp, visited );
			if (a) {
				/* If the target was not already in our current scopes,
				 * make note of it in the newsubs list.
				 */
				ID2 mid;
				mid.mid = a->e_id;
				mid.mval.mv_data = NULL;
				if (op->ors_scope == LDAP_SCOPE_SUBTREE) {
					isc->id = a->e_id;
					/* if ID is a child of any of our current scopes,
					 * ignore it, it's already included.
					 */
					if (mdb_idscopechk(op, isc))
						goto skip;
				}
				if (mdb_id2l_insert(isc->scopes, &mid) == 0) {
					mdb_idl_insert(newsubs, a->e_id);
				}
skip:			mdb_entry_return( op, a );

			} else if (matched) {
				/* Alias could not be dereferenced, or it deref'd to
				 * an ID we've already seen. Ignore it.
				 */
				mdb_entry_return( op, matched );
				rs->sr_text = NULL;
				rs->sr_err = 0;
			}
		}
		/* 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 = mdb_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 (MDB_IDL_IS_ZERO(newsubs)) break;
			MDB_IDL_CPY(oldsubs, newsubs);
			MDB_IDL_ZERO(newsubs);
			cursoro = 0;
			ido = mdb_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.
		 */
		{
			MDB_val edata;
			rs->sr_err = mdb_id2edata(op, mci, ido, &edata);
			if ( rs->sr_err != MDB_SUCCESS ) {
				goto nextido;
			}
			e_id = ido;
		}
	}
	return rs->sr_err;
}
Exemple #2
0
static int
list_candidates(
	Operation *op,
	MDB_txn *rtxn,
	Filter	*flist,
	int		ftype,
	ID *ids,
	ID *tmp,
	ID *save )
{
	int rc = 0;
	Filter	*f;

	Debug( LDAP_DEBUG_FILTER, "=> mdb_list_candidates 0x%x\n", ftype, 0, 0 );
	for ( f = flist; f != NULL; f = f->f_next ) {
		/* ignore precomputed scopes */
		if ( f->f_choice == SLAPD_FILTER_COMPUTED &&
		     f->f_result == LDAP_SUCCESS ) {
			continue;
		}
		MDB_IDL_ZERO( save );
		rc = mdb_filter_candidates( op, rtxn, f, save, tmp,
			save+MDB_IDL_UM_SIZE );

		if ( rc != 0 ) {
			if ( ftype == LDAP_FILTER_AND ) {
				rc = 0;
				continue;
			}
			break;
		}

		
		if ( ftype == LDAP_FILTER_AND ) {
			if ( f == flist ) {
				MDB_IDL_CPY( ids, save );
			} else {
				mdb_idl_intersection( ids, save );
			}
			if( MDB_IDL_IS_ZERO( ids ) )
				break;
		} else {
			if ( f == flist ) {
				MDB_IDL_CPY( ids, save );
			} else {
				mdb_idl_union( ids, save );
			}
		}
	}

	if( rc == LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_FILTER,
			"<= mdb_list_candidates: id=%ld first=%ld last=%ld\n",
			(long) ids[0],
			(long) MDB_IDL_FIRST(ids),
			(long) MDB_IDL_LAST(ids) );

	} else {
		Debug( LDAP_DEBUG_FILTER,
			"<= mdb_list_candidates: undefined rc=%d\n",
			rc, 0, 0 );
	}

	return rc;
}
Exemple #3
0
static int search_candidates(
	Operation *op,
	SlapReply *rs,
	Entry *e,
	IdScopes *isc,
	MDB_cursor *mci,
	ID	*ids,
	ID *stack )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	int rc, depth = 1;
	Filter		*f, rf, xf, nf, sf;
	AttributeAssertion aa_ref = ATTRIBUTEASSERTION_INIT;
	AttributeAssertion aa_subentry = ATTRIBUTEASSERTION_INIT;

	/*
	 * This routine takes as input a filter (user-filter)
	 * and rewrites it as follows:
	 *	(&(scope=DN)[(objectClass=subentry)]
	 *		(|[(objectClass=referral)](user-filter))
	 */

	Debug(LDAP_DEBUG_TRACE,
		"search_candidates: base=\"%s\" (0x%08lx) scope=%d\n",
		e->e_nname.bv_val, (long) e->e_id, op->oq_search.rs_scope );

	f = op->oq_search.rs_filter;

	/* If the user's filter uses objectClass=*,
	 * these clauses are redundant.
	 */
	if (!oc_filter(op->oq_search.rs_filter, 1, &depth)
		&& !get_subentries_visibility(op)) {
		if( !get_manageDSAit(op) && !get_domainScope(op) ) {
			/* match referral objects */
			struct berval bv_ref = BER_BVC( "referral" );
			rf.f_choice = LDAP_FILTER_EQUALITY;
			rf.f_ava = &aa_ref;
			rf.f_av_desc = slap_schema.si_ad_objectClass;
			rf.f_av_value = bv_ref;
			rf.f_next = f;
			xf.f_or = &rf;
			xf.f_choice = LDAP_FILTER_OR;
			xf.f_next = NULL;
			f = &xf;
			depth++;
		}
	}

	if( get_subentries_visibility( op ) ) {
		struct berval bv_subentry = BER_BVC( "subentry" );
		sf.f_choice = LDAP_FILTER_EQUALITY;
		sf.f_ava = &aa_subentry;
		sf.f_av_desc = slap_schema.si_ad_objectClass;
		sf.f_av_value = bv_subentry;
		sf.f_next = f;
		nf.f_choice = LDAP_FILTER_AND;
		nf.f_and = &sf;
		nf.f_next = NULL;
		f = &nf;
		depth++;
	}

	/* Allocate IDL stack, plus 1 more for former tmp */
	if ( depth+1 > mdb->mi_search_stack_depth ) {
		stack = ch_malloc( (depth + 1) * MDB_IDL_UM_SIZE * sizeof( ID ) );
	}

	if( op->ors_deref & LDAP_DEREF_SEARCHING ) {
		rc = search_aliases( op, rs, e->e_id, isc, mci, stack );
	} else {
		rc = LDAP_SUCCESS;
	}

	if ( rc == LDAP_SUCCESS ) {
		rc = mdb_filter_candidates( op, isc->mt, f, ids,
			stack, stack+MDB_IDL_UM_SIZE );
	}

	if ( depth+1 > mdb->mi_search_stack_depth ) {
		ch_free( stack );
	}

	if( rc ) {
		Debug(LDAP_DEBUG_TRACE,
			"mdb_search_candidates: failed (rc=%d)\n",
			rc, NULL, NULL );

	} else {
		Debug(LDAP_DEBUG_TRACE,
			"mdb_search_candidates: id=%ld first=%ld last=%ld\n",
			(long) ids[0],
			(long) MDB_IDL_FIRST(ids),
			(long) MDB_IDL_LAST(ids) );
	}

	return rc;
}