1 /* filterentry.c - apply a filter to an entry */
4 * Copyright 1998-1999 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 * or an ldap error code
72 Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
74 switch ( f->f_choice ) {
75 case LDAP_FILTER_EQUALITY:
76 Debug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
77 #ifdef SLAPD_SCHEMA_NOT_COMPAT
78 rc = test_ava_filter( be, conn, op, e, f->f_ava,
79 LDAP_FILTER_EQUALITY );
81 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
82 LDAP_FILTER_EQUALITY );
86 case LDAP_FILTER_SUBSTRINGS:
87 Debug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
88 rc = test_substring_filter( be, conn, op, e, f );
92 #ifdef SLAPD_SCHEMA_NOT_COMPAT
93 rc = test_ava_filter( be, conn, op, e, f->f_ava,
96 Debug( LDAP_DEBUG_FILTER, " GE\n", 0, 0, 0 );
97 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
103 #ifdef SLAPD_SCHEMA_NOT_COMPAT
104 rc = test_ava_filter( be, conn, op, e, f->f_ava,
107 Debug( LDAP_DEBUG_FILTER, " LE\n", 0, 0, 0 );
108 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
113 case LDAP_FILTER_PRESENT:
114 Debug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
115 #ifdef SLAPD_SCHEMA_NOT_COMPAT
116 rc = test_presence_filter( be, conn, op, e, f->f_desc );
118 rc = test_presence_filter( be, conn, op, e, f->f_type );
122 case LDAP_FILTER_APPROX:
123 Debug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 );
124 #ifdef SLAPD_SCHEMA_NOT_COMPAT
125 rc = test_ava_filter( be, conn, op, e, f->f_ava,
126 LDAP_FILTER_APPROX );
128 rc = test_approx_filter( be, conn, op, e, &f->f_ava );
132 case LDAP_FILTER_AND:
133 Debug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 );
134 rc = test_filter_and( be, conn, op, e, f->f_and );
138 Debug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 );
139 rc = test_filter_or( be, conn, op, e, f->f_or );
142 case LDAP_FILTER_NOT:
143 Debug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 );
144 rc = test_filter( be, conn, op, e, f->f_not );
147 case LDAP_COMPARE_TRUE:
148 rc = LDAP_COMPARE_FALSE;
150 case LDAP_COMPARE_FALSE:
151 rc = LDAP_COMPARE_TRUE;
156 case LDAP_FILTER_EXT:
157 Debug( LDAP_DEBUG_FILTER, " EXT\n", 0, 0, 0 );
158 #if SLAPD_SCHEMA_NOT_COMPAT && notyet
159 rc = test_mra_filter( be, conn, op, e, f->f_mra );
166 Debug( LDAP_DEBUG_FILTER, " UNDEFINED\n", 0, 0, 0 );
171 Debug( LDAP_DEBUG_ANY, " unknown filter type %lu\n",
176 Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
187 #ifdef SLAPD_SCHEMA_NOT_COMPAT
188 AttributeAssertion *ava,
198 #ifdef SLAPD_SCHEMA_NOT_COMPAT
199 if ( be != NULL && ! access_allowed( be, conn, op, e,
200 ava->aa_desc, ava->aa_value, ACL_SEARCH ) )
203 if ( be != NULL && ! access_allowed( be, conn, op, e,
204 ava->ava_type, &ava->ava_value, ACL_SEARCH ) )
210 #ifdef SLAPD_SCHEMA_NOT_COMPAT
211 if ( (a = attr_find( e->e_attrs, ava->aa_desc )) == NULL )
213 if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL )
216 return LDAP_COMPARE_FALSE;
219 #ifdef SLAPD_SCHEMA_NOT_COMPAT
220 /* not yet implemented */
222 if ( a->a_syntax == 0 ) {
223 a->a_syntax = attr_syntax( ava->ava_type );
227 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
228 #ifdef SLAPD_SCHEMA_NOT_COMPAT
232 case LDAP_FILTER_EQUALITY:
234 case LDAP_FILTER_APPROX:
242 if( rc == LDAP_COMPARE_TRUE ) return LDAP_COMPARE_TRUE;
244 int rc = value_cmp( a->a_vals[i], &ava->ava_value, a->a_syntax,
248 case LDAP_FILTER_EQUALITY:
249 case LDAP_FILTER_APPROX:
251 return LDAP_COMPARE_TRUE;
257 return LDAP_COMPARE_TRUE;
263 return LDAP_COMPARE_TRUE;
270 return( LDAP_COMPARE_FALSE );
275 test_presence_filter(
280 #ifdef SLAPD_SCHEMA_NOT_COMPAT
281 AttributeDescription *desc
287 #ifdef SLAPD_SCHEMA_NOT_COMPAT
288 if ( be != NULL && ! access_allowed( be, conn, op, e,
289 desc, NULL, ACL_SEARCH ) )
291 if ( be != NULL && ! access_allowed( be, conn, op, e,
292 type, NULL, ACL_SEARCH ) )
298 #ifdef SLAPD_SCHEMA_NOT_COMPAT
299 return attr_find( e->e_attrs, desc ) != NULL
301 return attr_find( e->e_attrs, type ) != NULL
303 ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
306 #ifndef SLAPD_SCHEMA_NOT_COMPAT
317 char *w1, *w2, *c1, *c2;
321 if ( be != NULL && ! access_allowed( be, conn, op, e,
322 ava->ava_type, NULL, ACL_SEARCH ) )
327 if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
328 return LDAP_COMPARE_FALSE;
331 /* for each value in the attribute */
332 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
334 * try to match words in the filter value in order
335 * in the attribute value.
338 w2 = a->a_vals[i]->bv_val;
339 /* for each word in the filter value */
340 for ( w1 = first_word( ava->ava_value.bv_val ); w1 != NULL;
341 w1 = next_word( w1 ) ) {
342 if ( (c1 = phonetic( w1 )) == NULL ) {
347 * for each word in the attribute value from
348 * where we left off...
350 for ( w2 = first_word( w2 ); w2 != NULL;
351 w2 = next_word( w2 ) ) {
353 if ( strcmp( c1, c2 ) == 0 ) {
362 * if we stopped because we ran out of words
363 * before making a match, go on to the next
364 * value. otherwise try to keep matching
365 * words in this value from where we left off.
370 w2 = next_word( w2 );
374 * if we stopped because we ran out of words we
378 return LDAP_COMPARE_TRUE;
382 return LDAP_COMPARE_FALSE;
397 int rtn = LDAP_COMPARE_TRUE;
399 Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 );
401 for ( f = flist; f != NULL; f = f->f_next ) {
402 int rc = test_filter( be, conn, op, e, f );
404 if ( rc == LDAP_COMPARE_FALSE ) {
405 rtn = LDAP_COMPARE_FALSE;
408 if ( rc != LDAP_COMPARE_TRUE ) {
413 Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
427 int rtn = LDAP_COMPARE_FALSE;
429 Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
431 for ( f = flist; f != NULL; f = f->f_next ) {
432 int rc = test_filter( be, conn, op, e, f );
434 if ( rc == LDAP_COMPARE_TRUE ) {
435 rtn = LDAP_COMPARE_TRUE;
438 if ( rc != LDAP_COMPARE_TRUE ) {
443 Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
447 #ifndef SLAPD_SCHEMA_NOT_COMPAT
449 strcpy_regex( char *d, char *s )
478 test_substring_filter(
486 #ifndef SLAPD_SCHEMA_NOT_COMPAT
489 char *p, *end, *realval, *tmp;
495 Debug( LDAP_DEBUG_FILTER, "begin test_substring_filter\n", 0, 0, 0 );
497 if ( be != NULL && ! access_allowed( be, conn, op, e,
498 f->f_sub_type, NULL, ACL_SEARCH ) )
503 if ( (a = attr_find( e->e_attrs, f->f_sub_type )) == NULL ) {
504 return LDAP_COMPARE_FALSE;
507 if ( a->a_syntax & SYNTAX_BIN ) {
508 Debug( LDAP_DEBUG_FILTER, "test_substring_filter bin attr\n",
514 * construct a regular expression corresponding to the
515 * filter and let regex do the work
520 end = pat + sizeof(pat) - 2; /* leave room for null */
521 if ( f->f_sub_initial != NULL ) {
523 p = strchr( p, '\0' );
524 /* 2 * in case every char is special */
525 if ( p + 2 * f->f_sub_initial->bv_len > end ) {
526 Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
530 strcpy_regex( p, f->f_sub_initial->bv_val );
531 p = strchr( p, '\0' );
533 if ( f->f_sub_any != NULL ) {
534 for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
536 if ( p + 2 * f->f_sub_any[i]->bv_len + 2 > end ) {
537 Debug( LDAP_DEBUG_ANY,
538 "not enough pattern space\n", 0, 0, 0 );
542 p = strchr( p, '\0' );
543 strcpy_regex( p, f->f_sub_any[i]->bv_val );
544 p = strchr( p, '\0' );
547 if ( f->f_sub_final != NULL ) {
549 if ( p + 2 * f->f_sub_final->bv_len + 2 > end ) {
550 Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
555 p = strchr( p, '\0' );
556 strcpy_regex( p, f->f_sub_final->bv_val );
557 p = strchr( p, '\0' );
561 /* compile the regex */
562 Debug( LDAP_DEBUG_FILTER, "test_substring_filter: regcomp pat: %s\n",
564 if ((rc = regcomp(&re, pat, REG_EXTENDED|REG_NOSUB))) {
567 regerror(rc, &re, error, sizeof(error));
568 Debug( LDAP_DEBUG_ANY, "regcomp failed (%s) %s\n",
573 /* for each value in the attribute see if regex matches */
574 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
577 if ( val->bv_len < sizeof(buf) ) {
578 strcpy( buf, val->bv_val );
581 tmp = (char *) ch_malloc( val->bv_len + 1 );
582 strcpy( tmp, val->bv_val );
586 value_normalize( realval, a->a_syntax );
588 rc = !regexec(&re, realval, 0, NULL, 0);
595 return LDAP_COMPARE_TRUE;
602 Debug( LDAP_DEBUG_FILTER, "end test_substring_filter 1\n", 0, 0, 0 );
603 return LDAP_COMPARE_FALSE;