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>
28 #ifdef LDAP_COMP_MATCH
33 peek_componentId_type( ComponentAssertionValue* cav );
36 strip_cav_str( ComponentAssertionValue* cav, char* str);
39 peek_cav_str( ComponentAssertionValue* cav, char* str );
42 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
43 ComponentFilter** filt, const char** text );
46 test_comp_filter_attr( Operation *op, Attribute *a, struct berval *bv,
50 componentFilterValidate(
58 componentFilterMatch (
66 /* FIXME: to be implemented */
73 slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav)
77 len = ldap_pvt_filter_value_unescape( bv->bv_val );
78 cav->cav_ptr = cav->cav_buf = bv->bv_val;
79 cav->cav_end = bv->bv_val + len;
83 get_comp_filter ( Operation* op, struct berval* bv, ComponentFilter** filt,
86 ComponentAssertionValue cav;
89 LDAP_LOG( FILTER, ENTRY, "get_comp_filter\n", 0, 0, 0 );
91 Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
93 slapd_ber2cav(bv, &cav);
94 rc = parse_comp_filter( op, &cav, filt, text );
95 bv->bv_val = cav.cav_ptr;
100 eat_whsp( ComponentAssertionValue* cav )
104 if ( cav->cav_ptr[count++] == ' ' ) cav->cav_ptr++;
110 cav_cur_len( ComponentAssertionValue* cav )
112 return cav->cav_end - cav->cav_ptr;
116 comp_first_element( ComponentAssertionValue* cav )
119 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
120 return LDAP_COMP_FILTER_ITEM;
122 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
123 return LDAP_COMP_FILTER_AND;
125 else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
126 return LDAP_COMP_FILTER_OR;
128 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
129 return LDAP_COMP_FILTER_NOT;
132 return LDAP_COMP_FILTER_UNDEFINED;
136 comp_next_element( ComponentAssertionValue* cav )
140 if ( *(cav->cav_ptr) == ',' ) {
141 /* move pointer to the next CA */
143 return comp_first_element( cav );
145 else return LDAP_COMP_FILTER_UNDEFINED;
149 get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
150 ComponentFilter** f, const char** text )
152 ComponentFilter **new;
159 LDAP_LOG( FILTER, ENTRY, "get_comp_filter_list\n", 0, 0, 0 );
161 Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
164 for ( tag = comp_first_element( cav ); tag != LDAP_COMP_FILTER_UNDEFINED;
165 tag = comp_next_element( cav ) )
167 err = parse_comp_filter( op, cav, new, text );
168 if ( err != LDAP_SUCCESS )
170 new = &(*new)->cf_next;
175 return( LDAP_SUCCESS );
179 get_componentId( Operation *op, ComponentAssertionValue* cav,
180 ComponentId ** cid, const char** text )
186 type = peek_componentId_type( cav );
189 LDAP_LOG( FILTER, ENTRY, "get_compId [%d]\n", type, 0, 0 );
191 Debug( LDAP_DEBUG_FILTER, "get_compId [%d]\n", type, 0, 0 );
197 case LDAP_COMPREF_IDENTIFIER :
198 _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
199 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
200 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
201 _cid.ci_val.ci_identifier.bv_len = len;
204 case LDAP_COMPREF_FROM_BEGINNING :
205 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
206 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
207 _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
210 case LDAP_COMPREF_FROM_END :
211 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
212 cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
213 _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
216 case LDAP_COMPREF_COUNT :
217 _cid.ci_val.ci_count = 0;
220 case LDAP_COMPREF_CONTENT :
221 /* FIXEME: yet to be implemented */
223 case LDAP_COMPREF_SELECT :
224 /* FIXEME: yet to be implemented */
226 case LDAP_COMPREF_ALL :
227 _cid.ci_val.ci_all = '*';
230 LDAP_LOG( FILTER, ENTRY, "get_compId : ALL\n", 0, 0, 0 );
232 Debug( LDAP_DEBUG_FILTER, "get_compId : ALL\n", 0, 0, 0 );
236 return LDAP_COMPREF_UNDEFINED;
239 *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
245 peek_componentId_type( ComponentAssertionValue* cav )
248 if ( cav->cav_ptr[0] == '-' )
249 return LDAP_COMPREF_FROM_END;
250 else if ( cav->cav_ptr[0] == '(' )
251 return LDAP_COMPREF_SELECT;
252 else if ( cav->cav_ptr[0] == '*' )
253 return LDAP_COMPREF_ALL;
254 else if ( cav->cav_ptr[0] == '0' )
255 return LDAP_COMPREF_COUNT;
256 else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' )
257 return LDAP_COMPREF_FROM_BEGINNING;
258 else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
259 strncmp(cav->cav_ptr,"content",7) == 0 )
260 return LDAP_COMPREF_CONTENT;
261 else if ( cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z' )
262 return LDAP_COMPREF_IDENTIFIER;
264 return LDAP_COMPREF_UNDEFINED;
268 comp_next_id( ComponentAssertionValue* cav )
271 if ( *(cav->cav_ptr) == '.' ) {
273 return LDAP_COMPREF_DEFINED;
275 else return LDAP_COMPREF_UNDEFINED;
279 get_component_reference( Operation *op, ComponentAssertionValue* cav,
280 ComponentReference** cr, const char** text )
284 ComponentReference* ca_comp_ref;
285 ComponentId** cr_list;
289 op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
291 cr_list = &ca_comp_ref->cr_list;
292 strip_cav_str( cav, "\"");
293 for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
294 ; type = comp_next_id( cav ), count++ ) {
295 rc = get_componentId( op, cav, cr_list, text );
296 if ( rc == LDAP_SUCCESS ) {
297 if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
298 cr_list = &(*cr_list)->ci_next;
301 ca_comp_ref->cr_len = count;
302 strip_cav_str( cav, "\"");
304 if ( rc == LDAP_SUCCESS ) {
308 else op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
314 get_ca_use_default( Operation *op, ComponentAssertionValue* cav,
315 int* ca_use_def, const char** text )
318 if ( peek_cav_str( cav, "useDefaultValues" ) == LDAP_SUCCESS ) {
319 strip_cav_str( cav, "useDefaultValues" );
320 if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
321 strip_cav_str( cav, "TRUE" );
324 else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
325 strip_cav_str( cav, "FALSE" );
329 return LDAP_INVALID_SYNTAX;
331 else /* If not defined, default value is TRUE */
337 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
338 MatchingRule** mr, const char** text )
342 struct berval rule_text = { 0L, NULL };
346 for ( ; ; count++ ) {
347 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
348 cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
349 cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
354 *text = "component matching rule not recognized";
355 return LDAP_INAPPROPRIATE_MATCHING;
358 rule_text.bv_len = count;
359 rule_text.bv_val = cav->cav_ptr;
360 *mr = mr_bvfind( &rule_text );
361 cav->cav_ptr += count;
363 LDAP_LOG( FILTER, ENTRY, "get_matching_rule: %s\n", (*mr)->smr_mrule.mr_oid, 0, 0 );
365 Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n", (*mr)->smr_mrule.mr_oid, 0, 0 );
368 *text = "component matching rule not recognized";
369 return LDAP_INAPPROPRIATE_MATCHING;
375 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
381 * Four cases of GSER <Values>
383 * StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
384 * 2) '...'B or '...'H :
385 * BitStringVal, OctetStringVal
387 * SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
388 * 4) Between two white spaces
389 * INTEGER, BOOLEAN, NULL,ENUMERATE, etc
392 if ( cav->cav_ptr[0] == '"' ) {
393 for( count = 0 ; ; count++ ) {
394 if ( cav->cav_ptr[count] == '\0' ||
395 ( cav->cav_ptr[count] == '"' && cav->cav_ptr[count-1] != '"') )
399 else if ( cav->cav_ptr[0] == '\'' ) {
400 for( count = 0 ; ; count++ ) {
401 if ( cav->cav_ptr[count] == '\0' ||
402 (cav->cav_ptr[count] == '\'' && cav->cav_ptr[count] == 'B')||
403 (cav->cav_ptr[count] == '\'' && cav->cav_ptr[count] == 'H') )
408 else if ( cav->cav_ptr[0] == '{' ) {
409 for( count = 0 ; ; count++ ) {
410 if ( cav->cav_ptr[count] == '\0' ||
411 (cav->cav_ptr[count] == '}' && cav->cav_ptr[count] == ' ') )
416 for( count = 0 ; ; count++ ) {
417 if ( cav->cav_ptr[count] == ' ')
422 bv->bv_val = cav->cav_ptr;
424 cav->cav_ptr += count;
428 get_matching_value( Operation *op, ComponentAssertion* ca,
429 ComponentAssertionValue* cav, struct berval* bv,
435 if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
436 get_GSER_value( cav, bv );
439 /* embeded componentFilterMatch Description */
440 bv->bv_val = cav->cav_ptr;
441 bv->bv_len = cav_cur_len( cav );
447 /* Don't move the position pointer, just peek given string */
449 peek_cav_str( ComponentAssertionValue* cav, char* str )
452 if ( cav_cur_len( cav ) >= strlen( str ) &&
453 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
456 return LDAP_INVALID_SYNTAX;
460 strip_cav_str( ComponentAssertionValue* cav, char* str)
463 if ( cav_cur_len( cav ) >= strlen( str ) &&
464 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 ) {
465 cav->cav_ptr += strlen( str );
469 return LDAP_INVALID_SYNTAX;
473 * TAG : "item", "and", "or", "not"
476 strip_cav_tag( ComponentAssertionValue* cav )
480 if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
481 strip_cav_str( cav , "item:" );
482 return LDAP_COMP_FILTER_ITEM;
484 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
485 strip_cav_str( cav , "and:" );
486 return LDAP_COMP_FILTER_AND;
488 else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
489 strip_cav_str( cav , "or:" );
490 return LDAP_COMP_FILTER_OR;
492 else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
493 strip_cav_str( cav , "not:" );
494 return LDAP_COMP_FILTER_NOT;
501 * when encoding, "item" is denotation of ComponentAssertion
502 * ComponentAssertion :: SEQUENCE {
503 * component ComponentReference (SIZE(1..MAX)) OPTIONAL,
504 * useDefaultValues BOOLEAN DEFAULT TRUE,
505 * rule MATCHING-RULE.&id,
506 * value MATCHING-RULE.&AssertionType }
509 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
513 ComponentAssertion* _ca;
516 LDAP_LOG( FILTER, ENTRY, "get_item: %s\n", 0, 0, 0 );
518 Debug( LDAP_DEBUG_FILTER, "get_item: %s\n", 0, 0, 0 );
520 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
522 rc = peek_cav_str( cav, "component" );
523 if ( rc == LDAP_SUCCESS ) {
524 strip_cav_str( cav, "component" );
525 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
526 if ( rc != LDAP_SUCCESS ) {
527 rc = LDAP_INVALID_SYNTAX;
528 op->o_tmpfree( _ca, op->o_tmpmemctx );
533 strip_cav_str( cav,",");
534 rc = peek_cav_str( cav, "useDefaultValues");
535 if ( rc == LDAP_SUCCESS ) {
536 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
537 if ( rc != LDAP_SUCCESS ) {
538 rc = LDAP_INVALID_SYNTAX;
539 op->o_tmpfree( _ca, op->o_tmpmemctx );
544 if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
545 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
546 rc = LDAP_INAPPROPRIATE_MATCHING;
547 op->o_tmpfree( _ca, op->o_tmpmemctx );
551 strip_cav_str( cav,",");
552 if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
553 get_matching_value( op, _ca, cav, &_ca->ca_ma_value,text ) == LDAP_SUCCESS )) {
554 rc = LDAP_INVALID_SYNTAX;
555 op->o_tmpfree( _ca, op->o_tmpmemctx );
559 /* componentFilterMatch contains componentFilterMatch in it */
560 if ( _ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT) ) {
562 bv.bv_val = cav->cav_ptr;
563 bv.bv_len = cav_cur_len( cav );
564 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
565 if ( rc != LDAP_SUCCESS ) {
566 op->o_tmpfree( _ca, op->o_tmpmemctx );
569 cav->cav_ptr = bv.bv_val;
570 assert( cav->cav_end >= bv.bv_val );
578 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
579 ComponentFilter** filt, const char** text )
582 * A component filter looks like this coming in:
583 * Filter ::= CHOICE {
584 * item [0] ComponentAssertion,
585 * and [1] SEQUENCE OF ComponentFilter,
586 * or [2] SEQUENCE OF ComponentFilter,
587 * not [3] ComponentFilter,
595 /* TAG : item, and, or, not in RFC 2254 */
596 tag = strip_cav_tag( cav );
598 if ( tag == LBER_ERROR ) {
599 *text = "error decoding comp filter";
600 return LDAP_PROTOCOL_ERROR;
603 if ( tag != LDAP_COMP_FILTER_NOT )
604 strip_cav_str( cav, "{");
611 switch ( f.cf_choice ) {
612 case LDAP_COMP_FILTER_AND:
614 LDAP_LOG( FILTER, ENTRY, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
616 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
618 err = get_comp_filter_list( op, cav, &f.cf_and, text );
619 if ( err != LDAP_SUCCESS ) {
622 if ( f.cf_and == NULL ) {
623 f.cf_choice = SLAPD_FILTER_COMPUTED;
624 f.cf_result = LDAP_COMPARE_TRUE;
628 case LDAP_COMP_FILTER_OR:
630 LDAP_LOG( FILTER, ENTRY, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
632 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
634 err = get_comp_filter_list( op, cav, &f.cf_or, text );
635 if ( err != LDAP_SUCCESS ) {
638 if ( f.cf_or == NULL ) {
639 f.cf_choice = SLAPD_FILTER_COMPUTED;
640 f.cf_result = LDAP_COMPARE_FALSE;
642 /* no assert - list could be empty */
645 case LDAP_COMP_FILTER_NOT:
647 LDAP_LOG( FILTER, ENTRY, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
649 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
651 err = parse_comp_filter( op, cav, &f.cf_not, text );
652 if ( err != LDAP_SUCCESS ) {
656 assert( f.cf_not != NULL );
657 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
658 int fresult = f.cf_not->cf_result;
659 f.cf_choice = SLAPD_FILTER_COMPUTED;
660 op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
664 case LDAP_COMPARE_TRUE:
665 f.cf_result = LDAP_COMPARE_FALSE;
667 case LDAP_COMPARE_FALSE:
668 f.cf_result = LDAP_COMPARE_TRUE;
671 /* (!Undefined) is Undefined */
676 case LDAP_COMP_FILTER_ITEM:
678 LDAP_LOG( FILTER, ENTRY, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
680 Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
682 err = get_item( op, cav, &f.cf_ca, text );
683 if ( err != LDAP_SUCCESS ) {
687 assert( f.cf_ca != NULL );
691 f.cf_choice = SLAPD_FILTER_COMPUTED;
692 f.cf_result = SLAPD_COMPARE_UNDEFINED;
696 if ( tag != LDAP_COMP_FILTER_NOT )
697 strip_cav_str( cav, "}");
699 if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
701 f.cf_choice = SLAPD_FILTER_COMPUTED;
702 f.cf_result = SLAPD_COMPARE_UNDEFINED;
706 if ( err == LDAP_SUCCESS ) {
707 *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
715 test_comp_filter_and(
719 ComponentFilter *flist )
722 int rtn = LDAP_COMPARE_TRUE;
724 for ( f = flist ; f != NULL; f = f->cf_next ) {
725 int rc = test_comp_filter_attr( op, a, bv, f );
726 if ( rc == LDAP_COMPARE_FALSE ) {
731 if ( rc != LDAP_COMPARE_TRUE ) {
744 ComponentFilter *flist )
747 int rtn = LDAP_COMPARE_TRUE;
749 for ( f = flist ; f != NULL; f = f->cf_next ) {
750 int rc = test_comp_filter_attr( op, a, bv, f );
751 if ( rc == LDAP_COMPARE_TRUE ) {
756 if ( rc != LDAP_COMPARE_FALSE ) {
765 * Convert attribute value to C internal data structure
766 * This function has an associated ASN.1 type
767 * bv must contain the value for the type( type name is T1 )
768 * This function is linked to ssyn_attr2comp
772 * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
775 test_comp_filter_item(
779 ComponentAssertion *ca )
781 int rc = LDAP_COMPARE_TRUE;
783 ComponentSyntaxInfo* csi_attr, *csi_assert;
785 if ( (ca->ca_ma_rule->smr_usage & SLAP_MR_COMPONENT) && ca->ca_cf ) {
786 /* componentFilterMatch inside of componentFilterMatch */
787 rc = test_comp_filter_attr( op, a, bv, ca->ca_cf );
791 assert( !(ca->ca_ma_rule->smr_usage & SLAP_MR_COMPONENT) );
792 /* FIXME : Return ALWAYS true */
793 return LDAP_COMPARE_TRUE;
797 * If matched, LDAP_COMPARE_TRUE is returned
800 test_comp_filter_entry(
803 MatchingRuleAssertion *mra )
808 mra->cf->cf_ca->ca_mra = mra;
811 LDAP_LOG( FILTER, ENTRY, "test_comp_filter_entry\n", 0, 0, 0 );
813 Debug( LDAP_DEBUG_FILTER, "test_comp_filter_entry\n", 0, 0, 0 );
815 if ( mra->ma_desc ) {
817 * ma_desc is available, so filtering for one attribute
818 * SEARCH permissionc can be checked directly
820 if ( !access_allowed( op, e, mra->ma_desc,
821 &mra->ma_value, ACL_SEARCH, NULL ) )
823 return LDAP_INSUFFICIENT_ACCESS;
825 /* Find attributes that componentFilter Match can be applied to */
826 for( a=attrs_find( e->e_attrs, mra->ma_desc );
828 a = attrs_find( a->a_next, mra->ma_desc ) )
830 struct berval *bv = a->a_vals;
832 for ( ; bv->bv_val != NULL ; bv++ ) {
835 rc = test_comp_filter_attr( op, a, bv, mra->cf );
836 if ( rc == LDAP_COMPARE_TRUE ) return rc;
842 * No attribute description : test all
844 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
845 struct berval *bv, value;
846 const char *text = NULL;
849 /* check if matching is appropriate */
850 if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type
855 /* check search access */
856 if ( !access_allowed( op, e,
857 a->a_desc, &value, ACL_SEARCH, NULL ) ) {
863 for ( ; bv->bv_val != NULL ; bv++ ) {
866 rc = test_comp_filter_attr( op, a, bv, mra->cf );
867 if ( rc == LDAP_COMPARE_TRUE ) break;
869 if ( rc != LDAP_SUCCESS ) return rc;
873 return LDAP_COMPARE_FALSE;
877 test_comp_filter_attr(
886 LDAP_LOG( FILTER, ENTRY, "test_comp_filter_attr\n", 0, 0, 0 );
888 Debug( LDAP_DEBUG_FILTER, "test_comp_filter_attr\n", 0, 0, 0 );
890 switch ( f->cf_choice ) {
891 case SLAPD_FILTER_COMPUTED:
894 case LDAP_COMP_FILTER_AND:
895 rc = test_comp_filter_and( op, a, bv, f->cf_and );
897 case LDAP_COMP_FILTER_OR:
898 rc = test_comp_filter_or( op, a, bv, f->cf_or );
900 case LDAP_COMP_FILTER_NOT:
901 rc = test_comp_filter_attr( op, a, bv, f->cf_not );
904 case LDAP_COMPARE_TRUE:
905 rc = LDAP_COMPARE_FALSE;
907 case LDAP_COMPARE_FALSE:
908 rc = LDAP_COMPARE_TRUE;
912 case LDAP_COMP_FILTER_ITEM:
913 rc = test_comp_filter_item( op, a, bv, f->cf_ca );
916 rc = LDAP_PROTOCOL_ERROR;