Exemple #1
0
static int
dyngroup_response( Operation *op, SlapReply *rs )
{
	slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
	adpair *ap = on->on_bi.bi_private;

	/* If we've been configured and the current response is
	 * what we're looking for...
	 */
	if ( ap && op->o_tag == LDAP_REQ_COMPARE &&
		rs->sr_err == LDAP_NO_SUCH_ATTRIBUTE ) {

		for (;ap;ap=ap->ap_next) {
			if ( op->oq_compare.rs_ava->aa_desc == ap->ap_mem ) {
				/* This compare is for one of the attributes we're
				 * interested in. We'll use slapd's existing dyngroup
				 * evaluator to get the answer we want.
				 */
				int cache = op->o_do_not_cache;
				
				op->o_do_not_cache = 1;
				rs->sr_err = backend_group( op, NULL, &op->o_req_ndn,
					&op->oq_compare.rs_ava->aa_value, NULL, ap->ap_uri );
				op->o_do_not_cache = cache;
				switch ( rs->sr_err ) {
				case LDAP_SUCCESS:
					rs->sr_err = LDAP_COMPARE_TRUE;
					break;

				case LDAP_NO_SUCH_OBJECT:
					rs->sr_err = LDAP_COMPARE_FALSE;
					break;
				}
				break;
			}
		}
	}
	/* Default is to just fall through to the normal processing */
	return SLAP_CB_CONTINUE;
}
Exemple #2
0
static int
aci_group_member (
	struct berval		*subj,
	const struct berval	*defgrpoc,
	const struct berval	*defgrpat,
	Operation		*op,
	Entry			*e,
	int			nmatch,
	regmatch_t		*matches
)
{
	struct berval		subjdn;
	struct berval		grpoc;
	struct berval		grpat;
	ObjectClass		*grp_oc = NULL;
	AttributeDescription	*grp_ad = NULL;
	const char		*text;
	int			rc;

	/* format of string is "{group|role}/objectClassValue/groupAttrName" */
	if ( acl_get_part( subj, 0, '/', &subjdn ) < 0 ) {
		return 0;
	}

	if ( acl_get_part( subj, 1, '/', &grpoc ) < 0 ) {
		grpoc = *defgrpoc;
	}

	if ( acl_get_part( subj, 2, '/', &grpat ) < 0 ) {
		grpat = *defgrpat;
	}

	rc = slap_bv2ad( &grpat, &grp_ad, &text );
	if ( rc != LDAP_SUCCESS ) {
		rc = 0;
		goto done;
	}
	rc = 0;

	grp_oc = oc_bvfind( &grpoc );

	if ( grp_oc != NULL && grp_ad != NULL ) {
		char		buf[ ACI_BUF_SIZE ];
		struct berval	bv, ndn;
		AclRegexMatches amatches = { 0 };

		amatches.dn_count = nmatch;
		memcpy( amatches.dn_data, matches, sizeof( amatches.dn_data ) );

		bv.bv_len = sizeof( buf ) - 1;
		bv.bv_val = (char *)&buf;
		if ( acl_string_expand( &bv, &subjdn,
				&e->e_nname, NULL, &amatches ) )
		{
			rc = LDAP_OTHER;
			goto done;
		}

		if ( dnNormalize( 0, NULL, NULL, &bv, &ndn, op->o_tmpmemctx ) == LDAP_SUCCESS )
		{
			rc = ( backend_group( op, e, &ndn, &op->o_ndn,
				grp_oc, grp_ad ) == 0 );
			slap_sl_free( ndn.bv_val, op->o_tmpmemctx );
		}
	}

done:
	return rc;
}
Exemple #3
0
static int
dynlist_compare( Operation *op, SlapReply *rs )
{
	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
	dynlist_info_t	*dli = (dynlist_info_t *)on->on_bi.bi_private;
	Operation o = *op;
	Entry *e = NULL;
	dynlist_map_t *dlm;
	BackendDB *be;

	for ( ; dli != NULL; dli = dli->dli_next ) {
		for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next )
			if ( op->oq_compare.rs_ava->aa_desc == dlm->dlm_member_ad )
				break;

		if ( dlm ) {
			/* This compare is for one of the attributes we're
			 * interested in. We'll use slapd's existing dyngroup
			 * evaluator to get the answer we want.
			 */
			BerVarray id = NULL, authz = NULL;

			o.o_do_not_cache = 1;

			if ( ad_dgIdentity && backend_attribute( &o, NULL, &o.o_req_ndn,
				ad_dgIdentity, &id, ACL_READ ) == LDAP_SUCCESS )
			{
				/* if not rootdn and dgAuthz is present,
				 * check if user can be authorized as dgIdentity */
				if ( ad_dgAuthz && !BER_BVISEMPTY( id ) && !be_isroot( op )
					&& backend_attribute( &o, NULL, &o.o_req_ndn,
						ad_dgAuthz, &authz, ACL_READ ) == LDAP_SUCCESS )
				{
					
					rs->sr_err = slap_sasl_matches( op, authz,
						&o.o_ndn, &o.o_ndn );
					ber_bvarray_free_x( authz, op->o_tmpmemctx );
					if ( rs->sr_err != LDAP_SUCCESS ) {
						goto done;
					}
				}

				o.o_dn = *id;
				o.o_ndn = *id;
				o.o_groups = NULL; /* authz changed, invalidate cached groups */
			}

			rs->sr_err = backend_group( &o, NULL, &o.o_req_ndn,
				&o.oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad );
			switch ( rs->sr_err ) {
			case LDAP_SUCCESS:
				rs->sr_err = LDAP_COMPARE_TRUE;
				break;

			case LDAP_NO_SUCH_OBJECT:
				/* NOTE: backend_group() returns noSuchObject
				 * if op_ndn does not exist; however, since
				 * dynamic list expansion means that the
				 * member attribute is virtually present, the
				 * non-existence of the asserted value implies
				 * the assertion is FALSE rather than
				 * UNDEFINED */
				rs->sr_err = LDAP_COMPARE_FALSE;
				break;
			}

done:;
			if ( id ) ber_bvarray_free_x( id, o.o_tmpmemctx );

			return SLAP_CB_CONTINUE;
		}
	}

	be = select_backend( &o.o_req_ndn, 1 );
	if ( !be || !be->be_search ) {
		return SLAP_CB_CONTINUE;
	}

	if ( overlay_entry_get_ov( &o, &o.o_req_ndn, NULL, NULL, 0, &e, on ) !=
		LDAP_SUCCESS || e == NULL )
	{
		return SLAP_CB_CONTINUE;
	}

	/* check for dynlist objectClass; done if not found */
	dli = (dynlist_info_t *)on->on_bi.bi_private;
	while ( dli != NULL && !is_entry_objectclass_or_sub( e, dli->dli_oc ) ) {
		dli = dli->dli_next;
	}
	if ( dli == NULL ) {
		goto release;
	}

	if ( ad_dgIdentity ) {
		Attribute *id = attrs_find( e->e_attrs, ad_dgIdentity );
		if ( id ) {
			Attribute *authz;

			/* if not rootdn and dgAuthz is present,
			 * check if user can be authorized as dgIdentity */
			if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op )
				&& ( authz = attrs_find( e->e_attrs, ad_dgAuthz ) ) )
			{
				if ( slap_sasl_matches( op, authz->a_nvals,
					&o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS )
				{
					goto release;
				}
			}

			o.o_dn = id->a_vals[0];
			o.o_ndn = id->a_nvals[0];
			o.o_groups = NULL;
		}
	}

	/* generate dynamic list with dynlist_response() and compare */
	{
		SlapReply	r = { REP_SEARCH };
		dynlist_cc_t	dc = { { 0, dynlist_sc_compare_entry, 0, 0 }, 0 };
		AttributeName	an[2];

		dc.dc_ava = op->orc_ava;
		dc.dc_res = &rs->sr_err;
		o.o_callback = (slap_callback *) &dc;

		o.o_tag = LDAP_REQ_SEARCH;
		o.ors_limit = NULL;
		o.ors_tlimit = SLAP_NO_LIMIT;
		o.ors_slimit = SLAP_NO_LIMIT;

		o.ors_filterstr = *slap_filterstr_objectClass_pres;
		o.ors_filter = (Filter *) slap_filter_objectClass_pres;

		o.ors_scope = LDAP_SCOPE_BASE;
		o.ors_deref = LDAP_DEREF_NEVER;
		an[0].an_name = op->orc_ava->aa_desc->ad_cname;
		an[0].an_desc = op->orc_ava->aa_desc;
		BER_BVZERO( &an[1].an_name );
		o.ors_attrs = an;
		o.ors_attrsonly = 0;

		o.o_acl_priv = ACL_COMPARE;

		o.o_bd = be;
		(void)be->be_search( &o, &r );

		if ( o.o_dn.bv_val != op->o_dn.bv_val ) {
			slap_op_groups_free( &o );
		}
	}

