Home | History | Annotate | Line # | Download | only in comp_match
      1 /*	$NetBSD: init.c,v 1.2 2021/08/14 16:14:51 christos Exp $	*/
      2 
      3 /* Copyright 2004 IBM Corporation
      4  * All rights reserved.
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted only as authorized by the OpenLDAP
      7  * Public License.
      8  */
      9 /* ACKNOWLEDGEMENTS
     10  * This work originally developed by Sang Seok Lim
     11  * 2004/06/18	03:20:00	slim (at) OpenLDAP.org
     12  */
     13 
     14 #include <sys/cdefs.h>
     15 __RCSID("$NetBSD: init.c,v 1.2 2021/08/14 16:14:51 christos Exp $");
     16 
     17 #include "portable.h"
     18 #include <ac/string.h>
     19 #include <ac/socket.h>
     20 #include <ldap_pvt.h>
     21 #include "lutil.h"
     22 #include <ldap.h>
     23 #include "slap.h"
     24 #include "component.h"
     25 
     26 #include "componentlib.h"
     27 #include "asn.h"
     28 #include <asn-gser.h>
     29 
     30 #include <string.h>
     31 
     32 #ifndef SLAPD_COMP_MATCH
     33 #define SLAPD_COMP_MATCH SLAPD_MOD_DYNAMIC
     34 #endif
     35 
     36 /*
     37  * Attribute and MatchingRule aliasing table
     38  */
     39 AttributeAliasing aa_table [ MAX_ALIASING_ENTRY ];
     40 MatchingRuleAliasing mra_table [ MAX_ALIASING_ENTRY ];
     41 
     42 OD_entry* gOD_table = NULL;
     43 AsnTypetoMatchingRuleTable* gATMR_table = NULL;
     44 
     45 int
     46 load_derived_matching_rule ( char* cfg_path ){
     47 }
     48 
     49 AttributeAliasing*
     50 comp_is_aliased_attribute( void *in  )
     51 {
     52 	AttributeAliasing* curr_aa;
     53 	int i;
     54 	AttributeDescription *ad = (AttributeDescription*)in;
     55 
     56 	for ( i = 0; aa_table[i].aa_aliasing_ad && i < MAX_ALIASING_ENTRY; i++ ) {
     57 		if ( strncmp(aa_table[i].aa_aliasing_ad->ad_cname.bv_val , ad->ad_cname.bv_val, ad->ad_cname.bv_len) == 0 )
     58 			return &aa_table[i];
     59 	}
     60 	return NULL;
     61 }
     62 
     63 static int
     64 add_aa_entry( int index, char* aliasing_at_name, char* aliased_at_name, char* mr_name, char* component_filter )
     65 {
     66 	char text[1][128];
     67 	int rc;
     68 	struct berval type;
     69 
     70 	/* get and store aliasing AttributeDescription */
     71 	type.bv_val = aliasing_at_name;
     72 	type.bv_len = strlen ( aliasing_at_name );
     73 	rc = slap_bv2ad ( &type, &aa_table[index].aa_aliasing_ad,(const char**)text );
     74 	if ( rc != LDAP_SUCCESS ) return rc;
     75 
     76 	/* get and store aliased AttributeDescription */
     77 	type.bv_val = aliased_at_name;
     78 	type.bv_len = strlen ( aliased_at_name );
     79 	rc = slap_bv2ad ( &type, &aa_table[index].aa_aliased_ad,(const char**)text );
     80 	if ( rc != LDAP_SUCCESS ) return rc;
     81 
     82 	/* get and store componentFilterMatch */
     83 	type.bv_val = mr_name;
     84 	type.bv_len = strlen ( mr_name);
     85 	aa_table[index].aa_mr = mr_bvfind ( &type );
     86 
     87 	/* get and store a component filter */
     88 	type.bv_val = component_filter;
     89 	type.bv_len = strlen ( component_filter );
     90 	rc = get_comp_filter( NULL, &type, &aa_table[index].aa_cf,(const char**)text);
     91 
     92 	aa_table[index].aa_cf_str = component_filter;
     93 
     94 	return rc;
     95 }
     96 
     97 /*
     98  * Initialize attribute aliasing table when this module is loaded
     99  * add_aa_entry ( index for the global table,
    100  *                name of the aliasing attribute,
    101  *                component filter with filling value parts "xxx"
    102  *              )
    103  * "xxx" will be replaced with effective values later.
    104  * See RFC3687 to understand the content of a component filter.
    105  */
    106 char* pre_processed_comp_filter[] = {
    107 /*1*/"item:{ component \"toBeSigned.issuer.rdnSequence\", rule distinguishedNameMatch, value xxx }",
    108 /*2*/"item:{ component \"toBeSigned.serialNumber\", rule integerMatch, value xxx }",
    109 /*3*/"and:{ item:{ component \"toBeSigned.serialNumber\", rule integerMatch, value xxx }, item:{ component \"toBeSigned.issuer.rdnSequence\", rule distinguishedNameMatch, value xxx } }"
    110 };
    111 
    112 static int
    113 init_attribute_aliasing_table ()
    114 {
    115 	int rc;
    116 	int index = 0 ;
    117 
    118 	rc = add_aa_entry ( index, "x509CertificateIssuer", "userCertificate","componentFilterMatch", pre_processed_comp_filter[index] );
    119 	if ( rc != LDAP_SUCCESS ) return LDAP_PARAM_ERROR;
    120 	index++;
    121 
    122 	rc = add_aa_entry ( index, "x509CertificateSerial","userCertificate", "componentFilterMatch", pre_processed_comp_filter[index] );
    123 	if ( rc != LDAP_SUCCESS ) return LDAP_PARAM_ERROR;
    124 	index++;
    125 
    126 	rc = add_aa_entry ( index, "x509CertificateSerialAndIssuer", "userCertificate", "componentFilterMatch", pre_processed_comp_filter[index] );
    127 	if ( rc != LDAP_SUCCESS ) return LDAP_PARAM_ERROR;
    128 	index++;
    129 
    130 	return LDAP_SUCCESS;
    131 }
    132 
    133 void
    134 init_component_description_table () {
    135 	AsnTypeId id;
    136 	struct berval mr;
    137 	AsnTypetoSyntax* asn_to_syn;
    138 	Syntax* syn;
    139 
    140 	for ( id = BASICTYPE_BOOLEAN; id != ASNTYPE_END ; id++ ) {
    141 		asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_subtypes = NULL;
    142 		asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_syntax =  NULL;
    143 
    144 		/* Equality Matching Rule */
    145 		if ( asntype_to_compMR_mapping_tbl[id].atc_equality ) {
    146 			mr.bv_val = asntype_to_compMR_mapping_tbl[id].atc_equality;
    147 			mr.bv_len = strlen(asntype_to_compMR_mapping_tbl[id].atc_equality);
    148 			asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_equality = mr_bvfind( &mr );
    149 		}
    150 		/* Approx Matching Rule */
    151 		if ( asntype_to_compMR_mapping_tbl[id].atc_approx ) {
    152 			mr.bv_val = asntype_to_compMR_mapping_tbl[id].atc_approx;
    153 			mr.bv_len = strlen(asntype_to_compMR_mapping_tbl[id].atc_approx);
    154 			asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_approx = mr_bvfind( &mr );
    155 		}
    156 
    157 		/* Ordering Matching Rule */
    158 		if ( asntype_to_compMR_mapping_tbl[id].atc_ordering ) {
    159 			mr.bv_val = asntype_to_compMR_mapping_tbl[id].atc_ordering;
    160 			mr.bv_len = strlen(asntype_to_compMR_mapping_tbl[id].atc_ordering);
    161 			asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_ordering= mr_bvfind( &mr );
    162 		}
    163 
    164 		/* Substr Matching Rule */
    165 		if ( asntype_to_compMR_mapping_tbl[id].atc_substr ) {
    166 			mr.bv_val = asntype_to_compMR_mapping_tbl[id].atc_substr;
    167 			mr.bv_len = strlen(asntype_to_compMR_mapping_tbl[id].atc_substr);
    168 			asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_substr = mr_bvfind( &mr );
    169 		}
    170 		/* Syntax */
    171 
    172 		asn_to_syn = &asn_to_syntax_mapping_tbl[ id ];
    173 		if ( asn_to_syn->ats_syn_oid )
    174 			syn = syn_find ( asn_to_syn->ats_syn_oid );
    175 		else
    176 			syn = NULL;
    177 		asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_syntax = syn;
    178 
    179 		/* Initialize Component Descriptions of primitive ASN.1 types */
    180 		asntype_to_compdesc_mapping_tbl[id].atcd_cd.cd_comp_type = (AttributeType*)&asntype_to_compType_mapping_tbl[id].ac_comp_type;
    181 	}
    182 }
    183 
    184 MatchingRule*
    185 retrieve_matching_rule( char* mr_oid, AsnTypeId type ) {
    186 	char* tmp;
    187 	struct berval mr_name = BER_BVNULL;
    188 	AsnTypetoMatchingRuleTable* atmr;
    189 
    190 	for ( atmr = gATMR_table ; atmr ; atmr = atmr->atmr_table_next ) {
    191 		if ( strcmp( atmr->atmr_oid, mr_oid ) == 0 ) {
    192 			tmp = atmr->atmr_table[type].atmr_mr_name;
    193 			if ( tmp ) {
    194 				mr_name.bv_val = tmp;
    195 				mr_name.bv_len = strlen( tmp );
    196 				return mr_bvfind ( &mr_name );
    197 			}
    198 		}
    199 	}
    200 	return (MatchingRule*)NULL;
    201 }
    202 
    203 void*
    204 comp_convert_attr_to_comp LDAP_P (( Attribute* a, Syntax *syn, struct berval* bv ))
    205 {
    206 	char* peek_head;
    207         int mode, bytesDecoded, size, rc;
    208         void* component;
    209 	char* oid = a->a_desc->ad_type->sat_atype.at_oid ;
    210         GenBuf* b = NULL;
    211         ExpBuf* buf = NULL;
    212 	OidDecoderMapping* odm;
    213 
    214 	/* look for the decoder registered for the given attribute */
    215 	odm = RetrieveOidDecoderMappingbyOid( oid, strlen(oid) );
    216 
    217 	if ( !odm || (!odm->BER_Decode && !odm->GSER_Decode) )
    218 		return (void*)NULL;
    219 
    220 	buf = ExpBufAllocBuf();
    221 	ExpBuftoGenBuf( buf, &b );
    222 	ExpBufInstallDataInBuf ( buf, bv->bv_val, bv->bv_len );
    223 	BufResetInReadMode( b );
    224 
    225 	mode = DEC_ALLOC_MODE_2;
    226 	/*
    227 	 * How can we decide which decoder will be called, GSER or BER?
    228 	 * Currently BER decoder is called for a certificate.
    229 	 * The flag of Attribute will say something about it in the future
    230 	 */
    231 	if ( syn && slap_syntax_is_ber ( syn ) ) {
    232 #if 0
    233 		rc =BDecComponentTop(odm->BER_Decode, a->a_comp_data->cd_mem_op, b, 0,0, &component,&bytesDecoded,mode ) ;
    234 #endif
    235 		rc = odm->BER_Decode ( a->a_comp_data->cd_mem_op, b, (ComponentSyntaxInfo*)&component, &bytesDecoded, mode );
    236 	}
    237 	else {
    238 		rc = odm->GSER_Decode( a->a_comp_data->cd_mem_op, b, (ComponentSyntaxInfo**)component, &bytesDecoded, mode);
    239 	}
    240 
    241 	ExpBufFreeBuf( buf );
    242 	GenBufFreeBuf( b );
    243 	if ( rc == -1 ) {
    244 #if 0
    245 		ShutdownNibbleMemLocal ( a->a_comp_data->cd_mem_op );
    246 		free ( a->a_comp_data );
    247 		a->a_comp_data = NULL;
    248 #endif
    249 		return (void*)NULL;
    250 	}
    251 	else {
    252 		return component;
    253 	}
    254 }
    255 
    256 #include <nibble-alloc.h>
    257 void
    258 comp_free_component ( void* mem_op ) {
    259 	ShutdownNibbleMemLocal( (NibbleMem*)mem_op );
    260 	return;
    261 }
    262 
    263 void
    264 comp_convert_assert_to_comp (
    265 	void* mem_op,
    266 	ComponentSyntaxInfo *csi_attr,
    267 	struct berval* bv,
    268 	ComponentSyntaxInfo** csi, int* len, int mode )
    269 {
    270 	int rc;
    271 	GenBuf* genBuf;
    272 	ExpBuf* buf;
    273 	gser_decoder_func *decoder = csi_attr->csi_comp_desc->cd_gser_decoder;
    274 
    275 	buf = ExpBufAllocBuf();
    276 	ExpBuftoGenBuf( buf, &genBuf );
    277 	ExpBufInstallDataInBuf ( buf, bv->bv_val, bv->bv_len );
    278 	BufResetInReadMode( genBuf );
    279 
    280 	if ( csi_attr->csi_comp_desc->cd_type_id == BASICTYPE_ANY )
    281 		decoder = ((ComponentAny*)csi_attr)->cai->GSER_Decode;
    282 
    283 	rc = (*decoder)( mem_op, genBuf, csi, len, mode );
    284 	ExpBufFreeBuf ( buf );
    285 	GenBufFreeBuf( genBuf );
    286 }
    287 
    288 int intToAscii( int value, char* buf ) {
    289 	int minus=0,i,temp;
    290 	int total_num_digits;
    291 
    292 	if ( value == 0 ){
    293 		buf[0] = '0';
    294 		return 1;
    295 	}
    296 
    297 	if ( value < 0 ){
    298 		minus = 1;
    299 		value = value*(-1);
    300 		buf[0] = '-';
    301 	}
    302 
    303 	/* How many digits */
    304 	for ( temp = value, total_num_digits=0 ; temp ; total_num_digits++ )
    305 		temp = temp/10;
    306 
    307 	total_num_digits += minus;
    308 
    309 	for ( i = minus ; value ; i++ ) {
    310 		buf[ total_num_digits - i - 1 ]= (char)(value%10 + '0');
    311 		value = value/10;
    312 	}
    313 	return i;
    314 }
    315 
    316 int
    317 comp_convert_asn_to_ldap ( MatchingRule* mr, ComponentSyntaxInfo* csi, struct berval* bv, int *allocated )
    318 {
    319 	int rc;
    320 	struct berval prettied;
    321 	Syntax* syn;
    322 
    323 	AsnTypetoSyntax* asn_to_syn =
    324 		&asn_to_syntax_mapping_tbl[csi->csi_comp_desc->cd_type_id];
    325 	if ( asn_to_syn->ats_syn_oid )
    326 		csi->csi_syntax = syn_find ( asn_to_syn->ats_syn_oid );
    327 	else
    328 		csi->csi_syntax = NULL;
    329 
    330 
    331         switch ( csi->csi_comp_desc->cd_type_id ) {
    332           case BASICTYPE_BOOLEAN :
    333 		bv->bv_val = (char*)malloc( 5 );
    334 		*allocated = 1;
    335 		bv->bv_len = 5;
    336 		if ( ((ComponentBool*)csi)->value > 0 ) {
    337 			strcpy ( bv->bv_val , "TRUE" );
    338 			bv->bv_len = 4;
    339 		}
    340 		else {
    341 			strcpy ( bv->bv_val , "FALSE" );
    342 			bv->bv_len = 5;
    343 		}
    344                 break ;
    345           case BASICTYPE_NULL :
    346                 bv->bv_len = 0;
    347                 break;
    348           case BASICTYPE_INTEGER :
    349 		bv->bv_val = (char*)malloc( INITIAL_ATTR_SIZE );
    350 		*allocated = 1;
    351 		bv->bv_len = INITIAL_ATTR_SIZE;
    352 		bv->bv_len = intToAscii(((ComponentInt*)csi)->value, bv->bv_val );
    353 		if ( bv->bv_len <= 0 )
    354 			return LDAP_INVALID_SYNTAX;
    355                 break;
    356           case BASICTYPE_REAL :
    357 		return LDAP_INVALID_SYNTAX;
    358           case BASICTYPE_ENUMERATED :
    359 		bv->bv_val = (char*)malloc( INITIAL_ATTR_SIZE );
    360 		*allocated = 1;
    361 		bv->bv_len = INITIAL_ATTR_SIZE;
    362 		bv->bv_len = intToAscii(((ComponentEnum*)csi)->value, bv->bv_val );
    363 		if ( bv->bv_len <= 0 )
    364 			return LDAP_INVALID_SYNTAX;
    365                 break;
    366           case BASICTYPE_OID :
    367           case BASICTYPE_OCTETSTRING :
    368           case BASICTYPE_BITSTRING :
    369           case BASICTYPE_NUMERIC_STR :
    370           case BASICTYPE_PRINTABLE_STR :
    371           case BASICTYPE_UNIVERSAL_STR :
    372           case BASICTYPE_IA5_STR :
    373           case BASICTYPE_BMP_STR :
    374           case BASICTYPE_UTF8_STR :
    375           case BASICTYPE_UTCTIME :
    376           case BASICTYPE_GENERALIZEDTIME :
    377           case BASICTYPE_GRAPHIC_STR :
    378           case BASICTYPE_VISIBLE_STR :
    379           case BASICTYPE_GENERAL_STR :
    380           case BASICTYPE_OBJECTDESCRIPTOR :
    381           case BASICTYPE_VIDEOTEX_STR :
    382           case BASICTYPE_T61_STR :
    383           case BASICTYPE_OCTETCONTAINING :
    384           case BASICTYPE_BITCONTAINING :
    385           case BASICTYPE_RELATIVE_OID :
    386 		bv->bv_val = ((ComponentOcts*)csi)->value.octs;
    387 		bv->bv_len = ((ComponentOcts*)csi)->value.octetLen;
    388                 break;
    389 	  case BASICTYPE_ANY :
    390 		csi = ((ComponentAny*)csi)->value;
    391 		if ( csi->csi_comp_desc->cd_type != ASN_BASIC ||
    392 			csi->csi_comp_desc->cd_type_id == BASICTYPE_ANY )
    393 			return LDAP_INVALID_SYNTAX;
    394 		return comp_convert_asn_to_ldap( mr, csi, bv, allocated );
    395           case COMPOSITE_ASN1_TYPE :
    396 		break;
    397           case RDNSequence :
    398 		/*dnMatch*/
    399 		if( strncmp( mr->smr_mrule.mr_oid, DN_MATCH_OID, strlen(DN_MATCH_OID) ) != 0 )
    400 			return LDAP_INVALID_SYNTAX;
    401 		*allocated = 1;
    402 		rc = ConvertRDNSequence2RFC2253( (irRDNSequence*)csi, bv );
    403 		if ( rc != LDAP_SUCCESS ) return rc;
    404 		break;
    405           case RelativeDistinguishedName :
    406 		/*rdnMatch*/
    407 		if( strncmp( mr->smr_mrule.mr_oid, RDN_MATCH_OID, strlen(RDN_MATCH_OID) ) != 0 )
    408 			return LDAP_INVALID_SYNTAX;
    409 		*allocated = 1;
    410 		rc = ConvertRDN2RFC2253((irRelativeDistinguishedName*)csi,bv);
    411 		if ( rc != LDAP_SUCCESS ) return rc;
    412 		break;
    413           case TelephoneNumber :
    414           case FacsimileTelephoneNumber__telephoneNumber :
    415 		break;
    416           case DirectoryString :
    417 		return LDAP_INVALID_SYNTAX;
    418           case ASN_COMP_CERTIFICATE :
    419           case ASNTYPE_END :
    420 		break;
    421           default :
    422                 /*Only ASN Basic Type can be converted into LDAP string*/
    423 		return LDAP_INVALID_SYNTAX;
    424         }
    425 
    426 	if ( csi->csi_syntax ) {
    427 		if ( csi->csi_syntax->ssyn_validate ) {
    428  			rc = csi->csi_syntax->ssyn_validate(csi->csi_syntax, bv);
    429 			if ( rc != LDAP_SUCCESS )
    430 				return LDAP_INVALID_SYNTAX;
    431 		}
    432 		if ( csi->csi_syntax->ssyn_pretty ) {
    433 			rc = csi->csi_syntax->ssyn_pretty(csi->csi_syntax, bv, &prettied , NULL );
    434 			if ( rc != LDAP_SUCCESS )
    435 				return LDAP_INVALID_SYNTAX;
    436 #if 0
    437 			free ( bv->bv_val );/*potential memory leak?*/
    438 #endif
    439 			bv->bv_val = prettied.bv_val;
    440 			bv->bv_len = prettied.bv_len;
    441 		}
    442 	}
    443 
    444 	return LDAP_SUCCESS;
    445 }
    446 
    447 /*
    448  * If <all> type component referenced is used
    449  * more than one component will be tested
    450  */
    451 #define IS_TERMINAL_COMPREF(cr) (cr->cr_curr->ci_next == NULL)
    452 int
    453 comp_test_all_components (
    454 	void* attr_mem_op,
    455 	void* assert_mem_op,
    456 	ComponentSyntaxInfo *csi_attr,
    457 	ComponentAssertion* ca )
    458 {
    459 	int rc;
    460 	ComponentSyntaxInfo *csi_temp = NULL, *csi_assert = NULL, *comp_elmt = NULL;
    461 	ComponentReference *cr = ca->ca_comp_ref;
    462 	struct berval *ca_val = &ca->ca_ma_value;
    463 
    464 	switch ( cr->cr_curr->ci_type ) {
    465 	    case LDAP_COMPREF_ALL:
    466 		if ( IS_TERMINAL_COMPREF(cr) ) {
    467 			FOR_EACH_LIST_ELMT( comp_elmt, &((ComponentList*)csi_attr)->comp_list )
    468 			{
    469 				rc = comp_test_one_component( attr_mem_op, assert_mem_op, comp_elmt, ca );
    470 				if ( rc == LDAP_COMPARE_TRUE ) {
    471 					break;
    472 				}
    473 			}
    474 		} else {
    475 			ComponentId *start_compid = ca->ca_comp_ref->cr_curr->ci_next;
    476 			FOR_EACH_LIST_ELMT( comp_elmt, &((ComponentList*)csi_attr)->comp_list )
    477 			{
    478 				cr->cr_curr = start_compid;
    479 				rc = comp_test_components ( attr_mem_op, assert_mem_op, comp_elmt, ca );
    480 				if ( rc != LDAP_COMPARE_FALSE ) {
    481 					break;
    482 				}
    483 #if 0
    484 				if ( rc == LDAP_COMPARE_TRUE ) {
    485 					break;
    486 				}
    487 #endif
    488 			}
    489 		}
    490 		break;
    491 	    case LDAP_COMPREF_CONTENT:
    492 	    case LDAP_COMPREF_SELECT:
    493 	    case LDAP_COMPREF_DEFINED:
    494 	    case LDAP_COMPREF_UNDEFINED:
    495 	    case LDAP_COMPREF_IDENTIFIER:
    496 	    case LDAP_COMPREF_FROM_BEGINNING:
    497 	    case LDAP_COMPREF_FROM_END:
    498 	    case LDAP_COMPREF_COUNT:
    499 		rc = LDAP_OPERATIONS_ERROR;
    500 		break;
    501 	    default:
    502 		rc = LDAP_OPERATIONS_ERROR;
    503 	}
    504 	return rc;
    505 }
    506 
    507 void
    508 eat_bv_whsp ( struct berval* in )
    509 {
    510 	char* end = in->bv_val + in->bv_len;
    511         for ( ; ( *in->bv_val == ' ' ) && ( in->bv_val < end ) ; ) {
    512                 in->bv_val++;
    513         }
    514 }
    515 
    516 /*
    517  * Perform matching one referenced component against assertion
    518  * If the matching rule in a component filter is allComponentsMatch
    519  * or its derivatives the extracted component's ASN.1 specification
    520  * is applied to the assertion value as its syntax
    521  * Otherwise, the matching rule's syntax is applied to the assertion value
    522  * By RFC 3687
    523  */
    524 int
    525 comp_test_one_component (
    526 	void* attr_mem_op,
    527 	void* assert_mem_op,
    528 	ComponentSyntaxInfo *csi_attr,
    529 	ComponentAssertion *ca )
    530 {
    531 	int len, rc;
    532 	ComponentSyntaxInfo *csi_assert = NULL;
    533 	char* oid = NULL;
    534 	MatchingRule* mr = ca->ca_ma_rule;
    535 
    536 	if ( mr->smr_usage & SLAP_MR_COMPONENT ) {
    537 		/* If allComponentsMatch or its derivatives */
    538 		if ( !ca->ca_comp_data.cd_tree ) {
    539 			comp_convert_assert_to_comp( assert_mem_op, csi_attr, &ca->ca_ma_value, &csi_assert, &len, DEC_ALLOC_MODE_0 );
    540 			ca->ca_comp_data.cd_tree = (void*)csi_assert;
    541 		} else {
    542 			csi_assert = ca->ca_comp_data.cd_tree;
    543 		}
    544 
    545 		if ( !csi_assert )
    546 			return LDAP_PROTOCOL_ERROR;
    547 
    548 		if ( strcmp( mr->smr_mrule.mr_oid, OID_ALL_COMP_MATCH ) != 0 )
    549                 {
    550                         /* allComponentMatch's derivatives */
    551 			oid =  mr->smr_mrule.mr_oid;
    552                 }
    553                         return csi_attr->csi_comp_desc->cd_all_match(
    554                                			 oid, csi_attr, csi_assert );
    555 
    556 	} else {
    557 		/* LDAP existing matching rules */
    558 		struct berval attr_bv = BER_BVNULL;
    559 		struct berval n_attr_bv = BER_BVNULL;
    560 		struct berval* assert_bv = &ca->ca_ma_value;
    561 		int allocated = 0;
    562 		/*Attribute is converted to compatible LDAP encodings*/
    563 		if ( comp_convert_asn_to_ldap( mr, csi_attr, &attr_bv, &allocated ) != LDAP_SUCCESS )
    564 			return LDAP_INAPPROPRIATE_MATCHING;
    565 		/* extracted component value is not normalized */
    566 		if ( ca->ca_ma_rule->smr_normalize ) {
    567 			rc = ca->ca_ma_rule->smr_normalize (
    568 				SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
    569 				NULL, ca->ca_ma_rule,
    570 				&attr_bv, &n_attr_bv, NULL );
    571 			if ( rc != LDAP_SUCCESS )
    572 				return rc;
    573 			if ( allocated && attr_bv.bv_val )
    574 				free (attr_bv.bv_val);
    575 		} else {
    576 			n_attr_bv = attr_bv;
    577 		}
    578 #if 0
    579 		/*Assertion value is validated by MR's syntax*/
    580 		if ( !ca->ca_comp_data.cd_tree ) {
    581 			ca->ca_comp_data.cd_tree = assert_bv;
    582 		}
    583 		else {
    584 			assert_bv = ca->ca_comp_data.cd_tree;
    585 		}
    586 #endif
    587 		if ( !n_attr_bv.bv_val )
    588 			return LDAP_COMPARE_FALSE;
    589 		rc = csi_value_match( mr, &n_attr_bv, assert_bv );
    590 		if ( n_attr_bv.bv_val )
    591 			free ( n_attr_bv.bv_val );
    592 		return rc;
    593 	}
    594 }
    595 
    596 int
    597 comp_test_components( void* attr_nm, void* assert_nm, ComponentSyntaxInfo* csi_attr, ComponentAssertion* ca) {
    598 	char* peek_head;
    599 	int mode, bytesDecoded = 0, rc;
    600 	GenBuf* b;
    601 	ExpBuf* buf;
    602 	OidDecoderMapping* odm;
    603 	struct berval bv;
    604 	char oid[MAX_OID_LEN];
    605 	void* contained_comp, *anytype_comp;
    606 	ComponentReference* cr = ca->ca_comp_ref;
    607 
    608 	if ( !cr )
    609 		return comp_test_one_component ( attr_nm, assert_nm, csi_attr, ca );
    610 	/* Extracting the component referenced by ca->ca_comp_ref */
    611 	csi_attr = (ComponentSyntaxInfo*)csi_attr->csi_comp_desc->cd_extract_i( attr_nm, cr, csi_attr );
    612 	if ( !csi_attr ) return LDAP_INVALID_SYNTAX;
    613 	/* perform matching, considering the type of a Component Reference(CR)*/
    614 	switch( cr->cr_curr->ci_type ) {
    615 	   case LDAP_COMPREF_IDENTIFIER:
    616 	   case LDAP_COMPREF_FROM_BEGINNING:
    617 	   case LDAP_COMPREF_FROM_END:
    618 	   case LDAP_COMPREF_COUNT:
    619 		/*
    620 		 * Exactly one component is referenced
    621 		 * Fast Path for matching for this case
    622 		 */
    623 		rc = comp_test_one_component ( attr_nm, assert_nm, csi_attr, ca );
    624 		break;
    625 	   case LDAP_COMPREF_ALL:
    626 		/*
    627 		 * If <all> type CR is used
    628 		 * more than one component will be tested
    629 		 */
    630 		rc = comp_test_all_components ( attr_nm, assert_nm, csi_attr, ca );
    631 		break;
    632 
    633 	   case LDAP_COMPREF_CONTENT:
    634 		/*
    635 		 * <content> type CR is used
    636 		 * check if it is followed by <select> type CR.
    637 		 * 1) If so, look up the corresponding decoder  in the mapping
    638 		 * table(OID to decoder) by <select>
    639 		 * and then decode the OCTET/BIT STRING with the decoder
    640 		 * Finally, extract the target component with the remaining CR.
    641 		 * 2) If not, just return the current component, It SHOULD not be
    642 		 * extracted further, because the component MUST be BIT/OCTET
    643                  * string.
    644                  */
    645 
    646 		cr->cr_curr = cr->cr_curr->ci_next;
    647 		if ( !cr->cr_curr ) {
    648 			/* case 2) in above description */
    649 			rc = comp_test_one_component ( attr_nm, assert_nm, csi_attr, ca );
    650 			break;
    651 		}
    652 
    653 		if ( cr->cr_curr->ci_type == LDAP_COMPREF_SELECT ) {
    654 			/* Look up OID mapping table */
    655 			odm = RetrieveOidDecoderMappingbyBV( &cr->cr_curr->ci_val.ci_select_value );
    656 
    657 			if ( !odm || !odm->BER_Decode )
    658 				return  LDAP_PROTOCOL_ERROR;
    659 
    660 			/* current component MUST be either BIT or OCTET STRING */
    661 			if ( csi_attr->csi_comp_desc->cd_type_id != BASICTYPE_BITSTRING ) {
    662 				bv.bv_val = ((ComponentBits*)csi_attr)->value.bits;
    663 				bv.bv_len = ((ComponentBits*)csi_attr)->value.bitLen;
    664 			}
    665 			else if ( csi_attr->csi_comp_desc->cd_type_id != BASICTYPE_BITSTRING ) {
    666 				bv.bv_val = ((ComponentOcts*)csi_attr)->value.octs;
    667 				bv.bv_len = ((ComponentOcts*)csi_attr)->value.octetLen;
    668 			}
    669 			else
    670 				return LDAP_PROTOCOL_ERROR;
    671 
    672 			buf = ExpBufAllocBuf();
    673 			ExpBuftoGenBuf( buf, &b );
    674 			ExpBufInstallDataInBuf ( buf, bv.bv_val, bv.bv_len );
    675 			BufResetInReadMode( b );
    676 			mode = DEC_ALLOC_MODE_2;
    677 
    678 			/* Try to decode with BER/DER decoder */
    679 			rc = odm->BER_Decode ( attr_nm, b, (ComponentSyntaxInfo*)&contained_comp, &bytesDecoded, mode );
    680 
    681 			ExpBufFreeBuf( buf );
    682 			GenBufFreeBuf( b );
    683 
    684 			if ( rc != LDAP_SUCCESS ) return LDAP_PROTOCOL_ERROR;
    685 
    686 			/* xxx.content.(x.xy.xyz).rfc822Name */
    687 			/* In the aboe Ex. move CR to the right to (x.xy.xyz)*/
    688 			cr->cr_curr = cr->cr_curr->ci_next;
    689 			if (!cr->cr_curr )
    690 				rc = comp_test_one_component ( attr_nm, assert_nm, csi_attr, ca );
    691 			else
    692 				rc = comp_test_components( attr_nm, assert_nm, contained_comp, ca );
    693 		}
    694 		else {
    695 			/* Invalid Component reference */
    696 			rc = LDAP_PROTOCOL_ERROR;
    697 		}
    698 		break;
    699 	   case LDAP_COMPREF_SELECT:
    700 		if (csi_attr->csi_comp_desc->cd_type_id != BASICTYPE_ANY )
    701 			return LDAP_INVALID_SYNTAX;
    702 		rc = CheckSelectTypeCorrect( attr_nm, ((ComponentAny*)csi_attr)->cai, &cr->cr_curr->ci_val.ci_select_value );
    703 		if ( rc < 0 ) return LDAP_INVALID_SYNTAX;
    704 
    705 		/* point to the real component, not any type component */
    706 		csi_attr = ((ComponentAny*)csi_attr)->value;
    707 		cr->cr_curr = cr->cr_curr->ci_next;
    708 		if ( cr->cr_curr )
    709 			rc =  comp_test_components( attr_nm, assert_nm, csi_attr, ca);
    710 		else
    711 			rc =  comp_test_one_component( attr_nm, assert_nm, csi_attr, ca);
    712 		break;
    713 	   default:
    714 		rc = LDAP_INVALID_SYNTAX;
    715 	}
    716 	return rc;
    717 }
    718 
    719 
    720 void*
    721 comp_nibble_memory_allocator ( int init_mem, int inc_mem ) {
    722 	void* nm;
    723 	nm = (void*)InitNibbleMemLocal( (unsigned long)init_mem, (unsigned long)inc_mem );
    724 	if ( !nm ) return NULL;
    725 	else return (void*)nm;
    726 }
    727 
    728 void
    729 comp_nibble_memory_free ( void* nm ) {
    730 	ShutdownNibbleMemLocal( nm );
    731 }
    732 
    733 void*
    734 comp_get_component_description ( int id ) {
    735 	if ( asntype_to_compdesc_mapping_tbl[id].atcd_typeId == id )
    736 		return &asntype_to_compdesc_mapping_tbl[id].atcd_cd;
    737 	else
    738 		return NULL;
    739 }
    740 
    741 int
    742 comp_component_encoder ( void* mem_op, ComponentSyntaxInfo* csi , struct berval* nval ) {
    743         int size, rc;
    744         GenBuf* b;
    745         ExpBuf* buf;
    746 	struct berval bv;
    747 
    748 	buf = ExpBufAllocBufAndData();
    749 	ExpBufResetInWriteRvsMode(buf);
    750 	ExpBuftoGenBuf( buf, &b );
    751 
    752 	if ( !csi->csi_comp_desc->cd_gser_encoder && !csi->csi_comp_desc->cd_ldap_encoder )
    753 		return (-1);
    754 
    755 	/*
    756 	 * if an LDAP specific encoder is provided :
    757 	 * dn and rdn have their LDAP specific encoder
    758 	 */
    759 	if ( csi->csi_comp_desc->cd_ldap_encoder ) {
    760 		rc = csi->csi_comp_desc->cd_ldap_encoder( csi, &bv );
    761 		if ( rc != LDAP_SUCCESS )
    762 			return rc;
    763 		if ( mem_op )
    764 			nval->bv_val = CompAlloc( mem_op, bv.bv_len );
    765 		else
    766 			nval->bv_val = malloc( size );
    767 		memcpy( nval->bv_val, bv.bv_val, bv.bv_len );
    768 		nval->bv_len = bv.bv_len;
    769 		/*
    770 		 * This free will be eliminated by making ldap_encoder
    771 		 * use nibble memory in it
    772 		 */
    773 		free ( bv.bv_val );
    774 		GenBufFreeBuf( b );
    775 		BufFreeBuf( buf );
    776 		return LDAP_SUCCESS;
    777 	}
    778 
    779 	rc = csi->csi_comp_desc->cd_gser_encoder( b, csi );
    780 	if ( rc < 0 ) {
    781 		GenBufFreeBuf( b );
    782 		BufFreeBuf( buf );
    783 		return rc;
    784 	}
    785 
    786 	size = ExpBufDataSize( buf );
    787 	if ( size > 0 ) {
    788 		if ( mem_op )
    789 			nval->bv_val = CompAlloc ( mem_op, size );
    790 		else
    791 			nval->bv_val = malloc( size );
    792 		nval->bv_len = size;
    793 		BufResetInReadMode(b);
    794 		BufCopy( nval->bv_val, b, size );
    795 	}
    796 	ExpBufFreeBuf( buf );
    797 	GenBufFreeBuf( b );
    798 
    799 	return LDAP_SUCCESS;
    800 }
    801 
    802 #if SLAPD_COMP_MATCH == SLAPD_MOD_DYNAMIC
    803 
    804 #include "certificate.h"
    805 
    806 extern convert_attr_to_comp_func* attr_converter;
    807 extern convert_assert_to_comp_func* assert_converter;
    808 extern convert_asn_to_ldap_func* csi_converter;
    809 extern free_component_func* component_destructor;
    810 extern test_component_func* test_components;
    811 extern alloc_nibble_func* nibble_mem_allocator;
    812 extern free_nibble_func* nibble_mem_free;
    813 extern test_membership_func* is_aliased_attribute;
    814 extern get_component_info_func* get_component_description;
    815 extern component_encoder_func* component_encoder;
    816 
    817 
    818 int init_module(int argc, char *argv[]) {
    819 	/*
    820 	 * Initialize function pointers in slapd
    821 	 */
    822 	attr_converter = (convert_attr_to_comp_func*)comp_convert_attr_to_comp;
    823 	assert_converter = (convert_assert_to_comp_func*)comp_convert_assert_to_comp;
    824 	component_destructor = (free_component_func*)comp_free_component;
    825 	test_components = (test_component_func*)comp_test_components;
    826 	nibble_mem_allocator = (free_nibble_func*)comp_nibble_memory_allocator;
    827 	nibble_mem_free = (free_nibble_func*)comp_nibble_memory_free;
    828 	is_aliased_attribute = (test_membership_func*)comp_is_aliased_attribute;
    829 	get_component_description = (get_component_info_func*)comp_get_component_description;
    830 	component_encoder = (component_encoder_func*)comp_component_encoder;
    831 
    832 	/* file path needs to be */
    833 	load_derived_matching_rule ("derived_mr.cfg");
    834 
    835 	/* the initialization for example X.509 certificate */
    836 	init_module_AuthenticationFramework();
    837 	init_module_AuthorityKeyIdentifierDefinition();
    838 	init_module_CertificateRevokationList();
    839 	init_attribute_aliasing_table ();
    840 	init_component_description_table ();
    841 	return 0;
    842 }
    843 
    844 #endif /* SLAPD_PASSWD */
    845