1 /* component.c -- Component Filter Match Routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2006 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, ComponentFilter *f );
68 componentCertificateValidate(
76 componentFilterValidate(
84 allComponentsValidate(
92 componentFilterMatch (
100 ComponentSyntaxInfo *csi_attr = (ComponentSyntaxInfo*)value;
101 MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue;
104 if ( !mr || !ma->ma_cf ) return LDAP_INAPPROPRIATE_MATCHING;
106 /* Check if the component module is loaded */
107 if ( !attr_converter || !nibble_mem_allocator ) {
111 rc = test_comp_filter( syntax, csi_attr, ma->ma_cf );
113 if ( rc == LDAP_COMPARE_TRUE ) {
117 else if ( rc == LDAP_COMPARE_FALSE ) {
122 return LDAP_INAPPROPRIATE_MATCHING;
127 directoryComponentsMatch(
132 struct berval *value,
133 void *assertedValue )
135 /* Only for registration */
146 struct berval *value,
147 void *assertedValue )
149 /* Only for registration */
155 slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav )
157 cav->cav_ptr = cav->cav_buf = bv->bv_val;
158 cav->cav_end = bv->bv_val + bv->bv_len;
164 dup_comp_ref ( Operation* op, ComponentReference* cr )
166 ComponentReference* dup_cr;
167 ComponentId* ci_curr;
168 ComponentId** ci_temp;
170 dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
172 dup_cr->cr_len = cr->cr_len;
173 dup_cr->cr_string = cr->cr_string;
175 ci_temp = &dup_cr->cr_list;
176 ci_curr = cr->cr_list;
178 for ( ; ci_curr != NULL ;
179 ci_curr = ci_curr->ci_next, ci_temp = &(*ci_temp)->ci_next )
181 *ci_temp = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
182 if ( !ci_temp ) return NULL;
183 **ci_temp = *ci_curr;
186 dup_cr->cr_curr = dup_cr->cr_list;
192 dup_comp_filter_list (
195 ComponentFilter* in_f,
196 ComponentFilter** out_f )
198 ComponentFilter **new, *f;
202 for ( f = in_f; f != NULL; f = f->cf_next ) {
203 rc = dup_comp_filter( op, bv, f, new );
204 if ( rc != LDAP_SUCCESS ) {
207 new = &(*new)->cf_next;
213 get_len_of_next_assert_value ( struct berval* bv, char separator )
217 if ( (bv->bv_val[ i ] == separator) || ( i >= bv->bv_len) )
221 bv->bv_val += (i + 1);
222 bv->bv_len -= (i + 1);
227 dup_comp_filter_item (
229 struct berval* assert_bv,
230 ComponentAssertion* in_ca,
231 ComponentAssertion** out_ca )
235 if ( !in_ca->ca_comp_ref ) return SLAPD_DISCONNECT;
237 *out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
238 if ( !(*out_ca) ) return LDAP_NO_MEMORY;
240 (*out_ca)->ca_comp_data.cd_tree = NULL;
241 (*out_ca)->ca_comp_data.cd_mem_op = NULL;
243 (*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref );
244 (*out_ca)->ca_use_def = 0;
245 (*out_ca)->ca_ma_rule = in_ca->ca_ma_rule;
247 (*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val;
248 len = get_len_of_next_assert_value ( assert_bv, '$' );
249 if ( len <= 0 ) return SLAPD_DISCONNECT;
250 (*out_ca)->ca_ma_value.bv_len = len;
259 ComponentFilter *in_f,
260 ComponentFilter **out_f )
263 ComponentFilter dup_f = {0};
265 if ( !in_f ) return LDAP_PROTOCOL_ERROR;
267 switch ( in_f->cf_choice ) {
268 case LDAP_COMP_FILTER_AND:
269 rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and);
270 dup_f.cf_choice = LDAP_COMP_FILTER_AND;
272 case LDAP_COMP_FILTER_OR:
273 rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or);
274 dup_f.cf_choice = LDAP_COMP_FILTER_OR;
276 case LDAP_COMP_FILTER_NOT:
277 rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not);
278 dup_f.cf_choice = LDAP_COMP_FILTER_NOT;
280 case LDAP_COMP_FILTER_ITEM:
281 rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca );
282 dup_f.cf_choice = LDAP_COMP_FILTER_ITEM;
285 rc = LDAP_PROTOCOL_ERROR;
288 if ( rc == LDAP_SUCCESS ) {
289 *out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx );
297 get_aliased_filter_aa ( Operation* op, AttributeAssertion* a_assert, AttributeAliasing* aa, const char** text )
299 struct berval assert_bv;
301 Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
304 return LDAP_PROTOCOL_ERROR;
306 assert_bv = a_assert->aa_value;
308 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
309 * the component assertion value in assert_bv
310 * Multiple values may be separated with '$'
312 return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &a_assert->aa_cf );
316 get_aliased_filter( Operation* op,
317 MatchingRuleAssertion* ma, AttributeAliasing* aa,
320 struct berval assert_bv;
322 Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
324 if ( !aa->aa_cf ) return LDAP_PROTOCOL_ERROR;
326 assert_bv = ma->ma_value;
327 /* Attribute Description is replaced with aliased one */
328 ma->ma_desc = aa->aa_aliased_ad;
329 ma->ma_rule = aa->aa_mr;
331 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
332 * the component assertion value in assert_bv
333 * Multiple values may be separated with '$'
335 return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf );
339 get_comp_filter( Operation* op, struct berval* bv,
340 ComponentFilter** filt, const char **text )
342 ComponentAssertionValue cav;
345 Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
346 if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) {
349 rc = parse_comp_filter( op, &cav, filt, text );
350 bv->bv_val = cav.cav_ptr;
356 eat_whsp( ComponentAssertionValue* cav )
358 for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) {
364 cav_cur_len( ComponentAssertionValue* cav )
366 return cav->cav_end - cav->cav_ptr;
370 comp_first_element( ComponentAssertionValue* cav )
373 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
374 return LDAP_COMP_FILTER_ITEM;
376 } else if ( cav_cur_len( cav ) >= 7 &&
377 strncmp( cav->cav_ptr, "and", 3 ) == 0 )
379 return LDAP_COMP_FILTER_AND;
381 } else if ( cav_cur_len( cav ) >= 6 &&
382 strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
384 return LDAP_COMP_FILTER_OR;
386 } else if ( cav_cur_len( cav ) >= 7 &&
387 strncmp( cav->cav_ptr, "not", 3 ) == 0 )
389 return LDAP_COMP_FILTER_NOT;
392 return LDAP_COMP_FILTER_UNDEFINED;
397 comp_next_element( ComponentAssertionValue* cav )
400 if ( *(cav->cav_ptr) == ',' ) {
401 /* move pointer to the next CA */
403 return comp_first_element( cav );
405 else return LDAP_COMP_FILTER_UNDEFINED;
409 get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
410 ComponentFilter** f, const char** text )
412 ComponentFilter **new;
416 Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
418 for ( tag = comp_first_element( cav );
419 tag != LDAP_COMP_FILTER_UNDEFINED;
420 tag = comp_next_element( cav ) )
422 err = parse_comp_filter( op, cav, new, text );
423 if ( err != LDAP_SUCCESS ) return ( err );
424 new = &(*new)->cf_next;
428 return( LDAP_SUCCESS );
432 get_componentId( Operation *op, ComponentAssertionValue* cav,
433 ComponentId ** cid, const char** text )
439 type = peek_componentId_type( cav );
441 Debug( LDAP_DEBUG_FILTER, "get_compId [%lu]\n",
442 (unsigned long) type, 0, 0 );
447 case LDAP_COMPREF_IDENTIFIER :
448 _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
449 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
450 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
451 _cid.ci_val.ci_identifier.bv_len = len;
454 case LDAP_COMPREF_FROM_BEGINNING :
455 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
456 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
457 _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
460 case LDAP_COMPREF_FROM_END :
461 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
462 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
463 _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
466 case LDAP_COMPREF_COUNT :
467 _cid.ci_val.ci_count = 0;
470 case LDAP_COMPREF_CONTENT :
471 _cid.ci_val.ci_content = 1;
472 cav->cav_ptr += strlen("content");
474 case LDAP_COMPREF_SELECT :
475 if ( cav->cav_ptr[len] != '(' ) return LDAP_COMPREF_UNDEFINED;
476 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
477 cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
479 _cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
480 _cid.ci_val.ci_select_value.bv_len = len - 1 ;
481 cav->cav_ptr += len + 1;
483 case LDAP_COMPREF_ALL :
484 _cid.ci_val.ci_all = '*';
488 return LDAP_COMPREF_UNDEFINED;
492 *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
494 *cid = malloc( sizeof( ComponentId ) );
501 peek_componentId_type( ComponentAssertionValue* cav )
505 if ( cav->cav_ptr[0] == '-' ) {
506 return LDAP_COMPREF_FROM_END;
508 } else if ( cav->cav_ptr[0] == '(' ) {
509 return LDAP_COMPREF_SELECT;
511 } else if ( cav->cav_ptr[0] == '*' ) {
512 return LDAP_COMPREF_ALL;
514 } else if ( cav->cav_ptr[0] == '0' ) {
515 return LDAP_COMPREF_COUNT;
517 } else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' ) {
518 return LDAP_COMPREF_FROM_BEGINNING;
520 } else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
521 strncmp(cav->cav_ptr,"content",7) == 0 )
523 return LDAP_COMPREF_CONTENT;
524 } else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
525 (cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
527 return LDAP_COMPREF_IDENTIFIER;
530 return LDAP_COMPREF_UNDEFINED;
534 comp_next_id( ComponentAssertionValue* cav )
536 if ( *(cav->cav_ptr) == '.' ) {
538 return LDAP_COMPREF_DEFINED;
541 return LDAP_COMPREF_UNDEFINED;
547 get_component_reference(
549 ComponentAssertionValue* cav,
550 ComponentReference** cr,
555 ComponentReference* ca_comp_ref;
556 ComponentId** cr_list;
561 start = cav->cav_ptr;
562 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) return rc;
564 ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ),
567 ca_comp_ref = malloc( sizeof( ComponentReference ) );
570 if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
572 cr_list = &ca_comp_ref->cr_list;
574 for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
575 ; type = comp_next_id( cav ), count++ )
577 rc = get_componentId( op, cav, cr_list, text );
578 if ( rc == LDAP_SUCCESS ) {
579 if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
580 cr_list = &(*cr_list)->ci_next;
582 } else if ( rc == LDAP_COMPREF_UNDEFINED ) {
586 ca_comp_ref->cr_len = count;
588 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
590 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
600 (*cr)->cr_string.bv_val = start;
601 (*cr)->cr_string.bv_len = end - start + 1;
607 insert_component_reference(
608 ComponentReference *cr,
609 ComponentReference** cr_list)
611 if ( !cr ) return LDAP_PARAM_ERROR;
617 cr->cr_next = *cr_list;
624 * If there is '.' in the name of a given attribute
625 * the first '.'- following characters are considered
626 * as a component reference of the attribute
627 * EX) userCertificate.toBeSigned.serialNumber
628 * attribute : userCertificate
629 * component reference : toBeSigned.serialNumber
632 is_component_reference( char* attr ) {
634 for ( i=0; attr[i] != '\0' ; i++ ) {
635 if ( attr[i] == '.' ) return (1);
641 extract_component_reference(
643 ComponentReference** cr )
648 ComponentAssertionValue cav;
651 for ( i=0; attr[i] != '\0' ; i++ ) {
652 if ( attr[i] == '.' ) break;
655 if (attr[i] != '.' ) return LDAP_PARAM_ERROR;
658 cr_ptr = attr + i + 1 ;
659 cr_len = strlen ( cr_ptr );
660 if ( cr_len <= 0 ) return LDAP_PARAM_ERROR;
662 /* enclosed between double quotes*/
663 cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
664 memcpy( cav.cav_buf+1, cr_ptr, cr_len );
665 cav.cav_buf[0] = '"';
666 cav.cav_buf[cr_len+1] = '"';
667 cav.cav_end = cr_ptr + cr_len + 2;
669 rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
670 if ( rc != LDAP_SUCCESS ) return rc;
671 (*cr)->cr_string.bv_val = cav.cav_buf;
672 (*cr)->cr_string.bv_len = cr_len + 2;
678 get_ca_use_default( Operation *op,
679 ComponentAssertionValue* cav,
680 int* ca_use_def, const char** text )
682 strip_cav_str( cav, "useDefaultValues" );
684 if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
685 strip_cav_str( cav, "TRUE" );
688 } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
689 strip_cav_str( cav, "FALSE" );
693 return LDAP_INVALID_SYNTAX;
700 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
701 MatchingRule** mr, const char** text )
704 struct berval rule_text = { 0L, NULL };
708 for ( ; ; count++ ) {
709 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
710 cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
711 cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
718 *text = "component matching rule not recognized";
719 return LDAP_INAPPROPRIATE_MATCHING;
722 rule_text.bv_len = count;
723 rule_text.bv_val = cav->cav_ptr;
724 *mr = mr_bvfind( &rule_text );
725 cav->cav_ptr += count;
726 Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n",
727 (*mr)->smr_mrule.mr_oid, 0, 0 );
729 *text = "component matching rule not recognized";
730 return LDAP_INAPPROPRIATE_MATCHING;
736 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
738 int count, sequent_dquote, unclosed_brace, succeed;
742 * Four cases of GSER <Values>
744 * StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
745 * 2) '...'B or '...'H :
746 * BitStringVal, OctetStringVal
748 * SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
749 * 4) Between two white spaces
750 * INTEGER, BOOLEAN, NULL,ENUMERATE, etc
754 if ( cav->cav_ptr[0] == '"' ) {
755 for( count = 1, sequent_dquote = 0 ; ; count++ ) {
756 /* In order to find escaped double quote */
757 if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
758 else sequent_dquote = 0;
760 if ( cav->cav_ptr[count] == '\0' ||
761 (cav->cav_ptr+count) > cav->cav_end )
766 if ( ( cav->cav_ptr[count] == '"' &&
767 cav->cav_ptr[count-1] != '"') ||
768 ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) )
775 if ( !succeed || cav->cav_ptr[count] != '"' ) {
776 return LDAP_FILTER_ERROR;
779 bv->bv_val = cav->cav_ptr + 1;
780 bv->bv_len = count - 1; /* exclude '"' */
782 } else if ( cav->cav_ptr[0] == '\'' ) {
783 for( count = 1 ; ; count++ ) {
784 if ( cav->cav_ptr[count] == '\0' ||
785 (cav->cav_ptr+count) > cav->cav_end )
789 if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B') ||
790 (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') )
798 !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
800 return LDAP_FILTER_ERROR;
803 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
804 bv->bv_len = count - 2;/* exclude "'H" or "'B" */
806 } else if ( cav->cav_ptr[0] == '{' ) {
807 for( count = 1, unclosed_brace = 1 ; ; count++ ) {
808 if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
809 if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
811 if ( cav->cav_ptr[count] == '\0' ||
812 (cav->cav_ptr+count) > cav->cav_end )
816 if ( unclosed_brace == 0 ) {
822 if ( !succeed || cav->cav_ptr[count] != '}' ) return LDAP_FILTER_ERROR;
824 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
825 bv->bv_len = count - 1;/* exclude "'B" */
829 /*Find following white space where the value is ended*/
830 for( count = 1 ; ; count++ ) {
831 if ( cav->cav_ptr[count] == '\0' ||
832 cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' ||
833 cav->cav_ptr[count] == '{' ||
834 (cav->cav_ptr+count) > cav->cav_end )
839 bv->bv_val = cav->cav_ptr;
843 cav->cav_ptr += bv->bv_len;
848 get_matching_value( Operation *op, ComponentAssertion* ca,
849 ComponentAssertionValue* cav, struct berval* bv,
852 if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
853 if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
854 return LDAP_FILTER_ERROR;
858 /* embeded componentFilterMatch Description */
859 bv->bv_val = cav->cav_ptr;
860 bv->bv_len = cav_cur_len( cav );
866 /* Don't move the position pointer, just peek given string */
868 peek_cav_str( ComponentAssertionValue* cav, char* str )
871 if ( cav_cur_len( cav ) >= strlen( str ) &&
872 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
877 return LDAP_INVALID_SYNTAX;
881 strip_cav_str( ComponentAssertionValue* cav, char* str)
884 if ( cav_cur_len( cav ) >= strlen( str ) &&
885 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
887 cav->cav_ptr += strlen( str );
891 return LDAP_INVALID_SYNTAX;
895 * TAG : "item", "and", "or", "not"
898 strip_cav_tag( ComponentAssertionValue* cav )
902 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
903 strip_cav_str( cav , "item:" );
904 return LDAP_COMP_FILTER_ITEM;
906 } else if ( cav_cur_len( cav ) >= 7 &&
907 strncmp( cav->cav_ptr, "and", 3 ) == 0 )
909 strip_cav_str( cav , "and:" );
910 return LDAP_COMP_FILTER_AND;
912 } else if ( cav_cur_len( cav ) >= 6 &&
913 strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
915 strip_cav_str( cav , "or:" );
916 return LDAP_COMP_FILTER_OR;
918 } else if ( cav_cur_len( cav ) >= 7 &&
919 strncmp( cav->cav_ptr, "not", 3 ) == 0 )
921 strip_cav_str( cav , "not:" );
922 return LDAP_COMP_FILTER_NOT;
929 * when encoding, "item" is denotation of ComponentAssertion
930 * ComponentAssertion :: SEQUENCE {
931 * component ComponentReference (SIZE(1..MAX)) OPTIONAL,
932 * useDefaultValues BOOLEAN DEFAULT TRUE,
933 * rule MATCHING-RULE.&id,
934 * value MATCHING-RULE.&AssertionType }
937 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
941 ComponentAssertion* _ca;
945 Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
947 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
949 _ca = malloc( sizeof( ComponentAssertion ) );
951 if ( !_ca ) return LDAP_NO_MEMORY;
953 _ca->ca_comp_data.cd_tree = NULL;
954 _ca->ca_comp_data.cd_mem_op = NULL;
956 rc = peek_cav_str( cav, "component" );
957 if ( rc == LDAP_SUCCESS ) {
958 strip_cav_str( cav, "component" );
959 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
960 if ( rc != LDAP_SUCCESS ) {
962 op->o_tmpfree( _ca, op->o_tmpmemctx );
965 return LDAP_INVALID_SYNTAX;
967 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
970 _ca->ca_comp_ref = NULL;
973 rc = peek_cav_str( cav, "useDefaultValues");
974 if ( rc == LDAP_SUCCESS ) {
975 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
976 if ( rc != LDAP_SUCCESS ) {
978 op->o_tmpfree( _ca, op->o_tmpmemctx );
981 return LDAP_INVALID_SYNTAX;
983 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
986 else _ca->ca_use_def = 1;
988 if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
989 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
991 op->o_tmpfree( _ca, op->o_tmpmemctx );
994 return LDAP_INAPPROPRIATE_MATCHING;
997 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
999 if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
1000 get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
1002 op->o_tmpfree( _ca, op->o_tmpmemctx );
1005 return LDAP_INVALID_SYNTAX;
1009 * Normalize the value of this component assertion when the matching
1010 * rule is one of existing matching rules
1012 mr = _ca->ca_ma_rule;
1013 if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
1015 value.bv_val[value.bv_len] = '\0';
1016 rc = mr->smr_normalize (
1017 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
1019 &value, &_ca->ca_ma_value, op->o_tmpmemctx );
1020 if ( rc != LDAP_SUCCESS )
1024 _ca->ca_ma_value = value;
1026 * Validate the value of this component assertion
1028 if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
1029 return LDAP_INVALID_SYNTAX;
1033 /* componentFilterMatch contains componentFilterMatch in it */
1034 if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
1036 bv.bv_val = cav->cav_ptr;
1037 bv.bv_len = cav_cur_len( cav );
1038 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
1039 if ( rc != LDAP_SUCCESS ) {
1041 op->o_tmpfree( _ca, op->o_tmpmemctx );
1046 cav->cav_ptr = bv.bv_val;
1047 assert( cav->cav_end >= bv.bv_val );
1051 return LDAP_SUCCESS;
1055 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
1056 ComponentFilter** filt, const char** text )
1059 * A component filter looks like this coming in:
1060 * Filter ::= CHOICE {
1061 * item [0] ComponentAssertion,
1062 * and [1] SEQUENCE OF ComponentFilter,
1063 * or [2] SEQUENCE OF ComponentFilter,
1064 * not [3] ComponentFilter,
1071 /* TAG : item, and, or, not in RFC 2254 */
1072 tag = strip_cav_tag( cav );
1074 if ( tag == LBER_ERROR ) {
1075 *text = "error decoding comp filter";
1076 return LDAP_PROTOCOL_ERROR;
1079 if ( tag != LDAP_COMP_FILTER_NOT )
1080 strip_cav_str( cav, "{");
1087 switch ( f.cf_choice ) {
1088 case LDAP_COMP_FILTER_AND:
1089 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
1090 err = get_comp_filter_list( op, cav, &f.cf_and, text );
1091 if ( err != LDAP_SUCCESS ) {
1094 if ( f.cf_and == NULL ) {
1095 f.cf_choice = SLAPD_FILTER_COMPUTED;
1096 f.cf_result = LDAP_COMPARE_TRUE;
1100 case LDAP_COMP_FILTER_OR:
1101 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
1102 err = get_comp_filter_list( op, cav, &f.cf_or, text );
1103 if ( err != LDAP_SUCCESS ) {
1106 if ( f.cf_or == NULL ) {
1107 f.cf_choice = SLAPD_FILTER_COMPUTED;
1108 f.cf_result = LDAP_COMPARE_FALSE;
1110 /* no assert - list could be empty */
1113 case LDAP_COMP_FILTER_NOT:
1114 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
1115 err = parse_comp_filter( op, cav, &f.cf_not, text );
1116 if ( err != LDAP_SUCCESS ) {
1120 assert( f.cf_not != NULL );
1121 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
1122 int fresult = f.cf_not->cf_result;
1123 f.cf_choice = SLAPD_FILTER_COMPUTED;
1124 op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
1127 switch ( fresult ) {
1128 case LDAP_COMPARE_TRUE:
1129 f.cf_result = LDAP_COMPARE_FALSE;
1131 case LDAP_COMPARE_FALSE:
1132 f.cf_result = LDAP_COMPARE_TRUE;
1135 /* (!Undefined) is Undefined */
1140 case LDAP_COMP_FILTER_ITEM:
1141 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1142 err = get_item( op, cav, &f.cf_ca, text );
1143 if ( err != LDAP_SUCCESS ) {
1147 assert( f.cf_ca != NULL );
1151 f.cf_choice = SLAPD_FILTER_COMPUTED;
1152 f.cf_result = SLAPD_COMPARE_UNDEFINED;
1156 if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1157 *text = "Component Filter Syntax Error";
1161 if ( tag != LDAP_COMP_FILTER_NOT )
1162 strip_cav_str( cav, "}");
1164 if ( err == LDAP_SUCCESS ) {
1166 *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1168 *filt = malloc( sizeof(f) );
1177 test_comp_filter_and(
1179 ComponentSyntaxInfo *a,
1180 ComponentFilter *flist )
1183 int rtn = LDAP_COMPARE_TRUE;
1185 for ( f = flist ; f != NULL; f = f->cf_next ) {
1186 int rc = test_comp_filter( syn, a, f );
1187 if ( rc == LDAP_COMPARE_FALSE ) {
1192 if ( rc != LDAP_COMPARE_TRUE ) {
1201 test_comp_filter_or(
1203 ComponentSyntaxInfo *a,
1204 ComponentFilter *flist )
1207 int rtn = LDAP_COMPARE_TRUE;
1209 for ( f = flist ; f != NULL; f = f->cf_next ) {
1210 int rc = test_comp_filter( syn, a, f );
1211 if ( rc == LDAP_COMPARE_TRUE ) {
1216 if ( rc != LDAP_COMPARE_FALSE ) {
1225 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1226 struct berval* bv_assert )
1231 assert( mr != NULL );
1232 assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1234 if( !mr->smr_match ) return LDAP_INAPPROPRIATE_MATCHING;
1236 rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1237 mr, bv_attr, bv_assert );
1239 if ( rc != LDAP_SUCCESS ) return rc;
1241 return match ? LDAP_COMPARE_FALSE : LDAP_COMPARE_TRUE;
1245 * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1248 test_comp_filter_item(
1250 ComponentSyntaxInfo *csi_attr,
1251 ComponentAssertion *ca )
1254 void *attr_nm, *assert_nm;
1256 if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1257 OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1258 /* componentFilterMatch inside of componentFilterMatch */
1259 rc = test_comp_filter( syn, csi_attr, ca->ca_cf );
1263 /* Memory for storing will-be-extracted attribute values */
1264 attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1265 if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
1267 /* Memory for storing component assertion values */
1268 if( !ca->ca_comp_data.cd_mem_op ) {
1269 assert_nm = nibble_mem_allocator ( 256, 64 );
1271 nibble_mem_free ( attr_nm );
1272 return LDAP_PROTOCOL_ERROR;
1274 ca->ca_comp_data.cd_mem_op = assert_nm;
1277 assert_nm = ca->ca_comp_data.cd_mem_op;
1280 /* component reference initialization */
1281 if ( ca->ca_comp_ref ) {
1282 ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1284 rc = test_components( attr_nm, assert_nm, csi_attr, ca );
1286 /* free memory used for storing extracted attribute value */
1287 nibble_mem_free ( attr_nm );
1294 ComponentSyntaxInfo *a,
1295 ComponentFilter *f )
1299 if ( !f ) return LDAP_PROTOCOL_ERROR;
1301 Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
1302 switch ( f->cf_choice ) {
1303 case SLAPD_FILTER_COMPUTED:
1306 case LDAP_COMP_FILTER_AND:
1307 rc = test_comp_filter_and( syn, a, f->cf_and );
1309 case LDAP_COMP_FILTER_OR:
1310 rc = test_comp_filter_or( syn, a, f->cf_or );
1312 case LDAP_COMP_FILTER_NOT:
1313 rc = test_comp_filter( syn, a, f->cf_not );
1316 case LDAP_COMPARE_TRUE:
1317 rc = LDAP_COMPARE_FALSE;
1319 case LDAP_COMPARE_FALSE:
1320 rc = LDAP_COMPARE_TRUE;
1324 case LDAP_COMP_FILTER_ITEM:
1325 rc = test_comp_filter_item( syn, a, f->cf_ca );
1328 rc = LDAP_PROTOCOL_ERROR;
1335 free_comp_filter_list( ComponentFilter* f )
1337 ComponentFilter* tmp;
1338 for ( tmp = f; tmp; tmp = tmp->cf_next ) {
1339 free_comp_filter( tmp );
1344 free_comp_filter( ComponentFilter* f )
1347 Debug( LDAP_DEBUG_FILTER,
1348 "free_comp_filter: Invalid filter so failed to release memory\n",
1352 switch ( f->cf_choice ) {
1353 case LDAP_COMP_FILTER_AND:
1354 case LDAP_COMP_FILTER_OR:
1355 free_comp_filter_list( f->cf_any );
1357 case LDAP_COMP_FILTER_NOT:
1358 free_comp_filter( f->cf_any );
1360 case LDAP_COMP_FILTER_ITEM:
1361 if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op ) {
1362 nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1371 component_free( ComponentFilter *f ) {
1372 free_comp_filter( f );
1376 free_ComponentData( Attribute *a ) {
1377 if ( a->a_comp_data->cd_mem_op )
1378 component_destructor( a->a_comp_data->cd_mem_op );
1379 free ( a->a_comp_data );
1380 a->a_comp_data = NULL;