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