1 /* component.c -- Component Filter Match Routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2004 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;
43 #define OID_ALL_COMP_MATCH "1.2.36.79672281.1.13.6"
44 #define OID_COMP_FILTER_MATCH "1.2.36.79672281.1.13.2"
45 #define MAX_LDAP_STR_LEN 128
48 peek_componentId_type( ComponentAssertionValue* cav );
51 strip_cav_str( ComponentAssertionValue* cav, char* str);
54 peek_cav_str( ComponentAssertionValue* cav, char* str );
57 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
58 ComponentFilter** filt, const char** text );
61 free_comp_filter( ComponentFilter* f );
64 test_comp_filter( Syntax *syn, Attribute *a, struct berval *bv,
68 componentCertificateValidate(
76 componentFilterValidate(
84 allComponentsValidate(
92 componentFilterMatch (
100 Attribute *a = (Attribute*)value;
101 MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue;
105 if ( !(mr && mr->smr_usage & SLAP_MR_COMPONENT) || !ma->ma_cf )
106 return LDAP_INAPPROPRIATE_MATCHING;
108 rc = test_comp_filter( syntax, a, a->a_vals, ma->ma_cf );
110 if ( rc == LDAP_COMPARE_TRUE ) {
114 else if ( rc == LDAP_COMPARE_FALSE ) {
119 return LDAP_INAPPROPRIATE_MATCHING;
124 directoryComponentsMatch(
129 struct berval *value,
130 void *assertedValue )
132 /* Only for Registeration */
143 struct berval *value,
144 void *assertedValue )
146 /* Only for Registeration */
152 slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav )
156 cav->cav_ptr = cav->cav_buf = bv->bv_val;
157 cav->cav_end = bv->bv_val + bv->bv_len;
162 static ComponentReference*
163 dup_comp_ref ( Operation* op, ComponentReference* cr )
166 ComponentReference* dup_cr;
167 ComponentId* ci_curr;
168 ComponentId** ci_temp;
171 dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
173 dup_cr->cr_len = cr->cr_len;
174 dup_cr->cr_string = cr->cr_string;
176 ci_temp = &dup_cr->cr_list;
177 ci_curr = cr->cr_list;
179 for ( ; ci_curr ; ci_curr = ci_curr->ci_next, ci_temp = &(*ci_temp)->ci_next ) {
180 *ci_temp = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
181 if ( !ci_temp ) return NULL;
182 **ci_temp = *ci_curr;
185 dup_cr->cr_curr = dup_cr->cr_list;
191 dup_comp_filter_list (
194 ComponentFilter* in_f,
195 ComponentFilter** out_f )
197 ComponentFilter **new, *f;
201 for ( f = in_f; f != NULL; f = f->cf_next ) {
202 rc = dup_comp_filter( op, bv, f, new );
203 if ( rc != LDAP_SUCCESS ) {
206 new = &(*new)->cf_next;
212 get_len_of_next_assert_value ( struct berval* bv, char separator )
216 if ( (bv->bv_val[ i ] == separator) || ( i >= bv->bv_len) )
220 bv->bv_val += (i + 1);
221 bv->bv_len -= (i + 1);
226 dup_comp_filter_item (
228 struct berval* assert_bv,
229 ComponentAssertion* in_ca,
230 ComponentAssertion** out_ca )
232 ComponentAssertion* ca;
235 if ( !in_ca->ca_comp_ref )
236 return SLAPD_DISCONNECT;
238 *out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
240 return LDAP_NO_MEMORY;
242 (*out_ca)->ca_comp_data.cd_tree = NULL;
243 (*out_ca)->ca_comp_data.cd_mem_op = NULL;
245 (*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref );
246 (*out_ca)->ca_use_def = 0;
247 (*out_ca)->ca_ma_rule = in_ca->ca_ma_rule;
249 (*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val;
250 len = get_len_of_next_assert_value ( assert_bv, '$' );
252 return SLAPD_DISCONNECT;
253 (*out_ca)->ca_ma_value.bv_len = len;
262 ComponentFilter *in_f,
263 ComponentFilter **out_f )
266 ComponentFilter dup_f;
267 bzero( &dup_f, sizeof(dup_f));
269 if ( !in_f ) return LDAP_PROTOCOL_ERROR;
271 switch ( in_f->cf_choice ) {
272 case LDAP_COMP_FILTER_AND:
273 rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and);
274 dup_f.cf_choice = LDAP_COMP_FILTER_AND;
276 case LDAP_COMP_FILTER_OR:
277 rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or);
278 dup_f.cf_choice = LDAP_COMP_FILTER_OR;
280 case LDAP_COMP_FILTER_NOT:
281 rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not);
282 dup_f.cf_choice = LDAP_COMP_FILTER_NOT;
284 case LDAP_COMP_FILTER_ITEM:
285 rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca );
286 dup_f.cf_choice = LDAP_COMP_FILTER_ITEM;
289 rc = LDAP_PROTOCOL_ERROR;
292 if ( rc == LDAP_SUCCESS ) {
293 *out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx );
302 get_aliased_filter ( Operation* op, MatchingRuleAssertion* ma, AttributeAliasing* aa, const char** text )
305 struct berval assert_bv;
306 ComponentAssertion* ca;
308 Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
310 if ( !aa->aa_cf ) return LDAP_PROTOCOL_ERROR;
312 assert_bv = ma->ma_value;
313 /* Attribute Description is replaced with aliased one */
314 ma->ma_desc = aa->aa_aliased_ad;
315 ma->ma_rule = aa->aa_mr;
317 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
318 * the component assertion value in assert_bv
319 * Multiple values may be separated with '$'
321 rc = dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf );
325 get_comp_filter( Operation* op, struct berval* bv, ComponentFilter** filt,
328 ComponentAssertionValue cav;
331 Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
332 if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) {
335 rc = parse_comp_filter( op, &cav, filt, text );
336 bv->bv_val = cav.cav_ptr;
342 eat_whsp( ComponentAssertionValue* cav )
344 for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) {
350 cav_cur_len( ComponentAssertionValue* cav )
352 return cav->cav_end - cav->cav_ptr;
356 comp_first_element( ComponentAssertionValue* cav )
359 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
360 return LDAP_COMP_FILTER_ITEM;
362 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
363 return LDAP_COMP_FILTER_AND;
365 else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
366 return LDAP_COMP_FILTER_OR;
368 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
369 return LDAP_COMP_FILTER_NOT;
372 return LDAP_COMP_FILTER_UNDEFINED;
376 comp_next_element( ComponentAssertionValue* cav )
380 if ( *(cav->cav_ptr) == ',' ) {
381 /* move pointer to the next CA */
383 return comp_first_element( cav );
385 else return LDAP_COMP_FILTER_UNDEFINED;
389 get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
390 ComponentFilter** f, const char** text )
392 ComponentFilter **new;
396 Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
398 for ( tag = comp_first_element( cav ); tag != LDAP_COMP_FILTER_UNDEFINED;
399 tag = comp_next_element( cav ) )
401 err = parse_comp_filter( op, cav, new, text );
402 if ( err != LDAP_SUCCESS )
404 new = &(*new)->cf_next;
408 return( LDAP_SUCCESS );
412 get_componentId( Operation *op, ComponentAssertionValue* cav,
413 ComponentId ** cid, const char** text )
419 type = peek_componentId_type( cav );
421 Debug( LDAP_DEBUG_FILTER, "get_compId [%d]\n", type, 0, 0 );
426 case LDAP_COMPREF_IDENTIFIER :
427 _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
428 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
429 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
430 _cid.ci_val.ci_identifier.bv_len = len;
433 case LDAP_COMPREF_FROM_BEGINNING :
434 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
435 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
436 _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
439 case LDAP_COMPREF_FROM_END :
440 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
441 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
442 _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
445 case LDAP_COMPREF_COUNT :
446 _cid.ci_val.ci_count = 0;
449 case LDAP_COMPREF_CONTENT :
450 _cid.ci_val.ci_content = 1;
451 cav->cav_ptr += strlen("content");
453 case LDAP_COMPREF_SELECT :
454 if ( cav->cav_ptr[len] != '(' )
455 return LDAP_COMPREF_UNDEFINED;
456 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
457 cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
459 _cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
460 _cid.ci_val.ci_select_value.bv_len = len - 1 ;
461 cav->cav_ptr += len + 1;
463 case LDAP_COMPREF_ALL :
464 _cid.ci_val.ci_all = '*';
468 return LDAP_COMPREF_UNDEFINED;
472 *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
474 *cid = malloc( sizeof( ComponentId ) );
480 peek_componentId_type( ComponentAssertionValue* cav )
483 if ( cav->cav_ptr[0] == '-' )
484 return LDAP_COMPREF_FROM_END;
485 else if ( cav->cav_ptr[0] == '(' )
486 return LDAP_COMPREF_SELECT;
487 else if ( cav->cav_ptr[0] == '*' )
488 return LDAP_COMPREF_ALL;
489 else if ( cav->cav_ptr[0] == '0' )
490 return LDAP_COMPREF_COUNT;
491 else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' )
492 return LDAP_COMPREF_FROM_BEGINNING;
493 else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
494 strncmp(cav->cav_ptr,"content",7) == 0 )
495 return LDAP_COMPREF_CONTENT;
496 else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
497 (cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
499 return LDAP_COMPREF_IDENTIFIER;
501 return LDAP_COMPREF_UNDEFINED;
505 comp_next_id( ComponentAssertionValue* cav )
508 if ( *(cav->cav_ptr) == '.' ) {
510 return LDAP_COMPREF_DEFINED;
512 else return LDAP_COMPREF_UNDEFINED;
516 get_component_reference( Operation *op, ComponentAssertionValue* cav,
517 ComponentReference** cr, const char** text )
521 ComponentReference* ca_comp_ref;
522 ComponentId** cr_list;
526 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS )
530 ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
532 ca_comp_ref = malloc( sizeof( ComponentReference ) );
534 if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
536 cr_list = &ca_comp_ref->cr_list;
538 for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
539 ; type = comp_next_id( cav ), count++ ) {
540 rc = get_componentId( op, cav, cr_list, text );
541 if ( rc == LDAP_SUCCESS ) {
542 if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
543 cr_list = &(*cr_list)->ci_next;
545 else if ( rc == LDAP_COMPREF_UNDEFINED )
548 ca_comp_ref->cr_len = count;
550 if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
552 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
558 if ( rc == LDAP_SUCCESS ) {
563 op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
565 free( ca_comp_ref ) ;
571 get_ca_use_default( Operation *op, ComponentAssertionValue* cav,
572 int* ca_use_def, const char** text )
574 strip_cav_str( cav, "useDefaultValues" );
575 if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
576 strip_cav_str( cav, "TRUE" );
578 } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
579 strip_cav_str( cav, "FALSE" );
582 return LDAP_INVALID_SYNTAX;
589 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
590 MatchingRule** mr, const char** text )
593 struct berval rule_text = { 0L, NULL };
597 for ( ; ; count++ ) {
598 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
599 cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
600 cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
605 *text = "component matching rule not recognized";
606 return LDAP_INAPPROPRIATE_MATCHING;
609 rule_text.bv_len = count;
610 rule_text.bv_val = cav->cav_ptr;
611 *mr = mr_bvfind( &rule_text );
612 cav->cav_ptr += count;
613 Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n", (*mr)->smr_mrule.mr_oid, 0, 0 );
615 *text = "component matching rule not recognized";
616 return LDAP_INAPPROPRIATE_MATCHING;
622 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
624 int count, sequent_dquote, unclosed_brace, succeed;
628 * Four cases of GSER <Values>
630 * StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
631 * 2) '...'B or '...'H :
632 * BitStringVal, OctetStringVal
634 * SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
635 * 4) Between two white spaces
636 * INTEGER, BOOLEAN, NULL,ENUMERATE, etc
640 if ( cav->cav_ptr[0] == '"' ) {
641 for( count = 1, sequent_dquote = 0 ; ; count++ ) {
642 /* In order to find escaped double quote */
643 if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
644 else sequent_dquote = 0;
646 if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
650 if ( ( cav->cav_ptr[count] == '"' && cav->cav_ptr[count-1] != '"') ||
651 ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) ) {
657 if ( !succeed || cav->cav_ptr[count] != '"' )
658 return LDAP_FILTER_ERROR;
660 bv->bv_val = cav->cav_ptr + 1;
661 bv->bv_len = count - 1; /* exclude '"' */
663 else if ( cav->cav_ptr[0] == '\'' ) {
664 for( count = 1 ; ; count++ ) {
665 if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
668 if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B')||
669 (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') ) {
675 if ( !succeed || !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
676 return LDAP_FILTER_ERROR;
678 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
679 bv->bv_len = count - 2;/* exclude "'H" or "'B" */
682 else if ( cav->cav_ptr[0] == '{' ) {
683 for( count = 1, unclosed_brace = 1 ; ; count++ ) {
684 if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
685 if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
687 if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end )
689 if ( unclosed_brace == 0 ) {
695 if ( !succeed || cav->cav_ptr[count] != '}' )
696 return LDAP_FILTER_ERROR;
698 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
699 bv->bv_len = count - 1;/* exclude "'B" */
703 /*Find following white space where the value is ended*/
704 for( count = 1 ; ; count++ ) {
705 if ( cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == ' ' || (cav->cav_ptr+count) > cav->cav_end ) {
709 bv->bv_val = cav->cav_ptr;
713 cav->cav_ptr += bv->bv_len;
719 get_matching_value( Operation *op, ComponentAssertion* ca,
720 ComponentAssertionValue* cav, struct berval* bv,
723 if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
724 if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
725 return LDAP_FILTER_ERROR;
729 /* embeded componentFilterMatch Description */
730 bv->bv_val = cav->cav_ptr;
731 bv->bv_len = cav_cur_len( cav );
737 /* Don't move the position pointer, just peek given string */
739 peek_cav_str( ComponentAssertionValue* cav, char* str )
742 if ( cav_cur_len( cav ) >= strlen( str ) &&
743 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
746 return LDAP_INVALID_SYNTAX;
750 strip_cav_str( ComponentAssertionValue* cav, char* str)
753 if ( cav_cur_len( cav ) >= strlen( str ) &&
754 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 ) {
755 cav->cav_ptr += strlen( str );
759 return LDAP_INVALID_SYNTAX;
763 * TAG : "item", "and", "or", "not"
766 strip_cav_tag( ComponentAssertionValue* cav )
770 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
771 strip_cav_str( cav , "item:" );
772 return LDAP_COMP_FILTER_ITEM;
774 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
775 strip_cav_str( cav , "and:" );
776 return LDAP_COMP_FILTER_AND;
778 else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
779 strip_cav_str( cav , "or:" );
780 return LDAP_COMP_FILTER_OR;
782 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
783 strip_cav_str( cav , "not:" );
784 return LDAP_COMP_FILTER_NOT;
791 * when encoding, "item" is denotation of ComponentAssertion
792 * ComponentAssertion :: SEQUENCE {
793 * component ComponentReference (SIZE(1..MAX)) OPTIONAL,
794 * useDefaultValues BOOLEAN DEFAULT TRUE,
795 * rule MATCHING-RULE.&id,
796 * value MATCHING-RULE.&AssertionType }
799 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
803 ComponentAssertion* _ca;
808 Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
810 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
812 _ca = malloc( sizeof( ComponentAssertion ) );
814 if ( !_ca ) return LDAP_NO_MEMORY;
816 _ca->ca_comp_data.cd_tree = NULL;
817 _ca->ca_comp_data.cd_mem_op = NULL;
819 rc = peek_cav_str( cav, "component" );
820 if ( rc == LDAP_SUCCESS ) {
821 strip_cav_str( cav, "component" );
822 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
823 if ( rc != LDAP_SUCCESS ) {
825 op->o_tmpfree( _ca, op->o_tmpmemctx );
828 return LDAP_INVALID_SYNTAX;
832 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
835 rc = peek_cav_str( cav, "useDefaultValues");
836 if ( rc == LDAP_SUCCESS ) {
837 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
838 if ( rc != LDAP_SUCCESS ) {
840 op->o_tmpfree( _ca, op->o_tmpmemctx );
843 return LDAP_INVALID_SYNTAX;
845 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
848 else _ca->ca_use_def = 1;
850 if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
851 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
853 op->o_tmpfree( _ca, op->o_tmpmemctx );
856 return LDAP_INAPPROPRIATE_MATCHING;
859 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
861 if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
862 get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
864 op->o_tmpfree( _ca, op->o_tmpmemctx );
867 return LDAP_INVALID_SYNTAX;
871 * Normalize the value of this component assertion when the matching
872 * rule is one of existing matching rules
874 mr = _ca->ca_ma_rule;
875 if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
877 value.bv_val[value.bv_len] = '\0';
878 rc = mr->smr_normalize (
879 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
881 &value, &_ca->ca_ma_value, op->o_tmpmemctx );
882 if ( rc != LDAP_SUCCESS )
886 _ca->ca_ma_value = value;
888 * Validate the value of this component assertion
890 if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
891 return LDAP_INVALID_SYNTAX;
895 /* componentFilterMatch contains componentFilterMatch in it */
896 if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
898 bv.bv_val = cav->cav_ptr;
899 bv.bv_len = cav_cur_len( cav );
900 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
901 if ( rc != LDAP_SUCCESS ) {
903 op->o_tmpfree( _ca, op->o_tmpmemctx );
908 cav->cav_ptr = bv.bv_val;
909 assert( cav->cav_end >= bv.bv_val );
917 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
918 ComponentFilter** filt, const char** text )
921 * A component filter looks like this coming in:
922 * Filter ::= CHOICE {
923 * item [0] ComponentAssertion,
924 * and [1] SEQUENCE OF ComponentFilter,
925 * or [2] SEQUENCE OF ComponentFilter,
926 * not [3] ComponentFilter,
933 /* TAG : item, and, or, not in RFC 2254 */
934 tag = strip_cav_tag( cav );
936 if ( tag == LBER_ERROR ) {
937 *text = "error decoding comp filter";
938 return LDAP_PROTOCOL_ERROR;
941 if ( tag != LDAP_COMP_FILTER_NOT )
942 strip_cav_str( cav, "{");
949 switch ( f.cf_choice ) {
950 case LDAP_COMP_FILTER_AND:
951 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
952 err = get_comp_filter_list( op, cav, &f.cf_and, text );
953 if ( err != LDAP_SUCCESS ) {
956 if ( f.cf_and == NULL ) {
957 f.cf_choice = SLAPD_FILTER_COMPUTED;
958 f.cf_result = LDAP_COMPARE_TRUE;
962 case LDAP_COMP_FILTER_OR:
963 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
964 err = get_comp_filter_list( op, cav, &f.cf_or, text );
965 if ( err != LDAP_SUCCESS ) {
968 if ( f.cf_or == NULL ) {
969 f.cf_choice = SLAPD_FILTER_COMPUTED;
970 f.cf_result = LDAP_COMPARE_FALSE;
972 /* no assert - list could be empty */
975 case LDAP_COMP_FILTER_NOT:
976 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
977 err = parse_comp_filter( op, cav, &f.cf_not, text );
978 if ( err != LDAP_SUCCESS ) {
982 assert( f.cf_not != NULL );
983 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
984 int fresult = f.cf_not->cf_result;
985 f.cf_choice = SLAPD_FILTER_COMPUTED;
986 op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
990 case LDAP_COMPARE_TRUE:
991 f.cf_result = LDAP_COMPARE_FALSE;
993 case LDAP_COMPARE_FALSE:
994 f.cf_result = LDAP_COMPARE_TRUE;
997 /* (!Undefined) is Undefined */
1002 case LDAP_COMP_FILTER_ITEM:
1003 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1004 err = get_item( op, cav, &f.cf_ca, text );
1005 if ( err != LDAP_SUCCESS ) {
1009 assert( f.cf_ca != NULL );
1013 f.cf_choice = SLAPD_FILTER_COMPUTED;
1014 f.cf_result = SLAPD_COMPARE_UNDEFINED;
1018 if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1019 *text = "Component Filter Syntax Error";
1023 if ( tag != LDAP_COMP_FILTER_NOT )
1024 strip_cav_str( cav, "}");
1026 if ( err == LDAP_SUCCESS ) {
1028 *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1030 *filt = malloc( sizeof(f) );
1039 test_comp_filter_and(
1043 ComponentFilter *flist )
1046 int rtn = LDAP_COMPARE_TRUE;
1048 for ( f = flist ; f != NULL; f = f->cf_next ) {
1049 int rc = test_comp_filter( syn, a, bv, f );
1050 if ( rc == LDAP_COMPARE_FALSE ) {
1055 if ( rc != LDAP_COMPARE_TRUE ) {
1064 test_comp_filter_or(
1068 ComponentFilter *flist )
1071 int rtn = LDAP_COMPARE_TRUE;
1073 for ( f = flist ; f != NULL; f = f->cf_next ) {
1074 int rc = test_comp_filter( syn, a, bv, f );
1075 if ( rc == LDAP_COMPARE_TRUE ) {
1080 if ( rc != LDAP_COMPARE_FALSE ) {
1089 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1090 struct berval* bv_assert )
1095 assert( mr != NULL );
1096 assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1098 if( !mr->smr_match ) {
1099 return LDAP_INAPPROPRIATE_MATCHING;
1102 rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1103 mr, bv_attr, bv_assert );
1104 if ( rc == LDAP_SUCCESS )
1105 return match? LDAP_COMPARE_FALSE:LDAP_COMPARE_TRUE;
1111 * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1114 test_comp_filter_item(
1118 ComponentAssertion *ca )
1121 ComponentSyntaxInfo* csi_attr, *csi_assert=NULL;
1122 void *attr_nm, *assert_nm;
1124 if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1125 OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1126 /* componentFilterMatch inside of componentFilterMatch */
1127 rc = test_comp_filter( syn, a, bv, ca->ca_cf );
1131 /* load attribute containg components */
1132 if ( !a->a_comp_data && attr_converter && nibble_mem_allocator ) {
1133 a->a_comp_data = malloc( sizeof( ComponentData ) );
1134 /* Memory chunk pre-allocation for decoders */
1135 a->a_comp_data->cd_mem_op = (void*) nibble_mem_allocator ( 1024, 128 );
1136 a->a_comp_data->cd_tree = attr_converter (a, syn, bv);
1139 if ( a->a_comp_data->cd_tree == NULL ) {
1140 nibble_mem_free( a->a_comp_data->cd_mem_op );
1141 free ( a->a_comp_data );
1142 a->a_comp_data = NULL;
1143 return LDAP_PROTOCOL_ERROR;
1146 /* Memory for storing will-be-extracted attribute values */
1147 attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1148 if ( !attr_nm )return LDAP_PROTOCOL_ERROR;
1150 /* Memory for storing component assertion values */
1151 if( !ca->ca_comp_data.cd_mem_op ) {
1152 assert_nm = nibble_mem_allocator ( 256, 64 );
1154 nibble_mem_free ( attr_nm );
1155 return LDAP_PROTOCOL_ERROR;
1157 ca->ca_comp_data.cd_mem_op = assert_nm;
1160 assert_nm = ca->ca_comp_data.cd_mem_op;
1163 /* component reference initialization */
1164 ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1165 rc = test_components( attr_nm, assert_nm, (ComponentSyntaxInfo*)a->a_comp_data->cd_tree, ca );
1167 /* free memory used for storing extracted attribute value */
1168 nibble_mem_free ( attr_nm );
1177 ComponentFilter *f )
1181 if ( !f ) return LDAP_PROTOCOL_ERROR;
1183 Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
1184 switch ( f->cf_choice ) {
1185 case SLAPD_FILTER_COMPUTED:
1188 case LDAP_COMP_FILTER_AND:
1189 rc = test_comp_filter_and( syn, a, bv, f->cf_and );
1191 case LDAP_COMP_FILTER_OR:
1192 rc = test_comp_filter_or( syn, a, bv, f->cf_or );
1194 case LDAP_COMP_FILTER_NOT:
1195 rc = test_comp_filter( syn, a, bv, f->cf_not );
1198 case LDAP_COMPARE_TRUE:
1199 rc = LDAP_COMPARE_FALSE;
1201 case LDAP_COMPARE_FALSE:
1202 rc = LDAP_COMPARE_TRUE;
1206 case LDAP_COMP_FILTER_ITEM:
1207 rc = test_comp_filter_item( syn, a, bv, f->cf_ca );
1210 rc = LDAP_PROTOCOL_ERROR;
1217 free_comp_filter_list( ComponentFilter* f )
1219 ComponentFilter* tmp;
1220 for ( tmp = f ; tmp; tmp = tmp->cf_next );
1222 free_comp_filter( tmp );
1227 free_comp_filter( ComponentFilter* f )
1229 switch ( f->cf_choice ) {
1230 case LDAP_COMP_FILTER_AND:
1231 case LDAP_COMP_FILTER_OR:
1232 free_comp_filter_list( f->cf_any );
1234 case LDAP_COMP_FILTER_NOT:
1235 free_comp_filter( f->cf_any );
1237 case LDAP_COMP_FILTER_ITEM:
1238 if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op )
1239 nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1248 component_free( ComponentFilter *f ) {
1249 free_comp_filter( f );