1 /* filterentry.c - apply a filter to an entry */
8 #include <sys/socket.h>
12 extern Attribute *attr_find();
13 extern char *first_word();
14 extern char *next_word();
15 extern char *phonetic();
17 static int test_filter_list();
18 static int test_substring_filter();
19 static int test_ava_filter();
20 static int test_approx_filter();
21 static int test_presence_filter();
24 * test_filter - test a filter against a single entry.
25 * returns 0 filter matched
26 * -1 filter did not match
27 * >0 an ldap error code
41 Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
43 switch ( f->f_choice ) {
44 case LDAP_FILTER_EQUALITY:
45 Debug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
46 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
47 LDAP_FILTER_EQUALITY );
50 case LDAP_FILTER_SUBSTRINGS:
51 Debug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
52 rc = test_substring_filter( be, conn, op, e, f );
56 Debug( LDAP_DEBUG_FILTER, " GE\n", 0, 0, 0 );
57 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
62 Debug( LDAP_DEBUG_FILTER, " LE\n", 0, 0, 0 );
63 rc = test_ava_filter( be, conn, op, e, &f->f_ava,
67 case LDAP_FILTER_PRESENT:
68 Debug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
69 rc = test_presence_filter( be, conn, op, e, f->f_type );
72 case LDAP_FILTER_APPROX:
73 Debug( LDAP_DEBUG_FILTER, " APPROX\n", 0, 0, 0 );
74 rc = test_approx_filter( be, conn, op, e, &f->f_ava );
78 Debug( LDAP_DEBUG_FILTER, " AND\n", 0, 0, 0 );
79 rc = test_filter_list( be, conn, op, e, f->f_and,
84 Debug( LDAP_DEBUG_FILTER, " OR\n", 0, 0, 0 );
85 rc = test_filter_list( be, conn, op, e, f->f_or,
90 Debug( LDAP_DEBUG_FILTER, " NOT\n", 0, 0, 0 );
91 rc = (! test_filter( be, conn, op, e, f->f_not ) );
95 Debug( LDAP_DEBUG_ANY, " unknown filter type %d\n",
100 Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
117 if ( be != NULL && ! access_allowed( be, conn, op, e, ava->ava_type,
118 &ava->ava_value, op->o_dn, ACL_SEARCH ) ) {
122 if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
126 if ( a->a_syntax == 0 ) {
127 a->a_syntax = attr_syntax( ava->ava_type );
129 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
130 rc = value_cmp( a->a_vals[i], &ava->ava_value, a->a_syntax,
134 case LDAP_FILTER_EQUALITY:
158 test_presence_filter(
166 if ( be != NULL && ! access_allowed( be, conn, op, e, type, NULL,
167 op->o_dn, ACL_SEARCH ) ) {
171 return( attr_find( e->e_attrs, type ) != NULL ? 0 : -1 );
183 char *w1, *w2, *c1, *c2;
187 if ( be != NULL && ! access_allowed( be, conn, op, e, ava->ava_type,
188 NULL, op->o_dn, ACL_SEARCH ) ) {
192 if ( (a = attr_find( e->e_attrs, ava->ava_type )) == NULL ) {
196 /* for each value in the attribute */
197 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
199 * try to match words in the filter value in order
200 * in the attribute value.
203 w2 = a->a_vals[i]->bv_val;
204 /* for each word in the filter value */
205 for ( w1 = first_word( ava->ava_value.bv_val ); w1 != NULL;
206 w1 = next_word( w1 ) ) {
207 if ( (c1 = phonetic( w1 )) == NULL ) {
212 * for each word in the attribute value from
213 * where we left off...
215 for ( w2 = first_word( w2 ); w2 != NULL;
216 w2 = next_word( w2 ) ) {
218 if ( strcmp( c1, c2 ) == 0 ) {
227 * if we stopped because we ran out of words
228 * before making a match, go on to the next
229 * value. otherwise try to keep matching
230 * words in this value from where we left off.
235 w2 = next_word( w2 );
239 * if we stopped because we ran out of words we
263 Debug( LDAP_DEBUG_FILTER, "=> test_filter_list\n", 0, 0, 0 );
266 for ( f = flist; f != NULL; f = f->f_next ) {
267 if ( test_filter( be, conn, op, e, f ) != 0 ) {
268 if ( ftype == LDAP_FILTER_AND ) {
269 Debug( LDAP_DEBUG_FILTER,
270 "<= test_filter_list 1\n", 0, 0, 0 );
278 Debug( LDAP_DEBUG_FILTER, "<= test_filter_list %d\n", nomatch, 0, 0 );
283 strcpy_special( char *d, char *s )
305 test_substring_filter(
315 char *p, *end, *realval, *tmp;
321 Debug( LDAP_DEBUG_FILTER, "begin test_substring_filter\n", 0, 0, 0 );
323 if ( be != NULL && ! access_allowed( be, conn, op, e, f->f_sub_type,
324 NULL, op->o_dn, ACL_SEARCH ) ) {
328 if ( (a = attr_find( e->e_attrs, f->f_sub_type )) == NULL ) {
332 if ( a->a_syntax & SYNTAX_BIN ) {
333 Debug( LDAP_DEBUG_FILTER, "test_substring_filter bin attr\n",
339 * construct a regular expression corresponding to the
340 * filter and let regex do the work
345 end = pat + sizeof(pat) - 2; /* leave room for null */
346 if ( f->f_sub_initial != NULL ) {
348 p = strchr( p, '\0' );
349 /* 2 * in case every char is special */
350 if ( p + 2 * strlen( f->f_sub_initial ) > end ) {
351 Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
355 strcpy_special( p, f->f_sub_initial );
356 p = strchr( p, '\0' );
358 if ( f->f_sub_any != NULL ) {
359 for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
361 if ( p + 2 * strlen( f->f_sub_any[i] ) + 2 > end ) {
362 Debug( LDAP_DEBUG_ANY,
363 "not enough pattern space\n", 0, 0, 0 );
367 p = strchr( p, '\0' );
368 strcpy_special( p, f->f_sub_any[i] );
369 p = strchr( p, '\0' );
372 if ( f->f_sub_final != NULL ) {
374 if ( p + 2 * strlen( f->f_sub_final ) + 2 > end ) {
375 Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
380 p = strchr( p, '\0' );
381 strcpy_special( p, f->f_sub_final );
382 p = strchr( p, '\0' );
386 /* compile the regex */
387 Debug( LDAP_DEBUG_FILTER, "test_substring_filter: regcomp pat: %s\n",
389 if ((rc = regcomp(&re, pat, 0))) {
392 regerror(rc, &re, error, sizeof(error));
393 Debug( LDAP_DEBUG_ANY, "regcomp failed (%s) %s\n",
398 /* for each value in the attribute see if regex matches */
399 for ( i = 0; a->a_vals[i] != NULL; i++ ) {
402 if ( val->bv_len < sizeof(buf) ) {
403 strcpy( buf, val->bv_val );
406 tmp = (char *) ch_malloc( val->bv_len + 1 );
407 strcpy( tmp, val->bv_val );
410 value_normalize( realval, a->a_syntax );
412 rc = !regexec(&re, realval, 0, NULL, 0);
425 Debug( LDAP_DEBUG_FILTER, "end test_substring_filter 1\n", 0, 0, 0 );