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@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 */
39AttributeAliasing aa_table [ MAX_ALIASING_ENTRY ];
40MatchingRuleAliasing mra_table [ MAX_ALIASING_ENTRY ];
41
42OD_entry* gOD_table = NULL;
43AsnTypetoMatchingRuleTable* gATMR_table = NULL;
44
45int
46load_derived_matching_rule ( char* cfg_path ){
47}
48
49AttributeAliasing*
50comp_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
63static int
64add_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 */
106char* 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
112static int
113init_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
133void
134init_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
184MatchingRule*
185retrieve_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
203void*
204comp_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>
257void
258comp_free_component ( void* mem_op ) {
259	ShutdownNibbleMemLocal( (NibbleMem*)mem_op );
260	return;
261}
262
263void
264comp_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
288int 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
316int
317comp_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)
452int
453comp_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
507void
508eat_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 */
524int
525comp_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
596int
597comp_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
720void*
721comp_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
728void
729comp_nibble_memory_free ( void* nm ) {
730	ShutdownNibbleMemLocal( nm );
731}
732
733void*
734comp_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
741int
742comp_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
806extern convert_attr_to_comp_func* attr_converter;
807extern convert_assert_to_comp_func* assert_converter;
808extern convert_asn_to_ldap_func* csi_converter;
809extern free_component_func* component_destructor;
810extern test_component_func* test_components;
811extern alloc_nibble_func* nibble_mem_allocator;
812extern free_nibble_func* nibble_mem_free;
813extern test_membership_func* is_aliased_attribute;
814extern get_component_info_func* get_component_description;
815extern component_encoder_func* component_encoder;
816
817
818int 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