1 /* filterentry.c - apply a filter to an entry */
6 #include <sys/socket.h>
14 extern Attribute *attr_find();
15 extern char *first_word();
16 extern char *next_word();
17 extern char *phonetic();
18 extern char *re_comp();
21 extern pthread_mutex_t regex_mutex;
24 static int test_filter_list();
25 static int test_substring_filter();
26 static int test_ava_filter();
27 static int test_approx_filter();
28 static int test_presence_filter();
31 * test_filter - test a filter against a single entry.
32 * returns 0 filter matched
33 * -1 filter did not match
34 * >0 an ldap error code
48 Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
50 switch ( f->f_choice ) {
51 case LDAP_FILTER_EQUALITY:
52 Debug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
53 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
54 LDAP_FILTER_EQUALITY );
57 case LDAP_FILTER_SUBSTRINGS:
58 Debug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
59 rc = test_substring_filter( be, conn, op, e, f );
63 Debug( LDAP_DEBUG_FILTER, " GE\n", 0, 0, 0 );
64 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
69 Debug( LDAP_DEBUG_FILTER, " LE\n", 0, 0, 0 );
70 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
74 case LDAP_FILTER_PRESENT:
75 Debug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
76 rc = test_presence_filter( be, conn, op, e, f->f_type );
79 case LDAP_FILTER_APPROX:
80 Debug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 );
81 rc = test_approx_filter( be, conn, op, e, &f->f_ava );
85 Debug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 );
86 rc = test_filter_list( be, conn, op, e, f->f_and,
91 Debug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 );
92 rc = test_filter_list( be, conn, op, e, f->f_or,
97 Debug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 );
98 rc = (! test_filter( be, conn, op, e, f->f_not ) );
102 Debug( LDAP_DEBUG_ANY, " unknown filter type %d\n",
107 Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
124 if ( be != NULL && ! access_allowed( be, conn, op, e, ava->ava_type,
125 &ava->ava_value, op->o_dn, ACL_SEARCH ) ) {
129 if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
133 if ( a->a_syntax == 0 ) {
134 a->a_syntax = attr_syntax( ava->ava_type );
136 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
137 rc = value_cmp( a->a_vals[i], &ava->ava_value, a->a_syntax,
141 case LDAP_FILTER_EQUALITY:
165 test_presence_filter(
173 if ( be != NULL && ! access_allowed( be, conn, op, e, type, NULL,
174 op->o_dn, ACL_SEARCH ) ) {
178 return( attr_find( e->e_attrs, type ) != NULL ? 0 : -1 );
190 char *w1, *w2, *c1, *c2;
194 if ( be != NULL && ! access_allowed( be, conn, op, e, ava->ava_type,
195 NULL, op->o_dn, ACL_SEARCH ) ) {
199 if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
203 /* for each value in the attribute */
204 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
206 * try to match words in the filter value in order
207 * in the attribute value.
210 w2 = a->a_vals[i]->bv_val;
211 /* for each word in the filter value */
212 for ( w1 = first_word( ava->ava_value.bv_val ); w1 != NULL;
213 w1 = next_word( w1 ) ) {
214 if ( (c1 = phonetic( w1 )) == NULL ) {
219 * for each word in the attribute value from
220 * where we left off...
222 for ( w2 = first_word( w2 ); w2 != NULL;
223 w2 = next_word( w2 ) ) {
225 if ( strcmp( c1, c2 ) == 0 ) {
234 * if we stopped because we ran out of words
235 * before making a match, go on to the next
236 * value. otherwise try to keep matching
237 * words in this value from where we left off.
242 w2 = next_word( w2 );
246 * if we stopped because we ran out of words we
270 Debug( LDAP_DEBUG_FILTER, "=> test_filter_list\n", 0, 0, 0 );
273 for ( f = flist; f != NULL; f = f->f_next ) {
274 if ( test_filter( be, conn, op, e, f ) != 0 ) {
275 if ( ftype == LDAP_FILTER_AND ) {
276 Debug( LDAP_DEBUG_FILTER,
277 "<= test_filter_list 1\n", 0, 0, 0 );
285 Debug( LDAP_DEBUG_FILTER, "<= test_filter_list %d\n", nomatch, 0, 0 );
290 strcpy_special( char *d, char *s )
312 test_substring_filter(
322 char *p, *end, *realval, *tmp;
327 Debug( LDAP_DEBUG_FILTER, "begin test_substring_filter\n", 0, 0, 0 );
329 if ( be != NULL && ! access_allowed( be, conn, op, e, f->f_sub_type,
330 NULL, op->o_dn, ACL_SEARCH ) ) {
334 if ( (a = attr_find( e->e_attrs, f->f_sub_type )) == NULL ) {
338 if ( a->a_syntax & SYNTAX_BIN ) {
339 Debug( LDAP_DEBUG_FILTER, "test_substring_filter bin attr\n",
345 * construct a regular expression corresponding to the
346 * filter and let regex do the work
351 end = pat + sizeof(pat) - 2; /* leave room for null */
352 if ( f->f_sub_initial != NULL ) {
354 p = strchr( p, '\0' );
355 /* 2 * in case every char is special */
356 if ( p + 2 * strlen( f->f_sub_initial ) > end ) {
357 Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
361 strcpy_special( p, f->f_sub_initial );
362 p = strchr( p, '\0' );
364 if ( f->f_sub_any != NULL ) {
365 for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
367 if ( p + 2 * strlen( f->f_sub_any[i] ) + 2 > end ) {
368 Debug( LDAP_DEBUG_ANY,
369 "not enough pattern space\n", 0, 0, 0 );
373 p = strchr( p, '\0' );
374 strcpy_special( p, f->f_sub_any[i] );
375 p = strchr( p, '\0' );
378 if ( f->f_sub_final != NULL ) {
380 if ( p + 2 * strlen( f->f_sub_final ) + 2 > end ) {
381 Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
386 p = strchr( p, '\0' );
387 strcpy_special( p, f->f_sub_final );
388 p = strchr( p, '\0' );
392 /* compile the regex */
394 if ( (p = compile( pat, NULL, NULL )) == NULL ) {
395 Debug( LDAP_DEBUG_ANY, "compile failed (%s)\n", p, 0, 0 );
399 pthread_mutex_lock( ®ex_mutex );
400 if ( (p = re_comp( pat )) != 0 ) {
401 Debug( LDAP_DEBUG_ANY, "re_comp failed (%s)\n", p, 0, 0 );
402 pthread_mutex_unlock( ®ex_mutex );
407 /* for each value in the attribute see if regex matches */
408 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
411 if ( val->bv_len < sizeof(buf) ) {
412 strcpy( buf, val->bv_val );
415 tmp = (char *) ch_malloc( val->bv_len + 1 );
416 strcpy( tmp, val->bv_val );
419 value_normalize( realval, a->a_syntax );
422 rc = step( realval, p );
424 rc = re_exec( realval );
434 pthread_mutex_unlock( ®ex_mutex );
442 pthread_mutex_unlock( ®ex_mutex );
445 Debug( LDAP_DEBUG_FILTER, "end test_substring_filter 1\n", 0, 0, 0 );