1 /* filterentry.c - apply a filter to an entry */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 1998-2004 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>
37 static int test_filter_and( Operation *op, Entry *e, Filter *flist );
38 static int test_filter_or( Operation *op, Entry *e, Filter *flist );
39 static int test_substrings_filter( Operation *op, Entry *e, Filter *f);
40 static int test_ava_filter( Operation *op, Entry *e, AttributeAssertion *ava, int type );
41 static int test_mra_filter( Operation *op, Entry *e, MatchingRuleAssertion *mra );
42 static int test_presence_filter( Operation *op, Entry *e, AttributeDescription *desc );
46 * test_filter - test a filter against a single entry.
48 * LDAP_COMPARE_TRUE filter matched
49 * LDAP_COMPARE_FALSE filter did not match
50 * SLAPD_COMPARE_UNDEFINED filter is undefined
51 * or an ldap result code indicating error
63 LDAP_LOG( FILTER, ENTRY, "test_filter: begin\n", 0, 0, 0 );
65 Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
68 switch ( f->f_choice ) {
69 case SLAPD_FILTER_COMPUTED:
71 LDAP_LOG( FILTER, DETAIL1,
72 "test_filter: COMPUTED %s (%d)\n",
73 f->f_result == LDAP_COMPARE_FALSE ? "false" :
74 f->f_result == LDAP_COMPARE_TRUE ? "true" :
75 f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
76 "error", f->f_result, 0 );
78 Debug( LDAP_DEBUG_FILTER, " COMPUTED %s (%d)\n",
79 f->f_result == LDAP_COMPARE_FALSE ? "false" :
80 f->f_result == LDAP_COMPARE_TRUE ? "true" :
81 f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" : "error",
88 case LDAP_FILTER_EQUALITY:
90 LDAP_LOG( FILTER, DETAIL1, "test_filter: EQUALITY\n", 0, 0, 0 );
92 Debug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
95 rc = test_ava_filter( op, e, f->f_ava,
96 LDAP_FILTER_EQUALITY );
99 case LDAP_FILTER_SUBSTRINGS:
101 LDAP_LOG( FILTER, DETAIL1, "test_filter SUBSTRINGS\n", 0, 0, 0 );
103 Debug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
106 rc = test_substrings_filter( op, e, f );
110 rc = test_ava_filter( op, e, f->f_ava,
115 rc = test_ava_filter( op, e, f->f_ava,
119 case LDAP_FILTER_PRESENT:
121 LDAP_LOG( FILTER, DETAIL1, "test_filter: PRESENT\n", 0, 0, 0 );
123 Debug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
126 rc = test_presence_filter( op, e, f->f_desc );
129 case LDAP_FILTER_APPROX:
131 LDAP_LOG( FILTER, DETAIL1, "test_filter: APPROX\n", 0, 0, 0 );
133 Debug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 );
135 rc = test_ava_filter( op, e, f->f_ava,
136 LDAP_FILTER_APPROX );
139 case LDAP_FILTER_AND:
141 LDAP_LOG( FILTER, DETAIL1, "test_filter: AND\n", 0, 0, 0 );
143 Debug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 );
146 rc = test_filter_and( op, e, f->f_and );
151 LDAP_LOG( FILTER, DETAIL1, "test_filter: OR\n", 0, 0, 0 );
153 Debug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 );
156 rc = test_filter_or( op, e, f->f_or );
159 case LDAP_FILTER_NOT:
161 LDAP_LOG( FILTER, DETAIL1, "test_filter: NOT\n", 0, 0, 0 );
163 Debug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 );
166 rc = test_filter( op, e, f->f_not );
168 /* Flip true to false and false to true
169 * but leave Undefined alone.
172 case LDAP_COMPARE_TRUE:
173 rc = LDAP_COMPARE_FALSE;
175 case LDAP_COMPARE_FALSE:
176 rc = LDAP_COMPARE_TRUE;
181 case LDAP_FILTER_EXT:
183 LDAP_LOG( FILTER, DETAIL1, "test_filter: EXT\n", 0, 0, 0 );
185 Debug( LDAP_DEBUG_FILTER, " EXT\n", 0, 0, 0 );
188 rc = test_mra_filter( op, e, f->f_mra );
193 LDAP_LOG( FILTER, INFO,
194 "test_filter: unknown filter type %lu\n", f->f_choice, 0, 0 );
196 Debug( LDAP_DEBUG_ANY, " unknown filter type %lu\n",
200 rc = LDAP_PROTOCOL_ERROR;
204 LDAP_LOG( FILTER, RESULTS, "test_filter: return=%d\n", rc, 0, 0 );
206 Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
212 static int test_mra_filter(
215 MatchingRuleAssertion *mra )
218 void *memctx = op ? op->o_tmpmemctx : NULL;
220 if ( mra->ma_desc ) {
222 * if ma_desc is available, then we're filtering for
223 * one attribute, and SEARCH permissions can be checked
226 if( !access_allowed( op, e,
227 mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
229 return LDAP_INSUFFICIENT_ACCESS;
232 for(a = attrs_find( e->e_attrs, mra->ma_desc );
234 a = attrs_find( a->a_next, mra->ma_desc ) )
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) {
246 for ( ; bv->bv_val != NULL; bv++ ) {
251 rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
252 bv, &mra->ma_value, &text );
254 if( rc != LDAP_SUCCESS ) {
259 return LDAP_COMPARE_TRUE;
266 * No attribute description: test all
268 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
269 struct berval *bv, value;
270 const char *text = NULL;
273 /* check if matching is appropriate */
274 if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type )) {
278 /* normalize for equality */
279 rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule,
280 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
281 &mra->ma_value, &value, &text, memctx );
282 if ( rc != LDAP_SUCCESS ) {
286 /* check search access */
287 if ( !access_allowed( op, e,
288 a->a_desc, &value, ACL_SEARCH, NULL ) ) {
289 op->o_tmpfree( value.bv_val, memctx );
294 if (mra->ma_rule == a->a_desc->ad_type->sat_equality)
298 for ( ; bv->bv_val != NULL; bv++ )
302 rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
305 if( rc != LDAP_SUCCESS ) {
310 rc = LDAP_COMPARE_TRUE;
314 op->o_tmpfree( value.bv_val, memctx );
315 if ( rc != LDAP_SUCCESS ) {
321 /* check attrs in DN AVAs if required */
322 if ( mra->ma_dnattrs ) {
327 /* parse and pretty the dn */
328 rc = dnPrettyDN( NULL, &e->e_name, &dn, memctx );
329 if ( rc != LDAP_SUCCESS ) {
330 return LDAP_INVALID_SYNTAX;
333 /* for each AVA of each RDN ... */
334 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
335 LDAPRDN rdn = dn[ iRDN ];
337 for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
338 LDAPAVA *ava = rdn[ iAVA ];
339 struct berval *bv = &ava->la_value, value;
340 AttributeDescription *ad = (AttributeDescription *)ava->la_private;
346 if ( mra->ma_desc ) {
347 /* have a mra type? check for subtype */
348 if ( !is_ad_subtype( ad, mra->ma_desc ) ) {
351 value = mra->ma_value;
354 const char *text = NULL;
356 /* check if matching is appropriate */
357 if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type )) {
361 /* normalize for equality */
362 rc = asserted_value_validate_normalize( ad,
364 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
365 &mra->ma_value, &value, &text, memctx );
366 if ( rc != LDAP_SUCCESS ) {
370 /* check search access */
371 if ( !access_allowed( op, e,
372 ad, &value, ACL_SEARCH, NULL ) ) {
373 op->o_tmpfree( value.bv_val, memctx );
379 rc = value_match( &ret, ad, mra->ma_rule, 0,
382 if ( value.bv_val != mra->ma_value.bv_val ) {
383 op->o_tmpfree( value.bv_val, memctx );
386 if ( rc == LDAP_SUCCESS && ret == 0 ) {
387 rc = LDAP_COMPARE_TRUE;
390 if( rc != LDAP_SUCCESS ) {
391 ldap_dnfree_x( dn, memctx );
396 ldap_dnfree_x( dn, memctx );
399 return LDAP_COMPARE_FALSE;
406 AttributeAssertion *ava,
412 if ( !access_allowed( 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;
449 for ( bv = a->a_nvals; bv->bv_val != NULL; bv++ ) {
454 rc = value_match( &ret, a->a_desc, mr, 0,
455 bv, &ava->aa_value, &text );
457 if( rc != LDAP_SUCCESS ) {
462 case LDAP_FILTER_EQUALITY:
463 case LDAP_FILTER_APPROX:
465 return LDAP_COMPARE_TRUE;
471 return LDAP_COMPARE_TRUE;
477 return LDAP_COMPARE_TRUE;
484 if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates
485 && op && op->o_bd && op->o_bd->be_has_subordinates ) {
490 * No other match should be allowed ...
492 assert( type == LDAP_FILTER_EQUALITY );
494 if (op->o_bd->be_has_subordinates( op, e, &hasSubordinates ) != LDAP_SUCCESS) {
498 if ( hasSubordinates == LDAP_COMPARE_TRUE ) {
501 } else if ( hasSubordinates == LDAP_COMPARE_FALSE ) {
508 if ( bvmatch( &ava->aa_value, &hs ) ) {
509 return LDAP_COMPARE_TRUE;
512 return LDAP_COMPARE_FALSE;
515 return( LDAP_COMPARE_FALSE );
520 test_presence_filter(
523 AttributeDescription *desc
528 if ( !access_allowed( op, e, desc, NULL, ACL_SEARCH, NULL ) )
530 return LDAP_INSUFFICIENT_ACCESS;
533 a = attrs_find( e->e_attrs, desc );
535 if ( a == NULL && desc == slap_schema.si_ad_hasSubordinates ) {
538 * XXX: fairly optimistic: if the function is defined,
539 * then PRESENCE must succeed, because hasSubordinate
540 * is boolean-valued; I think we may live with this
541 * simplification by now
543 if ( op && op->o_bd && op->o_bd->be_has_subordinates ) {
544 return LDAP_COMPARE_TRUE;
547 return LDAP_COMPARE_FALSE;
550 return a != NULL ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
562 int rtn = LDAP_COMPARE_TRUE; /* True if empty */
565 LDAP_LOG( FILTER, ENTRY, "test_filter_and: begin\n", 0, 0, 0 );
567 Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 );
571 for ( f = flist; f != NULL; f = f->f_next ) {
572 int rc = test_filter( op, e, f );
574 if ( rc == LDAP_COMPARE_FALSE ) {
575 /* filter is False */
580 if ( rc != LDAP_COMPARE_TRUE ) {
581 /* filter is Undefined unless later elements are False */
587 LDAP_LOG( FILTER, RESULTS, "test_filter_and: rc=%d\n", rtn, 0, 0 );
589 Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
603 int rtn = LDAP_COMPARE_FALSE; /* False if empty */
606 LDAP_LOG( FILTER, ENTRY, "test_filter_or: begin\n", 0, 0, 0 );
608 Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
612 for ( f = flist; f != NULL; f = f->f_next ) {
613 int rc = test_filter( op, e, f );
615 if ( rc == LDAP_COMPARE_TRUE ) {
621 if ( rc != LDAP_COMPARE_FALSE ) {
622 /* filter is Undefined unless later elements are True */
628 LDAP_LOG( FILTER, ENTRY, "test_filter_or: result=%d\n", rtn, 0, 0 );
630 Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
638 test_substrings_filter(
647 LDAP_LOG( FILTER, ENTRY, "test_substrings_filter: begin\n", 0, 0, 0 );
649 Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 );
653 if ( !access_allowed( op, e,
654 f->f_sub_desc, NULL, ACL_SEARCH, NULL ) )
656 return LDAP_INSUFFICIENT_ACCESS;
659 for(a = attrs_find( e->e_attrs, f->f_sub_desc );
661 a = attrs_find( a->a_next, f->f_sub_desc ) )
663 MatchingRule *mr = a->a_desc->ad_type->sat_substr;
670 for ( bv = a->a_nvals; bv->bv_val != NULL; bv++ )
676 rc = value_match( &ret, a->a_desc, mr, 0,
677 bv, f->f_sub, &text );
679 if( rc != LDAP_SUCCESS ) {
684 return LDAP_COMPARE_TRUE;
690 LDAP_LOG( FILTER, ENTRY, "test_substrings_filter: return FALSE\n", 0, 0, 0 );
692 Debug( LDAP_DEBUG_FILTER, "end test_substrings_filter 1\n", 0, 0, 0 );
695 return LDAP_COMPARE_FALSE;