]> git.sur5r.net Git - openldap/blob - contrib/slapd-modules/comp_match/init.c
1) existing matching rules support in component filter
[openldap] / contrib / slapd-modules / comp_match / init.c
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
20 #include "component.h"
21 #include "asn.h"
22 #include <asn-gser.h>
23
24 #include <string.h>
25
26 #ifndef SLAPD_COMP_MATCH
27 #define SLAPD_COMP_MATCH SLAPD_MOD_DYNAMIC
28 #endif
29
30
31 OD_entry* gOD_table = NULL;
32 AsnTypetoMatchingRuleTable* gATMR_table = NULL;
33
34 int
35 load_derived_matching_rule ( char* cfg_path ){
36 }
37
38 MatchingRule*
39 retrieve_matching_rule( char* mr_oid, AsnTypeId type ) {
40         char* tmp;
41         struct berval mr_name = BER_BVNULL;
42         AsnTypetoMatchingRuleTable* atmr;
43
44         for ( atmr = gATMR_table ; atmr ; atmr = atmr->atmr_table_next ) {
45                 if ( strcmp( atmr->atmr_oid, mr_oid ) == 0 ) {
46                         tmp = atmr->atmr_table[type].atmr_mr_name;
47                         if ( tmp ) {
48                                 mr_name.bv_val = tmp;
49                                 mr_name.bv_len = strlen( tmp );
50                                 return mr_bvfind ( &mr_name );
51                         }
52                 }
53         }
54         return (MatchingRule*)NULL;
55 }
56
57 OD_entry*
58 retrieve_oid_decoder_table ( char* oid ) {
59         OD_entry* curr_entry;
60         for ( curr_entry = gOD_table ; curr_entry != NULL ;
61                                 curr_entry = curr_entry->oe_next ) {
62                 if ( strcmp ( curr_entry->oe_oid , oid ) == 0 )
63                         return curr_entry;
64         }
65         return (OD_entry*) NULL;
66 }
67
68 int
69 add_OD_entry ( char* oid, gser_decoder_func* gser_decoder ,
70                 ber_decoder_func ber_decoder, converter_func* converter ) {
71         OD_entry* new_entry;
72
73         if ( !gOD_table ) {
74                 gOD_table = new_entry = (OD_entry*) malloc( sizeof ( OD_entry ) );
75                 gOD_table->oe_next = NULL;
76                 gOD_table->oe_prev = NULL;
77         }
78         else {
79                 new_entry = (OD_entry*) malloc( sizeof ( OD_entry ) );
80                 if ( !new_entry ) return -1;
81                 gOD_table->oe_prev = new_entry;
82                 new_entry->oe_next = gOD_table;
83                 new_entry->oe_prev = NULL;
84                 gOD_table = new_entry;
85         }
86
87         strcpy ( new_entry->oe_oid ,oid );
88         new_entry->oe_gser_decoder = gser_decoder;
89         new_entry->oe_ber_decoder = ber_decoder;
90         new_entry->oe_converter = converter;
91
92         return 1;
93 }
94
95 int
96 remove_OD_entry ( char* oid ) {
97         OD_entry* curr_entry;
98         for ( curr_entry = gOD_table ; curr_entry != NULL ;
99                                 curr_entry = curr_entry->oe_next ) {
100                 if ( strcmp ( curr_entry->oe_oid , oid ) == 0 ) {
101                         if ( !curr_entry->oe_next ) {
102                                 if ( curr_entry->oe_prev ) {
103                                         curr_entry->oe_prev->oe_next = NULL;
104                                 }
105                         } else {
106                                 curr_entry->oe_prev->oe_next = curr_entry->oe_next;
107                                 curr_entry->oe_next->oe_prev = curr_entry->oe_prev;
108                         }
109                         free ( curr_entry );
110                         return 1;
111                 }
112         }
113         return -1;
114 }
115
116 void* 
117 comp_convert_attr_to_comp LDAP_P (( Attribute* a, Syntax *syn, struct berval* bv ))
118 {
119
120         char* peek_head;
121         int mode, bytesDecoded, size, rc;
122         void* component;
123         char* oid = a->a_desc->ad_type->sat_atype.at_oid ;
124         GenBuf* b;
125         ExpBuf* buf;
126         OD_entry* od_entry;
127         
128         /* look for the decoder registered for the given attribute */
129         od_entry =  retrieve_oid_decoder_table ( oid );
130         if ( !od_entry || !od_entry->oe_ber_decoder ) return (void*)NULL;
131         if ( od_entry->oe_converter ) {
132                 size = (*od_entry->oe_converter)( bv );
133                 if ( size <= 0 ) return (void*)NULL;
134         }
135
136         buf = ExpBufAllocBuf();
137         ExpBuftoGenBuf( buf, &b );
138         ExpBufInstallDataInBuf ( buf, bv->bv_val, bv->bv_len );
139         BufResetInReadMode( b );
140
141         mode = DEC_ALLOC_MODE_2;
142         /*
143          * How can we decide which decoder will be called, GSER or BER?
144          * Currently BER decoder is called for a certificate.
145          * The flag of Attribute will say something about it in the future
146          */
147         if ( slap_syntax_is_ber ( syn ) ) {
148                 rc =BDecComponentTop(od_entry->oe_ber_decoder, a->a_comp_data->cd_mem_op, b, 0,0, &component,&bytesDecoded,mode ) ;
149         }
150         else {
151                 rc = od_entry->oe_gser_decoder( a->a_comp_data->cd_mem_op, b, component,&bytesDecoded,mode);
152         }
153
154         ExpBufFreeBuf( buf );
155         if ( rc == -1 ) {
156                 ShutdownNibbleMemLocal ( a->a_comp_data->cd_mem_op );
157                 a->a_comp_data->cd_mem_op = NULL;
158                 return (void*)NULL;
159         }
160         else {
161                 return component;
162         }
163 }
164
165 #include <nibble-alloc.h>
166 void
167 comp_free_component ( void* mem_op ) {
168         ShutdownNibbleMemLocal( (NibbleMem*)mem_op );
169         return;
170 }
171
172 int
173 comp_convert_assert_to_comp (
174         void* mem_op,
175         ComponentSyntaxInfo *csi_attr,
176         struct berval* bv,
177         ComponentSyntaxInfo** csi, int* len, int mode )
178 {
179         int rc;
180         GenBuf* genBuf;
181         ExpBuf* buf;
182         gser_decoder_func *decoder = csi_attr->csi_comp_desc->cd_gser_decoder;
183
184         buf = ExpBufAllocBuf();
185         ExpBuftoGenBuf( buf, &genBuf );
186         ExpBufInstallDataInBuf ( buf, bv->bv_val, bv->bv_len );
187         BufResetInReadMode( genBuf );
188
189         if ( csi_attr->csi_comp_desc->cd_type_id == BASICTYPE_ANY )
190                 decoder = ((ComponentAny*)csi_attr)->cai->GSER_Decode;
191
192         rc = (*decoder)( mem_op, genBuf, csi, len, mode );
193         ExpBufFreeBuf ( buf );
194         return rc;
195 }
196
197 int intToAscii( int value, char* buf ) {
198         int minus=0,i,temp;
199         int total_num_digits;
200
201         if ( value == 0 ){
202                 buf[0] = '0';
203                 return 1;
204         }
205
206         if ( value < 0 ){
207                 minus = 1;
208                 value = value*(-1);
209                 buf[0] = '-';
210         }
211         
212         /* How many digits */
213         for ( temp = value, total_num_digits=0 ; temp ; total_num_digits++ )
214                 temp = temp/10;
215
216         total_num_digits += minus;
217
218         for ( i = minus ; value ; i++ ) {
219                 buf[ total_num_digits - i - 1 ]= (char)(value%10 + '0');
220                 value = value/10;
221         }
222         return i;
223 }
224
225 int
226 comp_convert_asn_to_ldap ( MatchingRule* mr, ComponentSyntaxInfo* csi, struct berval* bv, int *allocated )
227 {
228         int value, rc;
229         Syntax* syn;
230
231         AsnTypetoSyntax* asn_to_syn =
232                 &asn_to_syntax_mapping_tbl[csi->csi_comp_desc->cd_type_id];
233         if ( asn_to_syn->ats_syn_oid )
234                 csi->csi_syntax = syn_find ( asn_to_syn->ats_syn_oid );
235         else 
236                 csi->csi_syntax = NULL;
237
238
239         switch ( csi->csi_comp_desc->cd_type_id ) {
240           case BASICTYPE_BOOLEAN :
241                 bv->bv_val = (char*)malloc( 5 );
242                 *allocated = 1;
243                 bv->bv_len = 5;
244                 if ( ((ComponentBool*)csi)->value > 0 ) {
245                         strcpy ( bv->bv_val , "TRUE" );
246                         bv->bv_len = 4;
247                 }
248                 else {
249                         strcpy ( bv->bv_val , "FALSE" );
250                         bv->bv_len = 5;
251                 }
252                 break ;
253           case BASICTYPE_NULL :
254                 bv->bv_len = 0;
255                 break;
256           case BASICTYPE_INTEGER :
257                 bv->bv_val = (char*)malloc( INITIAL_ATTR_SIZE );
258                 *allocated = 1;
259                 bv->bv_len = INITIAL_ATTR_SIZE;
260                 bv->bv_len = intToAscii(((ComponentInt*)csi)->value, bv->bv_val );
261                 if ( bv->bv_len <= 0 )
262                         return LDAP_INVALID_SYNTAX;
263                 break;
264           case BASICTYPE_REAL :
265                 return LDAP_INVALID_SYNTAX;
266           case BASICTYPE_ENUMERATED :
267                 bv->bv_val = (char*)malloc( INITIAL_ATTR_SIZE );
268                 *allocated = 1;
269                 bv->bv_len = INITIAL_ATTR_SIZE;
270                 bv->bv_len = intToAscii(((ComponentEnum*)csi)->value, bv->bv_val );
271                 if ( bv->bv_len <= 0 )
272                         return LDAP_INVALID_SYNTAX;
273                 break;
274           case BASICTYPE_OID :
275           case BASICTYPE_OCTETSTRING :
276           case BASICTYPE_BITSTRING :
277           case BASICTYPE_NUMERIC_STR :
278           case BASICTYPE_PRINTABLE_STR :
279           case BASICTYPE_UNIVERSAL_STR :
280           case BASICTYPE_IA5_STR :
281           case BASICTYPE_BMP_STR :
282           case BASICTYPE_UTF8_STR :
283           case BASICTYPE_UTCTIME :
284           case BASICTYPE_GENERALIZEDTIME :
285           case BASICTYPE_GRAPHIC_STR :
286           case BASICTYPE_VISIBLE_STR :
287           case BASICTYPE_GENERAL_STR :
288           case BASICTYPE_OBJECTDESCRIPTOR :
289           case BASICTYPE_VIDEOTEX_STR :
290           case BASICTYPE_T61_STR :
291           case BASICTYPE_OCTETCONTAINING :
292           case BASICTYPE_BITCONTAINING :
293           case BASICTYPE_RELATIVE_OID :
294                 bv->bv_val = ((ComponentOcts*)csi)->value.octs;
295                 bv->bv_len = ((ComponentOcts*)csi)->value.octetLen;
296                 break;
297           case BASICTYPE_ANY :
298                 csi = ((ComponentAny*)csi)->value;
299                 if ( csi->csi_comp_desc->cd_type != ASN_BASIC ||
300                         csi->csi_comp_desc->cd_type_id == BASICTYPE_ANY )
301                         return LDAP_INVALID_SYNTAX;
302                 return comp_convert_asn_to_ldap( mr, csi, bv, allocated );
303           case COMPOSITE_ASN1_TYPE :
304           case RDNSequence :
305                 /*dnMatch*/
306                 if( strncmp( mr->smr_mrule.mr_oid, DN_MATCH_OID, strlen(DN_MATCH_OID) ) != 0 )
307                         return LDAP_INVALID_SYNTAX;
308                 *allocated = 1;
309                 rc = ConvertRDNSequence2RFC2253( (irRDNSequence*)csi, bv );
310                 return rc;
311           case RelativeDistinguishedName :
312                 /*rdnMatch*/
313                 if( strncmp( mr->smr_mrule.mr_oid, RDN_MATCH_OID, strlen(RDN_MATCH_OID) ) != 0 )
314                         return LDAP_INVALID_SYNTAX;
315                 *allocated = 1;
316                 rc = ConvertRDN2RFC2253((irRelativeDistinguishedName*)csi,bv);
317                 return rc;
318           case TelephoneNumber :
319           case FacsimileTelephoneNumber__telephoneNumber :
320                 break;
321           case DirectoryString :
322                 return LDAP_INVALID_SYNTAX;
323           case ASN_COMP_CERTIFICATE :
324           case ASNTYPE_END :
325                 break;
326           default :
327                 /*Only ASN Basic Type can be converted into LDAP string*/
328                 return LDAP_INVALID_SYNTAX;
329         }
330
331         if ( csi->csi_syntax && csi->csi_syntax->ssyn_validate ) {
332                 if ( csi->csi_syntax->ssyn_validate(csi->csi_syntax, bv) != LDAP_SUCCESS )
333                         return LDAP_INVALID_SYNTAX;
334         }
335
336         return LDAP_SUCCESS;
337 }
338
339 /*
340  * If <all> type component referenced is used
341  * more than one component will be tested
342  */
343 #define IS_TERMINAL_COMPREF(cr) (cr->cr_curr->ci_next == NULL)
344 int
345 comp_test_all_components (
346         void* mem_op,
347         ComponentSyntaxInfo *csi_attr,
348         ComponentAssertion* ca )
349 {
350         int rc;
351         ComponentSyntaxInfo *csi_temp = NULL, *csi_assert = NULL, *comp_elmt = NULL;
352         ComponentReference *cr = ca->ca_comp_ref;
353         struct berval *ca_val = &ca->ca_ma_value;
354
355         switch ( cr->cr_curr->ci_type ) {
356             case LDAP_COMPREF_IDENTIFIER:
357             case LDAP_COMPREF_FROM_BEGINNING:
358             case LDAP_COMPREF_FROM_END:
359                 csi_temp = (ComponentSyntaxInfo*)csi_attr->csi_comp_desc->cd_extract_i( mem_op, cr, csi_attr );
360                 if ( cr->cr_curr->ci_type == LDAP_COMPREF_ALL ) {
361                         rc = comp_test_all_components ( mem_op, csi_temp, ca );
362                 } else {
363                         rc = comp_test_one_component( mem_op, csi_temp, ca );
364                 }
365                 break;
366             case LDAP_COMPREF_COUNT:
367                 /* "count" component reference should be the last component id */
368                 if ( IS_TERMINAL_COMPREF(cr) ) {
369                         ComponentInt *k;
370                         k = (ComponentInt*)CompAlloc( mem_op, sizeof(ComponentInt) );
371                         k->comp_desc = CompAlloc( mem_op, sizeof( ComponentDesc ) );
372                         k->comp_desc->cd_tag = 0;
373                         k->comp_desc->cd_gser_decoder = (gser_decoder_func*)GDecComponentInt;
374                         k->comp_desc->cd_ber_decoder = (ber_decoder_func*)BDecComponentInt;
375                         k->comp_desc->cd_extract_i = (extract_component_from_id_func*)NULL;
376                         k->comp_desc->cd_type = ASN_BASIC;
377                         k->comp_desc->cd_type_id = BASICTYPE_INTEGER;
378                         k->comp_desc->cd_all_match = (allcomponent_matching_func*)MatchingComponentInt;
379                         k->value = AsnListCount(&((ComponentList*)csi_attr)->comp_list);
380                         rc = comp_test_one_component( mem_op, k, ca );
381                 } else {
382                         rc = LDAP_INVALID_SYNTAX;
383                 }
384                 break;
385             case LDAP_COMPREF_ALL:
386                 if ( IS_TERMINAL_COMPREF(cr) ) {
387                         FOR_EACH_LIST_ELMT( comp_elmt, &((ComponentList*)csi_attr)->comp_list )
388                         {
389                                 rc = comp_test_one_component( mem_op, comp_elmt, ca );
390                                 if ( rc == LDAP_COMPARE_TRUE ) {
391                                         break;
392                                 }
393                         }
394                 } else {
395                         ComponentId *start_compid = ca->ca_comp_ref->cr_curr->ci_next;
396                         FOR_EACH_LIST_ELMT( comp_elmt, &((ComponentList*)csi_attr)->comp_list )
397                         {
398                                 cr->cr_curr = start_compid;
399                                 csi_temp = comp_elmt->csi_comp_desc->cd_extract_i( mem_op, cr, comp_elmt );
400                                 if ( cr->cr_curr->ci_type == LDAP_COMPREF_ALL ) {
401                                         rc = comp_test_all_components ( mem_op, csi_temp, ca );
402                                 } else {
403                                         rc = comp_test_one_component ( mem_op, csi_temp, ca );
404                                 }
405
406                                 if ( rc == LDAP_COMPARE_TRUE ) {
407                                         break;
408                                 }
409                         }
410                 }
411                 break;
412             case LDAP_COMPREF_CONTENT:
413             case LDAP_COMPREF_SELECT:
414             case LDAP_COMPREF_DEFINED:
415             case LDAP_COMPREF_UNDEFINED:
416                 rc = LDAP_OPERATIONS_ERROR;
417                 break;
418             default:
419                 rc = LDAP_OPERATIONS_ERROR;
420         }
421         return rc;
422 }
423
424 void
425 eat_bv_whsp ( struct berval* in )
426 {
427         char* end = in->bv_val + in->bv_len;
428         for ( ; ( *in->bv_val == ' ' ) && ( in->bv_val < end ) ; ) {
429                 in->bv_val++;
430         }
431 }
432
433 int
434 get_primitive_GSER_value ( struct berval* in )
435 {
436         int count, sequent_dquote, unclosed_brace, succeed;
437         char* ptr = in->bv_val;
438         char* end = in->bv_val + in->bv_len;
439
440         eat_bv_whsp( in );
441         /*
442          * Four cases of GSER <Values>
443          * 1) "..." :
444          *      StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
445          * 2) '...'B or '...'H :
446          *      BitStringVal, OctetStringVal
447          * 3) {...} :
448          *      SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE, BIT STRING(bit list)
449          * 4) Between two white spaces
450          *      INTEGER, BOOLEAN, NULL,ENUMERATE, REAL
451          */
452
453         if ( in->bv_len <= 0 )
454                 return LDAP_INVALID_SYNTAX;
455
456         succeed = 0;
457         if ( ptr[0] == '"' ) {
458                 for( count = 1, sequent_dquote = 0 ; ; count++ ) {
459                         /* In order to find escaped double quote */
460                         if ( ptr[count] == '"' ) sequent_dquote++;
461                         else sequent_dquote = 0;
462
463                         if ( ptr[count] == '\0' || (ptr + count) > end ) {
464                                 break;
465                         }
466
467                         if ( ( ptr[count] == '"' && ptr[count-1] != '"') ||
468                         ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) ) {
469                                 succeed = 1;
470                                 break;
471                         }
472                 }
473
474                 if ( !succeed || ptr[count] != '"' )
475                         return LDAP_FILTER_ERROR;
476
477                 in->bv_val = ptr+1; /*the next to '"'*/
478                 in->bv_len = count - 1; /* exclude '"' */
479         }
480         else if ( ptr[0] == '\'' ) {
481                 for( count = 1 ; ; count++ ) {
482                         if ( ptr[count] == '\0' || (ptr+count) > end ) {
483                                 break;
484                         }
485                         if ((ptr[count-1] == '\'' && ptr[count] == 'B')||
486                         (ptr[count-1] == '\'' && ptr[count] == 'H') ) {
487                                 succeed = 1;
488                                 break;
489                         }
490                 }
491
492                 if ( !succeed || !(ptr[count] == 'H' || ptr[count] == 'B') )
493                         return LDAP_FILTER_ERROR;
494
495                 in->bv_val = ptr+1; /* the next to '"' */
496                 in->bv_len = count - 2; /* exclude "'H" or "'B" */
497
498         }
499         else if ( ptr[0] == '{' ) {
500                 for( count = 1, unclosed_brace = 1 ; ; count++ ) {
501                         if ( ptr[count] == '{' ) unclosed_brace++;
502                         if ( ptr[count] == '}' ) unclosed_brace--;
503
504                         if ( ptr[count] == '\0' || (ptr+count) > end )
505                                 break;
506                         if ( unclosed_brace == 0 ) {
507                                 succeed = 1;
508                                 break;
509                         }
510                 }
511
512                 if ( !succeed || ptr[count] != '}' )
513                         return LDAP_FILTER_ERROR;
514
515                 in->bv_val = ptr+1; /*the next to '"'*/
516                 in->bv_len = count - 1; /* exclude '"' */
517         }
518         else {
519                 /*Find  following white space where the value is ended*/
520                 for( count = 1 ; ; count++ ) {
521                         if ( ptr[count] == '\0' || ptr[count] == ' ' ||
522                                         (ptr+count) >end ) {
523                                 break;
524                         }
525                 }
526                 if ( ptr[count] != ' ' )
527                         return LDAP_FILTER_ERROR;
528
529                 in->bv_val = ptr; /*the next to '"'*/
530                 in->bv_len = count; /* exclude '"' */
531         }
532
533         return LDAP_SUCCESS;
534 }
535
536 /*
537  * Perform matching one referenced component against assertion
538  * If the matching rule in a component filter is allComponentsMatch
539  * or its derivatives the extracted component's ASN.1 specification
540  * is applied to the assertion value as its syntax
541  * Otherwise, the matching rule's syntax is applied to the assertion value
542  * By RFC 3687
543  */
544 int
545 comp_test_one_component (
546         void* mem_op,
547         ComponentSyntaxInfo *csi_attr,
548         ComponentAssertion *ca )
549 {
550         int len, rc;
551         ComponentSyntaxInfo *csi_assert = NULL;
552         char* oid = NULL;
553         MatchingRule* mr = ca->ca_ma_rule;
554
555         if ( mr->smr_usage & SLAP_MR_COMPONENT ) {
556                 /* If allComponentsMatch or its derivatives */
557                 if ( !ca->ca_comp_data.cd_tree ) {
558                         comp_convert_assert_to_comp( mem_op, csi_attr, &ca->ca_ma_value, &csi_assert, &len, DEC_ALLOC_MODE_0 );
559                         ca->ca_comp_data.cd_tree = (void*)csi_assert;
560                 } else {
561                         csi_assert = ca->ca_comp_data.cd_tree;
562                 }
563
564                 if ( !csi_assert )
565                         return LDAP_PROTOCOL_ERROR;
566
567                 if ( strcmp( mr->smr_mrule.mr_oid, OID_ALL_COMP_MATCH ) != 0 )
568                 {
569                         /* allComponentMatch's derivatives */
570                         oid =  mr->smr_mrule.mr_oid;
571                 }
572                         return csi_attr->csi_comp_desc->cd_all_match(
573                                                  oid, csi_attr, csi_assert );
574
575         } else {
576                 /* LDAP existing matching rules */
577                 struct berval attr_bv = BER_BVNULL;
578                 struct berval* assert_bv = &ca->ca_ma_value;
579                 int allocated = 0;
580                 /*Attribute is converted to compatible LDAP encodings*/
581                 if ( comp_convert_asn_to_ldap( mr, csi_attr, &attr_bv, &allocated ) != LDAP_SUCCESS )
582                         return LDAP_INAPPROPRIATE_MATCHING;
583
584                 /*Assertion value is validated by MR's syntax*/
585                 if ( !ca->ca_comp_data.cd_tree ) {
586                         if ( get_primitive_GSER_value( assert_bv ) != LDAP_SUCCESS ) 
587                                 return LDAP_INVALID_SYNTAX;
588                         assert_bv->bv_val[assert_bv->bv_len] = '\0';
589                         if ( mr->smr_syntax->ssyn_validate( mr->smr_syntax, assert_bv ) != LDAP_SUCCESS ) {
590                                 return LDAP_INVALID_SYNTAX;
591                         }
592                         ca->ca_comp_data.cd_tree = assert_bv;
593                 }
594                 else {
595                         assert_bv = ca->ca_comp_data.cd_tree;
596                 }
597
598                 rc = csi_value_match( mr, &attr_bv, assert_bv );
599                 if ( allocated ) free (attr_bv.bv_val);
600                 return rc;
601         }
602 }
603
604 void*
605 comp_nibble_memory_allocator ( int init_mem, int inc_mem ) {
606         void* nm;
607         nm = InitNibbleMemLocal( init_mem, inc_mem );
608         if ( !nm ) return NULL;
609         else return (void*)nm;
610 }
611
612 void
613 comp_nibble_memory_free ( void* nm ) {
614         ShutdownNibbleMemLocal( nm );
615 }
616
617 #if SLAPD_COMP_MATCH == SLAPD_MOD_DYNAMIC
618
619 #include "certificate.h"
620
621 extern convert_attr_to_comp_func* attr_converter;
622 extern convert_assert_to_comp_func* assert_converter;
623 extern convert_asn_to_ldap_func* csi_converter;
624 extern free_component_func* component_destructor;
625 extern test_component_func* test_one_component;
626 extern test_component_func* test_all_components;
627 extern alloc_nibble_func* nibble_mem_allocator;
628 extern free_nibble_func* nibble_mem_free;
629
630
631 int init_module(int argc, char *argv[]) {
632         /*
633          * Initialize function pointers in slapd
634          */
635         attr_converter = comp_convert_attr_to_comp;
636         assert_converter = comp_convert_assert_to_comp;
637         component_destructor = comp_free_component;
638         test_one_component = comp_test_one_component;
639         test_all_components = comp_test_all_components;
640         nibble_mem_allocator = comp_nibble_memory_allocator;
641         nibble_mem_free = comp_nibble_memory_free;
642
643         /* file path needs to be */
644         load_derived_matching_rule ("derived_mr.cfg");
645
646         /* the initialization for example X.509 certificate */
647         init_module_AuthenticationFramework();
648         return 0;
649 }
650
651 #endif /* SLAPD_PASSWD */