xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/component.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: component.c,v 1.3 2021/08/14 16:14:58 christos Exp $	*/
24e6df137Slukem 
32de962bdSlukem /* component.c -- Component Filter Match Routines */
4d11b170bStron /* $OpenLDAP$ */
52de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
62de962bdSlukem  *
7*549b59edSchristos  * Copyright 2003-2021 The OpenLDAP Foundation.
82de962bdSlukem  * Portions Copyright 2004 by IBM Corporation.
92de962bdSlukem  * All rights reserved.
102de962bdSlukem  *
112de962bdSlukem  * Redistribution and use in source and binary forms, with or without
122de962bdSlukem  * modification, are permitted only as authorized by the OpenLDAP
132de962bdSlukem  * Public License.
142de962bdSlukem  *
152de962bdSlukem  * A copy of this license is available in the file LICENSE in the
162de962bdSlukem  * top-level directory of the distribution or, alternatively, at
172de962bdSlukem  * <http://www.OpenLDAP.org/license.html>.
182de962bdSlukem  */
192de962bdSlukem 
20376af7d7Schristos #include <sys/cdefs.h>
21*549b59edSchristos __RCSID("$NetBSD: component.c,v 1.3 2021/08/14 16:14:58 christos Exp $");
22376af7d7Schristos 
232de962bdSlukem #include "portable.h"
242de962bdSlukem 
252de962bdSlukem #include <ac/string.h>
262de962bdSlukem #include <ac/socket.h>
272de962bdSlukem 
282de962bdSlukem #include "lutil.h"
292de962bdSlukem #include <ldap.h>
302de962bdSlukem #include "slap.h"
312de962bdSlukem 
322de962bdSlukem #ifdef LDAP_COMP_MATCH
332de962bdSlukem 
342de962bdSlukem #include "component.h"
352de962bdSlukem 
362de962bdSlukem /*
372de962bdSlukem  * Following function pointers are initialized
382de962bdSlukem  * when a component module is loaded
392de962bdSlukem  */
402de962bdSlukem alloc_nibble_func* nibble_mem_allocator = NULL;
412de962bdSlukem free_nibble_func* nibble_mem_free = NULL;
422de962bdSlukem convert_attr_to_comp_func* attr_converter = NULL;
432de962bdSlukem convert_assert_to_comp_func* assert_converter = NULL ;
442de962bdSlukem free_component_func* component_destructor = NULL ;
452de962bdSlukem test_component_func* test_components = NULL;
462de962bdSlukem test_membership_func* is_aliased_attribute = NULL;
472de962bdSlukem component_encoder_func* component_encoder = NULL;
482de962bdSlukem get_component_info_func* get_component_description = NULL;
492de962bdSlukem #define OID_ALL_COMP_MATCH "1.2.36.79672281.1.13.6"
502de962bdSlukem #define OID_COMP_FILTER_MATCH "1.2.36.79672281.1.13.2"
512de962bdSlukem #define MAX_LDAP_STR_LEN 128
522de962bdSlukem 
532de962bdSlukem static int
542de962bdSlukem peek_componentId_type( ComponentAssertionValue* cav );
552de962bdSlukem 
562de962bdSlukem static int
572de962bdSlukem strip_cav_str( ComponentAssertionValue* cav, char* str);
582de962bdSlukem 
592de962bdSlukem static int
602de962bdSlukem peek_cav_str( ComponentAssertionValue* cav, char* str );
612de962bdSlukem 
622de962bdSlukem static int
632de962bdSlukem parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
642de962bdSlukem 				ComponentFilter** filt, const char** text );
652de962bdSlukem 
662de962bdSlukem static void
672de962bdSlukem free_comp_filter( ComponentFilter* f );
682de962bdSlukem 
692de962bdSlukem static int
702de962bdSlukem test_comp_filter( Syntax *syn, ComponentSyntaxInfo *a, ComponentFilter *f );
712de962bdSlukem 
722de962bdSlukem int
componentCertificateValidate(Syntax * syntax,struct berval * val)732de962bdSlukem componentCertificateValidate(
742de962bdSlukem 	Syntax *syntax,
752de962bdSlukem 	struct berval *val )
762de962bdSlukem {
772de962bdSlukem 	return LDAP_SUCCESS;
782de962bdSlukem }
792de962bdSlukem 
802de962bdSlukem int
componentFilterValidate(Syntax * syntax,struct berval * val)812de962bdSlukem componentFilterValidate(
822de962bdSlukem 	Syntax *syntax,
832de962bdSlukem 	struct berval *val )
842de962bdSlukem {
852de962bdSlukem 	return LDAP_SUCCESS;
862de962bdSlukem }
872de962bdSlukem 
882de962bdSlukem int
allComponentsValidate(Syntax * syntax,struct berval * val)892de962bdSlukem allComponentsValidate(
902de962bdSlukem 	Syntax *syntax,
912de962bdSlukem 	struct berval *val )
922de962bdSlukem {
932de962bdSlukem 	return LDAP_SUCCESS;
942de962bdSlukem }
952de962bdSlukem 
962de962bdSlukem int
componentFilterMatch(int * matchp,slap_mask_t flags,Syntax * syntax,MatchingRule * mr,struct berval * value,void * assertedValue)972de962bdSlukem componentFilterMatch (
982de962bdSlukem 	int *matchp,
992de962bdSlukem 	slap_mask_t flags,
1002de962bdSlukem 	Syntax *syntax,
1012de962bdSlukem 	MatchingRule *mr,
1022de962bdSlukem 	struct berval *value,
1032de962bdSlukem 	void *assertedValue )
1042de962bdSlukem {
1052de962bdSlukem 	ComponentSyntaxInfo *csi_attr = (ComponentSyntaxInfo*)value;
1062de962bdSlukem 	MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue;
1072de962bdSlukem 	int rc;
1082de962bdSlukem 
1092de962bdSlukem 	if ( !mr || !ma->ma_cf ) return LDAP_INAPPROPRIATE_MATCHING;
1102de962bdSlukem 
1112de962bdSlukem 	/* Check if the component module is loaded */
1122de962bdSlukem 	if ( !attr_converter || !nibble_mem_allocator ) {
1132de962bdSlukem 		return LDAP_OTHER;
1142de962bdSlukem 	}
1152de962bdSlukem 
1162de962bdSlukem 	rc = test_comp_filter( syntax, csi_attr, ma->ma_cf );
1172de962bdSlukem 
1182de962bdSlukem 	if ( rc == LDAP_COMPARE_TRUE ) {
1192de962bdSlukem 		*matchp = 0;
1202de962bdSlukem 		return LDAP_SUCCESS;
1212de962bdSlukem 	}
1222de962bdSlukem 	else if ( rc == LDAP_COMPARE_FALSE ) {
1232de962bdSlukem 		*matchp = 1;
1242de962bdSlukem 		return LDAP_SUCCESS;
1252de962bdSlukem 	}
1262de962bdSlukem 	else {
1272de962bdSlukem 		return LDAP_INAPPROPRIATE_MATCHING;
1282de962bdSlukem 	}
1292de962bdSlukem }
1302de962bdSlukem 
1312de962bdSlukem int
directoryComponentsMatch(int * matchp,slap_mask_t flags,Syntax * syntax,MatchingRule * mr,struct berval * value,void * assertedValue)1322de962bdSlukem directoryComponentsMatch(
1332de962bdSlukem 	int *matchp,
1342de962bdSlukem 	slap_mask_t flags,
1352de962bdSlukem 	Syntax *syntax,
1362de962bdSlukem 	MatchingRule *mr,
1372de962bdSlukem 	struct berval *value,
1382de962bdSlukem 	void *assertedValue )
1392de962bdSlukem {
1402de962bdSlukem 	/* Only for registration */
1412de962bdSlukem 	*matchp = 0;
1422de962bdSlukem 	return LDAP_SUCCESS;
1432de962bdSlukem }
1442de962bdSlukem 
1452de962bdSlukem int
allComponentsMatch(int * matchp,slap_mask_t flags,Syntax * syntax,MatchingRule * mr,struct berval * value,void * assertedValue)1462de962bdSlukem allComponentsMatch(
1472de962bdSlukem 	int *matchp,
1482de962bdSlukem 	slap_mask_t flags,
1492de962bdSlukem 	Syntax *syntax,
1502de962bdSlukem 	MatchingRule *mr,
1512de962bdSlukem 	struct berval *value,
1522de962bdSlukem 	void *assertedValue )
1532de962bdSlukem {
1542de962bdSlukem 	/* Only for registration */
1552de962bdSlukem 	*matchp = 0;
1562de962bdSlukem 	return LDAP_SUCCESS;
1572de962bdSlukem }
1582de962bdSlukem 
1592de962bdSlukem static int
slapd_ber2cav(struct berval * bv,ComponentAssertionValue * cav)1602de962bdSlukem slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav )
1612de962bdSlukem {
1622de962bdSlukem 	cav->cav_ptr = cav->cav_buf = bv->bv_val;
1632de962bdSlukem 	cav->cav_end = bv->bv_val + bv->bv_len;
1642de962bdSlukem 
1652de962bdSlukem 	return LDAP_SUCCESS;
1662de962bdSlukem }
1672de962bdSlukem 
1682de962bdSlukem ComponentReference*
dup_comp_ref(Operation * op,ComponentReference * cr)1692de962bdSlukem dup_comp_ref ( Operation* op, ComponentReference* cr )
1702de962bdSlukem {
1712de962bdSlukem 	ComponentReference* dup_cr;
1722de962bdSlukem 	ComponentId* ci_curr;
1732de962bdSlukem 	ComponentId** ci_temp;
1742de962bdSlukem 
1752de962bdSlukem 	dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
1762de962bdSlukem 
1772de962bdSlukem 	dup_cr->cr_len = cr->cr_len;
1782de962bdSlukem 	dup_cr->cr_string = cr->cr_string;
1792de962bdSlukem 
1802de962bdSlukem 	ci_temp = &dup_cr->cr_list;
1812de962bdSlukem 	ci_curr = cr->cr_list;
1822de962bdSlukem 
1832de962bdSlukem 	for ( ; ci_curr != NULL ;
1842de962bdSlukem 		ci_curr = ci_curr->ci_next, ci_temp = &(*ci_temp)->ci_next )
1852de962bdSlukem 	{
1862de962bdSlukem 		*ci_temp = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
1872de962bdSlukem 		if ( !*ci_temp ) return NULL;
1882de962bdSlukem 		**ci_temp = *ci_curr;
1892de962bdSlukem 	}
1902de962bdSlukem 
1912de962bdSlukem 	dup_cr->cr_curr = dup_cr->cr_list;
1922de962bdSlukem 
1932de962bdSlukem 	return dup_cr;
1942de962bdSlukem }
1952de962bdSlukem 
1962de962bdSlukem static int
dup_comp_filter_list(Operation * op,struct berval * bv,ComponentFilter * in_f,ComponentFilter ** out_f)1972de962bdSlukem dup_comp_filter_list (
1982de962bdSlukem 	Operation *op,
1992de962bdSlukem 	struct berval *bv,
2002de962bdSlukem 	ComponentFilter* in_f,
2012de962bdSlukem 	ComponentFilter** out_f )
2022de962bdSlukem {
2032de962bdSlukem 	ComponentFilter **new, *f;
2042de962bdSlukem 	int		rc;
2052de962bdSlukem 
2062de962bdSlukem 	new = out_f;
2072de962bdSlukem 	for ( f = in_f; f != NULL; f = f->cf_next ) {
2082de962bdSlukem 		rc = dup_comp_filter( op, bv, f, new );
2092de962bdSlukem 		if ( rc != LDAP_SUCCESS ) {
2102de962bdSlukem 			return rc;
2112de962bdSlukem 		}
2122de962bdSlukem 		new = &(*new)->cf_next;
2132de962bdSlukem 	}
2142de962bdSlukem 	return LDAP_SUCCESS;
2152de962bdSlukem }
2162de962bdSlukem 
2172de962bdSlukem int
get_len_of_next_assert_value(struct berval * bv,char separator)2182de962bdSlukem get_len_of_next_assert_value ( struct berval* bv, char separator )
2192de962bdSlukem {
2204e6df137Slukem 	ber_len_t i = 0;
2212de962bdSlukem 	while (1) {
2222de962bdSlukem 		if ( (bv->bv_val[ i ] == separator) || ( i >= bv->bv_len) )
2232de962bdSlukem 			break;
2242de962bdSlukem 		i++;
2252de962bdSlukem 	}
2262de962bdSlukem 	bv->bv_val += (i + 1);
2272de962bdSlukem 	bv->bv_len -= (i + 1);
2282de962bdSlukem 	return i;
2292de962bdSlukem }
2302de962bdSlukem 
2312de962bdSlukem int
dup_comp_filter_item(Operation * op,struct berval * assert_bv,ComponentAssertion * in_ca,ComponentAssertion ** out_ca)2322de962bdSlukem dup_comp_filter_item (
2332de962bdSlukem 	Operation *op,
2342de962bdSlukem 	struct berval* assert_bv,
2352de962bdSlukem 	ComponentAssertion* in_ca,
2362de962bdSlukem 	ComponentAssertion** out_ca )
2372de962bdSlukem {
2382de962bdSlukem 	int len;
2392de962bdSlukem 
2402de962bdSlukem 	if ( !in_ca->ca_comp_ref ) return SLAPD_DISCONNECT;
2412de962bdSlukem 
2422de962bdSlukem 	*out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
2432de962bdSlukem 	if ( !(*out_ca) ) return LDAP_NO_MEMORY;
2442de962bdSlukem 
2452de962bdSlukem 	(*out_ca)->ca_comp_data.cd_tree = NULL;
2462de962bdSlukem 	(*out_ca)->ca_comp_data.cd_mem_op = NULL;
2472de962bdSlukem 
2482de962bdSlukem 	(*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref );
2492de962bdSlukem 	(*out_ca)->ca_use_def = 0;
2502de962bdSlukem 	(*out_ca)->ca_ma_rule = in_ca->ca_ma_rule;
2512de962bdSlukem 
2522de962bdSlukem 	(*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val;
2532de962bdSlukem 	len = get_len_of_next_assert_value ( assert_bv, '$' );
2542de962bdSlukem 	if ( len <= 0 ) return SLAPD_DISCONNECT;
2552de962bdSlukem 	(*out_ca)->ca_ma_value.bv_len = len;
2562de962bdSlukem 
2572de962bdSlukem 	return LDAP_SUCCESS;
2582de962bdSlukem }
2592de962bdSlukem 
2602de962bdSlukem int
dup_comp_filter(Operation * op,struct berval * bv,ComponentFilter * in_f,ComponentFilter ** out_f)2612de962bdSlukem dup_comp_filter (
2622de962bdSlukem 	Operation* op,
2632de962bdSlukem 	struct berval *bv,
2642de962bdSlukem 	ComponentFilter *in_f,
2652de962bdSlukem 	ComponentFilter **out_f )
2662de962bdSlukem {
2672de962bdSlukem 	int	rc;
2682de962bdSlukem 	ComponentFilter dup_f = {0};
2692de962bdSlukem 
2702de962bdSlukem 	if ( !in_f ) return LDAP_PROTOCOL_ERROR;
2712de962bdSlukem 
2722de962bdSlukem 	switch ( in_f->cf_choice ) {
2732de962bdSlukem 	case LDAP_COMP_FILTER_AND:
2742de962bdSlukem 		rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and);
2752de962bdSlukem 		dup_f.cf_choice = LDAP_COMP_FILTER_AND;
2762de962bdSlukem 		break;
2772de962bdSlukem 	case LDAP_COMP_FILTER_OR:
2782de962bdSlukem 		rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or);
2792de962bdSlukem 		dup_f.cf_choice = LDAP_COMP_FILTER_OR;
2802de962bdSlukem 		break;
2812de962bdSlukem 	case LDAP_COMP_FILTER_NOT:
2822de962bdSlukem 		rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not);
2832de962bdSlukem 		dup_f.cf_choice = LDAP_COMP_FILTER_NOT;
2842de962bdSlukem 		break;
2852de962bdSlukem 	case LDAP_COMP_FILTER_ITEM:
2862de962bdSlukem 		rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca );
2872de962bdSlukem 		dup_f.cf_choice = LDAP_COMP_FILTER_ITEM;
2882de962bdSlukem 		break;
2892de962bdSlukem 	default:
2902de962bdSlukem 		rc = LDAP_PROTOCOL_ERROR;
2912de962bdSlukem 	}
2922de962bdSlukem 
2932de962bdSlukem 	if ( rc == LDAP_SUCCESS ) {
2942de962bdSlukem 		*out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx );
2952de962bdSlukem 		**out_f = dup_f;
2962de962bdSlukem 	}
2972de962bdSlukem 
2982de962bdSlukem 	return( rc );
2992de962bdSlukem }
3002de962bdSlukem 
3012de962bdSlukem int
get_aliased_filter_aa(Operation * op,AttributeAssertion * a_assert,AttributeAliasing * aa,const char ** text)3022de962bdSlukem get_aliased_filter_aa ( Operation* op, AttributeAssertion* a_assert, AttributeAliasing* aa, const char** text )
3032de962bdSlukem {
3042de962bdSlukem 	struct berval assert_bv;
3052de962bdSlukem 
306*549b59edSchristos 	Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n" );
3072de962bdSlukem 
3082de962bdSlukem 	if ( !aa->aa_cf  )
3092de962bdSlukem 		return LDAP_PROTOCOL_ERROR;
3102de962bdSlukem 
3112de962bdSlukem 	assert_bv = a_assert->aa_value;
3122de962bdSlukem 	/*
3132de962bdSlukem 	 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
3142de962bdSlukem 	 * the component assertion value in assert_bv
3152de962bdSlukem 	 * Multiple values may be separated with '$'
3162de962bdSlukem 	 */
3172de962bdSlukem 	return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &a_assert->aa_cf );
3182de962bdSlukem }
3192de962bdSlukem 
3202de962bdSlukem int
get_aliased_filter(Operation * op,MatchingRuleAssertion * ma,AttributeAliasing * aa,const char ** text)3212de962bdSlukem get_aliased_filter( Operation* op,
3222de962bdSlukem 	MatchingRuleAssertion* ma, AttributeAliasing* aa,
3232de962bdSlukem 	const char** text )
3242de962bdSlukem {
3252de962bdSlukem 	struct berval assert_bv;
3262de962bdSlukem 
327*549b59edSchristos 	Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n" );
3282de962bdSlukem 
3292de962bdSlukem 	if ( !aa->aa_cf  ) return LDAP_PROTOCOL_ERROR;
3302de962bdSlukem 
3312de962bdSlukem 	assert_bv = ma->ma_value;
3322de962bdSlukem 	/* Attribute Description is replaced with aliased one */
3332de962bdSlukem 	ma->ma_desc = aa->aa_aliased_ad;
3342de962bdSlukem 	ma->ma_rule = aa->aa_mr;
3352de962bdSlukem 	/*
3362de962bdSlukem 	 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
3372de962bdSlukem 	 * the component assertion value in assert_bv
3382de962bdSlukem 	 * Multiple values may be separated with '$'
3392de962bdSlukem 	 */
3402de962bdSlukem 	return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf );
3412de962bdSlukem }
3422de962bdSlukem 
3432de962bdSlukem int
get_comp_filter(Operation * op,struct berval * bv,ComponentFilter ** filt,const char ** text)3442de962bdSlukem get_comp_filter( Operation* op, struct berval* bv,
3452de962bdSlukem 	ComponentFilter** filt, const char **text )
3462de962bdSlukem {
3472de962bdSlukem 	ComponentAssertionValue cav;
3482de962bdSlukem 	int rc;
3492de962bdSlukem 
350*549b59edSchristos 	Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n" );
3512de962bdSlukem 	if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) {
3522de962bdSlukem 		return rc;
3532de962bdSlukem 	}
3542de962bdSlukem 	rc = parse_comp_filter( op, &cav, filt, text );
355*549b59edSchristos 	/* bv->bv_val = cav.cav_ptr; */
3562de962bdSlukem 
3572de962bdSlukem 	return rc;
3582de962bdSlukem }
3592de962bdSlukem 
3602de962bdSlukem static void
eat_whsp(ComponentAssertionValue * cav)3612de962bdSlukem eat_whsp( ComponentAssertionValue* cav )
3622de962bdSlukem {
3632de962bdSlukem 	for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) {
3642de962bdSlukem 		cav->cav_ptr++;
3652de962bdSlukem 	}
3662de962bdSlukem }
3672de962bdSlukem 
3682de962bdSlukem static int
cav_cur_len(ComponentAssertionValue * cav)3692de962bdSlukem cav_cur_len( ComponentAssertionValue* cav )
3702de962bdSlukem {
3712de962bdSlukem 	return cav->cav_end - cav->cav_ptr;
3722de962bdSlukem }
3732de962bdSlukem 
3742de962bdSlukem static ber_tag_t
comp_first_element(ComponentAssertionValue * cav)3752de962bdSlukem comp_first_element( ComponentAssertionValue* cav )
3762de962bdSlukem {
3772de962bdSlukem 	eat_whsp( cav );
3782de962bdSlukem 	if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
3792de962bdSlukem 		return LDAP_COMP_FILTER_ITEM;
3802de962bdSlukem 
3812de962bdSlukem 	} else if ( cav_cur_len( cav ) >= 7 &&
3822de962bdSlukem 		strncmp( cav->cav_ptr, "and", 3 ) == 0 )
3832de962bdSlukem 	{
3842de962bdSlukem 		return LDAP_COMP_FILTER_AND;
3852de962bdSlukem 
3862de962bdSlukem 	} else if ( cav_cur_len( cav ) >= 6 &&
3872de962bdSlukem 		strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
3882de962bdSlukem 	{
3892de962bdSlukem 		return LDAP_COMP_FILTER_OR;
3902de962bdSlukem 
3912de962bdSlukem 	} else if ( cav_cur_len( cav ) >= 7 &&
3922de962bdSlukem 		strncmp( cav->cav_ptr, "not", 3 ) == 0 )
3932de962bdSlukem 	{
3942de962bdSlukem 		return LDAP_COMP_FILTER_NOT;
3952de962bdSlukem 
3962de962bdSlukem 	} else {
3972de962bdSlukem 		return LDAP_COMP_FILTER_UNDEFINED;
3982de962bdSlukem 	}
3992de962bdSlukem }
4002de962bdSlukem 
4012de962bdSlukem static ber_tag_t
comp_next_element(ComponentAssertionValue * cav)4022de962bdSlukem comp_next_element( ComponentAssertionValue* cav )
4032de962bdSlukem {
4042de962bdSlukem 	eat_whsp( cav );
4052de962bdSlukem 	if ( *(cav->cav_ptr) == ',' ) {
4062de962bdSlukem 		/* move pointer to the next CA */
4072de962bdSlukem 		cav->cav_ptr++;
4082de962bdSlukem 		return comp_first_element( cav );
4092de962bdSlukem 	}
4102de962bdSlukem 	else return LDAP_COMP_FILTER_UNDEFINED;
4112de962bdSlukem }
4122de962bdSlukem 
4132de962bdSlukem static int
get_comp_filter_list(Operation * op,ComponentAssertionValue * cav,ComponentFilter ** f,const char ** text)4142de962bdSlukem get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
4152de962bdSlukem 	ComponentFilter** f, const char** text )
4162de962bdSlukem {
4172de962bdSlukem 	ComponentFilter **new;
4182de962bdSlukem 	int		err;
4192de962bdSlukem 	ber_tag_t	tag;
4202de962bdSlukem 
421*549b59edSchristos 	Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n" );
4222de962bdSlukem 	new = f;
4232de962bdSlukem 	for ( tag = comp_first_element( cav );
4242de962bdSlukem 		tag != LDAP_COMP_FILTER_UNDEFINED;
4252de962bdSlukem 		tag = comp_next_element( cav ) )
4262de962bdSlukem 	{
4272de962bdSlukem 		err = parse_comp_filter( op, cav, new, text );
4282de962bdSlukem 		if ( err != LDAP_SUCCESS ) return ( err );
4292de962bdSlukem 		new = &(*new)->cf_next;
4302de962bdSlukem 	}
4312de962bdSlukem 	*new = NULL;
4322de962bdSlukem 
4332de962bdSlukem 	return( LDAP_SUCCESS );
4342de962bdSlukem }
4352de962bdSlukem 
4362de962bdSlukem static int
get_componentId(Operation * op,ComponentAssertionValue * cav,ComponentId ** cid,const char ** text)4372de962bdSlukem get_componentId( Operation *op, ComponentAssertionValue* cav,
4382de962bdSlukem 	ComponentId ** cid, const char** text )
4392de962bdSlukem {
4402de962bdSlukem 	ber_tag_t type;
4412de962bdSlukem 	ComponentId _cid;
4422de962bdSlukem 	int len;
4432de962bdSlukem 
4442de962bdSlukem 	type = peek_componentId_type( cav );
4452de962bdSlukem 
4462de962bdSlukem 	Debug( LDAP_DEBUG_FILTER, "get_compId [%lu]\n",
447*549b59edSchristos 		(unsigned long) type );
4482de962bdSlukem 	len = 0;
4492de962bdSlukem 	_cid.ci_type = type;
4502de962bdSlukem 	_cid.ci_next = NULL;
4512de962bdSlukem 	switch ( type ) {
4522de962bdSlukem 	case LDAP_COMPREF_IDENTIFIER :
4532de962bdSlukem 		_cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
4542de962bdSlukem 		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
4552de962bdSlukem 			cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
4562de962bdSlukem 		_cid.ci_val.ci_identifier.bv_len = len;
4572de962bdSlukem 		cav->cav_ptr += len;
4582de962bdSlukem 		break;
4592de962bdSlukem 	case LDAP_COMPREF_FROM_BEGINNING :
4602de962bdSlukem 		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
4612de962bdSlukem 			cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
4622de962bdSlukem 		_cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
4632de962bdSlukem 		cav->cav_ptr += len;
4642de962bdSlukem 		break;
4652de962bdSlukem 	case LDAP_COMPREF_FROM_END :
4662de962bdSlukem 		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
4672de962bdSlukem 			cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
4682de962bdSlukem 		_cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
4692de962bdSlukem 		cav->cav_ptr += len;
4702de962bdSlukem 		break;
4712de962bdSlukem 	case LDAP_COMPREF_COUNT :
4722de962bdSlukem 		_cid.ci_val.ci_count = 0;
4732de962bdSlukem 		cav->cav_ptr++;
4742de962bdSlukem 		break;
4752de962bdSlukem 	case LDAP_COMPREF_CONTENT :
4762de962bdSlukem 		_cid.ci_val.ci_content = 1;
4772de962bdSlukem 		cav->cav_ptr += strlen("content");
4782de962bdSlukem 		break;
4792de962bdSlukem 	case LDAP_COMPREF_SELECT :
4802de962bdSlukem 		if ( cav->cav_ptr[len] != '(' ) return LDAP_COMPREF_UNDEFINED;
4812de962bdSlukem 		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
4822de962bdSlukem 	  	      cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
4832de962bdSlukem 			; len++ );
4842de962bdSlukem 		_cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
4852de962bdSlukem 		_cid.ci_val.ci_select_value.bv_len = len - 1 ;
4862de962bdSlukem 		cav->cav_ptr += len + 1;
4872de962bdSlukem 		break;
4882de962bdSlukem 	case LDAP_COMPREF_ALL :
4892de962bdSlukem 		_cid.ci_val.ci_all = '*';
4902de962bdSlukem 		cav->cav_ptr++;
4912de962bdSlukem 		break;
4922de962bdSlukem 	default :
4932de962bdSlukem 		return LDAP_COMPREF_UNDEFINED;
4942de962bdSlukem 	}
4952de962bdSlukem 
4962de962bdSlukem 	if ( op ) {
4972de962bdSlukem 		*cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
4982de962bdSlukem 	} else {
4994e6df137Slukem 		*cid = SLAP_MALLOC( sizeof( ComponentId ) );
5004e6df137Slukem 	}
5014e6df137Slukem 	if (*cid == NULL) {
5024e6df137Slukem 		return LDAP_NO_MEMORY;
5032de962bdSlukem 	}
5042de962bdSlukem 	**cid = _cid;
5052de962bdSlukem 	return LDAP_SUCCESS;
5062de962bdSlukem }
5072de962bdSlukem 
5082de962bdSlukem static int
peek_componentId_type(ComponentAssertionValue * cav)5092de962bdSlukem peek_componentId_type( ComponentAssertionValue* cav )
5102de962bdSlukem {
5112de962bdSlukem 	eat_whsp( cav );
5122de962bdSlukem 
5132de962bdSlukem 	if ( cav->cav_ptr[0] == '-' ) {
5142de962bdSlukem 		return LDAP_COMPREF_FROM_END;
5152de962bdSlukem 
5162de962bdSlukem 	} else if ( cav->cav_ptr[0] == '(' ) {
5172de962bdSlukem 		return LDAP_COMPREF_SELECT;
5182de962bdSlukem 
5192de962bdSlukem 	} else if ( cav->cav_ptr[0] == '*' ) {
5202de962bdSlukem 		return LDAP_COMPREF_ALL;
5212de962bdSlukem 
5222de962bdSlukem 	} else if ( cav->cav_ptr[0] == '0' ) {
5232de962bdSlukem 		return LDAP_COMPREF_COUNT;
5242de962bdSlukem 
5252de962bdSlukem 	} else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' ) {
5262de962bdSlukem 		return LDAP_COMPREF_FROM_BEGINNING;
5272de962bdSlukem 
5282de962bdSlukem 	} else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
5292de962bdSlukem 		strncmp(cav->cav_ptr,"content",7) == 0 )
5302de962bdSlukem 	{
5312de962bdSlukem 		return LDAP_COMPREF_CONTENT;
5322de962bdSlukem 	} else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
5332de962bdSlukem 			(cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
5342de962bdSlukem 	{
5352de962bdSlukem 		return LDAP_COMPREF_IDENTIFIER;
5362de962bdSlukem 	}
5372de962bdSlukem 
5382de962bdSlukem 	return LDAP_COMPREF_UNDEFINED;
5392de962bdSlukem }
5402de962bdSlukem 
5412de962bdSlukem static ber_tag_t
comp_next_id(ComponentAssertionValue * cav)5422de962bdSlukem comp_next_id( ComponentAssertionValue* cav )
5432de962bdSlukem {
5442de962bdSlukem 	if ( *(cav->cav_ptr) == '.' ) {
5452de962bdSlukem 		cav->cav_ptr++;
5462de962bdSlukem 		return LDAP_COMPREF_DEFINED;
5472de962bdSlukem 	}
5482de962bdSlukem 
5492de962bdSlukem 	return LDAP_COMPREF_UNDEFINED;
5502de962bdSlukem }
5512de962bdSlukem 
5522de962bdSlukem 
5532de962bdSlukem 
5542de962bdSlukem static int
get_component_reference(Operation * op,ComponentAssertionValue * cav,ComponentReference ** cr,const char ** text)5552de962bdSlukem get_component_reference(
5562de962bdSlukem 	Operation *op,
5572de962bdSlukem 	ComponentAssertionValue* cav,
5582de962bdSlukem 	ComponentReference** cr,
5592de962bdSlukem 	const char** text )
5602de962bdSlukem {
5612de962bdSlukem 	int rc, count = 0;
5622de962bdSlukem 	ber_int_t type;
5632de962bdSlukem 	ComponentReference* ca_comp_ref;
5642de962bdSlukem 	ComponentId** cr_list;
5652de962bdSlukem 	char* start, *end;
5662de962bdSlukem 
5672de962bdSlukem 	eat_whsp( cav );
5682de962bdSlukem 
5692de962bdSlukem 	start = cav->cav_ptr;
5702de962bdSlukem 	if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) return rc;
5712de962bdSlukem 	if ( op ) {
5722de962bdSlukem 		ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ),
5732de962bdSlukem 			op->o_tmpmemctx );
5742de962bdSlukem 	} else {
5754e6df137Slukem 		ca_comp_ref = SLAP_MALLOC( sizeof( ComponentReference ) );
5762de962bdSlukem 	}
5772de962bdSlukem 
5782de962bdSlukem 	if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
5792de962bdSlukem 
5802de962bdSlukem 	cr_list = &ca_comp_ref->cr_list;
5812de962bdSlukem 
5822de962bdSlukem 	for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
5832de962bdSlukem 		; type = comp_next_id( cav ), count++ )
5842de962bdSlukem 	{
5852de962bdSlukem 		rc = get_componentId( op, cav, cr_list, text );
5862de962bdSlukem 		if ( rc == LDAP_SUCCESS ) {
5872de962bdSlukem 			if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
5882de962bdSlukem 			cr_list = &(*cr_list)->ci_next;
5892de962bdSlukem 
5902de962bdSlukem 		} else if ( rc == LDAP_COMPREF_UNDEFINED ) {
5912de962bdSlukem 			if ( op ) {
5922de962bdSlukem 				op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
5932de962bdSlukem 			} else {
5942de962bdSlukem 				free( ca_comp_ref );
5952de962bdSlukem 			}
5962de962bdSlukem 			return rc;
5972de962bdSlukem 		}
5982de962bdSlukem 	}
5992de962bdSlukem 	ca_comp_ref->cr_len = count;
6002de962bdSlukem 	end = cav->cav_ptr;
6012de962bdSlukem 	if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
6022de962bdSlukem 		if ( op ) {
6032de962bdSlukem 			op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
6042de962bdSlukem 		} else {
6052de962bdSlukem 			free( ca_comp_ref );
6062de962bdSlukem 		}
6072de962bdSlukem 		return rc;
6082de962bdSlukem 	}
6092de962bdSlukem 
6102de962bdSlukem 	*cr = ca_comp_ref;
6112de962bdSlukem 	**cr = *ca_comp_ref;
6122de962bdSlukem 
6132de962bdSlukem 	(*cr)->cr_string.bv_val = start;
6142de962bdSlukem 	(*cr)->cr_string.bv_len = end - start + 1;
6152de962bdSlukem 
6162de962bdSlukem 	return rc;
6172de962bdSlukem }
6182de962bdSlukem 
6192de962bdSlukem int
insert_component_reference(ComponentReference * cr,ComponentReference ** cr_list)6202de962bdSlukem insert_component_reference(
6212de962bdSlukem 	ComponentReference *cr,
6222de962bdSlukem 	ComponentReference** cr_list)
6232de962bdSlukem {
6242de962bdSlukem 	if ( !cr ) return LDAP_PARAM_ERROR;
6252de962bdSlukem 
6262de962bdSlukem 	if ( !(*cr_list) ) {
6272de962bdSlukem 		*cr_list = cr;
6282de962bdSlukem 		cr->cr_next = NULL;
6292de962bdSlukem 	} else {
6302de962bdSlukem 		cr->cr_next = *cr_list;
6312de962bdSlukem 		*cr_list = cr;
6322de962bdSlukem 	}
6332de962bdSlukem 	return LDAP_SUCCESS;
6342de962bdSlukem }
6352de962bdSlukem 
6362de962bdSlukem /*
6372de962bdSlukem  * If there is '.' in the name of a given attribute
6382de962bdSlukem  * the first '.'- following characters are considered
6392de962bdSlukem  * as a component reference of the attribute
6402de962bdSlukem  * EX) userCertificate.toBeSigned.serialNumber
6412de962bdSlukem  * attribute : userCertificate
6422de962bdSlukem  * component reference : toBeSigned.serialNumber
6432de962bdSlukem  */
6442de962bdSlukem int
is_component_reference(char * attr)6452de962bdSlukem is_component_reference( char* attr ) {
6462de962bdSlukem 	int i;
6472de962bdSlukem 	for ( i=0; attr[i] != '\0' ; i++ ) {
6482de962bdSlukem 		if ( attr[i] == '.' ) return (1);
6492de962bdSlukem 	}
6502de962bdSlukem 	return (0);
6512de962bdSlukem }
6522de962bdSlukem 
6532de962bdSlukem int
extract_component_reference(char * attr,ComponentReference ** cr)6542de962bdSlukem extract_component_reference(
6552de962bdSlukem 	char* attr,
6562de962bdSlukem 	ComponentReference** cr )
6572de962bdSlukem {
6582de962bdSlukem 	int i, rc;
6592de962bdSlukem 	char* cr_ptr;
6602de962bdSlukem 	int cr_len;
6612de962bdSlukem 	ComponentAssertionValue cav;
6622de962bdSlukem 	char text[1][128];
6632de962bdSlukem 
6642de962bdSlukem 	for ( i=0; attr[i] != '\0' ; i++ ) {
6652de962bdSlukem 		if ( attr[i] == '.' ) break;
6662de962bdSlukem 	}
6672de962bdSlukem 
6682de962bdSlukem 	if (attr[i] != '.' ) return LDAP_PARAM_ERROR;
6692de962bdSlukem 	attr[i] = '\0';
6702de962bdSlukem 
6712de962bdSlukem 	cr_ptr = attr + i + 1 ;
6722de962bdSlukem 	cr_len = strlen ( cr_ptr );
6732de962bdSlukem 	if ( cr_len <= 0 ) return LDAP_PARAM_ERROR;
6742de962bdSlukem 
6752de962bdSlukem 	/* enclosed between double quotes*/
6762de962bdSlukem 	cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
6772de962bdSlukem 	memcpy( cav.cav_buf+1, cr_ptr, cr_len );
6782de962bdSlukem 	cav.cav_buf[0] = '"';
6792de962bdSlukem 	cav.cav_buf[cr_len+1] = '"';
6802de962bdSlukem 	cav.cav_end = cr_ptr + cr_len + 2;
6812de962bdSlukem 
6822de962bdSlukem 	rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
6832de962bdSlukem 	if ( rc != LDAP_SUCCESS ) return rc;
6842de962bdSlukem 	(*cr)->cr_string.bv_val = cav.cav_buf;
6852de962bdSlukem 	(*cr)->cr_string.bv_len = cr_len + 2;
6862de962bdSlukem 
6872de962bdSlukem 	return LDAP_SUCCESS;
6882de962bdSlukem }
6892de962bdSlukem 
6902de962bdSlukem static int
get_ca_use_default(Operation * op,ComponentAssertionValue * cav,int * ca_use_def,const char ** text)6912de962bdSlukem get_ca_use_default( Operation *op,
6922de962bdSlukem 	ComponentAssertionValue* cav,
6932de962bdSlukem 	int* ca_use_def, const char**  text )
6942de962bdSlukem {
6952de962bdSlukem 	strip_cav_str( cav, "useDefaultValues" );
6962de962bdSlukem 
6972de962bdSlukem 	if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
6982de962bdSlukem 		strip_cav_str( cav, "TRUE" );
6992de962bdSlukem 		*ca_use_def = 1;
7002de962bdSlukem 
7012de962bdSlukem 	} else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
7022de962bdSlukem 		strip_cav_str( cav, "FALSE" );
7032de962bdSlukem 		*ca_use_def = 0;
7042de962bdSlukem 
7052de962bdSlukem 	} else {
7062de962bdSlukem 		return LDAP_INVALID_SYNTAX;
7072de962bdSlukem 	}
7082de962bdSlukem 
7092de962bdSlukem 	return LDAP_SUCCESS;
7102de962bdSlukem }
7112de962bdSlukem 
7122de962bdSlukem static int
get_matching_rule(Operation * op,ComponentAssertionValue * cav,MatchingRule ** mr,const char ** text)7132de962bdSlukem get_matching_rule( Operation *op, ComponentAssertionValue* cav,
7142de962bdSlukem 		MatchingRule** mr, const char**  text )
7152de962bdSlukem {
7162de962bdSlukem 	int count = 0;
7172de962bdSlukem 	struct berval rule_text = { 0L, NULL };
7182de962bdSlukem 
7192de962bdSlukem 	eat_whsp( cav );
7202de962bdSlukem 
7212de962bdSlukem 	for ( ; ; count++ ) {
7222de962bdSlukem 		if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
7232de962bdSlukem 			cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
7242de962bdSlukem 			cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
7252de962bdSlukem 		{
7262de962bdSlukem 			break;
7272de962bdSlukem 		}
7282de962bdSlukem 	}
7292de962bdSlukem 
7302de962bdSlukem 	if ( count == 0 ) {
7312de962bdSlukem 		*text = "component matching rule not recognized";
7322de962bdSlukem 		return LDAP_INAPPROPRIATE_MATCHING;
7332de962bdSlukem 	}
7342de962bdSlukem 
7352de962bdSlukem 	rule_text.bv_len = count;
7362de962bdSlukem 	rule_text.bv_val = cav->cav_ptr;
7372de962bdSlukem 	*mr = mr_bvfind( &rule_text );
7382de962bdSlukem 	cav->cav_ptr += count;
7392de962bdSlukem 	Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n",
740*549b59edSchristos 		(*mr)->smr_mrule.mr_oid );
7412de962bdSlukem 	if ( *mr == NULL ) {
7422de962bdSlukem 		*text = "component matching rule not recognized";
7432de962bdSlukem 		return LDAP_INAPPROPRIATE_MATCHING;
7442de962bdSlukem 	}
7452de962bdSlukem 	return LDAP_SUCCESS;
7462de962bdSlukem }
7472de962bdSlukem 
7482de962bdSlukem static int
get_GSER_value(ComponentAssertionValue * cav,struct berval * bv)7492de962bdSlukem get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
7502de962bdSlukem {
7512de962bdSlukem 	int count, sequent_dquote, unclosed_brace, succeed;
7522de962bdSlukem 
7532de962bdSlukem 	eat_whsp( cav );
7542de962bdSlukem 	/*
7552de962bdSlukem 	 * Four cases of GSER <Values>
7562de962bdSlukem 	 * 1) "..." :
7572de962bdSlukem 	 *	StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
7582de962bdSlukem 	 * 2) '...'B or '...'H :
7592de962bdSlukem 	 *	BitStringVal, OctetStringVal
7602de962bdSlukem 	 * 3) {...} :
7612de962bdSlukem 	 *	SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
7622de962bdSlukem 	 * 4) Between two white spaces
7632de962bdSlukem 	 *	INTEGER, BOOLEAN, NULL,ENUMERATE, etc
7642de962bdSlukem 	 */
7652de962bdSlukem 
7662de962bdSlukem 	succeed = 0;
7672de962bdSlukem 	if ( cav->cav_ptr[0] == '"' ) {
7682de962bdSlukem 		for( count = 1, sequent_dquote = 0 ; ; count++ ) {
7692de962bdSlukem 			/* In order to find escaped double quote */
7702de962bdSlukem 			if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
7712de962bdSlukem 			else sequent_dquote = 0;
7722de962bdSlukem 
7732de962bdSlukem 			if ( cav->cav_ptr[count] == '\0' ||
7742de962bdSlukem 				(cav->cav_ptr+count) > cav->cav_end )
7752de962bdSlukem 			{
7762de962bdSlukem 				break;
7772de962bdSlukem 			}
7782de962bdSlukem 
7792de962bdSlukem 			if ( ( cav->cav_ptr[count] == '"' &&
7802de962bdSlukem 				cav->cav_ptr[count-1] != '"') ||
7812de962bdSlukem 				( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) )
7822de962bdSlukem 			{
7832de962bdSlukem 				succeed = 1;
7842de962bdSlukem 				break;
7852de962bdSlukem 			}
7862de962bdSlukem 		}
7872de962bdSlukem 
7882de962bdSlukem 		if ( !succeed || cav->cav_ptr[count] != '"' ) {
7892de962bdSlukem 			return LDAP_FILTER_ERROR;
7902de962bdSlukem 		}
7912de962bdSlukem 
7922de962bdSlukem 		bv->bv_val = cav->cav_ptr + 1;
7932de962bdSlukem 		bv->bv_len = count - 1; /* exclude '"' */
7942de962bdSlukem 
7952de962bdSlukem 	} else if ( cav->cav_ptr[0] == '\'' ) {
7962de962bdSlukem 		for( count = 1 ; ; count++ ) {
7972de962bdSlukem 			if ( cav->cav_ptr[count] == '\0' ||
7982de962bdSlukem 				(cav->cav_ptr+count) > cav->cav_end )
7992de962bdSlukem 			{
8002de962bdSlukem 				break;
8012de962bdSlukem 			}
8022de962bdSlukem 			if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B') ||
8032de962bdSlukem 				(cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') )
8042de962bdSlukem 			{
8052de962bdSlukem 				succeed = 1;
8062de962bdSlukem 				break;
8072de962bdSlukem 			}
8082de962bdSlukem 		}
8092de962bdSlukem 
8102de962bdSlukem 		if ( !succeed ||
8112de962bdSlukem 			!(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
8122de962bdSlukem 		{
8132de962bdSlukem 			return LDAP_FILTER_ERROR;
8142de962bdSlukem 		}
8152de962bdSlukem 
8162de962bdSlukem 		bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
8172de962bdSlukem 		bv->bv_len = count - 2;/* exclude "'H" or "'B" */
8182de962bdSlukem 
8192de962bdSlukem 	} else if ( cav->cav_ptr[0] == '{' ) {
8202de962bdSlukem 		for( count = 1, unclosed_brace = 1 ; ; count++ ) {
8212de962bdSlukem 			if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
8222de962bdSlukem 			if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
8232de962bdSlukem 
8242de962bdSlukem 			if ( cav->cav_ptr[count] == '\0' ||
8252de962bdSlukem 				(cav->cav_ptr+count) > cav->cav_end )
8262de962bdSlukem 			{
8272de962bdSlukem 				break;
8282de962bdSlukem 			}
8292de962bdSlukem 			if ( unclosed_brace == 0 ) {
8302de962bdSlukem 				succeed = 1;
8312de962bdSlukem 				break;
8322de962bdSlukem 			}
8332de962bdSlukem 		}
8342de962bdSlukem 
8352de962bdSlukem 		if ( !succeed || cav->cav_ptr[count] != '}' ) return LDAP_FILTER_ERROR;
8362de962bdSlukem 
8372de962bdSlukem 		bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
8382de962bdSlukem 		bv->bv_len = count - 1;/* exclude  "'B" */
8392de962bdSlukem 
8402de962bdSlukem 	} else {
8412de962bdSlukem 		succeed = 1;
8422de962bdSlukem 		/*Find  following white space where the value is ended*/
8432de962bdSlukem 		for( count = 1 ; ; count++ ) {
8442de962bdSlukem 			if ( cav->cav_ptr[count] == '\0' ||
8452de962bdSlukem 				cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' ||
8462de962bdSlukem 				cav->cav_ptr[count] == '{' ||
8472de962bdSlukem 				(cav->cav_ptr+count) > cav->cav_end )
8482de962bdSlukem 			{
8492de962bdSlukem 				break;
8502de962bdSlukem 			}
8512de962bdSlukem 		}
8522de962bdSlukem 		bv->bv_val = cav->cav_ptr;
8532de962bdSlukem 		bv->bv_len = count;
8542de962bdSlukem 	}
8552de962bdSlukem 
8562de962bdSlukem 	cav->cav_ptr += bv->bv_len;
8572de962bdSlukem 	return LDAP_SUCCESS;
8582de962bdSlukem }
8592de962bdSlukem 
8602de962bdSlukem static int
get_matching_value(Operation * op,ComponentAssertion * ca,ComponentAssertionValue * cav,struct berval * bv,const char ** text)8612de962bdSlukem get_matching_value( Operation *op, ComponentAssertion* ca,
8622de962bdSlukem 	ComponentAssertionValue* cav, struct berval* bv,
8632de962bdSlukem 	const char**  text )
8642de962bdSlukem {
8652de962bdSlukem 	if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
8662de962bdSlukem 		if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
8672de962bdSlukem 			return LDAP_FILTER_ERROR;
8682de962bdSlukem 		}
8692de962bdSlukem 
8702de962bdSlukem 	} else {
871*549b59edSchristos 		/* embedded componentFilterMatch Description */
8722de962bdSlukem 		bv->bv_val = cav->cav_ptr;
8732de962bdSlukem 		bv->bv_len = cav_cur_len( cav );
8742de962bdSlukem 	}
8752de962bdSlukem 
8762de962bdSlukem 	return LDAP_SUCCESS;
8772de962bdSlukem }
8782de962bdSlukem 
8792de962bdSlukem /* Don't move the position pointer, just peek given string */
8802de962bdSlukem static int
peek_cav_str(ComponentAssertionValue * cav,char * str)8812de962bdSlukem peek_cav_str( ComponentAssertionValue* cav, char* str )
8822de962bdSlukem {
8832de962bdSlukem 	eat_whsp( cav );
8842de962bdSlukem 	if ( cav_cur_len( cav ) >= strlen( str ) &&
8852de962bdSlukem 		strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
8862de962bdSlukem 	{
8872de962bdSlukem 		return LDAP_SUCCESS;
8882de962bdSlukem 	}
8892de962bdSlukem 
8902de962bdSlukem 	return LDAP_INVALID_SYNTAX;
8912de962bdSlukem }
8922de962bdSlukem 
8932de962bdSlukem static int
strip_cav_str(ComponentAssertionValue * cav,char * str)8942de962bdSlukem strip_cav_str( ComponentAssertionValue* cav, char* str)
8952de962bdSlukem {
8962de962bdSlukem 	eat_whsp( cav );
8972de962bdSlukem 	if ( cav_cur_len( cav ) >= strlen( str ) &&
8982de962bdSlukem 		strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
8992de962bdSlukem 	{
9002de962bdSlukem 		cav->cav_ptr += strlen( str );
9012de962bdSlukem 		return LDAP_SUCCESS;
9022de962bdSlukem 	}
9032de962bdSlukem 
9042de962bdSlukem 	return LDAP_INVALID_SYNTAX;
9052de962bdSlukem }
9062de962bdSlukem 
9072de962bdSlukem /*
9082de962bdSlukem  * TAG : "item", "and", "or", "not"
9092de962bdSlukem  */
9102de962bdSlukem static ber_tag_t
strip_cav_tag(ComponentAssertionValue * cav)9112de962bdSlukem strip_cav_tag( ComponentAssertionValue* cav )
9122de962bdSlukem {
913*549b59edSchristos 	int rc;
9142de962bdSlukem 
9152de962bdSlukem 	eat_whsp( cav );
9162de962bdSlukem 	if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
917*549b59edSchristos 		if ( strip_cav_str( cav , "item:" ))
918*549b59edSchristos 			goto fail;
9192de962bdSlukem 		return LDAP_COMP_FILTER_ITEM;
9202de962bdSlukem 
9212de962bdSlukem 	} else if ( cav_cur_len( cav ) >= 7 &&
9222de962bdSlukem 		strncmp( cav->cav_ptr, "and", 3 ) == 0 )
9232de962bdSlukem 	{
924*549b59edSchristos 		if ( strip_cav_str( cav , "and:" ))
925*549b59edSchristos 			goto fail;
9262de962bdSlukem 		return LDAP_COMP_FILTER_AND;
9272de962bdSlukem 
9282de962bdSlukem 	} else if ( cav_cur_len( cav ) >= 6 &&
9292de962bdSlukem 		strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
9302de962bdSlukem 	{
931*549b59edSchristos 		if ( strip_cav_str( cav , "or:" ))
932*549b59edSchristos 			goto fail;
9332de962bdSlukem 		return LDAP_COMP_FILTER_OR;
9342de962bdSlukem 
9352de962bdSlukem 	} else if ( cav_cur_len( cav ) >= 7 &&
9362de962bdSlukem 		strncmp( cav->cav_ptr, "not", 3 ) == 0 )
9372de962bdSlukem 	{
938*549b59edSchristos 		if ( strip_cav_str( cav , "not:" ))
939*549b59edSchristos 			goto fail;
9402de962bdSlukem 		return LDAP_COMP_FILTER_NOT;
9412de962bdSlukem 	}
9422de962bdSlukem 
943*549b59edSchristos fail:
9442de962bdSlukem 	return LBER_ERROR;
9452de962bdSlukem }
9462de962bdSlukem 
9472de962bdSlukem /*
9482de962bdSlukem  * when encoding, "item" is denotation of ComponentAssertion
9492de962bdSlukem  * ComponentAssertion :: SEQUENCE {
9502de962bdSlukem  *	component		ComponentReference (SIZE(1..MAX)) OPTIONAL,
9512de962bdSlukem  *	useDefaultValues	BOOLEAN DEFAULT TRUE,
9522de962bdSlukem  *	rule			MATCHING-RULE.&id,
9532de962bdSlukem  *	value			MATCHING-RULE.&AssertionType }
9542de962bdSlukem  */
9552de962bdSlukem static int
get_item(Operation * op,ComponentAssertionValue * cav,ComponentAssertion ** ca,const char ** text)9562de962bdSlukem get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
9572de962bdSlukem 		const char** text )
9582de962bdSlukem {
959*549b59edSchristos 	int rc, freeval = 0;
9602de962bdSlukem 	ComponentAssertion* _ca;
9612de962bdSlukem 	struct berval value;
9622de962bdSlukem 	MatchingRule* mr;
9632de962bdSlukem 
964*549b59edSchristos 	Debug( LDAP_DEBUG_FILTER, "get_item \n" );
9652de962bdSlukem 	if ( op )
9662de962bdSlukem 		_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
9672de962bdSlukem 	else
9684e6df137Slukem 		_ca = SLAP_MALLOC( sizeof( ComponentAssertion ) );
9692de962bdSlukem 
9702de962bdSlukem 	if ( !_ca ) return LDAP_NO_MEMORY;
9712de962bdSlukem 
9722de962bdSlukem 	_ca->ca_comp_data.cd_tree = NULL;
9732de962bdSlukem 	_ca->ca_comp_data.cd_mem_op = NULL;
974*549b59edSchristos 	BER_BVZERO( &_ca->ca_ma_value );
9752de962bdSlukem 
9762de962bdSlukem 	rc = peek_cav_str( cav, "component" );
9772de962bdSlukem 	if ( rc == LDAP_SUCCESS ) {
9782de962bdSlukem 		strip_cav_str( cav, "component" );
9792de962bdSlukem 		rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
9802de962bdSlukem 		if ( rc != LDAP_SUCCESS ) {
981*549b59edSchristos 			rc = LDAP_INVALID_SYNTAX;
982*549b59edSchristos fail:
983*549b59edSchristos 			if ( freeval )
984*549b59edSchristos 				op->o_tmpfree( _ca->ca_ma_value.bv_val, op->o_tmpmemctx );
9852de962bdSlukem 			if ( op )
9862de962bdSlukem 				op->o_tmpfree( _ca, op->o_tmpmemctx );
9872de962bdSlukem 			else
9882de962bdSlukem 				free( _ca );
989*549b59edSchristos 			return rc;
9902de962bdSlukem 		}
9912de962bdSlukem 		if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
992*549b59edSchristos 			goto fail;
9932de962bdSlukem 	} else {
9942de962bdSlukem 		_ca->ca_comp_ref = NULL;
9952de962bdSlukem 	}
9962de962bdSlukem 
9972de962bdSlukem 	rc = peek_cav_str( cav, "useDefaultValues");
9982de962bdSlukem 	if ( rc == LDAP_SUCCESS ) {
9992de962bdSlukem 		rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
10002de962bdSlukem 		if ( rc != LDAP_SUCCESS ) {
1001*549b59edSchristos 			rc = LDAP_INVALID_SYNTAX;
1002*549b59edSchristos 			goto fail;
10032de962bdSlukem 		}
10042de962bdSlukem 		if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
1005*549b59edSchristos 			goto fail;
10062de962bdSlukem 	}
10072de962bdSlukem 	else _ca->ca_use_def = 1;
10082de962bdSlukem 
10092de962bdSlukem 	if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
10102de962bdSlukem 		get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
1011*549b59edSchristos 		rc = LDAP_INAPPROPRIATE_MATCHING;
1012*549b59edSchristos 		goto fail;
10132de962bdSlukem 	}
10142de962bdSlukem 
10152de962bdSlukem 	if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
1016*549b59edSchristos 		goto fail;
10172de962bdSlukem 	if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
10182de962bdSlukem 		get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
1019*549b59edSchristos 		rc = LDAP_INVALID_SYNTAX;
1020*549b59edSchristos 		goto fail;
10212de962bdSlukem 	}
10222de962bdSlukem 
10232de962bdSlukem 	/*
10242de962bdSlukem 	 * Normalize the value of this component assertion when the matching
10252de962bdSlukem 	 * rule is one of existing matching rules
10262de962bdSlukem 	 */
10272de962bdSlukem 	mr = _ca->ca_ma_rule;
10282de962bdSlukem 	if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
10292de962bdSlukem 
10302de962bdSlukem 		value.bv_val[value.bv_len] = '\0';
10312de962bdSlukem 		rc = mr->smr_normalize (
10322de962bdSlukem 			SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
10332de962bdSlukem 			NULL, mr,
10342de962bdSlukem 			&value, &_ca->ca_ma_value, op->o_tmpmemctx );
10352de962bdSlukem 		if ( rc != LDAP_SUCCESS )
1036*549b59edSchristos 			goto fail;
1037*549b59edSchristos 		freeval = 1;
10382de962bdSlukem 	}
10392de962bdSlukem 	else
10402de962bdSlukem 		_ca->ca_ma_value = value;
10412de962bdSlukem 	/*
10422de962bdSlukem 	 * Validate the value of this component assertion
10432de962bdSlukem 	 */
10442de962bdSlukem 	if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
1045*549b59edSchristos 		rc = LDAP_INVALID_SYNTAX;
1046*549b59edSchristos 		goto fail;
10472de962bdSlukem 	}
10482de962bdSlukem 
10492de962bdSlukem 
10502de962bdSlukem 	/* componentFilterMatch contains componentFilterMatch in it */
10512de962bdSlukem 	if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
10522de962bdSlukem 		struct berval bv;
10532de962bdSlukem 		bv.bv_val = cav->cav_ptr;
10542de962bdSlukem 		bv.bv_len = cav_cur_len( cav );
10552de962bdSlukem 		rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
1056*549b59edSchristos 		if ( rc != LDAP_SUCCESS )
1057*549b59edSchristos 			goto fail;
10582de962bdSlukem 		cav->cav_ptr = bv.bv_val;
10592de962bdSlukem 		assert( cav->cav_end >= bv.bv_val );
10602de962bdSlukem 	}
10612de962bdSlukem 
10622de962bdSlukem 	*ca = _ca;
10632de962bdSlukem 	return LDAP_SUCCESS;
10642de962bdSlukem }
10652de962bdSlukem 
10662de962bdSlukem static int
parse_comp_filter(Operation * op,ComponentAssertionValue * cav,ComponentFilter ** filt,const char ** text)10672de962bdSlukem parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
10682de962bdSlukem 				ComponentFilter** filt, const char** text )
10692de962bdSlukem {
10702de962bdSlukem 	/*
10712de962bdSlukem 	 * A component filter looks like this coming in:
10722de962bdSlukem 	 *	Filter ::= CHOICE {
10732de962bdSlukem 	 *		item	[0]	ComponentAssertion,
10742de962bdSlukem 	 *		and	[1]	SEQUENCE OF ComponentFilter,
10752de962bdSlukem 	 *		or	[2]	SEQUENCE OF ComponentFilter,
10762de962bdSlukem 	 *		not	[3]	ComponentFilter,
10772de962bdSlukem 	 *	}
10782de962bdSlukem 	 */
10792de962bdSlukem 
10802de962bdSlukem 	ber_tag_t	tag;
1081*549b59edSchristos 	int		err = LDAP_SUCCESS;
10822de962bdSlukem 	ComponentFilter	f;
10832de962bdSlukem 	/* TAG : item, and, or, not in RFC 4515 */
10842de962bdSlukem 	tag = strip_cav_tag( cav );
10852de962bdSlukem 
10862de962bdSlukem 	if ( tag == LBER_ERROR ) {
10872de962bdSlukem 		*text = "error decoding comp filter";
10882de962bdSlukem 		return LDAP_PROTOCOL_ERROR;
10892de962bdSlukem 	}
10902de962bdSlukem 
1091*549b59edSchristos 	if ( tag != LDAP_COMP_FILTER_NOT ) {
1092*549b59edSchristos 		err = strip_cav_str( cav, "{");
1093*549b59edSchristos 		if ( err )
1094*549b59edSchristos 			goto invalid;
1095*549b59edSchristos 	}
10962de962bdSlukem 
10972de962bdSlukem 	f.cf_next = NULL;
10982de962bdSlukem 	f.cf_choice = tag;
10992de962bdSlukem 
11002de962bdSlukem 	switch ( f.cf_choice ) {
11012de962bdSlukem 	case LDAP_COMP_FILTER_AND:
1102*549b59edSchristos 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n" );
11032de962bdSlukem 		err = get_comp_filter_list( op, cav, &f.cf_and, text );
11042de962bdSlukem 		if ( err != LDAP_SUCCESS ) {
11052de962bdSlukem 			break;
11062de962bdSlukem 		}
11072de962bdSlukem 		if ( f.cf_and == NULL ) {
11082de962bdSlukem 			f.cf_choice = SLAPD_FILTER_COMPUTED;
11092de962bdSlukem 			f.cf_result = LDAP_COMPARE_TRUE;
11102de962bdSlukem 		}
11112de962bdSlukem 		break;
11122de962bdSlukem 
11132de962bdSlukem 	case LDAP_COMP_FILTER_OR:
1114*549b59edSchristos 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n" );
11152de962bdSlukem 		err = get_comp_filter_list( op, cav, &f.cf_or, text );
11162de962bdSlukem 		if ( err != LDAP_SUCCESS ) {
11172de962bdSlukem 			break;
11182de962bdSlukem 		}
11192de962bdSlukem 		if ( f.cf_or == NULL ) {
11202de962bdSlukem 			f.cf_choice = SLAPD_FILTER_COMPUTED;
11212de962bdSlukem 			f.cf_result = LDAP_COMPARE_FALSE;
11222de962bdSlukem 		}
11232de962bdSlukem 		/* no assert - list could be empty */
11242de962bdSlukem 		break;
11252de962bdSlukem 
11262de962bdSlukem 	case LDAP_COMP_FILTER_NOT:
1127*549b59edSchristos 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n" );
11282de962bdSlukem 		err = parse_comp_filter( op, cav, &f.cf_not, text );
11292de962bdSlukem 		if ( err != LDAP_SUCCESS ) {
11302de962bdSlukem 			break;
11312de962bdSlukem 		}
11322de962bdSlukem 
11332de962bdSlukem 		assert( f.cf_not != NULL );
11342de962bdSlukem 		if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
11352de962bdSlukem 			int fresult = f.cf_not->cf_result;
11362de962bdSlukem 			f.cf_choice = SLAPD_FILTER_COMPUTED;
11372de962bdSlukem 			op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
11382de962bdSlukem 			f.cf_not = NULL;
11392de962bdSlukem 
11402de962bdSlukem 			switch ( fresult ) {
11412de962bdSlukem 			case LDAP_COMPARE_TRUE:
11422de962bdSlukem 				f.cf_result = LDAP_COMPARE_FALSE;
11432de962bdSlukem 				break;
11442de962bdSlukem 			case LDAP_COMPARE_FALSE:
11452de962bdSlukem 				f.cf_result = LDAP_COMPARE_TRUE;
11462de962bdSlukem 				break;
11472de962bdSlukem 			default: ;
11482de962bdSlukem 				/* (!Undefined) is Undefined */
11492de962bdSlukem 			}
11502de962bdSlukem 		}
11512de962bdSlukem 		break;
11522de962bdSlukem 
11532de962bdSlukem 	case LDAP_COMP_FILTER_ITEM:
1154*549b59edSchristos 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n" );
11552de962bdSlukem 		err = get_item( op, cav, &f.cf_ca, text );
11562de962bdSlukem 		if ( err != LDAP_SUCCESS ) {
11572de962bdSlukem 			break;
11582de962bdSlukem 		}
11592de962bdSlukem 
11602de962bdSlukem 		assert( f.cf_ca != NULL );
11612de962bdSlukem 		break;
11622de962bdSlukem 
11632de962bdSlukem 	default:
11642de962bdSlukem 		f.cf_choice = SLAPD_FILTER_COMPUTED;
11652de962bdSlukem 		f.cf_result = SLAPD_COMPARE_UNDEFINED;
11662de962bdSlukem 		break;
11672de962bdSlukem 	}
11682de962bdSlukem 
1169*549b59edSchristos invalid:
11702de962bdSlukem 	if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
11712de962bdSlukem 		*text = "Component Filter Syntax Error";
11722de962bdSlukem 		return err;
11732de962bdSlukem 	}
11742de962bdSlukem 
11752de962bdSlukem 	if ( tag != LDAP_COMP_FILTER_NOT )
1176*549b59edSchristos 		err = strip_cav_str( cav, "}");
11772de962bdSlukem 
11782de962bdSlukem 	if ( err == LDAP_SUCCESS ) {
11792de962bdSlukem 		if ( op ) {
11802de962bdSlukem 			*filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
11812de962bdSlukem 		} else {
11824e6df137Slukem 			*filt = SLAP_MALLOC( sizeof(f) );
11834e6df137Slukem 		}
11844e6df137Slukem 		if ( *filt == NULL ) {
11854e6df137Slukem 			return LDAP_NO_MEMORY;
11862de962bdSlukem 		}
11872de962bdSlukem 		**filt = f;
11882de962bdSlukem 	}
11892de962bdSlukem 
11902de962bdSlukem 	return( err );
11912de962bdSlukem }
11922de962bdSlukem 
11932de962bdSlukem static int
test_comp_filter_and(Syntax * syn,ComponentSyntaxInfo * a,ComponentFilter * flist)11942de962bdSlukem test_comp_filter_and(
11952de962bdSlukem 	Syntax *syn,
11962de962bdSlukem 	ComponentSyntaxInfo *a,
11972de962bdSlukem 	ComponentFilter *flist )
11982de962bdSlukem {
11992de962bdSlukem 	ComponentFilter *f;
12002de962bdSlukem 	int rtn = LDAP_COMPARE_TRUE;
12012de962bdSlukem 
12022de962bdSlukem 	for ( f = flist ; f != NULL; f = f->cf_next ) {
12032de962bdSlukem 		int rc = test_comp_filter( syn, a, f );
12042de962bdSlukem 		if ( rc == LDAP_COMPARE_FALSE ) {
12052de962bdSlukem 			rtn = rc;
12062de962bdSlukem 			break;
12072de962bdSlukem 		}
12082de962bdSlukem 
12092de962bdSlukem 		if ( rc != LDAP_COMPARE_TRUE ) {
12102de962bdSlukem 			rtn = rc;
12112de962bdSlukem 		}
12122de962bdSlukem 	}
12132de962bdSlukem 
12142de962bdSlukem 	return rtn;
12152de962bdSlukem }
12162de962bdSlukem 
12172de962bdSlukem static int
test_comp_filter_or(Syntax * syn,ComponentSyntaxInfo * a,ComponentFilter * flist)12182de962bdSlukem test_comp_filter_or(
12192de962bdSlukem 	Syntax *syn,
12202de962bdSlukem 	ComponentSyntaxInfo *a,
12212de962bdSlukem 	ComponentFilter *flist )
12222de962bdSlukem {
12232de962bdSlukem 	ComponentFilter *f;
12242de962bdSlukem 	int rtn = LDAP_COMPARE_TRUE;
12252de962bdSlukem 
12262de962bdSlukem 	for ( f = flist ; f != NULL; f = f->cf_next ) {
12272de962bdSlukem 		int rc = test_comp_filter( syn, a, f );
12282de962bdSlukem 		if ( rc == LDAP_COMPARE_TRUE ) {
12292de962bdSlukem 			rtn = rc;
12302de962bdSlukem 			break;
12312de962bdSlukem 		}
12322de962bdSlukem 
12332de962bdSlukem 		if ( rc != LDAP_COMPARE_FALSE ) {
12342de962bdSlukem 			rtn = rc;
12352de962bdSlukem 		}
12362de962bdSlukem 	}
12372de962bdSlukem 
12382de962bdSlukem 	return rtn;
12392de962bdSlukem }
12402de962bdSlukem 
12412de962bdSlukem int
csi_value_match(MatchingRule * mr,struct berval * bv_attr,struct berval * bv_assert)12422de962bdSlukem csi_value_match( MatchingRule *mr, struct berval* bv_attr,
12432de962bdSlukem 	struct berval* bv_assert )
12442de962bdSlukem {
12452de962bdSlukem 	int rc;
12462de962bdSlukem 	int match;
12472de962bdSlukem 
12482de962bdSlukem 	assert( mr != NULL );
12492de962bdSlukem 	assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
12502de962bdSlukem 
12512de962bdSlukem 	if( !mr->smr_match ) return LDAP_INAPPROPRIATE_MATCHING;
12522de962bdSlukem 
12532de962bdSlukem 	rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
12542de962bdSlukem 		mr, bv_attr, bv_assert );
12552de962bdSlukem 
12562de962bdSlukem 	if ( rc != LDAP_SUCCESS ) return rc;
12572de962bdSlukem 
12582de962bdSlukem 	return match ? LDAP_COMPARE_FALSE : LDAP_COMPARE_TRUE;
12592de962bdSlukem }
12602de962bdSlukem 
12612de962bdSlukem /*
12622de962bdSlukem  * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
12632de962bdSlukem  */
12642de962bdSlukem static int
test_comp_filter_item(Syntax * syn,ComponentSyntaxInfo * csi_attr,ComponentAssertion * ca)12652de962bdSlukem test_comp_filter_item(
12662de962bdSlukem 	Syntax *syn,
12672de962bdSlukem 	ComponentSyntaxInfo *csi_attr,
12682de962bdSlukem 	ComponentAssertion *ca )
12692de962bdSlukem {
12702de962bdSlukem 	int rc;
12712de962bdSlukem 	void *attr_nm, *assert_nm;
12722de962bdSlukem 
12732de962bdSlukem 	if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
12742de962bdSlukem 		OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
12752de962bdSlukem 		/* componentFilterMatch inside of componentFilterMatch */
12762de962bdSlukem 		rc = test_comp_filter( syn, csi_attr, ca->ca_cf );
12772de962bdSlukem 		return rc;
12782de962bdSlukem 	}
12792de962bdSlukem 
12802de962bdSlukem 	/* Memory for storing will-be-extracted attribute values */
12812de962bdSlukem 	attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
12822de962bdSlukem 	if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
12832de962bdSlukem 
12842de962bdSlukem 	/* Memory for storing component assertion values */
12852de962bdSlukem 	if( !ca->ca_comp_data.cd_mem_op ) {
12862de962bdSlukem 		assert_nm = nibble_mem_allocator ( 256, 64 );
12872de962bdSlukem 		if ( !assert_nm ) {
12882de962bdSlukem 			nibble_mem_free ( attr_nm );
12892de962bdSlukem 			return LDAP_PROTOCOL_ERROR;
12902de962bdSlukem 		}
12912de962bdSlukem 		ca->ca_comp_data.cd_mem_op = assert_nm;
12922de962bdSlukem 
12932de962bdSlukem 	} else {
12942de962bdSlukem 		assert_nm = ca->ca_comp_data.cd_mem_op;
12952de962bdSlukem 	}
12962de962bdSlukem 
12972de962bdSlukem 	/* component reference initialization */
12982de962bdSlukem 	if ( ca->ca_comp_ref ) {
12992de962bdSlukem 		ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
13002de962bdSlukem 	}
13012de962bdSlukem 	rc = test_components( attr_nm, assert_nm, csi_attr, ca );
13022de962bdSlukem 
13032de962bdSlukem 	/* free memory used for storing extracted attribute value */
13042de962bdSlukem 	nibble_mem_free ( attr_nm );
13052de962bdSlukem 	return rc;
13062de962bdSlukem }
13072de962bdSlukem 
13082de962bdSlukem static int
test_comp_filter(Syntax * syn,ComponentSyntaxInfo * a,ComponentFilter * f)13092de962bdSlukem test_comp_filter(
13102de962bdSlukem     Syntax *syn,
13112de962bdSlukem     ComponentSyntaxInfo *a,
13122de962bdSlukem     ComponentFilter *f )
13132de962bdSlukem {
13142de962bdSlukem 	int	rc;
13152de962bdSlukem 
13162de962bdSlukem 	if ( !f ) return LDAP_PROTOCOL_ERROR;
13172de962bdSlukem 
1318*549b59edSchristos 	Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n" );
13192de962bdSlukem 	switch ( f->cf_choice ) {
13202de962bdSlukem 	case SLAPD_FILTER_COMPUTED:
13212de962bdSlukem 		rc = f->cf_result;
13222de962bdSlukem 		break;
13232de962bdSlukem 	case LDAP_COMP_FILTER_AND:
13242de962bdSlukem 		rc = test_comp_filter_and( syn, a, f->cf_and );
13252de962bdSlukem 		break;
13262de962bdSlukem 	case LDAP_COMP_FILTER_OR:
13272de962bdSlukem 		rc = test_comp_filter_or( syn, a, f->cf_or );
13282de962bdSlukem 		break;
13292de962bdSlukem 	case LDAP_COMP_FILTER_NOT:
13302de962bdSlukem 		rc = test_comp_filter( syn, a, f->cf_not );
13312de962bdSlukem 
13322de962bdSlukem 		switch ( rc ) {
13332de962bdSlukem 		case LDAP_COMPARE_TRUE:
13342de962bdSlukem 			rc = LDAP_COMPARE_FALSE;
13352de962bdSlukem 			break;
13362de962bdSlukem 		case LDAP_COMPARE_FALSE:
13372de962bdSlukem 			rc = LDAP_COMPARE_TRUE;
13382de962bdSlukem 			break;
13392de962bdSlukem 		}
13402de962bdSlukem 		break;
13412de962bdSlukem 	case LDAP_COMP_FILTER_ITEM:
13422de962bdSlukem 		rc = test_comp_filter_item( syn, a, f->cf_ca );
13432de962bdSlukem 		break;
13442de962bdSlukem 	default:
13452de962bdSlukem 		rc = LDAP_PROTOCOL_ERROR;
13462de962bdSlukem 	}
13472de962bdSlukem 
13482de962bdSlukem 	return( rc );
13492de962bdSlukem }
13502de962bdSlukem 
13512de962bdSlukem static void
free_comp_filter_list(ComponentFilter * f)13522de962bdSlukem free_comp_filter_list( ComponentFilter* f )
13532de962bdSlukem {
13542de962bdSlukem 	ComponentFilter* tmp;
13552de962bdSlukem 	for ( tmp = f; tmp; tmp = tmp->cf_next ) {
13562de962bdSlukem 		free_comp_filter( tmp );
13572de962bdSlukem 	}
13582de962bdSlukem }
13592de962bdSlukem 
13602de962bdSlukem static void
free_comp_filter(ComponentFilter * f)13612de962bdSlukem free_comp_filter( ComponentFilter* f )
13622de962bdSlukem {
13632de962bdSlukem 	if ( !f ) {
13642de962bdSlukem 		Debug( LDAP_DEBUG_FILTER,
1365*549b59edSchristos 			"free_comp_filter: Invalid filter so failed to release memory\n" );
13662de962bdSlukem 		return;
13672de962bdSlukem 	}
13682de962bdSlukem 	switch ( f->cf_choice ) {
13692de962bdSlukem 	case LDAP_COMP_FILTER_AND:
13702de962bdSlukem 	case LDAP_COMP_FILTER_OR:
13712de962bdSlukem 		free_comp_filter_list( f->cf_any );
13722de962bdSlukem 		break;
13732de962bdSlukem 	case LDAP_COMP_FILTER_NOT:
13742de962bdSlukem 		free_comp_filter( f->cf_any );
13752de962bdSlukem 		break;
13762de962bdSlukem 	case LDAP_COMP_FILTER_ITEM:
13772de962bdSlukem 		if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op ) {
13782de962bdSlukem 			nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
13792de962bdSlukem 		}
13802de962bdSlukem 		break;
13812de962bdSlukem 	default:
13822de962bdSlukem 		break;
13832de962bdSlukem 	}
13842de962bdSlukem }
13852de962bdSlukem 
13862de962bdSlukem void
component_free(ComponentFilter * f)13872de962bdSlukem component_free( ComponentFilter *f ) {
13882de962bdSlukem 	free_comp_filter( f );
13892de962bdSlukem }
13902de962bdSlukem 
13912de962bdSlukem void
free_ComponentData(Attribute * a)13922de962bdSlukem free_ComponentData( Attribute *a ) {
13932de962bdSlukem 	if ( a->a_comp_data->cd_mem_op )
13942de962bdSlukem 		component_destructor( a->a_comp_data->cd_mem_op );
13952de962bdSlukem 	free ( a->a_comp_data );
13962de962bdSlukem 	a->a_comp_data = NULL;
13972de962bdSlukem }
13982de962bdSlukem #endif
1399