1 /* component.c -- Component Filter Match Routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2009 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 = SLAP_MALLOC( sizeof( ComponentId ) );
497 return LDAP_NO_MEMORY;
504 peek_componentId_type( ComponentAssertionValue* cav )
508 if ( cav->cav_ptr[0] == '-' ) {
509 return LDAP_COMPREF_FROM_END;
511 } else if ( cav->cav_ptr[0] == '(' ) {
512 return LDAP_COMPREF_SELECT;
514 } else if ( cav->cav_ptr[0] == '*' ) {
515 return LDAP_COMPREF_ALL;
517 } else if ( cav->cav_ptr[0] == '0' ) {
518 return LDAP_COMPREF_COUNT;
520 } else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' ) {
521 return LDAP_COMPREF_FROM_BEGINNING;
523 } else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
524 strncmp(cav->cav_ptr,"content",7) == 0 )
526 return LDAP_COMPREF_CONTENT;
527 } else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
528 (cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
530 return LDAP_COMPREF_IDENTIFIER;
533 return LDAP_COMPREF_UNDEFINED;
537 comp_next_id( ComponentAssertionValue* cav )
539 if ( *(cav->cav_ptr) == '.' ) {
541 return LDAP_COMPREF_DEFINED;
544 return LDAP_COMPREF_UNDEFINED;
550 get_component_reference(
552 ComponentAssertionValue* cav,
553 ComponentReference** cr,
558 ComponentReference* ca_comp_ref;
559 ComponentId** cr_list;
564 start = cav->cav_ptr;
565 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) return rc;
567 ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ),
570 ca_comp_ref = SLAP_MALLOC( sizeof( ComponentReference ) );
573 if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
575 cr_list = &ca_comp_ref->cr_list;
577 for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
578 ; type = comp_next_id( cav ), count++ )
580 rc = get_componentId( op, cav, cr_list, text );
581 if ( rc == LDAP_SUCCESS ) {
582 if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
583 cr_list = &(*cr_list)->ci_next;
585 } else if ( rc == LDAP_COMPREF_UNDEFINED ) {
587 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
594 ca_comp_ref->cr_len = count;
596 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
598 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
608 (*cr)->cr_string.bv_val = start;
609 (*cr)->cr_string.bv_len = end - start + 1;
615 insert_component_reference(
616 ComponentReference *cr,
617 ComponentReference** cr_list)
619 if ( !cr ) return LDAP_PARAM_ERROR;
625 cr->cr_next = *cr_list;
632 * If there is '.' in the name of a given attribute
633 * the first '.'- following characters are considered
634 * as a component reference of the attribute
635 * EX) userCertificate.toBeSigned.serialNumber
636 * attribute : userCertificate
637 * component reference : toBeSigned.serialNumber
640 is_component_reference( char* attr ) {
642 for ( i=0; attr[i] != '\0' ; i++ ) {
643 if ( attr[i] == '.' ) return (1);
649 extract_component_reference(
651 ComponentReference** cr )
656 ComponentAssertionValue cav;
659 for ( i=0; attr[i] != '\0' ; i++ ) {
660 if ( attr[i] == '.' ) break;
663 if (attr[i] != '.' ) return LDAP_PARAM_ERROR;
666 cr_ptr = attr + i + 1 ;
667 cr_len = strlen ( cr_ptr );
668 if ( cr_len <= 0 ) return LDAP_PARAM_ERROR;
670 /* enclosed between double quotes*/
671 cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
672 memcpy( cav.cav_buf+1, cr_ptr, cr_len );
673 cav.cav_buf[0] = '"';
674 cav.cav_buf[cr_len+1] = '"';
675 cav.cav_end = cr_ptr + cr_len + 2;
677 rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
678 if ( rc != LDAP_SUCCESS ) return rc;
679 (*cr)->cr_string.bv_val = cav.cav_buf;
680 (*cr)->cr_string.bv_len = cr_len + 2;
686 get_ca_use_default( Operation *op,
687 ComponentAssertionValue* cav,
688 int* ca_use_def, const char** text )
690 strip_cav_str( cav, "useDefaultValues" );
692 if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
693 strip_cav_str( cav, "TRUE" );
696 } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
697 strip_cav_str( cav, "FALSE" );
701 return LDAP_INVALID_SYNTAX;
708 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
709 MatchingRule** mr, const char** text )
712 struct berval rule_text = { 0L, NULL };
716 for ( ; ; count++ ) {
717 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
718 cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
719 cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
726 *text = "component matching rule not recognized";
727 return LDAP_INAPPROPRIATE_MATCHING;
730 rule_text.bv_len = count;
731 rule_text.bv_val = cav->cav_ptr;
732 *mr = mr_bvfind( &rule_text );
733 cav->cav_ptr += count;
734 Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n",
735 (*mr)->smr_mrule.mr_oid, 0, 0 );
737 *text = "component matching rule not recognized";
738 return LDAP_INAPPROPRIATE_MATCHING;
744 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
746 int count, sequent_dquote, unclosed_brace, succeed;
750 * Four cases of GSER <Values>
752 * StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
753 * 2) '...'B or '...'H :
754 * BitStringVal, OctetStringVal
756 * SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
757 * 4) Between two white spaces
758 * INTEGER, BOOLEAN, NULL,ENUMERATE, etc
762 if ( cav->cav_ptr[0] == '"' ) {
763 for( count = 1, sequent_dquote = 0 ; ; count++ ) {
764 /* In order to find escaped double quote */
765 if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
766 else sequent_dquote = 0;
768 if ( cav->cav_ptr[count] == '\0' ||
769 (cav->cav_ptr+count) > cav->cav_end )
774 if ( ( cav->cav_ptr[count] == '"' &&
775 cav->cav_ptr[count-1] != '"') ||
776 ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) )
783 if ( !succeed || cav->cav_ptr[count] != '"' ) {
784 return LDAP_FILTER_ERROR;
787 bv->bv_val = cav->cav_ptr + 1;
788 bv->bv_len = count - 1; /* exclude '"' */
790 } else if ( cav->cav_ptr[0] == '\'' ) {
791 for( count = 1 ; ; count++ ) {
792 if ( cav->cav_ptr[count] == '\0' ||
793 (cav->cav_ptr+count) > cav->cav_end )
797 if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B') ||
798 (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') )
806 !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
808 return LDAP_FILTER_ERROR;
811 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
812 bv->bv_len = count - 2;/* exclude "'H" or "'B" */
814 } else if ( cav->cav_ptr[0] == '{' ) {
815 for( count = 1, unclosed_brace = 1 ; ; count++ ) {
816 if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
817 if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
819 if ( cav->cav_ptr[count] == '\0' ||
820 (cav->cav_ptr+count) > cav->cav_end )
824 if ( unclosed_brace == 0 ) {
830 if ( !succeed || cav->cav_ptr[count] != '}' ) return LDAP_FILTER_ERROR;
832 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
833 bv->bv_len = count - 1;/* exclude "'B" */
837 /*Find following white space where the value is ended*/
838 for( count = 1 ; ; count++ ) {
839 if ( cav->cav_ptr[count] == '\0' ||
840 cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' ||
841 cav->cav_ptr[count] == '{' ||
842 (cav->cav_ptr+count) > cav->cav_end )
847 bv->bv_val = cav->cav_ptr;
851 cav->cav_ptr += bv->bv_len;
856 get_matching_value( Operation *op, ComponentAssertion* ca,
857 ComponentAssertionValue* cav, struct berval* bv,
860 if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
861 if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
862 return LDAP_FILTER_ERROR;
866 /* embeded componentFilterMatch Description */
867 bv->bv_val = cav->cav_ptr;
868 bv->bv_len = cav_cur_len( cav );
874 /* Don't move the position pointer, just peek given string */
876 peek_cav_str( ComponentAssertionValue* cav, char* str )
879 if ( cav_cur_len( cav ) >= strlen( str ) &&
880 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
885 return LDAP_INVALID_SYNTAX;
889 strip_cav_str( ComponentAssertionValue* cav, char* str)
892 if ( cav_cur_len( cav ) >= strlen( str ) &&
893 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
895 cav->cav_ptr += strlen( str );
899 return LDAP_INVALID_SYNTAX;
903 * TAG : "item", "and", "or", "not"
906 strip_cav_tag( ComponentAssertionValue* cav )
910 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
911 strip_cav_str( cav , "item:" );
912 return LDAP_COMP_FILTER_ITEM;
914 } else if ( cav_cur_len( cav ) >= 7 &&
915 strncmp( cav->cav_ptr, "and", 3 ) == 0 )
917 strip_cav_str( cav , "and:" );
918 return LDAP_COMP_FILTER_AND;
920 } else if ( cav_cur_len( cav ) >= 6 &&
921 strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
923 strip_cav_str( cav , "or:" );
924 return LDAP_COMP_FILTER_OR;
926 } else if ( cav_cur_len( cav ) >= 7 &&
927 strncmp( cav->cav_ptr, "not", 3 ) == 0 )
929 strip_cav_str( cav , "not:" );
930 return LDAP_COMP_FILTER_NOT;
937 * when encoding, "item" is denotation of ComponentAssertion
938 * ComponentAssertion :: SEQUENCE {
939 * component ComponentReference (SIZE(1..MAX)) OPTIONAL,
940 * useDefaultValues BOOLEAN DEFAULT TRUE,
941 * rule MATCHING-RULE.&id,
942 * value MATCHING-RULE.&AssertionType }
945 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
949 ComponentAssertion* _ca;
953 Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
955 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
957 _ca = SLAP_MALLOC( sizeof( ComponentAssertion ) );
959 if ( !_ca ) return LDAP_NO_MEMORY;
961 _ca->ca_comp_data.cd_tree = NULL;
962 _ca->ca_comp_data.cd_mem_op = NULL;
964 rc = peek_cav_str( cav, "component" );
965 if ( rc == LDAP_SUCCESS ) {
966 strip_cav_str( cav, "component" );
967 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
968 if ( rc != LDAP_SUCCESS ) {
970 op->o_tmpfree( _ca, op->o_tmpmemctx );
973 return LDAP_INVALID_SYNTAX;
975 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
978 _ca->ca_comp_ref = NULL;
981 rc = peek_cav_str( cav, "useDefaultValues");
982 if ( rc == LDAP_SUCCESS ) {
983 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
984 if ( rc != LDAP_SUCCESS ) {
986 op->o_tmpfree( _ca, op->o_tmpmemctx );
989 return LDAP_INVALID_SYNTAX;
991 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
994 else _ca->ca_use_def = 1;
996 if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
997 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
999 op->o_tmpfree( _ca, op->o_tmpmemctx );
1002 return LDAP_INAPPROPRIATE_MATCHING;
1005 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
1007 if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
1008 get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
1010 op->o_tmpfree( _ca, op->o_tmpmemctx );
1013 return LDAP_INVALID_SYNTAX;
1017 * Normalize the value of this component assertion when the matching
1018 * rule is one of existing matching rules
1020 mr = _ca->ca_ma_rule;
1021 if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
1023 value.bv_val[value.bv_len] = '\0';
1024 rc = mr->smr_normalize (
1025 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
1027 &value, &_ca->ca_ma_value, op->o_tmpmemctx );
1028 if ( rc != LDAP_SUCCESS )
1032 _ca->ca_ma_value = value;
1034 * Validate the value of this component assertion
1036 if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
1037 return LDAP_INVALID_SYNTAX;
1041 /* componentFilterMatch contains componentFilterMatch in it */
1042 if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
1044 bv.bv_val = cav->cav_ptr;
1045 bv.bv_len = cav_cur_len( cav );
1046 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
1047 if ( rc != LDAP_SUCCESS ) {
1049 op->o_tmpfree( _ca, op->o_tmpmemctx );
1054 cav->cav_ptr = bv.bv_val;
1055 assert( cav->cav_end >= bv.bv_val );
1059 return LDAP_SUCCESS;
1063 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
1064 ComponentFilter** filt, const char** text )
1067 * A component filter looks like this coming in:
1068 * Filter ::= CHOICE {
1069 * item [0] ComponentAssertion,
1070 * and [1] SEQUENCE OF ComponentFilter,
1071 * or [2] SEQUENCE OF ComponentFilter,
1072 * not [3] ComponentFilter,
1079 /* TAG : item, and, or, not in RFC 4515 */
1080 tag = strip_cav_tag( cav );
1082 if ( tag == LBER_ERROR ) {
1083 *text = "error decoding comp filter";
1084 return LDAP_PROTOCOL_ERROR;
1087 if ( tag != LDAP_COMP_FILTER_NOT )
1088 strip_cav_str( cav, "{");
1095 switch ( f.cf_choice ) {
1096 case LDAP_COMP_FILTER_AND:
1097 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
1098 err = get_comp_filter_list( op, cav, &f.cf_and, text );
1099 if ( err != LDAP_SUCCESS ) {
1102 if ( f.cf_and == NULL ) {
1103 f.cf_choice = SLAPD_FILTER_COMPUTED;
1104 f.cf_result = LDAP_COMPARE_TRUE;
1108 case LDAP_COMP_FILTER_OR:
1109 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
1110 err = get_comp_filter_list( op, cav, &f.cf_or, text );
1111 if ( err != LDAP_SUCCESS ) {
1114 if ( f.cf_or == NULL ) {
1115 f.cf_choice = SLAPD_FILTER_COMPUTED;
1116 f.cf_result = LDAP_COMPARE_FALSE;
1118 /* no assert - list could be empty */
1121 case LDAP_COMP_FILTER_NOT:
1122 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
1123 err = parse_comp_filter( op, cav, &f.cf_not, text );
1124 if ( err != LDAP_SUCCESS ) {
1128 assert( f.cf_not != NULL );
1129 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
1130 int fresult = f.cf_not->cf_result;
1131 f.cf_choice = SLAPD_FILTER_COMPUTED;
1132 op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
1135 switch ( fresult ) {
1136 case LDAP_COMPARE_TRUE:
1137 f.cf_result = LDAP_COMPARE_FALSE;
1139 case LDAP_COMPARE_FALSE:
1140 f.cf_result = LDAP_COMPARE_TRUE;
1143 /* (!Undefined) is Undefined */
1148 case LDAP_COMP_FILTER_ITEM:
1149 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1150 err = get_item( op, cav, &f.cf_ca, text );
1151 if ( err != LDAP_SUCCESS ) {
1155 assert( f.cf_ca != NULL );
1159 f.cf_choice = SLAPD_FILTER_COMPUTED;
1160 f.cf_result = SLAPD_COMPARE_UNDEFINED;
1164 if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1165 *text = "Component Filter Syntax Error";
1169 if ( tag != LDAP_COMP_FILTER_NOT )
1170 strip_cav_str( cav, "}");
1172 if ( err == LDAP_SUCCESS ) {
1174 *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1176 *filt = SLAP_MALLOC( sizeof(f) );
1178 if ( *filt == NULL ) {
1179 return LDAP_NO_MEMORY;
1188 test_comp_filter_and(
1190 ComponentSyntaxInfo *a,
1191 ComponentFilter *flist )
1194 int rtn = LDAP_COMPARE_TRUE;
1196 for ( f = flist ; f != NULL; f = f->cf_next ) {
1197 int rc = test_comp_filter( syn, a, f );
1198 if ( rc == LDAP_COMPARE_FALSE ) {
1203 if ( rc != LDAP_COMPARE_TRUE ) {
1212 test_comp_filter_or(
1214 ComponentSyntaxInfo *a,
1215 ComponentFilter *flist )
1218 int rtn = LDAP_COMPARE_TRUE;
1220 for ( f = flist ; f != NULL; f = f->cf_next ) {
1221 int rc = test_comp_filter( syn, a, f );
1222 if ( rc == LDAP_COMPARE_TRUE ) {
1227 if ( rc != LDAP_COMPARE_FALSE ) {
1236 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1237 struct berval* bv_assert )
1242 assert( mr != NULL );
1243 assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1245 if( !mr->smr_match ) return LDAP_INAPPROPRIATE_MATCHING;
1247 rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1248 mr, bv_attr, bv_assert );
1250 if ( rc != LDAP_SUCCESS ) return rc;
1252 return match ? LDAP_COMPARE_FALSE : LDAP_COMPARE_TRUE;
1256 * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1259 test_comp_filter_item(
1261 ComponentSyntaxInfo *csi_attr,
1262 ComponentAssertion *ca )
1265 void *attr_nm, *assert_nm;
1267 if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1268 OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1269 /* componentFilterMatch inside of componentFilterMatch */
1270 rc = test_comp_filter( syn, csi_attr, ca->ca_cf );
1274 /* Memory for storing will-be-extracted attribute values */
1275 attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1276 if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
1278 /* Memory for storing component assertion values */
1279 if( !ca->ca_comp_data.cd_mem_op ) {
1280 assert_nm = nibble_mem_allocator ( 256, 64 );
1282 nibble_mem_free ( attr_nm );
1283 return LDAP_PROTOCOL_ERROR;
1285 ca->ca_comp_data.cd_mem_op = assert_nm;
1288 assert_nm = ca->ca_comp_data.cd_mem_op;
1291 /* component reference initialization */
1292 if ( ca->ca_comp_ref ) {
1293 ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1295 rc = test_components( attr_nm, assert_nm, csi_attr, ca );
1297 /* free memory used for storing extracted attribute value */
1298 nibble_mem_free ( attr_nm );
1305 ComponentSyntaxInfo *a,
1306 ComponentFilter *f )
1310 if ( !f ) return LDAP_PROTOCOL_ERROR;
1312 Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
1313 switch ( f->cf_choice ) {
1314 case SLAPD_FILTER_COMPUTED:
1317 case LDAP_COMP_FILTER_AND:
1318 rc = test_comp_filter_and( syn, a, f->cf_and );
1320 case LDAP_COMP_FILTER_OR:
1321 rc = test_comp_filter_or( syn, a, f->cf_or );
1323 case LDAP_COMP_FILTER_NOT:
1324 rc = test_comp_filter( syn, a, f->cf_not );
1327 case LDAP_COMPARE_TRUE:
1328 rc = LDAP_COMPARE_FALSE;
1330 case LDAP_COMPARE_FALSE:
1331 rc = LDAP_COMPARE_TRUE;
1335 case LDAP_COMP_FILTER_ITEM:
1336 rc = test_comp_filter_item( syn, a, f->cf_ca );
1339 rc = LDAP_PROTOCOL_ERROR;
1346 free_comp_filter_list( ComponentFilter* f )
1348 ComponentFilter* tmp;
1349 for ( tmp = f; tmp; tmp = tmp->cf_next ) {
1350 free_comp_filter( tmp );
1355 free_comp_filter( ComponentFilter* f )
1358 Debug( LDAP_DEBUG_FILTER,
1359 "free_comp_filter: Invalid filter so failed to release memory\n",
1363 switch ( f->cf_choice ) {
1364 case LDAP_COMP_FILTER_AND:
1365 case LDAP_COMP_FILTER_OR:
1366 free_comp_filter_list( f->cf_any );
1368 case LDAP_COMP_FILTER_NOT:
1369 free_comp_filter( f->cf_any );
1371 case LDAP_COMP_FILTER_ITEM:
1372 if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op ) {
1373 nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1382 component_free( ComponentFilter *f ) {
1383 free_comp_filter( f );
1387 free_ComponentData( Attribute *a ) {
1388 if ( a->a_comp_data->cd_mem_op )
1389 component_destructor( a->a_comp_data->cd_mem_op );
1390 free ( a->a_comp_data );
1391 a->a_comp_data = NULL;