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