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>
18 static int test_filter_list(Backend *be, Connection *conn, Operation *op, Entry *e, Filter *flist, int ftype);
19 static int test_substring_filter(Backend *be, Connection *conn, Operation *op, Entry *e, Filter *f);
20 static int test_ava_filter(Backend *be, Connection *conn, Operation *op, Entry *e, Ava *ava, int type);
21 static int test_approx_filter(Backend *be, Connection *conn, Operation *op, Entry *e, Ava *ava);
22 static int test_presence_filter(Backend *be, Connection *conn, Operation *op, Entry *e, char *type);
25 * test_filter - test a filter against a single entry.
26 * returns 0 filter matched
27 * -1 filter did not match
28 * >0 an ldap error code
42 Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
44 switch ( f->f_choice ) {
45 case LDAP_FILTER_EQUALITY:
46 Debug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
47 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
48 LDAP_FILTER_EQUALITY );
51 case LDAP_FILTER_SUBSTRINGS:
52 Debug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
53 rc = test_substring_filter( be, conn, op, e, f );
57 Debug( LDAP_DEBUG_FILTER, " GE\n", 0, 0, 0 );
58 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
63 Debug( LDAP_DEBUG_FILTER, " LE\n", 0, 0, 0 );
64 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
68 case LDAP_FILTER_PRESENT:
69 Debug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
70 rc = test_presence_filter( be, conn, op, e, f->f_type );
73 case LDAP_FILTER_APPROX:
74 Debug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 );
75 rc = test_approx_filter( be, conn, op, e, &f->f_ava );
79 Debug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 );
80 rc = test_filter_list( be, conn, op, e, f->f_and,
85 Debug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 );
86 rc = test_filter_list( be, conn, op, e, f->f_or,
91 Debug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 );
92 rc = (! test_filter( be, conn, op, e, f->f_not ) );
96 Debug( LDAP_DEBUG_ANY, " unknown filter type %lu\n",
101 Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
118 if ( be != NULL && ! access_allowed( be, conn, op, e,
119 ava->ava_type, &ava->ava_value, ACL_SEARCH ) )
124 if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
128 if ( a->a_syntax == 0 ) {
129 a->a_syntax = attr_syntax( ava->ava_type );
131 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
132 rc = value_cmp( a->a_vals[i], &ava->ava_value, a->a_syntax,
136 case LDAP_FILTER_EQUALITY:
160 test_presence_filter(
168 if ( be != NULL && ! access_allowed( be, conn, op, e,
169 type, NULL, ACL_SEARCH ) )
174 return( attr_find( e->e_attrs, type ) != NULL ? 0 : -1 );
186 char *w1, *w2, *c1, *c2;
190 if ( be != NULL && ! access_allowed( be, conn, op, e,
191 ava->ava_type, NULL, ACL_SEARCH ) )
196 if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
200 /* for each value in the attribute */
201 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
203 * try to match words in the filter value in order
204 * in the attribute value.
207 w2 = a->a_vals[i]->bv_val;
208 /* for each word in the filter value */
209 for ( w1 = first_word( ava->ava_value.bv_val ); w1 != NULL;
210 w1 = next_word( w1 ) ) {
211 if ( (c1 = phonetic( w1 )) == NULL ) {
216 * for each word in the attribute value from
217 * where we left off...
219 for ( w2 = first_word( w2 ); w2 != NULL;
220 w2 = next_word( w2 ) ) {
222 if ( strcmp( c1, c2 ) == 0 ) {
231 * if we stopped because we ran out of words
232 * before making a match, go on to the next
233 * value. otherwise try to keep matching
234 * words in this value from where we left off.
239 w2 = next_word( w2 );
243 * if we stopped because we ran out of words we
267 Debug( LDAP_DEBUG_FILTER, "=> test_filter_list\n", 0, 0, 0 );
270 for ( f = flist; f != NULL; f = f->f_next ) {
271 if ( test_filter( be, conn, op, e, f ) != 0 ) {
272 if ( ftype == LDAP_FILTER_AND ) {
273 Debug( LDAP_DEBUG_FILTER,
274 "<= test_filter_list 1\n", 0, 0, 0 );
282 Debug( LDAP_DEBUG_FILTER, "<= test_filter_list %d\n", nomatch, 0, 0 );
287 strcpy_regex( char *d, char *s )
315 test_substring_filter(
325 char *p, *end, *realval, *tmp;
331 Debug( LDAP_DEBUG_FILTER, "begin test_substring_filter\n", 0, 0, 0 );
333 if ( be != NULL && ! access_allowed( be, conn, op, e,
334 f->f_sub_type, NULL, ACL_SEARCH ) )
339 if ( (a = attr_find( e->e_attrs, f->f_sub_type )) == NULL ) {
343 if ( a->a_syntax & SYNTAX_BIN ) {
344 Debug( LDAP_DEBUG_FILTER, "test_substring_filter bin attr\n",
350 * construct a regular expression corresponding to the
351 * filter and let regex do the work
356 end = pat + sizeof(pat) - 2; /* leave room for null */
357 if ( f->f_sub_initial != NULL ) {
359 p = strchr( p, '\0' );
360 /* 2 * in case every char is special */
361 if ( p + 2 * strlen( f->f_sub_initial ) > end ) {
362 Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
366 strcpy_regex( p, f->f_sub_initial );
367 p = strchr( p, '\0' );
369 if ( f->f_sub_any != NULL ) {
370 for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
372 if ( p + 2 * strlen( f->f_sub_any[i] ) + 2 > end ) {
373 Debug( LDAP_DEBUG_ANY,
374 "not enough pattern space\n", 0, 0, 0 );
378 p = strchr( p, '\0' );
379 strcpy_regex( p, f->f_sub_any[i] );
380 p = strchr( p, '\0' );
383 if ( f->f_sub_final != NULL ) {
385 if ( p + 2 * strlen( f->f_sub_final ) + 2 > end ) {
386 Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
391 p = strchr( p, '\0' );
392 strcpy_regex( p, f->f_sub_final );
393 p = strchr( p, '\0' );
397 /* compile the regex */
398 Debug( LDAP_DEBUG_FILTER, "test_substring_filter: regcomp pat: %s\n",
400 if ((rc = regcomp(&re, pat, REG_EXTENDED|REG_NOSUB))) {
403 regerror(rc, &re, error, sizeof(error));
404 Debug( LDAP_DEBUG_ANY, "regcomp failed (%s) %s\n",
409 /* for each value in the attribute see if regex matches */
410 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
413 if ( val->bv_len < sizeof(buf) ) {
414 strcpy( buf, val->bv_val );
417 tmp = (char *) ch_malloc( val->bv_len + 1 );
418 strcpy( tmp, val->bv_val );
421 value_normalize( realval, a->a_syntax );
423 rc = !regexec(&re, realval, 0, NULL, 0);
436 Debug( LDAP_DEBUG_FILTER, "end test_substring_filter 1\n", 0, 0, 0 );