1 /* Copyright 2004 IBM Corporation
3 * Redisribution and use in source and binary forms, with or without
4 * modification, are permitted only as authorizd by the OpenLADP
8 * This work originally developed by Sang Seok Lim
9 * 2004/06/18 03:20:00 slim@OpenLDAP.org
13 #include <ac/string.h>
14 #include <ac/socket.h>
20 #include "component.h"
26 #ifndef SLAPD_COMP_MATCH
27 #define SLAPD_COMP_MATCH SLAPD_MOD_DYNAMIC
31 OD_entry* gOD_table = NULL;
32 AsnTypetoMatchingRuleTable* gATMR_table = NULL;
35 load_derived_matching_rule ( char* cfg_path ){
39 retrieve_matching_rule( char* mr_oid, AsnTypeId type ) {
41 struct berval mr_name = BER_BVNULL;
42 AsnTypetoMatchingRuleTable* atmr;
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;
49 mr_name.bv_len = strlen( tmp );
50 return mr_bvfind ( &mr_name );
54 return (MatchingRule*)NULL;
58 retrieve_oid_decoder_table ( char* oid ) {
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 )
65 return (OD_entry*) NULL;
69 add_OD_entry ( char* oid, gser_decoder_func* gser_decoder ,
70 ber_decoder_func ber_decoder, converter_func* converter ) {
74 gOD_table = new_entry = (OD_entry*) malloc( sizeof ( OD_entry ) );
75 gOD_table->oe_next = NULL;
76 gOD_table->oe_prev = NULL;
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;
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;
96 remove_OD_entry ( char* oid ) {
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;
106 curr_entry->oe_prev->oe_next = curr_entry->oe_next;
107 curr_entry->oe_next->oe_prev = curr_entry->oe_prev;
117 comp_convert_attr_to_comp LDAP_P (( Attribute* a, Syntax *syn, struct berval* bv ))
121 int mode, bytesDecoded, size, rc;
123 char* oid = a->a_desc->ad_type->sat_atype.at_oid ;
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;
136 buf = ExpBufAllocBuf();
137 ExpBuftoGenBuf( buf, &b );
138 ExpBufInstallDataInBuf ( buf, bv->bv_val, bv->bv_len );
139 BufResetInReadMode( b );
141 mode = DEC_ALLOC_MODE_2;
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
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 ) ;
151 rc = od_entry->oe_gser_decoder( a->a_comp_data->cd_mem_op, b, component,&bytesDecoded,mode);
154 ExpBufFreeBuf( buf );
156 ShutdownNibbleMemLocal ( a->a_comp_data->cd_mem_op );
157 a->a_comp_data->cd_mem_op = NULL;
165 #include <nibble-alloc.h>
167 comp_free_component ( void* mem_op ) {
168 ShutdownNibbleMemLocal( (NibbleMem*)mem_op );
173 comp_convert_assert_to_comp (
175 ComponentSyntaxInfo *csi_attr,
177 ComponentSyntaxInfo** csi, int* len, int mode )
182 gser_decoder_func *decoder = csi_attr->csi_comp_desc->cd_gser_decoder;
184 buf = ExpBufAllocBuf();
185 ExpBuftoGenBuf( buf, &genBuf );
186 ExpBufInstallDataInBuf ( buf, bv->bv_val, bv->bv_len );
187 BufResetInReadMode( genBuf );
189 if ( csi_attr->csi_comp_desc->cd_type_id == BASICTYPE_ANY )
190 decoder = ((ComponentAny*)csi_attr)->cai->GSER_Decode;
192 rc = (*decoder)( mem_op, genBuf, csi, len, mode );
193 ExpBufFreeBuf ( buf );
197 int intToAscii( int value, char* buf ) {
199 int total_num_digits;
212 /* How many digits */
213 for ( temp = value, total_num_digits=0 ; temp ; total_num_digits++ )
216 total_num_digits += minus;
218 for ( i = minus ; value ; i++ ) {
219 buf[ total_num_digits - i - 1 ]= (char)(value%10 + '0');
226 comp_convert_asn_to_ldap ( MatchingRule* mr, ComponentSyntaxInfo* csi, struct berval* bv, int *allocated )
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 );
236 csi->csi_syntax = NULL;
239 switch ( csi->csi_comp_desc->cd_type_id ) {
240 case BASICTYPE_BOOLEAN :
241 bv->bv_val = (char*)malloc( 5 );
244 if ( ((ComponentBool*)csi)->value > 0 ) {
245 strcpy ( bv->bv_val , "TRUE" );
249 strcpy ( bv->bv_val , "FALSE" );
253 case BASICTYPE_NULL :
256 case BASICTYPE_INTEGER :
257 bv->bv_val = (char*)malloc( INITIAL_ATTR_SIZE );
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;
264 case BASICTYPE_REAL :
265 return LDAP_INVALID_SYNTAX;
266 case BASICTYPE_ENUMERATED :
267 bv->bv_val = (char*)malloc( INITIAL_ATTR_SIZE );
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;
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;
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 :
306 if( strncmp( mr->smr_mrule.mr_oid, DN_MATCH_OID, strlen(DN_MATCH_OID) ) != 0 )
307 return LDAP_INVALID_SYNTAX;
309 rc = ConvertRDNSequence2RFC2253( (irRDNSequence*)csi, bv );
311 case RelativeDistinguishedName :
313 if( strncmp( mr->smr_mrule.mr_oid, RDN_MATCH_OID, strlen(RDN_MATCH_OID) ) != 0 )
314 return LDAP_INVALID_SYNTAX;
316 rc = ConvertRDN2RFC2253((irRelativeDistinguishedName*)csi,bv);
318 case TelephoneNumber :
319 case FacsimileTelephoneNumber__telephoneNumber :
321 case DirectoryString :
322 return LDAP_INVALID_SYNTAX;
323 case ASN_COMP_CERTIFICATE :
327 /*Only ASN Basic Type can be converted into LDAP string*/
328 return LDAP_INVALID_SYNTAX;
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;
340 * If <all> type component referenced is used
341 * more than one component will be tested
343 #define IS_TERMINAL_COMPREF(cr) (cr->cr_curr->ci_next == NULL)
345 comp_test_all_components (
347 ComponentSyntaxInfo *csi_attr,
348 ComponentAssertion* ca )
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;
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 );
363 rc = comp_test_one_component( mem_op, csi_temp, ca );
366 case LDAP_COMPREF_COUNT:
367 /* "count" component reference should be the last component id */
368 if ( IS_TERMINAL_COMPREF(cr) ) {
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 );
382 rc = LDAP_INVALID_SYNTAX;
385 case LDAP_COMPREF_ALL:
386 if ( IS_TERMINAL_COMPREF(cr) ) {
387 FOR_EACH_LIST_ELMT( comp_elmt, &((ComponentList*)csi_attr)->comp_list )
389 rc = comp_test_one_component( mem_op, comp_elmt, ca );
390 if ( rc == LDAP_COMPARE_TRUE ) {
395 ComponentId *start_compid = ca->ca_comp_ref->cr_curr->ci_next;
396 FOR_EACH_LIST_ELMT( comp_elmt, &((ComponentList*)csi_attr)->comp_list )
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 );
403 rc = comp_test_one_component ( mem_op, csi_temp, ca );
406 if ( rc == LDAP_COMPARE_TRUE ) {
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;
419 rc = LDAP_OPERATIONS_ERROR;
425 eat_bv_whsp ( struct berval* in )
427 char* end = in->bv_val + in->bv_len;
428 for ( ; ( *in->bv_val == ' ' ) && ( in->bv_val < end ) ; ) {
434 get_primitive_GSER_value ( struct berval* in )
436 int count, sequent_dquote, unclosed_brace, succeed;
437 char* ptr = in->bv_val;
438 char* end = in->bv_val + in->bv_len;
442 * Four cases of GSER <Values>
444 * StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
445 * 2) '...'B or '...'H :
446 * BitStringVal, OctetStringVal
448 * SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE, BIT STRING(bit list)
449 * 4) Between two white spaces
450 * INTEGER, BOOLEAN, NULL,ENUMERATE, REAL
453 if ( in->bv_len <= 0 )
454 return LDAP_INVALID_SYNTAX;
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;
463 if ( ptr[count] == '\0' || (ptr + count) > end ) {
467 if ( ( ptr[count] == '"' && ptr[count-1] != '"') ||
468 ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) ) {
474 if ( !succeed || ptr[count] != '"' )
475 return LDAP_FILTER_ERROR;
477 in->bv_val = ptr+1; /*the next to '"'*/
478 in->bv_len = count - 1; /* exclude '"' */
480 else if ( ptr[0] == '\'' ) {
481 for( count = 1 ; ; count++ ) {
482 if ( ptr[count] == '\0' || (ptr+count) > end ) {
485 if ((ptr[count-1] == '\'' && ptr[count] == 'B')||
486 (ptr[count-1] == '\'' && ptr[count] == 'H') ) {
492 if ( !succeed || !(ptr[count] == 'H' || ptr[count] == 'B') )
493 return LDAP_FILTER_ERROR;
495 in->bv_val = ptr+1; /* the next to '"' */
496 in->bv_len = count - 2; /* exclude "'H" or "'B" */
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--;
504 if ( ptr[count] == '\0' || (ptr+count) > end )
506 if ( unclosed_brace == 0 ) {
512 if ( !succeed || ptr[count] != '}' )
513 return LDAP_FILTER_ERROR;
515 in->bv_val = ptr+1; /*the next to '"'*/
516 in->bv_len = count - 1; /* exclude '"' */
519 /*Find following white space where the value is ended*/
520 for( count = 1 ; ; count++ ) {
521 if ( ptr[count] == '\0' || ptr[count] == ' ' ||
526 if ( ptr[count] != ' ' )
527 return LDAP_FILTER_ERROR;
529 in->bv_val = ptr; /*the next to '"'*/
530 in->bv_len = count; /* exclude '"' */
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
545 comp_test_one_component (
547 ComponentSyntaxInfo *csi_attr,
548 ComponentAssertion *ca )
551 ComponentSyntaxInfo *csi_assert = NULL;
553 MatchingRule* mr = ca->ca_ma_rule;
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;
561 csi_assert = ca->ca_comp_data.cd_tree;
565 return LDAP_PROTOCOL_ERROR;
567 if ( strcmp( mr->smr_mrule.mr_oid, OID_ALL_COMP_MATCH ) != 0 )
569 /* allComponentMatch's derivatives */
570 oid = mr->smr_mrule.mr_oid;
572 return csi_attr->csi_comp_desc->cd_all_match(
573 oid, csi_attr, csi_assert );
576 /* LDAP existing matching rules */
577 struct berval attr_bv = BER_BVNULL;
578 struct berval* assert_bv = &ca->ca_ma_value;
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;
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;
592 ca->ca_comp_data.cd_tree = assert_bv;
595 assert_bv = ca->ca_comp_data.cd_tree;
598 rc = csi_value_match( mr, &attr_bv, assert_bv );
599 if ( allocated ) free (attr_bv.bv_val);
605 comp_nibble_memory_allocator ( int init_mem, int inc_mem ) {
607 nm = InitNibbleMemLocal( init_mem, inc_mem );
608 if ( !nm ) return NULL;
609 else return (void*)nm;
613 comp_nibble_memory_free ( void* nm ) {
614 ShutdownNibbleMemLocal( nm );
617 #if SLAPD_COMP_MATCH == SLAPD_MOD_DYNAMIC
619 #include "certificate.h"
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;
631 int init_module(int argc, char *argv[]) {
633 * Initialize function pointers in slapd
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;
643 /* file path needs to be */
644 load_derived_matching_rule ("derived_mr.cfg");
646 /* the initialization for example X.509 certificate */
647 init_module_AuthenticationFramework();
651 #endif /* SLAPD_PASSWD */