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( Backend *be,
19 Connection *conn, Operation *op,
20 Entry *e, Filter *flist );
21 static int test_filter_or( Backend *be,
22 Connection *conn, Operation *op,
23 Entry *e, Filter *flist );
24 static int test_substrings_filter( Backend *be,
25 Connection *conn, Operation *op,
27 static int test_ava_filter( Backend *be,
28 Connection *conn, Operation *op,
29 Entry *e, AttributeAssertion *ava, int type );
30 static int test_mra_filter( Backend *be,
31 Connection *conn, Operation *op,
32 Entry *e, MatchingRuleAssertion *mra );
33 static int test_presence_filter( Backend *be,
34 Connection *conn, Operation *op,
35 Entry *e, AttributeDescription *desc );
39 * test_filter - test a filter against a single entry.
41 * LDAP_COMPARE_TRUE filter matched
42 * LDAP_COMPARE_FALSE filter did not match
43 * SLAPD_COMPARE_UNDEFINED filter is undefined
44 * or an ldap result code indicating error
59 LDAP_LOG( FILTER, ENTRY, "test_filter: begin\n", 0, 0, 0 );
61 Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
65 switch ( f->f_choice ) {
66 case SLAPD_FILTER_COMPUTED:
68 LDAP_LOG( FILTER, DETAIL1,
69 "test_filter: COMPUTED %s (%d)\n",
70 f->f_result == LDAP_COMPARE_FALSE ? "false" :
71 f->f_result == LDAP_COMPARE_TRUE ? "true" :
72 f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
73 "error", f->f_result, 0 );
75 Debug( LDAP_DEBUG_FILTER, " COMPUTED %s (%d)\n",
76 f->f_result == LDAP_COMPARE_FALSE ? "false" :
77 f->f_result == LDAP_COMPARE_TRUE ? "true" :
78 f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" : "error",
85 case LDAP_FILTER_EQUALITY:
87 LDAP_LOG( FILTER, DETAIL1, "test_filter: EQUALITY\n", 0, 0, 0 );
89 Debug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
92 rc = test_ava_filter( be, conn, op, e, f->f_ava,
93 LDAP_FILTER_EQUALITY );
96 case LDAP_FILTER_SUBSTRINGS:
98 LDAP_LOG( FILTER, DETAIL1, "test_filter SUBSTRINGS\n", 0, 0, 0 );
100 Debug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
103 rc = test_substrings_filter( be, conn, op, e, f );
107 rc = test_ava_filter( be, conn, op, e, f->f_ava,
112 rc = test_ava_filter( be, conn, op, e, f->f_ava,
116 case LDAP_FILTER_PRESENT:
118 LDAP_LOG( FILTER, DETAIL1, "test_filter: PRESENT\n", 0, 0, 0 );
120 Debug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
123 rc = test_presence_filter( be, conn, op, e, f->f_desc );
126 case LDAP_FILTER_APPROX:
128 LDAP_LOG( FILTER, DETAIL1, "test_filter: APPROX\n", 0, 0, 0 );
130 Debug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 );
132 rc = test_ava_filter( be, conn, op, e, f->f_ava,
133 LDAP_FILTER_APPROX );
136 case LDAP_FILTER_AND:
138 LDAP_LOG( FILTER, DETAIL1, "test_filter: AND\n", 0, 0, 0 );
140 Debug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 );
143 rc = test_filter_and( be, conn, op, e, f->f_and );
148 LDAP_LOG( FILTER, DETAIL1, "test_filter: OR\n", 0, 0, 0 );
150 Debug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 );
153 rc = test_filter_or( be, conn, op, e, f->f_or );
156 case LDAP_FILTER_NOT:
158 LDAP_LOG( FILTER, DETAIL1, "test_filter: NOT\n", 0, 0, 0 );
160 Debug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 );
163 rc = test_filter( be, conn, op, e, f->f_not );
165 /* Flip true to false and false to true
166 * but leave Undefined alone.
169 case LDAP_COMPARE_TRUE:
170 rc = LDAP_COMPARE_FALSE;
172 case LDAP_COMPARE_FALSE:
173 rc = LDAP_COMPARE_TRUE;
178 case LDAP_FILTER_EXT:
180 LDAP_LOG( FILTER, DETAIL1, "test_filter: EXT\n", 0, 0, 0 );
182 Debug( LDAP_DEBUG_FILTER, " EXT\n", 0, 0, 0 );
185 rc = test_mra_filter( be, conn, op, e, f->f_mra );
190 LDAP_LOG( FILTER, INFO,
191 "test_filter: unknown filter type %lu\n", f->f_choice, 0, 0 );
193 Debug( LDAP_DEBUG_ANY, " unknown filter type %lu\n",
197 rc = LDAP_PROTOCOL_ERROR;
201 LDAP_LOG( FILTER, RESULTS, "test_filter: return=%d\n", rc, 0, 0 );
203 Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
209 static int test_mra_filter(
214 MatchingRuleAssertion *mra )
218 if ( mra->ma_desc ) {
220 * if ma_desc is available, then we're filtering for
221 * one attribute, and SEARCH permissions can be checked
224 if( !access_allowed( be, conn, op, e,
225 mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
227 return LDAP_INSUFFICIENT_ACCESS;
230 for(a = attrs_find( e->e_attrs, mra->ma_desc );
232 a = attrs_find( a->a_next, mra->ma_desc ) )
236 for ( bv = a->a_nvals ? a->a_nvals : a->a_vals;
237 bv->bv_val != NULL; bv++ )
239 for ( bv = a->a_vals; bv->bv_val != NULL; bv++ )
246 rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
247 bv, &mra->ma_value, &text );
249 if( rc != LDAP_SUCCESS ) {
254 return LDAP_COMPARE_TRUE;
261 * No attribute description: test all
263 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
264 struct berval *bv, value;
265 const char *text = NULL;
268 /* check if matching is appropriate */
269 if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type )) {
273 /* normalize for equality */
275 rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule,
276 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
277 &mra->ma_value, &value, &text );
279 rc = value_validate_normalize( a->a_desc,
281 &mra->ma_value, &value, &text );
283 if ( rc != LDAP_SUCCESS ) {
287 /* check search access */
288 if ( !access_allowed( be, conn, op, e,
289 a->a_desc, &value, ACL_SEARCH, NULL ) ) {
295 for ( bv = a->a_nvals ? a->a_nvals : a->a_vals;
296 bv->bv_val != NULL; bv++ )
298 for ( bv = a->a_vals; bv->bv_val != NULL; bv++ )
304 rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
307 if( rc != LDAP_SUCCESS ) {
312 return LDAP_COMPARE_TRUE;
318 /* check attrs in DN AVAs if required */
319 if ( mra->ma_dnattrs ) {
324 /* parse and pretty the dn */
325 rc = dnPrettyDN( NULL, &e->e_name, &dn );
326 if ( rc != LDAP_SUCCESS ) {
327 return LDAP_INVALID_SYNTAX;
330 /* for each AVA of each RDN ... */
331 for ( iRDN = 0; dn[ 0 ][ iRDN ]; iRDN++ ) {
332 LDAPRDN *rdn = dn[ 0 ][ iRDN ];
334 for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) {
335 LDAPAVA *ava = rdn[ 0 ][ iAVA ];
336 struct berval *bv = &ava->la_value, value;
337 AttributeDescription *ad = (AttributeDescription *)ava->la_private;
344 if ( mra->ma_desc ) {
345 /* have a mra type? check for subtype */
346 if ( !is_ad_subtype( ad, mra->ma_desc ) ) {
349 value = mra->ma_value;
352 const char *text = NULL;
354 /* check if matching is appropriate */
355 if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type )) {
359 /* normalize for equality */
361 rc = asserted_value_validate_normalize( ad,
363 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
364 &mra->ma_value, &value, &text );
366 rc = value_validate_normalize( ad, SLAP_MR_EQUALITY,
367 &mra->ma_value, &value, &text );
369 if ( rc != LDAP_SUCCESS ) {
373 /* check search access */
374 if ( !access_allowed( be, conn, op, e,
375 ad, &value, ACL_SEARCH, NULL ) ) {
381 rc = value_match( &ret, ad, mra->ma_rule, 0,
384 if( rc != LDAP_SUCCESS ) {
391 return LDAP_COMPARE_TRUE;
397 return LDAP_COMPARE_FALSE;
406 AttributeAssertion *ava,
412 if ( !access_allowed( be, conn, op, e,
413 ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL ) )
415 return LDAP_INSUFFICIENT_ACCESS;
418 for(a = attrs_find( e->e_attrs, ava->aa_desc );
420 a = attrs_find( a->a_next, ava->aa_desc ) )
426 case LDAP_FILTER_APPROX:
427 mr = a->a_desc->ad_type->sat_approx;
428 if( mr != NULL ) break;
430 /* use EQUALITY matching rule if no APPROX rule */
432 case LDAP_FILTER_EQUALITY:
433 mr = a->a_desc->ad_type->sat_equality;
438 mr = a->a_desc->ad_type->sat_ordering;
450 for ( bv = a->a_nvals ? a->a_nvals : a->a_vals;
451 bv->bv_val != NULL; bv++ )
453 for ( bv = a->a_vals; bv->bv_val != NULL; bv++ )
460 rc = value_match( &ret, a->a_desc, mr, 0,
461 bv, &ava->aa_value, &text );
463 if( rc != LDAP_SUCCESS ) {
468 case LDAP_FILTER_EQUALITY:
469 case LDAP_FILTER_APPROX:
471 return LDAP_COMPARE_TRUE;
477 return LDAP_COMPARE_TRUE;
483 return LDAP_COMPARE_TRUE;
490 if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates
491 && be && be->be_has_subordinates ) {
496 * No other match should be allowed ...
498 assert( type == LDAP_FILTER_EQUALITY );
500 if ( (*be->be_has_subordinates)( be, conn, op, e, &hasSubordinates ) ) {
504 if ( hasSubordinates == LDAP_COMPARE_TRUE ) {
506 hs.bv_len = sizeof( "TRUE" ) - 1;
508 } else if ( hasSubordinates == LDAP_COMPARE_FALSE ) {
510 hs.bv_len = sizeof( "FALSE" ) - 1;
516 if ( bvmatch( &ava->aa_value, &hs ) ) {
517 return LDAP_COMPARE_TRUE;
520 return LDAP_COMPARE_FALSE;
523 return( LDAP_COMPARE_FALSE );
528 test_presence_filter(
533 AttributeDescription *desc
538 if ( !access_allowed( be, conn, op, e, desc, NULL, ACL_SEARCH, NULL ) )
540 return LDAP_INSUFFICIENT_ACCESS;
543 a = attrs_find( e->e_attrs, desc );
545 if ( a == NULL && desc == slap_schema.si_ad_hasSubordinates ) {
548 * XXX: fairly optimistic: if the function is defined,
549 * then PRESENCE must succeed, because hasSubordinate
550 * is boolean-valued; I think we may live with this
551 * simplification by now
553 if ( be && be->be_has_subordinates ) {
554 return LDAP_COMPARE_TRUE;
557 return LDAP_COMPARE_FALSE;
560 return a != NULL ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
574 int rtn = LDAP_COMPARE_TRUE; /* True if empty */
577 LDAP_LOG( FILTER, ENTRY, "test_filter_and: begin\n", 0, 0, 0 );
579 Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 );
583 for ( f = flist; f != NULL; f = f->f_next ) {
584 int rc = test_filter( be, conn, op, e, f );
586 if ( rc == LDAP_COMPARE_FALSE ) {
587 /* filter is False */
592 if ( rc != LDAP_COMPARE_TRUE ) {
593 /* filter is Undefined unless later elements are False */
599 LDAP_LOG( FILTER, RESULTS, "test_filter_and: rc=%d\n", rtn, 0, 0 );
601 Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
617 int rtn = LDAP_COMPARE_FALSE; /* False if empty */
620 LDAP_LOG( FILTER, ENTRY, "test_filter_or: begin\n", 0, 0, 0 );
622 Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
626 for ( f = flist; f != NULL; f = f->f_next ) {
627 int rc = test_filter( be, conn, op, e, f );
629 if ( rc == LDAP_COMPARE_TRUE ) {
635 if ( rc != LDAP_COMPARE_FALSE ) {
636 /* filter is Undefined unless later elements are True */
642 LDAP_LOG( FILTER, ENTRY, "test_filter_or: result=%d\n", rtn, 0, 0 );
644 Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
652 test_substrings_filter(
663 LDAP_LOG( FILTER, ENTRY, "test_substrings_filter: begin\n", 0, 0, 0 );
665 Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 );
669 if ( !access_allowed( be, conn, op, e,
670 f->f_sub_desc, NULL, ACL_SEARCH, NULL ) )
672 return LDAP_INSUFFICIENT_ACCESS;
675 for(a = attrs_find( e->e_attrs, f->f_sub_desc );
677 a = attrs_find( a->a_next, f->f_sub_desc ) )
679 MatchingRule *mr = a->a_desc->ad_type->sat_substr;
687 for ( bv = a->a_nvals ? a->a_nvals : a->a_vals;
688 bv->bv_val != NULL; bv++ )
690 for ( bv = a->a_vals; bv->bv_val != NULL; bv++ )
697 rc = value_match( &ret, a->a_desc, mr, 0,
698 bv, f->f_sub, &text );
700 if( rc != LDAP_SUCCESS ) {
705 return LDAP_COMPARE_TRUE;
711 LDAP_LOG( FILTER, ENTRY, "test_substrings_filter: return FALSE\n", 0, 0, 0 );
713 Debug( LDAP_DEBUG_FILTER, "end test_substrings_filter 1\n", 0, 0, 0 );
716 return LDAP_COMPARE_FALSE;