From 98485f5247759e294994027fa6869a229287bba9 Mon Sep 17 00:00:00 2001
From: Sang Seok Lim <slim@openldap.org>
Date: Wed, 1 Dec 2004 22:11:55 +0000
Subject: [PATCH] 1) existing matching rules support in component filter 2)
 remove double buffering for decoded component values 3) caching decoded
 component assertion values

---
 .../slapd-modules/comp_match/certificate.c    |   8 +-
 contrib/slapd-modules/comp_match/component.h  |  19 ++
 .../slapd-modules/comp_match/componentlib.c   | 188 ++++++++++++++++++
 contrib/slapd-modules/comp_match/init.c       | 113 ++++++-----
 servers/slapd/component.c                     |  50 +----
 tests/data/compsearch.out                     | 119 +++++++++++
 tests/scripts/test031-component-filter        |  28 ++-
 7 files changed, 433 insertions(+), 92 deletions(-)

diff --git a/contrib/slapd-modules/comp_match/certificate.c b/contrib/slapd-modules/comp_match/certificate.c
index 08ba91d12d..48cb221341 100644
--- a/contrib/slapd-modules/comp_match/certificate.c
+++ b/contrib/slapd-modules/comp_match/certificate.c
@@ -1683,7 +1683,7 @@ int mode)
 	t->comp_desc->cd_free = (comp_free_func*)NULL;
 	t->comp_desc->cd_extract_i = (extract_component_from_id_func*)ExtractingComponentRelativeDistinguishedName;
 	t->comp_desc->cd_type = ASN_COMPOSITE;
-	t->comp_desc->cd_type_id = COMPOSITE_ASN1_TYPE;
+	t->comp_desc->cd_type_id = RelativeDistinguishedName ;
 	t->comp_desc->cd_all_match = (allcomponent_matching_func*)MatchingComponentRelativeDistinguishedName;
     (*bytesDecoded) += totalElmtsLen1;
 	return LDAP_SUCCESS;
@@ -1755,7 +1755,7 @@ int mode)
 	t->comp_desc->cd_free = (comp_free_func*)NULL;
 	t->comp_desc->cd_extract_i = (extract_component_from_id_func*)ExtractingComponentRelativeDistinguishedName;
 	t->comp_desc->cd_type = ASN_COMPOSITE;
-	t->comp_desc->cd_type_id = COMPOSITE_ASN1_TYPE;
+	t->comp_desc->cd_type_id = RelativeDistinguishedName ;
 	t->comp_desc->cd_all_match = (allcomponent_matching_func*)MatchingComponentRelativeDistinguishedName;
 	return LDAP_SUCCESS;
 }  /* GDecRelativeDistinguishedNameContent */
@@ -1913,7 +1913,7 @@ int mode)
 	t->comp_desc->cd_free = (comp_free_func*)NULL;
 	t->comp_desc->cd_extract_i = (extract_component_from_id_func*)ExtractingComponentRDNSequence;
 	t->comp_desc->cd_type = ASN_COMPOSITE;
-	t->comp_desc->cd_type_id = COMPOSITE_ASN1_TYPE;
+	t->comp_desc->cd_type_id = RDNSequence;
 	t->comp_desc->cd_all_match = (allcomponent_matching_func*)MatchingComponentRDNSequence;
     (*bytesDecoded) += totalElmtsLen1;
 	return LDAP_SUCCESS;
@@ -1985,7 +1985,7 @@ int mode)
 	t->comp_desc->cd_free = (comp_free_func*)NULL;
 	t->comp_desc->cd_extract_i = (extract_component_from_id_func*)ExtractingComponentRDNSequence;
 	t->comp_desc->cd_type = ASN_COMPOSITE;
-	t->comp_desc->cd_type_id = COMPOSITE_ASN1_TYPE;
+	t->comp_desc->cd_type_id = RDNSequence;
 	t->comp_desc->cd_all_match = (allcomponent_matching_func*)MatchingComponentRDNSequence;
 	return LDAP_SUCCESS;
 }  /* GDecRDNSequenceContent */
diff --git a/contrib/slapd-modules/comp_match/component.h b/contrib/slapd-modules/comp_match/component.h
index 6d1a0f3123..07c6ccddb6 100644
--- a/contrib/slapd-modules/comp_match/component.h
+++ b/contrib/slapd-modules/comp_match/component.h
@@ -508,4 +508,23 @@ m_convert_attr_to_comp ( Attribute* a, struct berval* bv );
 MatchingRule*
 retrieve_matching_rule( char* mr_oid, AsnTypeId type );
 
+#define INITIAL_DN_SIZE 128
+#define INITIAL_ATTR_SIZE 256
+#define INCREMENT_SIZE 32
+int increment_bv_mem ( struct berval* in );
+int intToAscii ( int value, char* buf );
+typedef ComponentList irRDNSequence;
+typedef ComponentList irRelativeDistinguishedName;
+typedef ComponentOid irAttributeType;
+typedef struct irAttributeTypeAndValue /* SEQUENCE */
+{
+	Syntax* syntax;
+	ComponentDesc* comp_desc;
+	struct berval identifier;
+	char id_buf[MAX_IDENTIFIER_LEN];
+	irAttributeType type; /* AttributeType */
+	ComponentAnyDefinedBy value; /* ANY DEFINED BY type */
+} irAttributeTypeAndValue;
+#define RDN_MATCH_OID "1.2.36.79672281.1.13.3"
+#define DN_MATCH_OID "2.5.13.1"
 #endif
