1 /* filterentry.c - apply a filter to an entry */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2013 The OpenLDAP Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17 * All rights reserved.
19 * Redistribution and use in source and binary forms are permitted
20 * provided that this notice is preserved and that due credit is given
21 * to the University of Michigan at Ann Arbor. The name of the University
22 * may not be used to endorse or promote products derived from this
23 * software without specific prior written permission. This software
24 * is provided ``as is'' without express or implied warranty.
31 #include <ac/socket.h>
32 #include <ac/string.h>
36 #ifdef LDAP_COMP_MATCH
37 #include "component.h"
40 static int test_filter_and( Operation *op, Entry *e, Filter *flist );
41 static int test_filter_or( Operation *op, Entry *e, Filter *flist );
42 static int test_substrings_filter( Operation *op, Entry *e, Filter *f);
43 static int test_ava_filter( Operation *op,
44 Entry *e, AttributeAssertion *ava, int type );
45 static int test_mra_filter( Operation *op,
46 Entry *e, MatchingRuleAssertion *mra );
47 static int test_presence_filter( Operation *op,
48 Entry *e, AttributeDescription *desc );
52 * test_filter - test a filter against a single entry.
54 * LDAP_COMPARE_TRUE filter matched
55 * LDAP_COMPARE_FALSE filter did not match
56 * SLAPD_COMPARE_UNDEFINED filter is undefined
57 * or an ldap result code indicating error
67 Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
69 if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
70 Debug( LDAP_DEBUG_FILTER, " UNDEFINED\n", 0, 0, 0 );
71 rc = SLAPD_COMPARE_UNDEFINED;
75 switch ( f->f_choice ) {
76 case SLAPD_FILTER_COMPUTED:
77 Debug( LDAP_DEBUG_FILTER, " COMPUTED %s (%d)\n",
78 f->f_result == LDAP_COMPARE_FALSE ? "false" :
79 f->f_result == LDAP_COMPARE_TRUE ? "true" :
80 f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" : "error",
86 case LDAP_FILTER_EQUALITY:
87 Debug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
88 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_EQUALITY );
91 case LDAP_FILTER_SUBSTRINGS:
92 Debug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
93 rc = test_substrings_filter( op, e, f );
97 Debug( LDAP_DEBUG_FILTER, " GE\n", 0, 0, 0 );
98 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_GE );
102 Debug( LDAP_DEBUG_FILTER, " LE\n", 0, 0, 0 );
103 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_LE );
106 case LDAP_FILTER_PRESENT:
107 Debug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
108 rc = test_presence_filter( op, e, f->f_desc );
111 case LDAP_FILTER_APPROX:
112 Debug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 );
113 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_APPROX );
116 case LDAP_FILTER_AND:
117 Debug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 );
118 rc = test_filter_and( op, e, f->f_and );
122 Debug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 );
123 rc = test_filter_or( op, e, f->f_or );
126 case LDAP_FILTER_NOT:
127 Debug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 );
128 rc = test_filter( op, e, f->f_not );
130 /* Flip true to false and false to true
131 * but leave Undefined alone.
134 case LDAP_COMPARE_TRUE:
135 rc = LDAP_COMPARE_FALSE;
137 case LDAP_COMPARE_FALSE:
138 rc = LDAP_COMPARE_TRUE;
143 case LDAP_FILTER_EXT:
144 Debug( LDAP_DEBUG_FILTER, " EXT\n", 0, 0, 0 );
145 rc = test_mra_filter( op, e, f->f_mra );
149 Debug( LDAP_DEBUG_ANY, " unknown filter type %lu\n",
151 rc = LDAP_PROTOCOL_ERROR;
154 Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
158 static int test_mra_filter(
161 MatchingRuleAssertion *mra )
165 BER_MEMFREE_FN *memfree;
166 #ifdef LDAP_COMP_MATCH
167 int i, num_attr_vals = 0;
172 memfree = slap_sl_mfuncs.bmf_free;
174 memctx = op->o_tmpmemctx;
175 memfree = op->o_tmpfree;
178 if ( mra->ma_desc ) {
180 * if ma_desc is available, then we're filtering for
181 * one attribute, and SEARCH permissions can be checked
184 if ( !access_allowed( op, e,
185 mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
187 return LDAP_INSUFFICIENT_ACCESS;
190 if ( mra->ma_desc == slap_schema.si_ad_entryDN ) {
194 rc = value_match( &ret, slap_schema.si_ad_entryDN, mra->ma_rule,
195 SLAP_MR_EXT, &e->e_nname, &mra->ma_value, &text );
198 if( rc != LDAP_SUCCESS ) return rc;
199 if ( ret == 0 ) return LDAP_COMPARE_TRUE;
200 return LDAP_COMPARE_FALSE;
203 for ( a = attrs_find( e->e_attrs, mra->ma_desc );
205 a = attrs_find( a->a_next, mra->ma_desc ) )
208 int normalize_attribute = 0;
210 #ifdef LDAP_COMP_MATCH
211 /* Component Matching */
212 if ( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
214 if ( !a->a_comp_data ) {
215 num_attr_vals = a->a_numvals;
216 if ( num_attr_vals <= 0 ) {
217 /* no attribute value */
218 return LDAP_INAPPROPRIATE_MATCHING;
222 /* following malloced will be freed by comp_tree_free () */
223 a->a_comp_data = SLAP_MALLOC( sizeof( ComponentData ) +
224 sizeof( ComponentSyntaxInfo* )*num_attr_vals );
226 if ( !a->a_comp_data ) return LDAP_NO_MEMORY;
227 a->a_comp_data->cd_tree = (ComponentSyntaxInfo**)
228 ((char*)a->a_comp_data + sizeof(ComponentData));
229 a->a_comp_data->cd_tree[num_attr_vals - 1] =
230 (ComponentSyntaxInfo*) NULL;
231 a->a_comp_data->cd_mem_op =
232 nibble_mem_allocator( 1024*16, 1024 );
237 /* If ma_rule is not the same as the attribute's
238 * normal rule, then we can't use the a_nvals.
240 if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
245 normalize_attribute = 1;
247 #ifdef LDAP_COMP_MATCH
250 for ( ; !BER_BVISNULL( bv ); bv++ ) {
255 #ifdef LDAP_COMP_MATCH
257 mra->ma_rule->smr_usage & SLAP_MR_COMPONENT )
259 /* Check if decoded component trees are already linked */
260 if ( num_attr_vals ) {
261 a->a_comp_data->cd_tree[i] = attr_converter(
262 a, a->a_desc->ad_type->sat_syntax, bv );
265 if ( !a->a_comp_data->cd_tree[i] ) {
266 return LDAP_OPERATIONS_ERROR;
268 rc = value_match( &ret, a->a_desc, mra->ma_rule,
270 (struct berval*)a->a_comp_data->cd_tree[i++],
275 struct berval nbv = BER_BVNULL;
277 if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
282 4.5.1. Search Request
284 If the type field is present and the matchingRule is present,
285 the matchValue is compared against entry attributes of the
286 specified type. In this case, the matchingRule MUST be one
287 suitable for use with the specified type (see [RFC4517]),
288 otherwise the filter item is Undefined.
291 In this case, since the matchingRule requires the assertion
292 value to be normalized, we normalize the attribute value
293 according to the syntax of the matchingRule.
295 This should likely be done inside value_match(), by passing
296 the appropriate flags, but this is not done at present.
299 if ( mra->ma_rule->smr_normalize(
300 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
301 mra->ma_rule->smr_syntax,
303 bv, &nbv, memctx ) != LDAP_SUCCESS )
305 /* FIXME: stop processing? */
313 rc = value_match( &ret, a->a_desc, mra->ma_rule,
314 SLAP_MR_EXT, &nbv, &mra->ma_value, &text );
316 if ( nbv.bv_val != bv->bv_val ) {
317 memfree( nbv.bv_val, memctx );
321 if ( rc != LDAP_SUCCESS ) return rc;
322 if ( ret == 0 ) return LDAP_COMPARE_TRUE;
328 * No attribute description: test all
330 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
331 struct berval *bv, value;
332 const char *text = NULL;
334 int normalize_attribute = 0;
336 /* check if matching is appropriate */
337 if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type ) ) {
341 /* normalize for equality */
342 rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule,
343 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
344 &mra->ma_value, &value, &text, memctx );
345 if ( rc != LDAP_SUCCESS ) continue;
347 /* check search access */
348 if ( !access_allowed( op, e,
349 a->a_desc, &value, ACL_SEARCH, NULL ) )
351 memfree( value.bv_val, memctx );
354 #ifdef LDAP_COMP_MATCH
355 /* Component Matching */
357 mra->ma_rule->smr_usage & SLAP_MR_COMPONENT )
361 rc = value_match( &ret, a->a_desc, mra->ma_rule,
363 (struct berval*)a, (void*)mra, &text );
364 if ( rc != LDAP_SUCCESS ) break;
367 rc = LDAP_COMPARE_TRUE;
375 if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
380 normalize_attribute = 1;
383 for ( ; !BER_BVISNULL( bv ); bv++ ) {
385 struct berval nbv = BER_BVNULL;
387 if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
388 /* see comment above */
389 if ( mra->ma_rule->smr_normalize(
390 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
391 mra->ma_rule->smr_syntax,
393 bv, &nbv, memctx ) != LDAP_SUCCESS )
395 /* FIXME: stop processing? */
403 rc = value_match( &ret, a->a_desc, mra->ma_rule,
404 SLAP_MR_EXT, &nbv, &value, &text );
406 if ( nbv.bv_val != bv->bv_val ) {
407 memfree( nbv.bv_val, memctx );
410 if ( rc != LDAP_SUCCESS ) break;
413 rc = LDAP_COMPARE_TRUE;
417 memfree( value.bv_val, memctx );
418 if ( rc != LDAP_SUCCESS ) return rc;
422 /* check attrs in DN AVAs if required */
423 if ( mra->ma_dnattrs && !BER_BVISEMPTY( &e->e_nname ) ) {
428 /* parse and pretty the dn */
429 rc = dnPrettyDN( NULL, &e->e_name, &dn, memctx );
430 if ( rc != LDAP_SUCCESS ) {
431 return LDAP_INVALID_SYNTAX;
434 /* for each AVA of each RDN ... */
435 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
436 LDAPRDN rdn = dn[ iRDN ];
438 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
439 LDAPAVA *ava = rdn[ iAVA ];
440 struct berval *bv = &ava->la_value,
443 AttributeDescription *ad =
444 (AttributeDescription *)ava->la_private;
448 assert( ad != NULL );
450 if ( mra->ma_desc ) {
451 /* have a mra type? check for subtype */
452 if ( !is_ad_subtype( ad, mra->ma_desc ) ) {
455 value = mra->ma_value;
458 const char *text = NULL;
460 /* check if matching is appropriate */
461 if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type ) ) {
465 /* normalize for equality */
466 rc = asserted_value_validate_normalize( ad,
468 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
469 &mra->ma_value, &value, &text, memctx );
470 if ( rc != LDAP_SUCCESS ) continue;
472 /* check search access */
473 if ( !access_allowed( op, e,
474 ad, &value, ACL_SEARCH, NULL ) )
476 memfree( value.bv_val, memctx );
481 if ( mra->ma_rule->smr_normalize ) {
482 /* see comment above */
483 if ( mra->ma_rule->smr_normalize(
484 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
485 mra->ma_rule->smr_syntax,
487 bv, &nbv, memctx ) != LDAP_SUCCESS )
489 /* FIXME: stop processing? */
500 rc = value_match( &ret, ad, mra->ma_rule, SLAP_MR_EXT,
501 &nbv, &value, &text );
504 if ( !BER_BVISNULL( &value ) && value.bv_val != mra->ma_value.bv_val ) {
505 memfree( value.bv_val, memctx );
508 if ( !BER_BVISNULL( &nbv ) && nbv.bv_val != bv->bv_val ) {
509 memfree( nbv.bv_val, memctx );
512 if ( rc == LDAP_SUCCESS && ret == 0 ) rc = LDAP_COMPARE_TRUE;
514 if ( rc != LDAP_SUCCESS ) {
515 ldap_dnfree_x( dn, memctx );
520 ldap_dnfree_x( dn, memctx );
523 return LDAP_COMPARE_FALSE;
530 AttributeAssertion *ava,
535 #ifdef LDAP_COMP_MATCH
536 int i, num_attr_vals = 0;
537 AttributeAliasing *a_alias = NULL;
540 if ( !access_allowed( op, e,
541 ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL ) )
543 return LDAP_INSUFFICIENT_ACCESS;
546 if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates
547 && op && op->o_bd && op->o_bd->be_has_subordinates )
549 int hasSubordinates = 0;
552 if( type != LDAP_FILTER_EQUALITY &&
553 type != LDAP_FILTER_APPROX )
555 /* No other match is allowed */
556 return LDAP_INAPPROPRIATE_MATCHING;
559 if ( op->o_bd->be_has_subordinates( op, e, &hasSubordinates ) !=
565 if ( hasSubordinates == LDAP_COMPARE_TRUE ) {
568 } else if ( hasSubordinates == LDAP_COMPARE_FALSE ) {
575 if ( bvmatch( &ava->aa_value, &hs ) ) return LDAP_COMPARE_TRUE;
576 return LDAP_COMPARE_FALSE;
579 if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
584 if( type != LDAP_FILTER_EQUALITY &&
585 type != LDAP_FILTER_APPROX )
587 /* No other match is allowed */
588 return LDAP_INAPPROPRIATE_MATCHING;
591 mr = slap_schema.si_ad_entryDN->ad_type->sat_equality;
592 assert( mr != NULL );
594 rc = value_match( &match, slap_schema.si_ad_entryDN, mr,
595 SLAP_MR_EXT, &e->e_nname, &ava->aa_value, &text );
597 if( rc != LDAP_SUCCESS ) return rc;
598 if( match == 0 ) return LDAP_COMPARE_TRUE;
599 return LDAP_COMPARE_FALSE;
602 rc = LDAP_COMPARE_FALSE;
604 #ifdef LDAP_COMP_MATCH
605 if ( is_aliased_attribute && ava->aa_cf )
607 a_alias = is_aliased_attribute ( ava->aa_desc );
609 ava->aa_desc = a_alias->aa_aliased_ad;
615 for(a = attrs_find( e->e_attrs, ava->aa_desc );
617 a = attrs_find( a->a_next, ava->aa_desc ) )
623 if (( ava->aa_desc != a->a_desc ) && !access_allowed( op,
624 e, a->a_desc, &ava->aa_value, ACL_SEARCH, NULL ))
626 rc = LDAP_INSUFFICIENT_ACCESS;
630 use = SLAP_MR_EQUALITY;
633 case LDAP_FILTER_APPROX:
634 use = SLAP_MR_EQUALITY_APPROX;
635 mr = a->a_desc->ad_type->sat_approx;
636 if( mr != NULL ) break;
638 /* fallthru: use EQUALITY matching rule if no APPROX rule */
640 case LDAP_FILTER_EQUALITY:
641 /* use variable set above so fall thru use is not clobbered */
642 mr = a->a_desc->ad_type->sat_equality;
647 use = SLAP_MR_ORDERING;
648 mr = a->a_desc->ad_type->sat_ordering;
656 rc = LDAP_INAPPROPRIATE_MATCHING;
660 /* We have no Sort optimization for Approx matches */
661 if (( a->a_flags & SLAP_ATTR_SORTED_VALS ) && type != LDAP_FILTER_APPROX ) {
665 /* For Ordering matches, we just need to do one comparison with
666 * either the first (least) or last (greatest) value.
668 if ( use == SLAP_MR_ORDERING ) {
671 which = (type == LDAP_FILTER_LE) ? 0 : a->a_numvals-1;
672 ret = value_match( &match, a->a_desc, mr, use,
673 &a->a_nvals[which], &ava->aa_value, &text );
674 if ( ret != LDAP_SUCCESS ) return ret;
675 if (( type == LDAP_FILTER_LE && match <= 0 ) ||
676 ( type == LDAP_FILTER_GE && match >= 0 ))
677 return LDAP_COMPARE_TRUE;
680 /* Only Equality will get here */
681 ret = attr_valfind( a, use | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH |
682 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
683 &ava->aa_value, &slot, NULL );
684 if ( ret == LDAP_SUCCESS )
685 return LDAP_COMPARE_TRUE;
686 else if ( ret != LDAP_NO_SUCH_ATTRIBUTE )
689 /* The following is useful if we want to know which values
690 * matched an ordering test. But here we don't care, we just
691 * want to know if any value did, and that is checked above.
693 if ( ret == LDAP_NO_SUCH_ATTRIBUTE ) {
694 /* If insertion point is not the end of the list, there was
695 * at least one value greater than the assertion.
697 if ( type == LDAP_FILTER_GE && slot < a->a_numvals )
698 return LDAP_COMPARE_TRUE;
699 /* Likewise, if insertion point is not the head of the list,
700 * there was at least one value less than the assertion.
702 if ( type == LDAP_FILTER_LE && slot > 0 )
703 return LDAP_COMPARE_TRUE;
704 return LDAP_COMPARE_FALSE;
710 #ifdef LDAP_COMP_MATCH
711 if ( nibble_mem_allocator && ava->aa_cf && !a->a_comp_data ) {
712 /* Component Matching */
713 for ( num_attr_vals = 0; a->a_vals[num_attr_vals].bv_val != NULL; num_attr_vals++ );
714 if ( num_attr_vals <= 0 )/* no attribute value */
715 return LDAP_INAPPROPRIATE_MATCHING;
716 num_attr_vals++;/* for NULL termination */
718 /* following malloced will be freed by comp_tree_free () */
719 a->a_comp_data = SLAP_MALLOC( sizeof( ComponentData ) + sizeof( ComponentSyntaxInfo* )*num_attr_vals );
721 if ( !a->a_comp_data ) {
722 return LDAP_NO_MEMORY;
725 a->a_comp_data->cd_tree = (ComponentSyntaxInfo**)((char*)a->a_comp_data + sizeof(ComponentData));
728 a->a_comp_data->cd_tree[ i-1 ] = (ComponentSyntaxInfo*)NULL;
731 a->a_comp_data->cd_mem_op = nibble_mem_allocator ( 1024*10*(num_attr_vals-1), 1024 );
732 if ( a->a_comp_data->cd_mem_op == NULL ) {
733 free ( a->a_comp_data );
734 a->a_comp_data = NULL;
735 return LDAP_OPERATIONS_ERROR;
742 for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
746 #ifdef LDAP_COMP_MATCH
747 if( attr_converter && ava->aa_cf && a->a_comp_data ) {
748 /* Check if decoded component trees are already linked */
749 struct berval cf_bv = { 20, "componentFilterMatch" };
750 MatchingRule* cf_mr = mr_bvfind( &cf_bv );
751 MatchingRuleAssertion mra;
752 mra.ma_cf = ava->aa_cf;
754 if ( a->a_comp_data->cd_tree[i] == NULL )
755 a->a_comp_data->cd_tree[i] = attr_converter (a, a->a_desc->ad_type->sat_syntax, (a->a_vals + i));
757 if ( !a->a_comp_data->cd_tree[i] ) {
758 free_ComponentData ( a );
759 return LDAP_OPERATIONS_ERROR;
762 ret = value_match( &match, a->a_desc, cf_mr,
764 (struct berval*)a->a_comp_data->cd_tree[i++],
765 (void*)&mra, &text );
766 if ( ret == LDAP_INAPPROPRIATE_MATCHING ) {
767 /* cached component tree is broken, just remove it */
768 free_ComponentData ( a );
772 ava->aa_desc = a_alias->aa_aliasing_ad;
777 ret = ordered_value_match( &match, a->a_desc, mr, use,
778 bv, &ava->aa_value, &text );
781 if( ret != LDAP_SUCCESS ) {
787 case LDAP_FILTER_EQUALITY:
788 case LDAP_FILTER_APPROX:
789 if ( match == 0 ) return LDAP_COMPARE_TRUE;
793 if ( match >= 0 ) return LDAP_COMPARE_TRUE;
797 if ( match <= 0 ) return LDAP_COMPARE_TRUE;
803 #ifdef LDAP_COMP_MATCH
805 ava->aa_desc = a_alias->aa_aliasing_ad;
813 test_presence_filter(
816 AttributeDescription *desc )
821 if ( !access_allowed( op, e, desc, NULL, ACL_SEARCH, NULL ) ) {
822 return LDAP_INSUFFICIENT_ACCESS;
825 if ( desc == slap_schema.si_ad_hasSubordinates ) {
827 * XXX: fairly optimistic: if the function is defined,
828 * then PRESENCE must succeed, because hasSubordinate
829 * is boolean-valued; I think we may live with this
830 * simplification by now.
832 if ( op && op->o_bd && op->o_bd->be_has_subordinates ) {
833 return LDAP_COMPARE_TRUE;
836 return LDAP_COMPARE_FALSE;
839 if ( desc == slap_schema.si_ad_entryDN ||
840 desc == slap_schema.si_ad_subschemaSubentry )
842 /* entryDN and subschemaSubentry are always present */
843 return LDAP_COMPARE_TRUE;
846 rc = LDAP_COMPARE_FALSE;
848 for(a = attrs_find( e->e_attrs, desc );
850 a = attrs_find( a->a_next, desc ) )
852 if (( desc != a->a_desc ) && !access_allowed( op,
853 e, a->a_desc, NULL, ACL_SEARCH, NULL ))
855 rc = LDAP_INSUFFICIENT_ACCESS;
859 rc = LDAP_COMPARE_TRUE;
874 int rtn = LDAP_COMPARE_TRUE; /* True if empty */
876 Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 );
878 for ( f = flist; f != NULL; f = f->f_next ) {
879 int rc = test_filter( op, e, f );
881 if ( rc == LDAP_COMPARE_FALSE ) {
882 /* filter is False */
887 if ( rc != LDAP_COMPARE_TRUE ) {
888 /* filter is Undefined unless later elements are False */
893 Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
905 int rtn = LDAP_COMPARE_FALSE; /* False if empty */
907 Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
909 for ( f = flist; f != NULL; f = f->f_next ) {
910 int rc = test_filter( op, e, f );
912 if ( rc == LDAP_COMPARE_TRUE ) {
918 if ( rc != LDAP_COMPARE_FALSE ) {
919 /* filter is Undefined unless later elements are True */
924 Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
930 test_substrings_filter(
938 Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 );
940 if ( !access_allowed( op, e,
941 f->f_sub_desc, NULL, ACL_SEARCH, NULL ) )
943 return LDAP_INSUFFICIENT_ACCESS;
946 rc = LDAP_COMPARE_FALSE;
948 for(a = attrs_find( e->e_attrs, f->f_sub_desc );
950 a = attrs_find( a->a_next, f->f_sub_desc ) )
955 if (( f->f_sub_desc != a->a_desc ) && !access_allowed( op,
956 e, a->a_desc, NULL, ACL_SEARCH, NULL ))
958 rc = LDAP_INSUFFICIENT_ACCESS;
962 mr = a->a_desc->ad_type->sat_substr;
964 rc = LDAP_INAPPROPRIATE_MATCHING;
968 for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
972 ret = value_match( &match, a->a_desc, mr, SLAP_MR_SUBSTR,
973 bv, f->f_sub, &text );
975 if( ret != LDAP_SUCCESS ) {
979 if ( match == 0 ) return LDAP_COMPARE_TRUE;
983 Debug( LDAP_DEBUG_FILTER, "end test_substrings_filter %d\n",