1 /* filterentry.c - apply a filter to an entry */
4 * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
12 #include <ac/socket.h>
13 #include <ac/string.h>
18 static int test_filter_and( Operation *op, Entry *e, Filter *flist );
19 static int test_filter_or( Operation *op, Entry *e, Filter *flist );
20 static int test_substrings_filter( Operation *op, Entry *e, Filter *f);
21 static int test_ava_filter( Operation *op, Entry *e, AttributeAssertion *ava, int type );
22 static int test_mra_filter( Operation *op, Entry *e, MatchingRuleAssertion *mra );
23 static int test_presence_filter( Operation *op, Entry *e, AttributeDescription *desc );
27 * test_filter - test a filter against a single entry.
29 * LDAP_COMPARE_TRUE filter matched
30 * LDAP_COMPARE_FALSE filter did not match
31 * SLAPD_COMPARE_UNDEFINED filter is undefined
32 * or an ldap result code indicating error
44 LDAP_LOG( FILTER, ENTRY, "test_filter: begin\n", 0, 0, 0 );
46 Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
49 switch ( f->f_choice ) {
50 case SLAPD_FILTER_COMPUTED:
52 LDAP_LOG( FILTER, DETAIL1,
53 "test_filter: COMPUTED %s (%d)\n",
54 f->f_result == LDAP_COMPARE_FALSE ? "false" :
55 f->f_result == LDAP_COMPARE_TRUE ? "true" :
56 f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
57 "error", f->f_result, 0 );
59 Debug( LDAP_DEBUG_FILTER, " COMPUTED %s (%d)\n",
60 f->f_result == LDAP_COMPARE_FALSE ? "false" :
61 f->f_result == LDAP_COMPARE_TRUE ? "true" :
62 f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" : "error",
69 case LDAP_FILTER_EQUALITY:
71 LDAP_LOG( FILTER, DETAIL1, "test_filter: EQUALITY\n", 0, 0, 0 );
73 Debug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
76 rc = test_ava_filter( op, e, f->f_ava,
77 LDAP_FILTER_EQUALITY );
80 case LDAP_FILTER_SUBSTRINGS:
82 LDAP_LOG( FILTER, DETAIL1, "test_filter SUBSTRINGS\n", 0, 0, 0 );
84 Debug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
87 rc = test_substrings_filter( op, e, f );
91 rc = test_ava_filter( op, e, f->f_ava,
96 rc = test_ava_filter( op, e, f->f_ava,
100 case LDAP_FILTER_PRESENT:
102 LDAP_LOG( FILTER, DETAIL1, "test_filter: PRESENT\n", 0, 0, 0 );
104 Debug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
107 rc = test_presence_filter( op, e, f->f_desc );
110 case LDAP_FILTER_APPROX:
112 LDAP_LOG( FILTER, DETAIL1, "test_filter: APPROX\n", 0, 0, 0 );
114 Debug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 );
116 rc = test_ava_filter( op, e, f->f_ava,
117 LDAP_FILTER_APPROX );
120 case LDAP_FILTER_AND:
122 LDAP_LOG( FILTER, DETAIL1, "test_filter: AND\n", 0, 0, 0 );
124 Debug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 );
127 rc = test_filter_and( op, e, f->f_and );
132 LDAP_LOG( FILTER, DETAIL1, "test_filter: OR\n", 0, 0, 0 );
134 Debug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 );
137 rc = test_filter_or( op, e, f->f_or );
140 case LDAP_FILTER_NOT:
142 LDAP_LOG( FILTER, DETAIL1, "test_filter: NOT\n", 0, 0, 0 );
144 Debug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 );
147 rc = test_filter( op, e, f->f_not );
149 /* Flip true to false and false to true
150 * but leave Undefined alone.
153 case LDAP_COMPARE_TRUE:
154 rc = LDAP_COMPARE_FALSE;
156 case LDAP_COMPARE_FALSE:
157 rc = LDAP_COMPARE_TRUE;
162 case LDAP_FILTER_EXT:
164 LDAP_LOG( FILTER, DETAIL1, "test_filter: EXT\n", 0, 0, 0 );
166 Debug( LDAP_DEBUG_FILTER, " EXT\n", 0, 0, 0 );
169 rc = test_mra_filter( op, e, f->f_mra );
174 LDAP_LOG( FILTER, INFO,
175 "test_filter: unknown filter type %lu\n", f->f_choice, 0, 0 );
177 Debug( LDAP_DEBUG_ANY, " unknown filter type %lu\n",
181 rc = LDAP_PROTOCOL_ERROR;
185 LDAP_LOG( FILTER, RESULTS, "test_filter: return=%d\n", rc, 0, 0 );
187 Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
193 static int test_mra_filter(
196 MatchingRuleAssertion *mra )
199 void *memctx = op ? op->o_tmpmemctx : NULL;
201 if ( mra->ma_desc ) {
203 * if ma_desc is available, then we're filtering for
204 * one attribute, and SEARCH permissions can be checked
207 if( !access_allowed( op, e,
208 mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
210 return LDAP_INSUFFICIENT_ACCESS;
213 for(a = attrs_find( e->e_attrs, mra->ma_desc );
215 a = attrs_find( a->a_next, mra->ma_desc ) )
218 /* If ma_rule is not the same as the attribute's
219 * normal rule, then we can't use the a_nvals.
221 if (mra->ma_rule == a->a_desc->ad_type->sat_equality) {
227 for ( ; bv->bv_val != NULL; bv++ ) {
232 rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
233 bv, &mra->ma_value, &text );
235 if( rc != LDAP_SUCCESS ) {
240 return LDAP_COMPARE_TRUE;
247 * No attribute description: test all
249 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
250 struct berval *bv, value;
251 const char *text = NULL;
254 /* check if matching is appropriate */
255 if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type )) {
259 /* normalize for equality */
260 rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule,
261 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
262 &mra->ma_value, &value, &text, memctx );
263 if ( rc != LDAP_SUCCESS ) {
267 /* check search access */
268 if ( !access_allowed( op, e,
269 a->a_desc, &value, ACL_SEARCH, NULL ) ) {
274 if (mra->ma_rule == a->a_desc->ad_type->sat_equality)
278 for ( ; bv->bv_val != NULL; bv++ )
283 rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
286 if( rc != LDAP_SUCCESS ) {
291 return LDAP_COMPARE_TRUE;
297 /* check attrs in DN AVAs if required */
298 if ( mra->ma_dnattrs ) {
303 /* parse and pretty the dn */
304 rc = dnPrettyDN( NULL, &e->e_name, &dn, memctx );
305 if ( rc != LDAP_SUCCESS ) {
306 return LDAP_INVALID_SYNTAX;
309 /* for each AVA of each RDN ... */
310 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
311 LDAPRDN rdn = dn[ iRDN ];
313 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
314 LDAPAVA *ava = rdn[ iAVA ];
315 struct berval *bv = &ava->la_value, value;
316 AttributeDescription *ad = (AttributeDescription *)ava->la_private;
323 if ( mra->ma_desc ) {
324 /* have a mra type? check for subtype */
325 if ( !is_ad_subtype( ad, mra->ma_desc ) ) {
328 value = mra->ma_value;
331 const char *text = NULL;
333 /* check if matching is appropriate */
334 if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type )) {
338 /* normalize for equality */
339 rc = asserted_value_validate_normalize( ad,
341 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
342 &mra->ma_value, &value, &text, memctx );
343 if ( rc != LDAP_SUCCESS ) {
347 /* check search access */
348 if ( !access_allowed( op, e,
349 ad, &value, ACL_SEARCH, NULL ) ) {
355 rc = value_match( &ret, ad, mra->ma_rule, 0,
358 if( rc != LDAP_SUCCESS ) {
359 ldap_dnfree_x( dn, memctx );
364 ldap_dnfree_x( dn, memctx );
365 return LDAP_COMPARE_TRUE;
371 return LDAP_COMPARE_FALSE;
378 AttributeAssertion *ava,
384 if ( !access_allowed( op, e,
385 ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL ) )
387 return LDAP_INSUFFICIENT_ACCESS;
390 for(a = attrs_find( e->e_attrs, ava->aa_desc );
392 a = attrs_find( a->a_next, ava->aa_desc ) )
398 case LDAP_FILTER_APPROX:
399 mr = a->a_desc->ad_type->sat_approx;
400 if( mr != NULL ) break;
402 /* use EQUALITY matching rule if no APPROX rule */
404 case LDAP_FILTER_EQUALITY:
405 mr = a->a_desc->ad_type->sat_equality;
410 mr = a->a_desc->ad_type->sat_ordering;
421 for ( bv = a->a_nvals; bv->bv_val != NULL; bv++ )
427 rc = value_match( &ret, a->a_desc, mr, 0,
428 bv, &ava->aa_value, &text );
430 if( rc != LDAP_SUCCESS ) {
435 case LDAP_FILTER_EQUALITY:
436 case LDAP_FILTER_APPROX:
438 return LDAP_COMPARE_TRUE;
444 return LDAP_COMPARE_TRUE;
450 return LDAP_COMPARE_TRUE;
457 if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates
458 && op && op->o_bd && op->o_bd->be_has_subordinates ) {
463 * No other match should be allowed ...
465 assert( type == LDAP_FILTER_EQUALITY );
467 if (op->o_bd->be_has_subordinates( op, e, &hasSubordinates ) != LDAP_SUCCESS) {
471 if ( hasSubordinates == LDAP_COMPARE_TRUE ) {
474 } else if ( hasSubordinates == LDAP_COMPARE_FALSE ) {
481 if ( bvmatch( &ava->aa_value, &hs ) ) {
482 return LDAP_COMPARE_TRUE;
485 return LDAP_COMPARE_FALSE;
488 return( LDAP_COMPARE_FALSE );
493 test_presence_filter(
496 AttributeDescription *desc
501 if ( !access_allowed( op, e, desc, NULL, ACL_SEARCH, NULL ) )
503 return LDAP_INSUFFICIENT_ACCESS;
506 a = attrs_find( e->e_attrs, desc );
508 if ( a == NULL && desc == slap_schema.si_ad_hasSubordinates ) {
511 * XXX: fairly optimistic: if the function is defined,
512 * then PRESENCE must succeed, because hasSubordinate
513 * is boolean-valued; I think we may live with this
514 * simplification by now
516 if ( op && op->o_bd && op->o_bd->be_has_subordinates ) {
517 return LDAP_COMPARE_TRUE;
520 return LDAP_COMPARE_FALSE;
523 return a != NULL ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
535 int rtn = LDAP_COMPARE_TRUE; /* True if empty */
538 LDAP_LOG( FILTER, ENTRY, "test_filter_and: begin\n", 0, 0, 0 );
540 Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 );
544 for ( f = flist; f != NULL; f = f->f_next ) {
545 int rc = test_filter( op, e, f );
547 if ( rc == LDAP_COMPARE_FALSE ) {
548 /* filter is False */
553 if ( rc != LDAP_COMPARE_TRUE ) {
554 /* filter is Undefined unless later elements are False */
560 LDAP_LOG( FILTER, RESULTS, "test_filter_and: rc=%d\n", rtn, 0, 0 );
562 Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
576 int rtn = LDAP_COMPARE_FALSE; /* False if empty */
579 LDAP_LOG( FILTER, ENTRY, "test_filter_or: begin\n", 0, 0, 0 );
581 Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
585 for ( f = flist; f != NULL; f = f->f_next ) {
586 int rc = test_filter( op, e, f );
588 if ( rc == LDAP_COMPARE_TRUE ) {
594 if ( rc != LDAP_COMPARE_FALSE ) {
595 /* filter is Undefined unless later elements are True */
601 LDAP_LOG( FILTER, ENTRY, "test_filter_or: result=%d\n", rtn, 0, 0 );
603 Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
611 test_substrings_filter(
620 LDAP_LOG( FILTER, ENTRY, "test_substrings_filter: begin\n", 0, 0, 0 );
622 Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 );
626 if ( !access_allowed( op, e,
627 f->f_sub_desc, NULL, ACL_SEARCH, NULL ) )
629 return LDAP_INSUFFICIENT_ACCESS;
632 for(a = attrs_find( e->e_attrs, f->f_sub_desc );
634 a = attrs_find( a->a_next, f->f_sub_desc ) )
636 MatchingRule *mr = a->a_desc->ad_type->sat_substr;
643 for ( bv = a->a_nvals; bv->bv_val != NULL; bv++ )
649 rc = value_match( &ret, a->a_desc, mr, 0,
650 bv, f->f_sub, &text );
652 if( rc != LDAP_SUCCESS ) {
657 return LDAP_COMPARE_TRUE;
663 LDAP_LOG( FILTER, ENTRY, "test_substrings_filter: return FALSE\n", 0, 0, 0 );
665 Debug( LDAP_DEBUG_FILTER, "end test_substrings_filter 1\n", 0, 0, 0 );
668 return LDAP_COMPARE_FALSE;