diff --git a/contrib/slapd-modules/comp_match/componentlib.c b/contrib/slapd-modules/comp_match/componentlib.c
index 4c0e22d114..013d309f71 100644
--- a/contrib/slapd-modules/comp_match/componentlib.c
+++ b/contrib/slapd-modules/comp_match/componentlib.c
@@ -2185,4 +2185,192 @@ int mode) {
 	return (*decoder)( mem_op, b, tag, elmtLen, (ComponentSyntaxInfo*)v,(int*)bytesDecoded, mode );
 }
 
+/*
+ * ASN.1 specification of a distinguished name
+ * DistinguishedName ::= RDNSequence
+ * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+ * RelativeDistinguishedName ::= SET SIZE(1..MAX) OF AttributeTypeandValue
+ * AttributeTypeandValue ::= SEQUENCE {
+ * 	type	AttributeType
+ *	value	AttributeValue
+ * }
+ * When dnMatch/rdnMatch is used in a component assertion value
+ * the component in DistinguishedName/RelativeDistinguishedName
+ * need to be converted to the LDAP encodings in RFC2253
+ * in order to be matched against the assertion value
+ * If allComponentMatch is used, the assertion value may be
+ * decoded into the Internal Representation(Component Tree)
+ * by the corresponding GSER or BER decoder
+ * Following routine converts a component tree(DistinguishedName) into
+ * LDAP encodings in RFC2253
+ * Example)
+ * IR : ComponentRDNSequence
+ * GSER : { { type cn, value sang },{ type o, value ibm}, {type c, value us} }
+ * LDAP Encodings : cn=sang,o=ibm,c=us 
+ */
+
+int
+increment_bv_mem ( struct berval* in ) {
+	int new_size = in->bv_len + INCREMENT_SIZE;
+	in->bv_val = realloc( in->bv_val, new_size );
+	in->bv_len = new_size;
+}
+
+int
+ConvertBER2Desc( char* in, int size, struct berval* out, int* pos ) {
+	int desc_size;
+	char* desc_ptr;
+	unsigned int firstArcNum;
+	unsigned int arcNum;
+	int i, rc, start_pos = *pos;
+	char buf[MAX_OID_LEN];
+	AttributeType *at;
+	struct berval bv_name;
+
+	/*convert BER oid to desc*/
+	for ( i = 0, arcNum = 0; (i < size) && (in[i] & 0x80 ); i++ )
+		arcNum = (arcNum << 7) + (in[i] & 0x7f);
+	arcNum = (arcNum << 7) + (in[i] & 0x7f);
+	i++;
+	firstArcNum = (unsigned short)(arcNum/40);
+	if ( firstArcNum > 2 )
+		firstArcNum = 2;
+	
+	arcNum = arcNum - (firstArcNum * 40 );
+
+	rc = intToAscii ( arcNum, buf );
+
+	/*check if the buffer can store the first/second arc and two dots*/
+	if ( out->bv_len < *pos + 2 + 1 + rc )
+		increment_bv_mem ( out );
+
+	if ( firstArcNum == 1)
+		out->bv_val[*pos] = '1';
+	else
+		out->bv_val[*pos] = '2';
+	(*pos)++;
+	out->bv_val[*pos] = '.';
+	(*pos)++;
+
+	memcpy( out->bv_val + *pos, buf, rc );
+	*pos += rc;
+	out->bv_val[*pos] = '.';
+	(*pos)++;
+
+	for ( ; i < size ; ) {
+		for ( arcNum=0; (i < size) && (in[i] & 0x80) ; i++ )
+			arcNum = (arcNum << 7) + (in[i] & 0x7f);
+		arcNum = (arcNum << 7) + (in[i] & 0x7f);
+		i++;
+
+		rc = intToAscii ( arcNum, buf );
+
+		if ( out->bv_len < *pos + rc + 1 )
+			increment_bv_mem ( out );
+
+		memcpy( out->bv_val + *pos, buf, rc );
+		*pos += rc;
+		out->bv_val[*pos] = '.';
+		(*pos)++;
+	}
+	(*pos)--;/*remove the last '.'*/
+
+	/*
+	 * lookup OID database to locate desc
+	 * then overwrite OID with desc in *out
+	 * If failed to look up desc, OID form is used
+	 */
+	bv_name.bv_val = out->bv_val + start_pos;
+	bv_name.bv_len = *pos - start_pos;
+	at = at_bvfind( &bv_name );
+	if ( !at )
+		return LDAP_SUCCESS;
+	desc_size = at->sat_cname.bv_len;
+	memcpy( out->bv_val + start_pos, at->sat_cname.bv_val, desc_size );
+	*pos = start_pos + desc_size;
+	return LDAP_SUCCESS;
+}
+
+int
+ConvertComponentAttributeTypeAndValue2RFC2253 ( irAttributeTypeAndValue* in, struct berval* out, int *pos ) {
+	int rc;
+	int value_size = ((ComponentUTF8String*)in->value.value)->value.octetLen;
+	char* value_ptr =  ((ComponentUTF8String*)in->value.value)->value.octs;
+
+	rc = ConvertBER2Desc( in->type.value.octs, in->type.value.octetLen, out, pos );
+	if ( rc != LDAP_SUCCESS ) return rc;
+	if ( out->bv_len < *pos + 1/*for '='*/  )
+		increment_bv_mem ( out );
+	/*Between type and value, put '='*/
+	out->bv_val[*pos] = '=';
+	(*pos)++;
+
+	/*Assume it is string*/		
+	if ( out->bv_len < *pos + value_size )
+		increment_bv_mem ( out );
+	memcpy( out->bv_val + *pos, value_ptr, value_size );
+	out->bv_len += value_size;
+	*pos += value_size;
+	
+	return LDAP_SUCCESS;
+}
+
+int
+ConvertRelativeDistinguishedName2RFC2253 ( irRelativeDistinguishedName* in, struct berval *out , int* pos) {
+	irAttributeTypeAndValue* attr_typeNvalue;
+	int rc;
+
+
+	FOR_EACH_LIST_ELMT( attr_typeNvalue, &in->comp_list)
+	{
+		rc = ConvertComponentAttributeTypeAndValue2RFC2253( attr_typeNvalue, out, pos );
+		if ( rc != LDAP_SUCCESS ) return LDAP_INVALID_SYNTAX;
+
+		if ( out->bv_len < pos + 1/*for '+'*/  )
+			increment_bv_mem ( out );
+		/*between multivalued RDNs, put comma*/
+		out->bv_val[*pos++] = '+';
+	}
+	(*pos)--;/*remove the last '+'*/
+	return LDAP_SUCCESS;
+}
+
+int 
+ConvertRDN2RFC2253 ( irRelativeDistinguishedName* in, struct berval *out ) {
+	int rc, pos = 0;
+	out->bv_val = (char*)malloc( INITIAL_DN_SIZE );
+	out->bv_len = INITIAL_DN_SIZE;
+
+	rc = ConvertRelativeDistinguishedName2RFC2253 ( in, out , &pos);
+	if ( rc != LDAP_SUCCESS ) return rc;
+	out->bv_val[pos] = '\0';
+	out->bv_len = pos;
+	return LDAP_SUCCESS;
+}
+
+int
+ConvertRDNSequence2RFC2253( irRDNSequence *in, struct berval* out ) {
+	irRelativeDistinguishedName* rdn_seq;
+	AsnList* seq = &in->comp_list;
+	int pos = 0, rc ;
+
+	out->bv_val = (char*)malloc( INITIAL_DN_SIZE );
+	out->bv_len = INITIAL_DN_SIZE;
+
+	FOR_EACH_LIST_ELMT( rdn_seq, seq )
+	{
+		rc = ConvertRelativeDistinguishedName2RFC2253( rdn_seq, out, &pos );
+		if ( rc != LDAP_SUCCESS ) return LDAP_INVALID_SYNTAX;
+
+		if ( out->bv_len < pos + 1/*for ','*/ )
+			increment_bv_mem ( out );
+		/*Between RDN, put comma*/
+		out->bv_val[pos++] = ',';
+	}
+	pos--;/*remove the last '+'*/
+	out->bv_val[pos] = '\0';
+	out->bv_len = pos;
+	return LDAP_SUCCESS;
+}
+
 #endif