release:;
	if ( e != NULL ) {
		overlay_entry_release_ov( &o, e, 0, on );
	}

	return SLAP_CB_CONTINUE;
}
Exemple #4
0
static int
limits_get( 
	Operation		*op,
	struct slap_limits_set 	**limit
)
{
	static struct berval empty_dn = BER_BVC( "" );
	struct slap_limits **lm;
	struct berval		*ndns[2];

	assert( op != NULL );
	assert( limit != NULL );

	ndns[0] = &op->o_ndn;
	ndns[1] = &op->o_req_ndn;

	Debug( LDAP_DEBUG_TRACE, "==> limits_get: %s self=\"%s\" this=\"%s\"\n",
			op->o_log_prefix,
			BER_BVISNULL( ndns[0] ) ? "[anonymous]" : ndns[0]->bv_val,
			BER_BVISNULL( ndns[1] ) ? "" : ndns[1]->bv_val );
	/*
	 * default values
	 */
	*limit = &op->o_bd->be_def_limit;

	if ( op->o_bd->be_limits == NULL ) {
		return( 0 );
	}

	for ( lm = op->o_bd->be_limits; lm[0] != NULL; lm++ ) {
		unsigned	style = lm[0]->lm_flags & SLAP_LIMITS_MASK;
		unsigned	type = lm[0]->lm_flags & SLAP_LIMITS_TYPE_MASK;
		unsigned	isthis = type == SLAP_LIMITS_TYPE_THIS;
		struct berval *ndn = ndns[isthis];

		if ( style == SLAP_LIMITS_ANY )
			goto found_any;

		if ( BER_BVISEMPTY( ndn ) ) {
			if ( style == SLAP_LIMITS_ANONYMOUS )
				goto found_nodn;
			if ( !isthis )
				continue;
			ndn = &empty_dn;
		}

		switch ( style ) {
		case SLAP_LIMITS_EXACT:
			if ( type == SLAP_LIMITS_TYPE_GROUP ) {
				int	rc = backend_group( op, NULL,
						&lm[0]->lm_pat, ndn,
						lm[0]->lm_group_oc,
						lm[0]->lm_group_ad );
				if ( rc == 0 ) {
					goto found_group;
				}
			} else {
				if ( dn_match( &lm[0]->lm_pat, ndn ) ) {
					goto found_dn;
				}
			}
			break;

		case SLAP_LIMITS_ONE:
		case SLAP_LIMITS_SUBTREE:
		case SLAP_LIMITS_CHILDREN: {
			ber_len_t d;
			
			/* ndn shorter than lm_pat */
			if ( ndn->bv_len < lm[0]->lm_pat.bv_len ) {
				break;
			}
			d = ndn->bv_len - lm[0]->lm_pat.bv_len;

			if ( d == 0 ) {
				/* allow exact match for SUBTREE only */
				if ( style != SLAP_LIMITS_SUBTREE ) {
					break;
				}
			} else {
				/* check for unescaped rdn separator */
				if ( !DN_SEPARATOR( ndn->bv_val[d - 1] ) ) {
					break;
				}
			}

			/* check that ndn ends with lm_pat */
			if ( strcmp( lm[0]->lm_pat.bv_val, &ndn->bv_val[d] ) != 0 ) {
				break;
			}

			/* in case of ONE, require exactly one rdn below lm_pat */
			if ( style == SLAP_LIMITS_ONE ) {
				if ( dn_rdnlen( NULL, ndn ) != d - 1 ) {
					break;
				}
			}

			goto found_dn;
		}

		case SLAP_LIMITS_REGEX:
			if ( regexec( &lm[0]->lm_regex, ndn->bv_val, 0, NULL, 0 ) == 0 ) {
				goto found_dn;
			}
			break;

		case SLAP_LIMITS_ANONYMOUS:
			break;

		case SLAP_LIMITS_USERS:
		found_nodn:
			Debug( LDAP_DEBUG_TRACE, "<== limits_get: type=%s match=%s\n",
				dn_source[isthis], limits2str( style ), 0 );
		found_any:
			*limit = &lm[0]->lm_limits;
			return( 0 );

		found_dn:
			Debug( LDAP_DEBUG_TRACE,
				"<== limits_get: type=%s match=%s dn=\"%s\"\n",
				dn_source[isthis], limits2str( style ), lm[0]->lm_pat.bv_val );
			*limit = &lm[0]->lm_limits;
			return( 0 );

		found_group:
			Debug( LDAP_DEBUG_TRACE, "<== limits_get: type=GROUP match=EXACT "
				"dn=\"%s\" oc=\"%s\" ad=\"%s\"\n",
				lm[0]->lm_pat.bv_val,
				lm[0]->lm_group_oc->soc_cname.bv_val,
				lm[0]->lm_group_ad->ad_cname.bv_val );
			*limit = &lm[0]->lm_limits;
			return( 0 );

		default:
			assert( 0 );	/* unreachable */
			return( -1 );
		}
	}

	return( 0 );
}
static int
dynlist_compare( Operation *op, SlapReply *rs )
{
	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
	dynlist_info_t	*dli = (dynlist_info_t *)on->on_bi.bi_private;
	Operation o = *op;
	Entry *e = NULL;
	dynlist_map_t *dlm;

	for ( ; dli != NULL; dli = dli->dli_next ) {
		for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next )
			if ( op->oq_compare.rs_ava->aa_desc == dlm->dlm_member_ad )
				break;

		if ( dli->dli_dlm && dlm ) {
			/* This compare is for one of the attributes we're
			 * interested in. We'll use slapd's existing dyngroup
			 * evaluator to get the answer we want.
			 */
			BerVarray id = NULL, authz = NULL;

			o.o_do_not_cache = 1;

			if ( ad_dgIdentity && backend_attribute( &o, NULL, &o.o_req_ndn,
				ad_dgIdentity, &id, ACL_READ ) == LDAP_SUCCESS )
			{
				/* if not rootdn and dgAuthz is present,
				 * check if user can be authorized as dgIdentity */
				if ( ad_dgAuthz && !BER_BVISEMPTY( id ) && !be_isroot( op )
					&& backend_attribute( &o, NULL, &o.o_req_ndn,
						ad_dgAuthz, &authz, ACL_READ ) == LDAP_SUCCESS )
				{
					
					rs->sr_err = slap_sasl_matches( op, authz,
						&o.o_ndn, &o.o_ndn );
					ber_bvarray_free_x( authz, op->o_tmpmemctx );
					if ( rs->sr_err != LDAP_SUCCESS ) {
						goto done;
					}
				}

				o.o_dn = *id;
				o.o_ndn = *id;
				o.o_groups = NULL; /* authz changed, invalidate cached groups */
			}

			rs->sr_err = backend_group( &o, NULL, &o.o_req_ndn,
				&o.oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad );
			switch ( rs->sr_err ) {
			case LDAP_SUCCESS:
				rs->sr_err = LDAP_COMPARE_TRUE;
				break;

			case LDAP_NO_SUCH_OBJECT:
				/* NOTE: backend_group() returns noSuchObject
				 * if op_ndn does not exist; however, since
				 * dynamic list expansion means that the
				 * member attribute is virtually present, the
				 * non-existence of the asserted value implies
				 * the assertion is FALSE rather than
				 * UNDEFINED */
				rs->sr_err = LDAP_COMPARE_FALSE;
				break;
			}

done:;
			if ( id ) ber_bvarray_free_x( id, o.o_tmpmemctx );

			return SLAP_CB_CONTINUE;
		}
	}

	if ( overlay_entry_get_ov( &o, &o.o_req_ndn, NULL, NULL, 0, &e, on ) !=
		LDAP_SUCCESS || e == NULL )
	{
		return SLAP_CB_CONTINUE;
	}

	if ( ad_dgIdentity ) {
		Attribute *id = attrs_find( e->e_attrs, ad_dgIdentity );
		if ( id ) {
			Attribute *authz;

			/* if not rootdn and dgAuthz is present,
			 * check if user can be authorized as dgIdentity */
			if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op )
				&& ( authz = attrs_find( e->e_attrs, ad_dgAuthz ) ) )
			{
				if ( slap_sasl_matches( op, authz->a_nvals,
					&o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS )
				{
					goto release;
				}
			}

			o.o_dn = id->a_vals[0];
			o.o_ndn = id->a_nvals[0];
			o.o_groups = NULL;
		}
	}

	dli = (dynlist_info_t *)on->on_bi.bi_private;
	for ( ; dli != NULL && rs->sr_err != LDAP_COMPARE_TRUE; dli = dli->dli_next ) {
		Attribute	*a;
		slap_callback	cb;
		SlapReply	r = { REP_SEARCH };
		AttributeName	an[2];
		int		rc;
		dynlist_sc_t	dlc = { 0 };

		if ( !is_entry_objectclass_or_sub( e, dli->dli_oc ))
			continue;

		/* if the entry has the right objectClass, generate
		 * the dynamic list and compare */
		dlc.dlc_dli = dli;
		cb.sc_private = &dlc;
		cb.sc_response = dynlist_sc_save_entry;
		cb.sc_cleanup = NULL;
		cb.sc_next = NULL;
		o.o_callback = &cb;

		o.o_tag = LDAP_REQ_SEARCH;
		o.ors_limit = NULL;
		o.ors_tlimit = SLAP_NO_LIMIT;
		o.ors_slimit = SLAP_NO_LIMIT;

		o.o_bd = select_backend( &o.o_req_ndn, 1 );
		if ( !o.o_bd || !o.o_bd->be_search ) {
			goto release;
		}

		o.ors_filterstr = *slap_filterstr_objectClass_pres;
		o.ors_filter = (Filter *) slap_filter_objectClass_pres;

		o.ors_scope = LDAP_SCOPE_BASE;
		o.ors_deref = LDAP_DEREF_NEVER;
		an[0].an_name = op->orc_ava->aa_desc->ad_cname;
		an[0].an_desc = op->orc_ava->aa_desc;
		BER_BVZERO( &an[1].an_name );
		o.ors_attrs = an;
		o.ors_attrsonly = 0;

		o.o_acl_priv = ACL_COMPARE;

		rc = o.o_bd->be_search( &o, &r );

		if ( o.o_dn.bv_val != op->o_dn.bv_val ) {
			slap_op_groups_free( &o );
		}

		if ( rc != 0 ) {
			goto release;
		}

		if ( dlc.dlc_e != NULL ) {
			r.sr_entry = dlc.dlc_e;
		}

		if ( r.sr_err != LDAP_SUCCESS || r.sr_entry == NULL ) {
			/* error? */
			goto release;
		}

		for ( a = attrs_find( r.sr_entry->e_attrs, op->orc_ava->aa_desc );
			a != NULL;
			a = attrs_find( a->a_next, op->orc_ava->aa_desc ) )
		{
			/* if we're here, we got a match... */
			rs->sr_err = LDAP_COMPARE_FALSE;

			if ( attr_valfind( a,
				SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
					SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
				&op->orc_ava->aa_value, NULL, op->o_tmpmemctx ) == 0 )
			{
				rs->sr_err = LDAP_COMPARE_TRUE;
				break;
			}
		}

		if ( r.sr_flags & REP_ENTRY_MUSTBEFREED ) {
			entry_free( r.sr_entry );
		}
	}

release:;
	if ( e != NULL ) {
		overlay_entry_release_ov( &o, e, 0, on );
	}

	return SLAP_CB_CONTINUE;
}