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 */
34AttributeAliasing aa_table [ MAX_ALIASING_ENTRY ];
35MatchingRuleAliasing mra_table [ MAX_ALIASING_ENTRY ];
36
37OD_entry* gOD_table = NULL;
38AsnTypetoMatchingRuleTable* gATMR_table = NULL;
39
40int
41load_derived_matching_rule ( char* cfg_path ){
42}
43
44AttributeAliasing*
45comp_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
58static int
59add_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 */
101char* 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
107static int
108init_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
128void
129init_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
179MatchingRule*
180retrieve_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
198void*
199comp_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>
252void
253comp_free_component ( void* mem_op ) {
254	ShutdownNibbleMemLocal( (NibbleMem*)mem_op );
255	return;
256}
257
258void
259comp_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
283int 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
311int
312comp_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)
447int
448comp_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
502void
503eat_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 */
519int
520comp_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
591int
592comp_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
715void*
716comp_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
723void
724comp_nibble_memory_free ( void* nm ) {
725	ShutdownNibbleMemLocal( nm );
726}
727
728void*
729comp_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
736int
737comp_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
801extern convert_attr_to_comp_func* attr_converter;
802extern convert_assert_to_comp_func* assert_converter;
803extern convert_asn_to_ldap_func* csi_converter;
804extern free_component_func* component_destructor;
805extern test_component_func* test_components;
806extern alloc_nibble_func* nibble_mem_allocator;
807extern free_nibble_func* nibble_mem_free;
808extern test_membership_func* is_aliased_attribute;
809extern get_component_info_func* get_component_description;
810extern component_encoder_func* component_encoder;
811
812
813int 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