1 /* component.c -- Component Filter Match Routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2005 The OpenLDAP Foundation.
6 * Portions Copyright 2004 by IBM Corporation.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
20 #include <ac/string.h>
21 #include <ac/socket.h>
27 #ifdef LDAP_COMP_MATCH
29 #include "component.h"
32 * Following function pointers are initialized
33 * when a component module is loaded
35 alloc_nibble_func* nibble_mem_allocator = NULL;
36 free_nibble_func* nibble_mem_free = NULL;
37 convert_attr_to_comp_func* attr_converter = NULL;
38 convert_assert_to_comp_func* assert_converter = NULL ;
39 free_component_func* component_destructor = NULL ;
40 test_component_func* test_components = NULL;
41 test_membership_func* is_aliased_attribute = NULL;
42 component_encoder_func* component_encoder = NULL;
43 get_component_info_func* get_component_description = NULL;
44 #define OID_ALL_COMP_MATCH "1.2.36.79672281.1.13.6"
45 #define OID_COMP_FILTER_MATCH "1.2.36.79672281.1.13.2"
46 #define MAX_LDAP_STR_LEN 128
49 peek_componentId_type( ComponentAssertionValue* cav );
52 strip_cav_str( ComponentAssertionValue* cav, char* str);
55 peek_cav_str( ComponentAssertionValue* cav, char* str );
58 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
59 ComponentFilter** filt, const char** text );
62 free_comp_filter( ComponentFilter* f );
65 test_comp_filter( Syntax *syn, ComponentSyntaxInfo *a, struct berval *bv,
69 componentCertificateValidate(
77 componentFilterValidate(
85 allComponentsValidate(
93 componentFilterMatch (
102 Attribute *a = (Attribute*)value;
103 MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue;
107 if ( !mr || !ma->ma_cf )
108 return LDAP_INAPPROPRIATE_MATCHING;
109 /* Check if the component module is loaded */
110 if ( !attr_converter || !nibble_mem_allocator )
111 return LDAP_INAPPROPRIATE_MATCHING;
113 /* Check if decoded component trees are already linked */
115 if ( !a->a_comp_data ) {
116 for ( ; a->a_vals[num_attr].bv_val != NULL; num_attr++ );
117 if ( num_attr <= 0 )/* no attribute value */
118 return LDAP_INAPPROPRIATE_MATCHING;
120 /* following malloced will be freed by comp_tree_free () */
121 a->a_comp_data = malloc( sizeof( ComponentData ) + sizeof( ComponentSyntaxInfo* )*num_attr );
122 if ( !a->a_comp_data )
123 return LDAP_NO_MEMORY;
124 a->a_comp_data->cd_tree = (ComponentSyntaxInfo**)((char*)a->a_comp_data + sizeof(ComponentData));
125 a->a_comp_data->cd_tree[ num_attr - 1] = (ComponentSyntaxInfo*)NULL;
126 a->a_comp_data->cd_mem_op = nibble_mem_allocator ( 1024*16, 1024 );
129 for ( bv = a->a_vals, i = 0 ; bv->bv_val != NULL; bv++, i++ ) {
130 /* decodes current attribute into components */
131 if ( num_attr != 0 ) {
132 a->a_comp_data->cd_tree[i] = attr_converter (a, syntax, bv);
135 if ( !a->a_comp_data->cd_tree[i] )
136 return LDAP_OPERATIONS_ERROR;
138 rc = test_comp_filter( syntax, a->a_comp_data->cd_tree[i], bv, ma->ma_cf );
140 if ( rc == LDAP_COMPARE_TRUE ) {
144 else if ( rc == LDAP_COMPARE_FALSE ) {
148 return LDAP_INAPPROPRIATE_MATCHING;
157 directoryComponentsMatch(
162 struct berval *value,
163 void *assertedValue )
165 /* Only for Registeration */
176 struct berval *value,
177 void *assertedValue )
179 /* Only for Registeration */
185 slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav )
189 cav->cav_ptr = cav->cav_buf = bv->bv_val;
190 cav->cav_end = bv->bv_val + bv->bv_len;
196 dup_comp_ref ( Operation* op, ComponentReference* cr )
199 ComponentReference* dup_cr;
200 ComponentId* ci_curr;
201 ComponentId** ci_temp;
204 dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
206 dup_cr->cr_len = cr->cr_len;
207 dup_cr->cr_string = cr->cr_string;
209 ci_temp = &dup_cr->cr_list;
210 ci_curr = cr->cr_list;
212 for ( ; ci_curr ; ci_curr = ci_curr->ci_next, ci_temp = &(*ci_temp)->ci_next ) {
213 *ci_temp = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
214 if ( !ci_temp ) return NULL;
215 **ci_temp = *ci_curr;
218 dup_cr->cr_curr = dup_cr->cr_list;
224 dup_comp_filter_list (
227 ComponentFilter* in_f,
228 ComponentFilter** out_f )
230 ComponentFilter **new, *f;
234 for ( f = in_f; f != NULL; f = f->cf_next ) {
235 rc = dup_comp_filter( op, bv, f, new );
236 if ( rc != LDAP_SUCCESS ) {
239 new = &(*new)->cf_next;
245 get_len_of_next_assert_value ( struct berval* bv, char separator )
249 if ( (bv->bv_val[ i ] == separator) || ( i >= bv->bv_len) )
253 bv->bv_val += (i + 1);
254 bv->bv_len -= (i + 1);
259 dup_comp_filter_item (
261 struct berval* assert_bv,
262 ComponentAssertion* in_ca,
263 ComponentAssertion** out_ca )
265 ComponentAssertion* ca;
268 if ( !in_ca->ca_comp_ref )
269 return SLAPD_DISCONNECT;
271 *out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
273 return LDAP_NO_MEMORY;
275 (*out_ca)->ca_comp_data.cd_tree = NULL;
276 (*out_ca)->ca_comp_data.cd_mem_op = NULL;
278 (*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref );
279 (*out_ca)->ca_use_def = 0;
280 (*out_ca)->ca_ma_rule = in_ca->ca_ma_rule;
282 (*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val;
283 len = get_len_of_next_assert_value ( assert_bv, '$' );
285 return SLAPD_DISCONNECT;
286 (*out_ca)->ca_ma_value.bv_len = len;
295 ComponentFilter *in_f,
296 ComponentFilter **out_f )
299 ComponentFilter dup_f = {0};
301 if ( !in_f ) return LDAP_PROTOCOL_ERROR;
303 switch ( in_f->cf_choice ) {
304 case LDAP_COMP_FILTER_AND:
305 rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and);
306 dup_f.cf_choice = LDAP_COMP_FILTER_AND;
308 case LDAP_COMP_FILTER_OR:
309 rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or);
310 dup_f.cf_choice = LDAP_COMP_FILTER_OR;
312 case LDAP_COMP_FILTER_NOT:
313 rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not);
314 dup_f.cf_choice = LDAP_COMP_FILTER_NOT;
316 case LDAP_COMP_FILTER_ITEM:
317 rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca );
318 dup_f.cf_choice = LDAP_COMP_FILTER_ITEM;
321 rc = LDAP_PROTOCOL_ERROR;
324 if ( rc == LDAP_SUCCESS ) {
325 *out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx );
334 get_aliased_filter ( Operation* op, MatchingRuleAssertion* ma, AttributeAliasing* aa, const char** text )
337 struct berval assert_bv;
338 ComponentAssertion* ca;
340 Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
342 if ( !aa->aa_cf ) return LDAP_PROTOCOL_ERROR;
344 assert_bv = ma->ma_value;
345 /* Attribute Description is replaced with aliased one */
346 ma->ma_desc = aa->aa_aliased_ad;
347 ma->ma_rule = aa->aa_mr;
349 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
350 * the component assertion value in assert_bv
351 * Multiple values may be separated with '$'
353 return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf );
357 get_comp_filter( Operation* op, struct berval* bv, ComponentFilter** filt,
360 ComponentAssertionValue cav;
363 Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
364 if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) {
367 rc = parse_comp_filter( op, &cav, filt, text );
368 bv->bv_val = cav.cav_ptr;
374 eat_whsp( ComponentAssertionValue* cav )
376 for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) {
382 cav_cur_len( ComponentAssertionValue* cav )
384 return cav->cav_end - cav->cav_ptr;
388 comp_first_element( ComponentAssertionValue* cav )
391 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
392 return LDAP_COMP_FILTER_ITEM;
394 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
395 return LDAP_COMP_FILTER_AND;
397 else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
398 return LDAP_COMP_FILTER_OR;
400 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
401 return LDAP_COMP_FILTER_NOT;
404 return LDAP_COMP_FILTER_UNDEFINED;
408 comp_next_element( ComponentAssertionValue* cav )
412 if ( *(cav->cav_ptr) == ',' ) {
413 /* move pointer to the next CA */
415 return comp_first_element( cav );
417 else return LDAP_COMP_FILTER_UNDEFINED;
421 get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
422 ComponentFilter** f, const char** text )
424 ComponentFilter **new;
428 Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
430 for ( tag = comp_first_element( cav ); tag != LDAP_COMP_FILTER_UNDEFINED;
431 tag = comp_next_element( cav ) )
433 err = parse_comp_filter( op, cav, new, text );
434 if ( err != LDAP_SUCCESS )
436 new = &(*new)->cf_next;
440 return( LDAP_SUCCESS );
444 get_componentId( Operation *op, ComponentAssertionValue* cav,
445 ComponentId ** cid, const char** text )
451 type = peek_componentId_type( cav );
453 Debug( LDAP_DEBUG_FILTER, "get_compId [%d]\n", type, 0, 0 );
458 case LDAP_COMPREF_IDENTIFIER :
459 _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
460 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
461 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
462 _cid.ci_val.ci_identifier.bv_len = len;
465 case LDAP_COMPREF_FROM_BEGINNING :
466 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
467 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
468 _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
471 case LDAP_COMPREF_FROM_END :
472 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
473 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
474 _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
477 case LDAP_COMPREF_COUNT :
478 _cid.ci_val.ci_count = 0;
481 case LDAP_COMPREF_CONTENT :
482 _cid.ci_val.ci_content = 1;
483 cav->cav_ptr += strlen("content");
485 case LDAP_COMPREF_SELECT :
486 if ( cav->cav_ptr[len] != '(' )
487 return LDAP_COMPREF_UNDEFINED;
488 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
489 cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
491 _cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
492 _cid.ci_val.ci_select_value.bv_len = len - 1 ;
493 cav->cav_ptr += len + 1;
495 case LDAP_COMPREF_ALL :
496 _cid.ci_val.ci_all = '*';
500 return LDAP_COMPREF_UNDEFINED;
504 *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
506 *cid = malloc( sizeof( ComponentId ) );
512 peek_componentId_type( ComponentAssertionValue* cav )
515 if ( cav->cav_ptr[0] == '-' )
516 return LDAP_COMPREF_FROM_END;
517 else if ( cav->cav_ptr[0] == '(' )
518 return LDAP_COMPREF_SELECT;
519 else if ( cav->cav_ptr[0] == '*' )
520 return LDAP_COMPREF_ALL;
521 else if ( cav->cav_ptr[0] == '0' )
522 return LDAP_COMPREF_COUNT;
523 else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' )
524 return LDAP_COMPREF_FROM_BEGINNING;
525 else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
526 strncmp(cav->cav_ptr,"content",7) == 0 )
527 return LDAP_COMPREF_CONTENT;
528 else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
529 (cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
531 return LDAP_COMPREF_IDENTIFIER;
533 return LDAP_COMPREF_UNDEFINED;
537 comp_next_id( ComponentAssertionValue* cav )
540 if ( *(cav->cav_ptr) == '.' ) {
542 return LDAP_COMPREF_DEFINED;
544 else return LDAP_COMPREF_UNDEFINED;
550 get_component_reference( Operation *op, ComponentAssertionValue* cav,
551 ComponentReference** cr, const char** text )
555 ComponentReference* ca_comp_ref;
556 ComponentId** cr_list;
561 start = cav->cav_ptr;
562 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS )
565 ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
567 ca_comp_ref = malloc( sizeof( ComponentReference ) );
569 if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
571 cr_list = &ca_comp_ref->cr_list;
573 for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
574 ; type = comp_next_id( cav ), count++ ) {
575 rc = get_componentId( op, cav, cr_list, text );
576 if ( rc == LDAP_SUCCESS ) {
577 if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
578 cr_list = &(*cr_list)->ci_next;
580 else if ( rc == LDAP_COMPREF_UNDEFINED )
583 ca_comp_ref->cr_len = count;
585 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
587 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
593 if ( rc == LDAP_SUCCESS ) {
598 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
600 free( ca_comp_ref ) ;
602 (*cr)->cr_string.bv_val = start;
603 (*cr)->cr_string.bv_len = end - start + 1;
609 insert_component_reference( ComponentReference *cr, ComponentReference** cr_list) {
611 return LDAP_PARAM_ERROR;
616 cr->cr_next = *cr_list;
623 * If there is '.' in the name of a given attribute
624 * the first '.'- following characters are considered
625 * as a component reference of the attribute
626 * EX) userCertificate.toBeSigned.serialNumber
627 * attribute : userCertificate
628 * component reference : toBeSigned.serialNumber
631 is_component_reference( char* attr ) {
633 for ( i=0; attr[i] != '\0' ; i++ ) {
634 if ( attr[i] == '.' )
641 extract_component_reference( char* attr, ComponentReference** cr ) {
645 ComponentAssertionValue cav;
648 for ( i=0; attr[i] != '\0' ; i++ ) {
649 if ( attr[i] == '.' ) break;
653 return LDAP_PARAM_ERROR;
656 cr_ptr = attr + i + 1 ;
657 cr_len = strlen ( cr_ptr );
659 return LDAP_PARAM_ERROR;
661 /* enclosed between double quotes*/
662 cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
663 memcpy( cav.cav_buf+1, cr_ptr, cr_len );
664 cav.cav_buf[0] = '"';
665 cav.cav_buf[cr_len+1] = '"';
666 cav.cav_end = cr_ptr + cr_len + 2;
668 rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
669 if ( rc != LDAP_SUCCESS )
671 (*cr)->cr_string.bv_val = cav.cav_buf;
672 (*cr)->cr_string.bv_len = cr_len + 2;
677 get_ca_use_default( Operation *op, ComponentAssertionValue* cav,
678 int* ca_use_def, const char** text )
680 strip_cav_str( cav, "useDefaultValues" );
681 if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
682 strip_cav_str( cav, "TRUE" );
684 } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
685 strip_cav_str( cav, "FALSE" );
688 return LDAP_INVALID_SYNTAX;
695 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
696 MatchingRule** mr, const char** text )
699 struct berval rule_text = { 0L, NULL };
703 for ( ; ; count++ ) {
704 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
705 cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
706 cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
711 *text = "component matching rule not recognized";
712 return LDAP_INAPPROPRIATE_MATCHING;
715 rule_text.bv_len = count;
716 rule_text.bv_val = cav->cav_ptr;
717 *mr = mr_bvfind( &rule_text );
718 cav->cav_ptr += count;
719 Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n", (*mr)->smr_mrule.mr_oid, 0, 0 );
721 *text = "component matching rule not recognized";
722 return LDAP_INAPPROPRIATE_MATCHING;
728 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
730 int count, sequent_dquote, unclosed_brace, succeed;
734 * Four cases of GSER <Values>
736 * StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
737 * 2) '...'B or '...'H :
738 * BitStringVal, OctetStringVal
740 * SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
741 * 4) Between two white spaces
742 * INTEGER, BOOLEAN, NULL,ENUMERATE, etc
746 if ( cav->cav_ptr[0] == '"' ) {
747 for( count = 1, sequent_dquote = 0 ; ; count++ ) {
748 /* In order to find escaped double quote */
749 if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
750 else sequent_dquote = 0;
752 if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
756 if ( ( cav->cav_ptr[count] == '"' && cav->cav_ptr[count-1] != '"') ||
757 ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) ) {
763 if ( !succeed || cav->cav_ptr[count] != '"' )
764 return LDAP_FILTER_ERROR;
766 bv->bv_val = cav->cav_ptr + 1;
767 bv->bv_len = count - 1; /* exclude '"' */
769 else if ( cav->cav_ptr[0] == '\'' ) {
770 for( count = 1 ; ; count++ ) {
771 if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
774 if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B')||
775 (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') ) {
781 if ( !succeed || !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
782 return LDAP_FILTER_ERROR;
784 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
785 bv->bv_len = count - 2;/* exclude "'H" or "'B" */
788 else if ( cav->cav_ptr[0] == '{' ) {
789 for( count = 1, unclosed_brace = 1 ; ; count++ ) {
790 if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
791 if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
793 if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end )
795 if ( unclosed_brace == 0 ) {
801 if ( !succeed || cav->cav_ptr[count] != '}' )
802 return LDAP_FILTER_ERROR;
804 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
805 bv->bv_len = count - 1;/* exclude "'B" */
809 /*Find following white space where the value is ended*/
810 for( count = 1 ; ; count++ ) {
811 if ( cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '{' || (cav->cav_ptr+count) > cav->cav_end ) {
815 bv->bv_val = cav->cav_ptr;
819 cav->cav_ptr += bv->bv_len;
825 get_matching_value( Operation *op, ComponentAssertion* ca,
826 ComponentAssertionValue* cav, struct berval* bv,
829 if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
830 if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
831 return LDAP_FILTER_ERROR;
835 /* embeded componentFilterMatch Description */
836 bv->bv_val = cav->cav_ptr;
837 bv->bv_len = cav_cur_len( cav );
843 /* Don't move the position pointer, just peek given string */
845 peek_cav_str( ComponentAssertionValue* cav, char* str )
848 if ( cav_cur_len( cav ) >= strlen( str ) &&
849 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
852 return LDAP_INVALID_SYNTAX;
856 strip_cav_str( ComponentAssertionValue* cav, char* str)
859 if ( cav_cur_len( cav ) >= strlen( str ) &&
860 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 ) {
861 cav->cav_ptr += strlen( str );
865 return LDAP_INVALID_SYNTAX;
869 * TAG : "item", "and", "or", "not"
872 strip_cav_tag( ComponentAssertionValue* cav )
876 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
877 strip_cav_str( cav , "item:" );
878 return LDAP_COMP_FILTER_ITEM;
880 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
881 strip_cav_str( cav , "and:" );
882 return LDAP_COMP_FILTER_AND;
884 else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
885 strip_cav_str( cav , "or:" );
886 return LDAP_COMP_FILTER_OR;
888 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
889 strip_cav_str( cav , "not:" );
890 return LDAP_COMP_FILTER_NOT;
897 * when encoding, "item" is denotation of ComponentAssertion
898 * ComponentAssertion :: SEQUENCE {
899 * component ComponentReference (SIZE(1..MAX)) OPTIONAL,
900 * useDefaultValues BOOLEAN DEFAULT TRUE,
901 * rule MATCHING-RULE.&id,
902 * value MATCHING-RULE.&AssertionType }
905 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
909 ComponentAssertion* _ca;
914 Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
916 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
918 _ca = malloc( sizeof( ComponentAssertion ) );
920 if ( !_ca ) return LDAP_NO_MEMORY;
922 _ca->ca_comp_data.cd_tree = NULL;
923 _ca->ca_comp_data.cd_mem_op = NULL;
925 rc = peek_cav_str( cav, "component" );
926 if ( rc == LDAP_SUCCESS ) {
927 strip_cav_str( cav, "component" );
928 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
929 if ( rc != LDAP_SUCCESS ) {
931 op->o_tmpfree( _ca, op->o_tmpmemctx );
934 return LDAP_INVALID_SYNTAX;
936 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
939 _ca->ca_comp_ref = NULL;
942 rc = peek_cav_str( cav, "useDefaultValues");
943 if ( rc == LDAP_SUCCESS ) {
944 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
945 if ( rc != LDAP_SUCCESS ) {
947 op->o_tmpfree( _ca, op->o_tmpmemctx );
950 return LDAP_INVALID_SYNTAX;
952 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
955 else _ca->ca_use_def = 1;
957 if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
958 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
960 op->o_tmpfree( _ca, op->o_tmpmemctx );
963 return LDAP_INAPPROPRIATE_MATCHING;
966 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
968 if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
969 get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
971 op->o_tmpfree( _ca, op->o_tmpmemctx );
974 return LDAP_INVALID_SYNTAX;
978 * Normalize the value of this component assertion when the matching
979 * rule is one of existing matching rules
981 mr = _ca->ca_ma_rule;
982 if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
984 value.bv_val[value.bv_len] = '\0';
985 rc = mr->smr_normalize (
986 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
988 &value, &_ca->ca_ma_value, op->o_tmpmemctx );
989 if ( rc != LDAP_SUCCESS )
993 _ca->ca_ma_value = value;
995 * Validate the value of this component assertion
997 if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
998 return LDAP_INVALID_SYNTAX;
1002 /* componentFilterMatch contains componentFilterMatch in it */
1003 if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
1005 bv.bv_val = cav->cav_ptr;
1006 bv.bv_len = cav_cur_len( cav );
1007 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
1008 if ( rc != LDAP_SUCCESS ) {
1010 op->o_tmpfree( _ca, op->o_tmpmemctx );
1015 cav->cav_ptr = bv.bv_val;
1016 assert( cav->cav_end >= bv.bv_val );
1020 return LDAP_SUCCESS;
1024 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
1025 ComponentFilter** filt, const char** text )
1028 * A component filter looks like this coming in:
1029 * Filter ::= CHOICE {
1030 * item [0] ComponentAssertion,
1031 * and [1] SEQUENCE OF ComponentFilter,
1032 * or [2] SEQUENCE OF ComponentFilter,
1033 * not [3] ComponentFilter,
1040 /* TAG : item, and, or, not in RFC 2254 */
1041 tag = strip_cav_tag( cav );
1043 if ( tag == LBER_ERROR ) {
1044 *text = "error decoding comp filter";
1045 return LDAP_PROTOCOL_ERROR;
1048 if ( tag != LDAP_COMP_FILTER_NOT )
1049 strip_cav_str( cav, "{");
1056 switch ( f.cf_choice ) {
1057 case LDAP_COMP_FILTER_AND:
1058 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
1059 err = get_comp_filter_list( op, cav, &f.cf_and, text );
1060 if ( err != LDAP_SUCCESS ) {
1063 if ( f.cf_and == NULL ) {
1064 f.cf_choice = SLAPD_FILTER_COMPUTED;
1065 f.cf_result = LDAP_COMPARE_TRUE;
1069 case LDAP_COMP_FILTER_OR:
1070 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
1071 err = get_comp_filter_list( op, cav, &f.cf_or, text );
1072 if ( err != LDAP_SUCCESS ) {
1075 if ( f.cf_or == NULL ) {
1076 f.cf_choice = SLAPD_FILTER_COMPUTED;
1077 f.cf_result = LDAP_COMPARE_FALSE;
1079 /* no assert - list could be empty */
1082 case LDAP_COMP_FILTER_NOT:
1083 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
1084 err = parse_comp_filter( op, cav, &f.cf_not, text );
1085 if ( err != LDAP_SUCCESS ) {
1089 assert( f.cf_not != NULL );
1090 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
1091 int fresult = f.cf_not->cf_result;
1092 f.cf_choice = SLAPD_FILTER_COMPUTED;
1093 op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
1096 switch ( fresult ) {
1097 case LDAP_COMPARE_TRUE:
1098 f.cf_result = LDAP_COMPARE_FALSE;
1100 case LDAP_COMPARE_FALSE:
1101 f.cf_result = LDAP_COMPARE_TRUE;
1104 /* (!Undefined) is Undefined */
1109 case LDAP_COMP_FILTER_ITEM:
1110 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1111 err = get_item( op, cav, &f.cf_ca, text );
1112 if ( err != LDAP_SUCCESS ) {
1116 assert( f.cf_ca != NULL );
1120 f.cf_choice = SLAPD_FILTER_COMPUTED;
1121 f.cf_result = SLAPD_COMPARE_UNDEFINED;
1125 if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1126 *text = "Component Filter Syntax Error";
1130 if ( tag != LDAP_COMP_FILTER_NOT )
1131 strip_cav_str( cav, "}");
1133 if ( err == LDAP_SUCCESS ) {
1135 *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1137 *filt = malloc( sizeof(f) );
1146 test_comp_filter_and(
1148 ComponentSyntaxInfo *a,
1150 ComponentFilter *flist )
1153 int rtn = LDAP_COMPARE_TRUE;
1155 for ( f = flist ; f != NULL; f = f->cf_next ) {
1156 int rc = test_comp_filter( syn, a, bv, f );
1157 if ( rc == LDAP_COMPARE_FALSE ) {
1162 if ( rc != LDAP_COMPARE_TRUE ) {
1171 test_comp_filter_or(
1173 ComponentSyntaxInfo *a,
1175 ComponentFilter *flist )
1178 int rtn = LDAP_COMPARE_TRUE;
1180 for ( f = flist ; f != NULL; f = f->cf_next ) {
1181 int rc = test_comp_filter( syn, a, bv, f );
1182 if ( rc == LDAP_COMPARE_TRUE ) {
1187 if ( rc != LDAP_COMPARE_FALSE ) {
1196 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1197 struct berval* bv_assert )
1202 assert( mr != NULL );
1203 assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1205 if( !mr->smr_match ) {
1206 return LDAP_INAPPROPRIATE_MATCHING;
1209 rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1210 mr, bv_attr, bv_assert );
1211 if ( rc == LDAP_SUCCESS )
1212 return match? LDAP_COMPARE_FALSE:LDAP_COMPARE_TRUE;
1218 * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1221 test_comp_filter_item(
1223 ComponentSyntaxInfo *csi_attr,
1225 ComponentAssertion *ca )
1228 void *attr_nm, *assert_nm;
1230 if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1231 OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1232 /* componentFilterMatch inside of componentFilterMatch */
1233 rc = test_comp_filter( syn, csi_attr, bv, ca->ca_cf );
1237 /* Memory for storing will-be-extracted attribute values */
1238 attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1239 if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
1241 /* Memory for storing component assertion values */
1242 if( !ca->ca_comp_data.cd_mem_op ) {
1243 assert_nm = nibble_mem_allocator ( 256, 64 );
1245 nibble_mem_free ( attr_nm );
1246 return LDAP_PROTOCOL_ERROR;
1248 ca->ca_comp_data.cd_mem_op = assert_nm;
1251 assert_nm = ca->ca_comp_data.cd_mem_op;
1254 /* component reference initialization */
1255 if ( ca->ca_comp_ref )
1256 ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1257 rc = test_components( attr_nm, assert_nm, csi_attr, ca );
1259 /* free memory used for storing extracted attribute value */
1260 nibble_mem_free ( attr_nm );
1267 ComponentSyntaxInfo *a,
1269 ComponentFilter *f )
1273 if ( !f ) return LDAP_PROTOCOL_ERROR;
1275 Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
1276 switch ( f->cf_choice ) {
1277 case SLAPD_FILTER_COMPUTED:
1280 case LDAP_COMP_FILTER_AND:
1281 rc = test_comp_filter_and( syn, a, bv, f->cf_and );
1283 case LDAP_COMP_FILTER_OR:
1284 rc = test_comp_filter_or( syn, a, bv, f->cf_or );
1286 case LDAP_COMP_FILTER_NOT:
1287 rc = test_comp_filter( syn, a, bv, f->cf_not );
1290 case LDAP_COMPARE_TRUE:
1291 rc = LDAP_COMPARE_FALSE;
1293 case LDAP_COMPARE_FALSE:
1294 rc = LDAP_COMPARE_TRUE;
1298 case LDAP_COMP_FILTER_ITEM:
1299 rc = test_comp_filter_item( syn, a, bv, f->cf_ca );
1302 rc = LDAP_PROTOCOL_ERROR;
1309 free_comp_filter_list( ComponentFilter* f )
1311 ComponentFilter* tmp;
1312 for ( tmp = f; tmp; tmp = tmp->cf_next )
1314 free_comp_filter( tmp );
1319 free_comp_filter( ComponentFilter* f )
1322 Debug( LDAP_DEBUG_FILTER, "free_comp_filter:Invalid filter so failed to release memory\n", 0, 0, 0 );
1325 switch ( f->cf_choice ) {
1326 case LDAP_COMP_FILTER_AND:
1327 case LDAP_COMP_FILTER_OR:
1328 free_comp_filter_list( f->cf_any );
1330 case LDAP_COMP_FILTER_NOT:
1331 free_comp_filter( f->cf_any );
1333 case LDAP_COMP_FILTER_ITEM:
1334 if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op )
1335 nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1344 component_free( ComponentFilter *f ) {
1345 free_comp_filter( f );