diff --git a/contrib/slapd-modules/comp_match/init.c b/contrib/slapd-modules/comp_match/init.c
index 0858efb75a..16c2b817db 100644
--- a/contrib/slapd-modules/comp_match/init.c
+++ b/contrib/slapd-modules/comp_match/init.c
@@ -133,13 +133,11 @@ comp_convert_attr_to_comp LDAP_P (( Attribute* a, Syntax *syn, struct berval* bv
 		if ( size <= 0 ) return (void*)NULL;
 	}
 
-        ExpBufInit( 2048 );
-        buf = ExpBufAllocBufAndData();
-        ExpBufResetInWriteRvsMode( buf );
-        ExpBuftoGenBuf( buf, &b );
-        BufPutSegRvs( b, bv->bv_val, bv->bv_len );
-        BufResetInReadMode( b );
-	
+	buf = ExpBufAllocBuf();
+	ExpBuftoGenBuf( buf, &b );
+	ExpBufInstallDataInBuf ( buf, bv->bv_val, bv->bv_len );
+	BufResetInReadMode( b );
+
 	mode = DEC_ALLOC_MODE_2;
 	/*
 	 * How can we decide which decoder will be called, GSER or BER?
@@ -153,13 +151,15 @@ comp_convert_attr_to_comp LDAP_P (( Attribute* a, Syntax *syn, struct berval* bv
 		rc = od_entry->oe_gser_decoder( a->a_comp_data->cd_mem_op, b, component,&bytesDecoded,mode);
 	}
 
+	ExpBufFreeBuf( buf );
 	if ( rc == -1 ) {
 		ShutdownNibbleMemLocal ( a->a_comp_data->cd_mem_op );
 		a->a_comp_data->cd_mem_op = NULL;
 		return (void*)NULL;
 	}
-	else
+	else {
 		return component;
+	}
 }
 
 #include <nibble-alloc.h>
@@ -176,21 +176,22 @@ comp_convert_assert_to_comp (
 	struct berval* bv,
 	ComponentSyntaxInfo** csi, int* len, int mode )
 {
+	int rc;
 	GenBuf* genBuf;
 	ExpBuf* buf;
 	gser_decoder_func *decoder = csi_attr->csi_comp_desc->cd_gser_decoder;
 
-	ExpBufInit( 2048 );
-	buf = ExpBufAllocBufAndData();
-	ExpBufResetInWriteRvsMode( buf );
+	buf = ExpBufAllocBuf();
 	ExpBuftoGenBuf( buf, &genBuf );
-	BufPutSegRvs( genBuf, bv->bv_val, bv->bv_len );
+	ExpBufInstallDataInBuf ( buf, bv->bv_val, bv->bv_len );
 	BufResetInReadMode( genBuf );
 
 	if ( csi_attr->csi_comp_desc->cd_type_id == BASICTYPE_ANY )
 		decoder = ((ComponentAny*)csi_attr)->cai->GSER_Decode;
 
-	return (*decoder)( mem_op, genBuf, csi, len, mode );
+	rc = (*decoder)( mem_op, genBuf, csi, len, mode );
+	ExpBufFreeBuf ( buf );
+	return rc;
 }
 
 int intToAscii( int value, char* buf ) {
@@ -222,10 +223,11 @@ int intToAscii( int value, char* buf ) {
 }
 
 int
-comp_convert_asn_to_ldap LDAP_P(( ComponentSyntaxInfo* csi, struct berval* bv ))
+comp_convert_asn_to_ldap ( MatchingRule* mr, ComponentSyntaxInfo* csi, struct berval* bv, int *allocated )
 {
-	int value;
+	int value, rc;
 	Syntax* syn;
+
 	AsnTypetoSyntax* asn_to_syn =
 		&asn_to_syntax_mapping_tbl[csi->csi_comp_desc->cd_type_id];
 	if ( asn_to_syn->ats_syn_oid )
@@ -233,8 +235,12 @@ comp_convert_asn_to_ldap LDAP_P(( ComponentSyntaxInfo* csi, struct berval* bv ))
 	else 
 		csi->csi_syntax = NULL;
 
+
         switch ( csi->csi_comp_desc->cd_type_id ) {
           case BASICTYPE_BOOLEAN :
+		bv->bv_val = (char*)malloc( 5 );
+		*allocated = 1;
+		bv->bv_len = 5;
 		if ( ((ComponentBool*)csi)->value > 0 ) {
 			strcpy ( bv->bv_val , "TRUE" );
 			bv->bv_len = 4;
@@ -245,20 +251,25 @@ comp_convert_asn_to_ldap LDAP_P(( ComponentSyntaxInfo* csi, struct berval* bv ))
 		}
                 break ;
           case BASICTYPE_NULL :
-                bv->bv_val = (char *) &((ComponentNull*)csi)->value;
-                bv->bv_len = sizeof(char);
+                bv->bv_len = 0;
                 break;
           case BASICTYPE_INTEGER :
+		bv->bv_val = (char*)malloc( INITIAL_ATTR_SIZE );
+		*allocated = 1;
+		bv->bv_len = INITIAL_ATTR_SIZE;
 		bv->bv_len = intToAscii(((ComponentInt*)csi)->value, bv->bv_val );
-		if ( bv->bv_len <= 0 ) return LDAP_INVALID_SYNTAX;
+		if ( bv->bv_len <= 0 )
+			return LDAP_INVALID_SYNTAX;
                 break;
           case BASICTYPE_REAL :
-                bv->bv_val = (char *) &((ComponentReal*)csi)->value;
-                bv->bv_len = sizeof(double);
-                break;
+		return LDAP_INVALID_SYNTAX;
           case BASICTYPE_ENUMERATED :
-                bv->bv_val = (char *) &((ComponentEnum*)csi)->value;
-                bv->bv_len = sizeof(int);
+		bv->bv_val = (char*)malloc( INITIAL_ATTR_SIZE );
+		*allocated = 1;
+		bv->bv_len = INITIAL_ATTR_SIZE;
+		bv->bv_len = intToAscii(((ComponentEnum*)csi)->value, bv->bv_val );
+		if ( bv->bv_len <= 0 )
+			return LDAP_INVALID_SYNTAX;
                 break;
           case BASICTYPE_OID :
           case BASICTYPE_OCTETSTRING :
@@ -280,25 +291,35 @@ comp_convert_asn_to_ldap LDAP_P(( ComponentSyntaxInfo* csi, struct berval* bv ))
           case BASICTYPE_OCTETCONTAINING :
           case BASICTYPE_BITCONTAINING :
           case BASICTYPE_RELATIVE_OID :
-                bv->bv_val = ((ComponentOcts*)csi)->value.octs;
-                bv->bv_len = ((ComponentOcts*)csi)->value.octetLen;
+		bv->bv_val = ((ComponentOcts*)csi)->value.octs;
+		bv->bv_len = ((ComponentOcts*)csi)->value.octetLen;
                 break;
 	  case BASICTYPE_ANY :
 		csi = ((ComponentAny*)csi)->value;
 		if ( csi->csi_comp_desc->cd_type != ASN_BASIC ||
 			csi->csi_comp_desc->cd_type_id == BASICTYPE_ANY )
 			return LDAP_INVALID_SYNTAX;
-		return comp_convert_asn_to_ldap( csi, bv );
+		return comp_convert_asn_to_ldap( mr, csi, bv, allocated );
           case COMPOSITE_ASN1_TYPE :
           case RDNSequence :
+		/*dnMatch*/
+		if( strncmp( mr->smr_mrule.mr_oid, DN_MATCH_OID, strlen(DN_MATCH_OID) ) != 0 )
+			return LDAP_INVALID_SYNTAX;
+		*allocated = 1;
+		rc = ConvertRDNSequence2RFC2253( (irRDNSequence*)csi, bv );
+		return rc;
           case RelativeDistinguishedName :
+		/*rdnMatch*/
+		if( strncmp( mr->smr_mrule.mr_oid, RDN_MATCH_OID, strlen(RDN_MATCH_OID) ) != 0 )
+			return LDAP_INVALID_SYNTAX;
+		*allocated = 1;
+		rc = ConvertRDN2RFC2253((irRelativeDistinguishedName*)csi,bv);
+		return rc;
           case TelephoneNumber :
           case FacsimileTelephoneNumber__telephoneNumber :
 		break;
           case DirectoryString :
-                bv->bv_val = ((ComponentOcts*)csi)->value.octs;
-                bv->bv_len = ((ComponentOcts*)csi)->value.octetLen;
-                break;
+		return LDAP_INVALID_SYNTAX;
           case ASN_COMP_CERTIFICATE :
           case ASNTYPE_END :
 		break;
@@ -526,7 +547,7 @@ comp_test_one_component (
 	ComponentSyntaxInfo *csi_attr,
 	ComponentAssertion *ca )
 {
-	int len;
+	int len, rc;
 	ComponentSyntaxInfo *csi_assert = NULL;
 	char* oid = NULL;
 	MatchingRule* mr = ca->ca_ma_rule;
@@ -553,29 +574,30 @@ comp_test_one_component (
 
 	} else {
 		/* LDAP existing matching rules */
-		struct berval attr_bv;
+		struct berval attr_bv = BER_BVNULL;
 		struct berval* assert_bv = &ca->ca_ma_value;
-		char attr_buf[MAX_LDAP_STR_LEN];
-		if ( csi_attr->csi_comp_desc->cd_type == ASN_BASIC ) {
-			/*Attribute component is converted to compatible LDAP encodings*/
-			attr_bv.bv_val = attr_buf;
-			if ( comp_convert_asn_to_ldap( csi_attr, &attr_bv ) != LDAP_SUCCESS )
-				return LDAP_INAPPROPRIATE_MATCHING;
-
-			/*Assertion value is validated by MR's syntax*/
+		int allocated = 0;
+		/*Attribute is converted to compatible LDAP encodings*/
+		if ( comp_convert_asn_to_ldap( mr, csi_attr, &attr_bv, &allocated ) != LDAP_SUCCESS )
+			return LDAP_INAPPROPRIATE_MATCHING;
+
+		/*Assertion value is validated by MR's syntax*/
+		if ( !ca->ca_comp_data.cd_tree ) {
 			if ( get_primitive_GSER_value( assert_bv ) != LDAP_SUCCESS ) 
 				return LDAP_INVALID_SYNTAX;
-
+			assert_bv->bv_val[assert_bv->bv_len] = '\0';
 			if ( mr->smr_syntax->ssyn_validate( mr->smr_syntax, assert_bv ) != LDAP_SUCCESS ) {
 				return LDAP_INVALID_SYNTAX;
 			}
-
-			return csi_value_match( mr, &attr_bv, assert_bv );
-                                                                               
-		} else if ( csi_attr->csi_comp_desc->cd_type == ASN_COMPOSITE ) {
-                        return LDAP_INAPPROPRIATE_MATCHING;
+			ca->ca_comp_data.cd_tree = assert_bv;
+		}
+		else {
+			assert_bv = ca->ca_comp_data.cd_tree;
 		}
 
+		rc = csi_value_match( mr, &attr_bv, assert_bv );
+		if ( allocated ) free (attr_bv.bv_val);
+		return rc;
 	}
 }
 
@@ -612,7 +634,6 @@ int init_module(int argc, char *argv[]) {
 	 */
 	attr_converter = comp_convert_attr_to_comp;
 	assert_converter = comp_convert_assert_to_comp;
-	csi_converter = comp_convert_asn_to_ldap;
 	component_destructor = comp_free_component;
 	test_one_component = comp_test_one_component;
 	test_all_components = comp_test_all_components;
diff --git a/servers/slapd/component.c b/servers/slapd/component.c
index 8060adb285..9b76edfa1b 100644
--- a/servers/slapd/component.c
+++ b/servers/slapd/component.c
@@ -36,7 +36,6 @@ alloc_nibble_func* nibble_mem_allocator = NULL;
 free_nibble_func* nibble_mem_free = NULL;
 convert_attr_to_comp_func* attr_converter = NULL ;
 convert_assert_to_comp_func* assert_converter = NULL ;
-convert_asn_to_ldap_func* csi_converter = NULL ;
 free_component_func* component_destructor = NULL ;
 test_component_func* test_one_component = NULL;
 test_component_func* test_all_components = NULL;
@@ -872,44 +871,6 @@ csi_value_match( MatchingRule *mr, struct berval* bv_attr,
 		return rc;
 }
 
-int
-component_value_match( MatchingRule* mr,
-	ComponentSyntaxInfo* csi_attr, ComponentSyntaxInfo* csi_assert )
-{
-	if ( mr->smr_usage & SLAP_MR_COMPONENT ){
-		if ( strcmp( mr->smr_mrule.mr_oid, OID_ALL_COMP_MATCH ) == 0 )
-		{
-			/* allComponentMatch */
-			return csi_attr->csi_comp_desc->cd_all_match( NULL,
-						csi_attr, csi_assert );
-		} else {
-			return csi_assert->csi_comp_desc->cd_all_match(
-				mr->smr_mrule.mr_oid, csi_attr, csi_assert );
-		}
-
-	} else {
-		if ( csi_attr->csi_comp_desc->cd_type == ASN_BASIC ) {
-			struct berval bv1, bv2;
-			char attr_buf[MAX_LDAP_STR_LEN],assert_buf[MAX_LDAP_STR_LEN];
-			bv1.bv_val = attr_buf;
-			bv2.bv_val = assert_buf;
-			if ( csi_converter &&
-				( csi_converter ( csi_attr, &bv1 ) == LDAP_SUCCESS ) &&
-				( csi_converter ( csi_assert, &bv2 ) == LDAP_SUCCESS ) )
-			{
-				return csi_value_match( mr, &bv1, &bv2 );
-
-			} else {
-				return LDAP_INAPPROPRIATE_MATCHING;
-			}
-
-		} else if ( csi_attr->csi_comp_desc->cd_type == ASN_COMPOSITE )
-		{
-			return LDAP_INAPPROPRIATE_MATCHING;
-		}
-	}
-}
-
 /*
  * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
  */
@@ -955,8 +916,15 @@ test_comp_filter_item(
 		return LDAP_PROTOCOL_ERROR;
 
 	/* Memory for storing component assertion values */
-	assert_nm = nibble_mem_allocator ( 256, 64 );
-	if ( !assert_nm ) return LDAP_PROTOCOL_ERROR;
+	if( !ca->ca_comp_data.cd_mem_op ) {
+		assert_nm = nibble_mem_allocator ( 256, 64 );
+		if ( !assert_nm )
+			return LDAP_PROTOCOL_ERROR;
+		ca->ca_comp_data.cd_mem_op = assert_nm;
+	}
+	else {
+		assert_nm = ca->ca_comp_data.cd_mem_op;
+	}
 	/* perform matching */
 	if ( ca->ca_comp_ref->cr_curr->ci_type == LDAP_COMPREF_ALL ) {
 		/*
diff --git a/tests/data/compsearch.out b/tests/data/compsearch.out
index eac55a008a..c9594a60e3 100644
--- a/tests/data/compsearch.out
+++ b/tests/data/compsearch.out
@@ -32,6 +32,125 @@ userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
  dAWtMjWq2ZJIa26bbvB4enGOF66KH5S823ZdKa0Kr2JcHAAYFpf+TQoGg5JO7TD3AECd7Qo9a+4Xr
  EkBJ/Q=
 
+dn: cn=beta,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+objectClass: extensibleObject
+uid:: Y2hhcmxpZSA=
+cn: beta
+sn: Jee
+userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
+ QQGEwJVUzAeFw0wNDEwMTIwMDAxNTBaFw0wNDExMTEwMDAxNTBaMA0xCzAJBgNVBAYTAlVTMIGfMA
+ 0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQcTs4uD+gAoQ1XkYN4woLtZaEi7XVEVIJQ6Rsn2QP3MO
+ NBT9jvrhVcnUJQtvEEkfnsNANKeYntUTvih76jErFNTmg7zl0govFSkiuS+tfrZnn/Ebix3+tTMnA
+ KUQXkYi5Mr+x3U44yYo1EPLpZlcV1Caafc30EMRQ/Gv/PdrqYwIDAQABo2YwZDAdBgNVHQ4EFgQUA
+ zNnruNiI38IPf39ZJGFx8mDsxgwNQYDVR0jBC4wLIAUAzNnruNiI38IPf39ZJGFx8mDsxihEaQPMA
+ 0xCzAJBgNVBAYTAlVTggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAf44laoKcTyS
+ uz3yQb/lfOBVDh6oMxysal0eEij+nypQJ1H+rsZ+ebUlKMiTYhrTk3n3H6moHaxICENIu4P5rD5Ue
+ dAWtMjWq2ZJIa26bbvB4enGOF66KH5S823ZdKa0Kr2JcHAAYFpf+TQoGg5JO7TD3AECd7Qo9a+4Xr
+ EkBJ/Q=
+
+dn: cn=charlie,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+objectClass: extensibleObject
+uid:: Y2hhcmxpZSA=
+cn: charlie
+sn: Jee
+userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
+ QQGEwJVUzAeFw0wNDEwMTIwMDAxNTBaFw0wNDExMTEwMDAxNTBaMA0xCzAJBgNVBAYTAlVTMIGfMA
+ 0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQcTs4uD+gAoQ1XkYN4woLtZaEi7XVEVIJQ6Rsn2QP3MO
+ NBT9jvrhVcnUJQtvEEkfnsNANKeYntUTvih76jErFNTmg7zl0govFSkiuS+tfrZnn/Ebix3+tTMnA
+ KUQXkYi5Mr+x3U44yYo1EPLpZlcV1Caafc30EMRQ/Gv/PdrqYwIDAQABo2YwZDAdBgNVHQ4EFgQUA
+ zNnruNiI38IPf39ZJGFx8mDsxgwNQYDVR0jBC4wLIAUAzNnruNiI38IPf39ZJGFx8mDsxihEaQPMA
+ 0xCzAJBgNVBAYTAlVTggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAf44laoKcTyS
+ uz3yQb/lfOBVDh6oMxysal0eEij+nypQJ1H+rsZ+ebUlKMiTYhrTk3n3H6moHaxICENIu4P5rD5Ue
+ dAWtMjWq2ZJIa26bbvB4enGOF66KH5S823ZdKa0Kr2JcHAAYFpf+TQoGg5JO7TD3AECd7Qo9a+4Xr
+ EkBJ/Q=
+
+dn: cn=beta,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+objectClass: extensibleObject
+uid:: Y2hhcmxpZSA=
+cn: beta
+sn: Jee
+userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
+ QQGEwJVUzAeFw0wNDEwMTIwMDAxNTBaFw0wNDExMTEwMDAxNTBaMA0xCzAJBgNVBAYTAlVTMIGfMA
+ 0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQcTs4uD+gAoQ1XkYN4woLtZaEi7XVEVIJQ6Rsn2QP3MO
+ NBT9jvrhVcnUJQtvEEkfnsNANKeYntUTvih76jErFNTmg7zl0govFSkiuS+tfrZnn/Ebix3+tTMnA
+ KUQXkYi5Mr+x3U44yYo1EPLpZlcV1Caafc30EMRQ/Gv/PdrqYwIDAQABo2YwZDAdBgNVHQ4EFgQUA
+ zNnruNiI38IPf39ZJGFx8mDsxgwNQYDVR0jBC4wLIAUAzNnruNiI38IPf39ZJGFx8mDsxihEaQPMA
+ 0xCzAJBgNVBAYTAlVTggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAf44laoKcTyS
+ uz3yQb/lfOBVDh6oMxysal0eEij+nypQJ1H+rsZ+ebUlKMiTYhrTk3n3H6moHaxICENIu4P5rD5Ue
+ dAWtMjWq2ZJIa26bbvB4enGOF66KH5S823ZdKa0Kr2JcHAAYFpf+TQoGg5JO7TD3AECd7Qo9a+4Xr
+ EkBJ/Q=
+
+dn: cn=charlie,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+objectClass: extensibleObject
+uid:: Y2hhcmxpZSA=
+cn: charlie
+sn: Jee
+userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
+ QQGEwJVUzAeFw0wNDEwMTIwMDAxNTBaFw0wNDExMTEwMDAxNTBaMA0xCzAJBgNVBAYTAlVTMIGfMA
+ 0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQcTs4uD+gAoQ1XkYN4woLtZaEi7XVEVIJQ6Rsn2QP3MO
+ NBT9jvrhVcnUJQtvEEkfnsNANKeYntUTvih76jErFNTmg7zl0govFSkiuS+tfrZnn/Ebix3+tTMnA
+ KUQXkYi5Mr+x3U44yYo1EPLpZlcV1Caafc30EMRQ/Gv/PdrqYwIDAQABo2YwZDAdBgNVHQ4EFgQUA
+ zNnruNiI38IPf39ZJGFx8mDsxgwNQYDVR0jBC4wLIAUAzNnruNiI38IPf39ZJGFx8mDsxihEaQPMA
+ 0xCzAJBgNVBAYTAlVTggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAf44laoKcTyS
+ uz3yQb/lfOBVDh6oMxysal0eEij+nypQJ1H+rsZ+ebUlKMiTYhrTk3n3H6moHaxICENIu4P5rD5Ue
+ dAWtMjWq2ZJIa26bbvB4enGOF66KH5S823ZdKa0Kr2JcHAAYFpf+TQoGg5JO7TD3AECd7Qo9a+4Xr
+ EkBJ/Q=
+
+dn: cn=beta,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+objectClass: extensibleObject
+uid:: Y2hhcmxpZSA=
+cn: beta
+sn: Jee
+userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
+ QQGEwJVUzAeFw0wNDEwMTIwMDAxNTBaFw0wNDExMTEwMDAxNTBaMA0xCzAJBgNVBAYTAlVTMIGfMA
+ 0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQcTs4uD+gAoQ1XkYN4woLtZaEi7XVEVIJQ6Rsn2QP3MO
+ NBT9jvrhVcnUJQtvEEkfnsNANKeYntUTvih76jErFNTmg7zl0govFSkiuS+tfrZnn/Ebix3+tTMnA
+ KUQXkYi5Mr+x3U44yYo1EPLpZlcV1Caafc30EMRQ/Gv/PdrqYwIDAQABo2YwZDAdBgNVHQ4EFgQUA
+ zNnruNiI38IPf39ZJGFx8mDsxgwNQYDVR0jBC4wLIAUAzNnruNiI38IPf39ZJGFx8mDsxihEaQPMA
+ 0xCzAJBgNVBAYTAlVTggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAf44laoKcTyS
+ uz3yQb/lfOBVDh6oMxysal0eEij+nypQJ1H+rsZ+ebUlKMiTYhrTk3n3H6moHaxICENIu4P5rD5Ue
+ dAWtMjWq2ZJIa26bbvB4enGOF66KH5S823ZdKa0Kr2JcHAAYFpf+TQoGg5JO7TD3AECd7Qo9a+4Xr
+ EkBJ/Q=
+
+dn: cn=charlie,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+objectClass: extensibleObject
+uid:: Y2hhcmxpZSA=
+cn: charlie
+sn: Jee
+userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
+ QQGEwJVUzAeFw0wNDEwMTIwMDAxNTBaFw0wNDExMTEwMDAxNTBaMA0xCzAJBgNVBAYTAlVTMIGfMA
+ 0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQcTs4uD+gAoQ1XkYN4woLtZaEi7XVEVIJQ6Rsn2QP3MO
+ NBT9jvrhVcnUJQtvEEkfnsNANKeYntUTvih76jErFNTmg7zl0govFSkiuS+tfrZnn/Ebix3+tTMnA
+ KUQXkYi5Mr+x3U44yYo1EPLpZlcV1Caafc30EMRQ/Gv/PdrqYwIDAQABo2YwZDAdBgNVHQ4EFgQUA
+ zNnruNiI38IPf39ZJGFx8mDsxgwNQYDVR0jBC4wLIAUAzNnruNiI38IPf39ZJGFx8mDsxihEaQPMA
+ 0xCzAJBgNVBAYTAlVTggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAf44laoKcTyS
+ uz3yQb/lfOBVDh6oMxysal0eEij+nypQJ1H+rsZ+ebUlKMiTYhrTk3n3H6moHaxICENIu4P5rD5Ue
+ dAWtMjWq2ZJIa26bbvB4enGOF66KH5S823ZdKa0Kr2JcHAAYFpf+TQoGg5JO7TD3AECd7Qo9a+4Xr
+ EkBJ/Q=
+
+dn: cn=beta,ou=Alumni Association,ou=People,dc=example,dc=com
+objectClass: OpenLDAPperson
+objectClass: extensibleObject
+uid:: Y2hhcmxpZSA=
+cn: beta
+sn: Jee
+userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
+ QQGEwJVUzAeFw0wNDEwMTIwMDAxNTBaFw0wNDExMTEwMDAxNTBaMA0xCzAJBgNVBAYTAlVTMIGfMA
+ 0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQcTs4uD+gAoQ1XkYN4woLtZaEi7XVEVIJQ6Rsn2QP3MO
+ NBT9jvrhVcnUJQtvEEkfnsNANKeYntUTvih76jErFNTmg7zl0govFSkiuS+tfrZnn/Ebix3+tTMnA
+ KUQXkYi5Mr+x3U44yYo1EPLpZlcV1Caafc30EMRQ/Gv/PdrqYwIDAQABo2YwZDAdBgNVHQ4EFgQUA
+ zNnruNiI38IPf39ZJGFx8mDsxgwNQYDVR0jBC4wLIAUAzNnruNiI38IPf39ZJGFx8mDsxihEaQPMA
+ 0xCzAJBgNVBAYTAlVTggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAf44laoKcTyS
+ uz3yQb/lfOBVDh6oMxysal0eEij+nypQJ1H+rsZ+ebUlKMiTYhrTk3n3H6moHaxICENIu4P5rD5Ue
+ dAWtMjWq2ZJIa26bbvB4enGOF66KH5S823ZdKa0Kr2JcHAAYFpf+TQoGg5JO7TD3AECd7Qo9a+4Xr
+ EkBJ/Q=
+
 dn: cn=charlie,ou=Alumni Association,ou=People,dc=example,dc=com
 objectClass: OpenLDAPperson
 objectClass: extensibleObject
diff --git a/tests/scripts/test031-component-filter b/tests/scripts/test031-component-filter
index ed9147515f..97afbd67eb 100755
--- a/tests/scripts/test031-component-filter
+++ b/tests/scripts/test031-component-filter
@@ -82,7 +82,7 @@ cat /dev/null > $SEARCHOUT
 echo "Testing Component Filter Match RFC3687 Certificate searching:"
 echo "# Testing Component Filter Match RFC3687 Certificate searching:" >> $SEARCHOUT
 
-FILTER="(usertCertificate:componentFilterMatch:=item:{ component \"tbsCertificate.serialNumber\", rule allComponentsMatch, value 0 })"
+FILTER="(userCertificate:componentFilterMatch:=item:{ component \"tbsCertificate.serialNumber\", rule allComponentsMatch, value 0 })"
 echo "        f=$FILTER ..."
 echo "#         f=$FILTER ..." >> $SEARCHOUT
 $LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
@@ -186,6 +186,32 @@ if test $RC != 0 ; then
 	exit $RC
 fi
 
+FILTER="(userCertificate:componentFilterMatch:=item:{ component \"tbsCertificate.issuer.rdnSequence\", rule distinguishedNameMatch, value \"c=US\" })"
+echo "        f=$FILTER ..."
+echo "#         f=$FILTER ..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
+	"$FILTER" >> $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+	echo "ldapsearch failed ($RC)!"
+	test $KILLSERVERS != no && kill -HUP $KILLPIDS
+	exit $RC
+fi
+
+FILTER="(userCertificate:componentFilterMatch:=item:{ component \"tbsCertificate.issuer.rdnSequence.1\", rule rdnMatch, value \"c=US\" })"
+echo "        f=$FILTER ..."
+echo "#         f=$FILTER ..." >> $SEARCHOUT
+$LDAPSEARCH -S "" -b "$BASEDN" -h $LOCALHOST -p $PORT1 \
+	"$FILTER" >> $SEARCHOUT 2>&1
+
+RC=$?
+if test $RC != 0 ; then
+	echo "ldapsearch failed ($RC)!"
+	test $KILLSERVERS != no && kill -HUP $KILLPIDS
+	exit $RC
+fi
+
 
 
 test $KILLSERVERS != no && kill -HUP $KILLPIDS
-- 
GitLab