1 /* filterentry.c - apply a filter to an entry */
4 * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
12 #include <ac/socket.h>
13 #include <ac/string.h>
15 #ifndef SLAPD_SCHEMA_NOT_COMPAT
21 static int test_filter_and( Backend *be,
22 Connection *conn, Operation *op,
23 Entry *e, Filter *flist );
24 static int test_filter_or( Backend *be,
25 Connection *conn, Operation *op,
26 Entry *e, Filter *flist );
27 static int test_substring_filter( Backend *be,
28 Connection *conn, Operation *op,
30 #ifdef SLAPD_SCHEMA_NOT_COMPAT
31 static int test_ava_filter( Backend *be,
32 Connection *conn, Operation *op,
33 Entry *e, AttributeAssertion *ava, int type );
34 static int test_mra_filter( Backend *be,
35 Connection *conn, Operation *op,
36 Entry *e, MatchingRuleAssertion *mra );
37 static int test_presence_filter( Backend *be,
38 Connection *conn, Operation *op,
39 Entry *e, AttributeDescription *desc );
41 static int test_ava_filter(Backend *be,
42 Connection *conn, Operation *op,
43 Entry *e, Ava *ava, int type);
44 static int test_approx_filter(Backend *be,
45 Connection *conn, Operation *op,
47 static int test_presence_filter(Backend *be,
48 Connection *conn, Operation *op,
49 Entry *e, char *type);
54 * test_filter - test a filter against a single entry.
56 * LDAP_COMPARE_TRUE filter matched
57 * LDAP_COMPARE_FALSE filter did not match
58 * SLAPD_COMPARE_UNDEFINED filter is undefined
59 * or an ldap result code indicating error
73 Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
75 switch ( f->f_choice ) {
76 #ifdef SLAPD_SCHEMA_NOT_COMPAT
77 case SLAPD_FILTER_COMPUTED:
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",
87 case LDAP_FILTER_EQUALITY:
88 Debug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
89 #ifdef SLAPD_SCHEMA_NOT_COMPAT
90 rc = test_ava_filter( be, conn, op, e, f->f_ava,
91 LDAP_FILTER_EQUALITY );
93 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
94 LDAP_FILTER_EQUALITY );
98 case LDAP_FILTER_SUBSTRINGS:
99 Debug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
100 rc = test_substring_filter( be, conn, op, e, f );
104 #ifdef SLAPD_SCHEMA_NOT_COMPAT
105 rc = test_ava_filter( be, conn, op, e, f->f_ava,
108 Debug( LDAP_DEBUG_FILTER, " GE\n", 0, 0, 0 );
109 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
115 #ifdef SLAPD_SCHEMA_NOT_COMPAT
116 rc = test_ava_filter( be, conn, op, e, f->f_ava,
119 Debug( LDAP_DEBUG_FILTER, " LE\n", 0, 0, 0 );
120 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
125 case LDAP_FILTER_PRESENT:
126 Debug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
127 #ifdef SLAPD_SCHEMA_NOT_COMPAT
128 rc = test_presence_filter( be, conn, op, e, f->f_desc );
130 rc = test_presence_filter( be, conn, op, e, f->f_type );
134 case LDAP_FILTER_APPROX:
135 Debug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 );
136 #ifdef SLAPD_SCHEMA_NOT_COMPAT
137 rc = test_ava_filter( be, conn, op, e, f->f_ava,
138 LDAP_FILTER_APPROX );
140 rc = test_approx_filter( be, conn, op, e, &f->f_ava );
144 case LDAP_FILTER_AND:
145 Debug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 );
146 rc = test_filter_and( be, conn, op, e, f->f_and );
150 Debug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 );
151 rc = test_filter_or( be, conn, op, e, f->f_or );
154 case LDAP_FILTER_NOT:
155 Debug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 );
156 rc = test_filter( be, conn, op, e, f->f_not );
159 case LDAP_COMPARE_TRUE:
160 rc = LDAP_COMPARE_FALSE;
162 case LDAP_COMPARE_FALSE:
163 rc = LDAP_COMPARE_TRUE;
168 #ifdef SLAPD_EXT_FILTERS
169 case LDAP_FILTER_EXT:
170 Debug( LDAP_DEBUG_FILTER, " EXT\n", 0, 0, 0 );
171 #if SLAPD_SCHEMA_NOT_COMPAT
172 rc = test_mra_filter( be, conn, op, e, f->f_mra );
174 rc = LDAP_UNWILLING_TO_PERFORM;
180 Debug( LDAP_DEBUG_ANY, " unknown filter type %lu\n",
182 rc = LDAP_PROTOCOL_ERROR;
185 Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
196 #ifdef SLAPD_SCHEMA_NOT_COMPAT
197 AttributeAssertion *ava,
207 #ifdef SLAPD_SCHEMA_NOT_COMPAT
208 if ( be != NULL && ! access_allowed( be, conn, op, e,
209 ava->aa_desc, ava->aa_value, ACL_SEARCH ) )
212 if ( be != NULL && ! access_allowed( be, conn, op, e,
213 ava->ava_type, &ava->ava_value, ACL_SEARCH ) )
216 return LDAP_INSUFFICIENT_ACCESS;
219 #ifdef SLAPD_SCHEMA_NOT_COMPAT
220 for(a = attrs_find( e->e_attrs, ava->aa_desc );
222 a = attrs_find( a->a_next, ava->aa_desc ) )
224 a = attr_find( e->e_attrs, ava->ava_type );
228 #ifdef SLAPD_SCHEMA_NOT_COMPAT
232 case LDAP_FILTER_EQUALITY:
233 case LDAP_FILTER_APPROX:
234 mr = a->a_desc->ad_type->sat_equality;
239 mr = a->a_desc->ad_type->sat_ordering;
250 if ( a->a_syntax == 0 ) {
251 a->a_syntax = attr_syntax( ava->ava_type );
255 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
257 #ifdef SLAPD_SCHEMA_NOT_COMPAT
261 rc = value_match( &ret, a->a_desc, mr,
262 a->a_vals[i], ava->aa_value,
265 if( rc != LDAP_SUCCESS ) {
269 ret = value_cmp( a->a_vals[i], &ava->ava_value, a->a_syntax,
274 case LDAP_FILTER_EQUALITY:
275 case LDAP_FILTER_APPROX:
277 return LDAP_COMPARE_TRUE;
283 return LDAP_COMPARE_TRUE;
289 return LDAP_COMPARE_TRUE;
296 return( LDAP_COMPARE_FALSE );
301 test_presence_filter(
306 #ifdef SLAPD_SCHEMA_NOT_COMPAT
307 AttributeDescription *desc
313 if ( be != NULL && ! access_allowed( be, conn, op, e,
314 desc, NULL, ACL_SEARCH ) )
316 return LDAP_INSUFFICIENT_ACCESS;
319 #ifdef SLAPD_SCHEMA_NOT_COMPAT
320 return attrs_find( e->e_attrs, desc ) != NULL
322 return attr_find( e->e_attrs, desc ) != NULL
324 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
327 #ifndef SLAPD_SCHEMA_NOT_COMPAT
337 char *w1, *w2, *c1, *c2;
341 if ( be != NULL && ! access_allowed( be, conn, op, e,
342 ava->ava_type, NULL, ACL_SEARCH ) )
344 return LDAP_INSUFFICIENT_ACCESS;
347 a = attr_find( e->e_attrs, ava->ava_type );
349 /* for each value in the attribute */
350 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
352 * try to match words in the filter value in order
353 * in the attribute value.
356 w2 = a->a_vals[i]->bv_val;
357 /* for each word in the filter value */
358 for ( w1 = first_word( ava->ava_value.bv_val ); w1 != NULL;
359 w1 = next_word( w1 ) ) {
360 if ( (c1 = phonetic( w1 )) == NULL ) {
365 * for each word in the attribute value from
366 * where we left off...
368 for ( w2 = first_word( w2 ); w2 != NULL;
369 w2 = next_word( w2 ) ) {
371 if ( strcmp( c1, c2 ) == 0 ) {
380 * if we stopped because we ran out of words
381 * before making a match, go on to the next
382 * value. otherwise try to keep matching
383 * words in this value from where we left off.
388 w2 = next_word( w2 );
392 * if we stopped because we ran out of words we
396 return LDAP_COMPARE_TRUE;
401 return LDAP_COMPARE_FALSE;
415 int rtn = LDAP_COMPARE_TRUE;
417 Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 );
419 for ( f = flist; f != NULL; f = f->f_next ) {
420 int rc = test_filter( be, conn, op, e, f );
422 if ( rc == LDAP_COMPARE_FALSE ) {
423 rtn = LDAP_COMPARE_FALSE;
426 if ( rc != LDAP_COMPARE_TRUE ) {
431 Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
445 int rtn = LDAP_COMPARE_FALSE;
447 Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
449 for ( f = flist; f != NULL; f = f->f_next ) {
450 int rc = test_filter( be, conn, op, e, f );
452 if ( rc == LDAP_COMPARE_TRUE ) {
453 rtn = LDAP_COMPARE_TRUE;
456 if ( rc != LDAP_COMPARE_TRUE ) {
461 Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
465 #ifndef SLAPD_SCHEMA_NOT_COMPAT
467 strcpy_regex( char *d, char *s )
496 test_substring_filter(
505 #ifndef SLAPD_SCHEMA_NOT_COMPAT
507 char *p, *end, *realval, *tmp;
514 Debug( LDAP_DEBUG_FILTER, "begin test_substring_filter\n", 0, 0, 0 );
516 if ( be != NULL && ! access_allowed( be, conn, op, e,
517 f->f_sub_desc, NULL, ACL_SEARCH ) )
519 return LDAP_INSUFFICIENT_ACCESS;
522 #ifdef SLAPD_SCHEMA_NOT_COMPAT
523 for(a = attrs_find( e->e_attrs, f->f_sub_desc );
525 a = attrs_find( a->a_next, f->f_sub_desc ) )
527 a = attr_find( e->e_attrs, f->f_sub_type );
531 #ifdef SLAPD_SCHEMA_NOT_COMPAT
533 MatchingRule *mr = a->a_desc->ad_type->sat_substr;
539 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
544 rc = value_match( &ret, a->a_desc, mr,
545 a->a_vals[i], f->f_sub,
548 if( rc != LDAP_SUCCESS ) {
553 return LDAP_COMPARE_TRUE;
557 if ( a->a_syntax & SYNTAX_BIN ) {
558 Debug( LDAP_DEBUG_FILTER, "test_substring_filter bin attr\n",
560 return LDAP_INAPPROPRIATE_MATCHING;
564 * construct a regular expression corresponding to the
565 * filter and let regex do the work
570 end = pat + sizeof(pat) - 2; /* leave room for null */
571 if ( f->f_sub_initial != NULL ) {
573 p = strchr( p, '\0' );
574 /* 2 * in case every char is special */
575 if ( p + 2 * f->f_sub_initial->bv_len > end ) {
576 Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
580 strcpy_regex( p, f->f_sub_initial->bv_val );
581 p = strchr( p, '\0' );
583 if ( f->f_sub_any != NULL ) {
584 for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
586 if ( p + 2 * f->f_sub_any[i]->bv_len + 2 > end ) {
587 Debug( LDAP_DEBUG_ANY,
588 "not enough pattern space\n", 0, 0, 0 );
592 p = strchr( p, '\0' );
593 strcpy_regex( p, f->f_sub_any[i]->bv_val );
594 p = strchr( p, '\0' );
597 if ( f->f_sub_final != NULL ) {
599 if ( p + 2 * f->f_sub_final->bv_len + 2 > end ) {
600 Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
605 p = strchr( p, '\0' );
606 strcpy_regex( p, f->f_sub_final->bv_val );
607 p = strchr( p, '\0' );
611 /* compile the regex */
612 Debug( LDAP_DEBUG_FILTER, "test_substring_filter: regcomp pat: %s\n",
614 if ((rc = regcomp(&re, pat, REG_EXTENDED|REG_NOSUB))) {
617 regerror(rc, &re, error, sizeof(error));
618 Debug( LDAP_DEBUG_ANY, "regcomp failed (%s) %s\n",
623 /* for each value in the attribute see if regex matches */
624 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
627 if ( val->bv_len < sizeof(buf) ) {
628 strcpy( buf, val->bv_val );
631 tmp = (char *) ch_malloc( val->bv_len + 1 );
632 strcpy( tmp, val->bv_val );
636 value_normalize( realval, a->a_syntax );
638 rc = !regexec(&re, realval, 0, NULL, 0);
645 return LDAP_COMPARE_TRUE;
653 Debug( LDAP_DEBUG_FILTER, "end test_substring_filter 1\n", 0, 0, 0 );
654 return LDAP_COMPARE_FALSE;