]> git.sur5r.net Git - openldap/blob - servers/slapd/filter.c
Fixed "faled" typo in debug message
[openldap] / servers / slapd / filter.c
1 /* filter.c - routines for parsing and dealing with filters */
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include "slap.h"
8
9 static int      get_filter_list();
10 static int      get_substring_filter();
11
12 extern int      get_ava();
13 extern char     *ch_malloc();
14 extern char     *ch_realloc();
15
16 int
17 get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr )
18 {
19         unsigned long   tag, len;
20         int             err;
21         Filter          *f;
22         char            *ftmp;
23
24         Debug( LDAP_DEBUG_FILTER, "begin get_filter\n", 0, 0, 0 );
25
26         /*
27          * A filter looks like this coming in:
28          *      Filter ::= CHOICE {
29          *              and             [0]     SET OF Filter,
30          *              or              [1]     SET OF Filter,
31          *              not             [2]     Filter,
32          *              equalityMatch   [3]     AttributeValueAssertion,
33          *              substrings      [4]     SubstringFilter,
34          *              greaterOrEqual  [5]     AttributeValueAssertion,
35          *              lessOrEqual     [6]     AttributeValueAssertion,
36          *              present         [7]     AttributeType,,
37          *              approxMatch     [8]     AttributeValueAssertion
38          *      }
39          *
40          *      SubstringFilter ::= SEQUENCE {
41          *              type               AttributeType,
42          *              SEQUENCE OF CHOICE {
43          *                      initial          [0] IA5String,
44          *                      any              [1] IA5String,
45          *                      final            [2] IA5String
46          *              }
47          *      }
48          */
49
50         f = (Filter *) ch_malloc( sizeof(Filter) );
51         *filt = f;
52         f->f_next = NULL;
53
54         err = 0;
55         *fstr = NULL;
56         f->f_choice = ber_peek_tag( ber, &len );
57 #ifdef COMPAT30
58         if ( conn->c_version == 30 ) {
59                 switch ( f->f_choice ) {
60                 case LDAP_FILTER_EQUALITY:
61                 case LDAP_FILTER_GE:
62                 case LDAP_FILTER_LE:
63                 case LDAP_FILTER_PRESENT:
64                 case LDAP_FILTER_PRESENT_30:
65                 case LDAP_FILTER_APPROX:
66                         (void) ber_skip_tag( ber, &len );
67                         if ( f->f_choice == LDAP_FILTER_PRESENT_30 ) {
68                                 f->f_choice = LDAP_FILTER_PRESENT;
69                         }
70                         break;
71                 default:
72                         break;
73                 }
74         }
75 #endif
76         switch ( f->f_choice ) {
77         case LDAP_FILTER_EQUALITY:
78                 Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
79                 if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
80                         *fstr = ch_malloc(4 + strlen( f->f_avtype ) +
81                             f->f_avvalue.bv_len);
82                         sprintf( *fstr, "(%s=%s)", f->f_avtype,
83                             f->f_avvalue.bv_val );
84                 }
85                 break;
86
87         case LDAP_FILTER_SUBSTRINGS:
88                 Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
89                 err = get_substring_filter( conn, ber, f, fstr );
90                 break;
91
92         case LDAP_FILTER_GE:
93                 Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
94                 if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
95                         *fstr = ch_malloc(5 + strlen( f->f_avtype ) +
96                             f->f_avvalue.bv_len);
97                         sprintf( *fstr, "(%s>=%s)", f->f_avtype,
98                             f->f_avvalue.bv_val );
99                 }
100                 break;
101
102         case LDAP_FILTER_LE:
103                 Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
104                 if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
105                         *fstr = ch_malloc(5 + strlen( f->f_avtype ) +
106                             f->f_avvalue.bv_len);
107                         sprintf( *fstr, "(%s<=%s)", f->f_avtype,
108                             f->f_avvalue.bv_val );
109                 }
110                 break;
111
112         case LDAP_FILTER_PRESENT:
113                 Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
114                 if ( ber_scanf( ber, "a", &f->f_type ) == LBER_ERROR ) {
115                         err = LDAP_PROTOCOL_ERROR;
116                 } else {
117                         err = LDAP_SUCCESS;
118                         attr_normalize( f->f_type );
119                         *fstr = ch_malloc( 5 + strlen( f->f_type ) );
120                         sprintf( *fstr, "(%s=*)", f->f_type );
121                 }
122                 break;
123
124         case LDAP_FILTER_APPROX:
125                 Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
126                 if ( (err = get_ava( ber, &f->f_ava )) == 0 ) {
127                         *fstr = ch_malloc(5 + strlen( f->f_avtype ) +
128                             f->f_avvalue.bv_len);
129                         sprintf( *fstr, "(%s~=%s)", f->f_avtype,
130                             f->f_avvalue.bv_val );
131                 }
132                 break;
133
134         case LDAP_FILTER_AND:
135                 Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
136                 if ( (err = get_filter_list( conn, ber, &f->f_and, &ftmp ))
137                     == 0 ) {
138                   if (ftmp == NULL) ftmp = strdup("");
139                         *fstr = ch_malloc( 4 + strlen( ftmp ) );
140                         sprintf( *fstr, "(&%s)", ftmp );
141                         free( ftmp );
142                 }
143                 break;
144
145         case LDAP_FILTER_OR:
146                 Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
147                 if ( (err = get_filter_list( conn, ber, &f->f_or, &ftmp ))
148                     == 0 ) {
149                   if (ftmp == NULL) ftmp = strdup("");
150                         *fstr = ch_malloc( 4 + strlen( ftmp ) );
151                         sprintf( *fstr, "(|%s)", ftmp );
152                         free( ftmp );
153                 }
154                 break;
155
156         case LDAP_FILTER_NOT:
157                 Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
158                 (void) ber_skip_tag( ber, &len );
159                 if ( (err = get_filter( conn, ber, &f->f_not, &ftmp )) == 0 ) {
160                   if (ftmp == NULL) ftmp = strdup("");
161                         *fstr = ch_malloc( 4 + strlen( ftmp ) );
162                         sprintf( *fstr, "(!%s)", ftmp );
163                         free( ftmp );
164                 }
165                 break;
166
167         default:
168                 Debug( LDAP_DEBUG_ANY, "unknown filter type %d\n", f->f_choice,
169                     0, 0 );
170                 err = LDAP_PROTOCOL_ERROR;
171                 break;
172         }
173
174         if ( err != 0 ) {
175                 free( (char *) f );
176                 if ( *fstr != NULL ) {
177                         free( *fstr );
178                 }
179         }
180
181         Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
182         return( err );
183 }
184
185 static int
186 get_filter_list( Connection *conn, BerElement *ber, Filter **f, char **fstr )
187 {
188         Filter          **new;
189         int             err;
190         unsigned long   tag, len;
191         char            *last, *ftmp;
192
193         Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
194
195 #ifdef COMPAT30
196         if ( conn->c_version == 30 ) {
197                 (void) ber_skip_tag( ber, &len );
198         }
199 #endif
200         *fstr = NULL;
201         new = f;
202         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
203             tag = ber_next_element( ber, &len, last ) ) {
204                 if ( (err = get_filter( conn, ber, new, &ftmp )) != 0 )
205                         return( err );
206                 if ( *fstr == NULL ) {
207                         *fstr = ftmp;
208                 } else {
209                         *fstr = ch_realloc( *fstr, strlen( *fstr ) +
210                             strlen( ftmp ) + 1 );
211                         strcat( *fstr, ftmp );
212                         free( ftmp );
213                 }
214                 new = &(*new)->f_next;
215         }
216         *new = NULL;
217
218         Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
219         return( 0 );
220 }
221
222 static int
223 get_substring_filter(
224     Connection  *conn,
225     BerElement  *ber,
226     Filter      *f,
227     char        **fstr
228 )
229 {
230         unsigned long   tag, len, rc;
231         char            *val, *last;
232         int             syntax;
233
234         Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
235
236 #ifdef COMPAT30
237         if ( conn->c_version == 30 ) {
238                 (void) ber_skip_tag( ber, &len );
239         }
240 #endif
241         if ( ber_scanf( ber, "{a", &f->f_sub_type ) == LBER_ERROR ) {
242                 return( LDAP_PROTOCOL_ERROR );
243         }
244         attr_normalize( f->f_sub_type );
245         syntax = attr_syntax( f->f_sub_type );
246         f->f_sub_initial = NULL;
247         f->f_sub_any = NULL;
248         f->f_sub_final = NULL;
249
250         *fstr = ch_malloc( strlen( f->f_sub_type ) + 3 );
251         sprintf( *fstr, "(%s=", f->f_sub_type );
252         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
253             tag = ber_next_element( ber, &len, last ) ) {
254 #ifdef COMPAT30
255                 if ( conn->c_version == 30 ) {
256                         rc = ber_scanf( ber, "{a}", &val );
257                 } else
258 #endif
259                         rc = ber_scanf( ber, "a", &val );
260                 if ( rc == LBER_ERROR ) {
261                         return( LDAP_PROTOCOL_ERROR );
262                 }
263                 if ( val == NULL || *val == '\0' ) {
264                         if ( val != NULL ) {
265                                 free( val );
266                         }
267                         return( LDAP_INVALID_SYNTAX );
268                 }
269                 value_normalize( val, syntax );
270
271                 switch ( tag ) {
272 #ifdef COMPAT30
273                 case LDAP_SUBSTRING_INITIAL_30:
274 #endif
275                 case LDAP_SUBSTRING_INITIAL:
276                         Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
277                         if ( f->f_sub_initial != NULL ) {
278                                 return( LDAP_PROTOCOL_ERROR );
279                         }
280                         f->f_sub_initial = val;
281                         *fstr = ch_realloc( *fstr, strlen( *fstr ) +
282                             strlen( val ) + 1 );
283                         strcat( *fstr, val );
284                         break;
285
286 #ifdef COMPAT30
287                 case LDAP_SUBSTRING_ANY_30:
288 #endif
289                 case LDAP_SUBSTRING_ANY:
290                         Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
291                         charray_add( &f->f_sub_any, val );
292                         *fstr = ch_realloc( *fstr, strlen( *fstr ) +
293                             strlen( val ) + 2 );
294                         strcat( *fstr, "*" );
295                         strcat( *fstr, val );
296                         break;
297
298 #ifdef COMPAT30
299                 case LDAP_SUBSTRING_FINAL_30:
300 #endif
301                 case LDAP_SUBSTRING_FINAL:
302                         Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
303                         if ( f->f_sub_final != NULL ) {
304                                 return( LDAP_PROTOCOL_ERROR );
305                         }
306                         f->f_sub_final = val;
307                         *fstr = ch_realloc( *fstr, strlen( *fstr ) +
308                             strlen( val ) + 2 );
309                         strcat( *fstr, "*" );
310                         strcat( *fstr, val );
311                         break;
312
313                 default:
314                         Debug( LDAP_DEBUG_FILTER, "  unknown type\n", tag, 0,
315                             0 );
316                         return( LDAP_PROTOCOL_ERROR );
317                 }
318         }
319         *fstr = ch_realloc( *fstr, strlen( *fstr ) + 3 );
320         if ( f->f_sub_final == NULL ) {
321                 strcat( *fstr, "*" );
322         }
323         strcat( *fstr, ")" );
324
325         Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
326         return( 0 );
327 }
328
329 void
330 filter_free( Filter *f )
331 {
332         Filter  *p, *next;
333
334         if ( f == NULL ) {
335                 return;
336         }
337
338         switch ( f->f_choice ) {
339         case LDAP_FILTER_EQUALITY:
340         case LDAP_FILTER_GE:
341         case LDAP_FILTER_LE:
342         case LDAP_FILTER_APPROX:
343                 ava_free( &f->f_ava, 0 );
344                 break;
345
346         case LDAP_FILTER_SUBSTRINGS:
347                 if ( f->f_sub_type != NULL ) {
348                         free( f->f_sub_type );
349                 }
350                 if ( f->f_sub_initial != NULL ) {
351                         free( f->f_sub_initial );
352                 }
353                 charray_free( f->f_sub_any );
354                 if ( f->f_sub_final != NULL ) {
355                         free( f->f_sub_final );
356                 }
357                 break;
358
359         case LDAP_FILTER_PRESENT:
360                 if ( f->f_type != NULL ) {
361                         free( f->f_type );
362                 }
363                 break;
364
365         case LDAP_FILTER_AND:
366         case LDAP_FILTER_OR:
367         case LDAP_FILTER_NOT:
368                 for ( p = f->f_list; p != NULL; p = next ) {
369                         next = p->f_next;
370                         filter_free( p );
371                 }
372                 break;
373
374         default:
375                 Debug( LDAP_DEBUG_ANY, "unknown filter type %d\n", f->f_choice,
376                     0, 0 );
377                 break;
378         }
379         free( f );
380 }
381
382 #ifdef LDAP_DEBUG
383
384 void
385 filter_print( Filter *f )
386 {
387         int     i;
388         Filter  *p;
389
390         if ( f == NULL ) {
391                 printf( "NULL" );
392         }
393
394         switch ( f->f_choice ) {
395         case LDAP_FILTER_EQUALITY:
396                 printf( "(%s=%s)", f->f_ava.ava_type,
397                     f->f_ava.ava_value.bv_val );
398                 break;
399
400         case LDAP_FILTER_GE:
401                 printf( "(%s>=%s)", f->f_ava.ava_type,
402                     f->f_ava.ava_value.bv_val );
403                 break;
404
405         case LDAP_FILTER_LE:
406                 printf( "(%s<=%s)", f->f_ava.ava_type,
407                     f->f_ava.ava_value.bv_val );
408                 break;
409
410         case LDAP_FILTER_APPROX:
411                 printf( "(%s~=%s)", f->f_ava.ava_type,
412                     f->f_ava.ava_value.bv_val );
413                 break;
414
415         case LDAP_FILTER_SUBSTRINGS:
416                 printf( "(%s=", f->f_sub_type );
417                 if ( f->f_sub_initial != NULL ) {
418                         printf( "%s", f->f_sub_initial );
419                 }
420                 if ( f->f_sub_any != NULL ) {
421                         for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
422                                 printf( "*%s", f->f_sub_any[i] );
423                         }
424                 }
425                 charray_free( f->f_sub_any );
426                 if ( f->f_sub_final != NULL ) {
427                         printf( "*%s", f->f_sub_final );
428                 }
429                 break;
430
431         case LDAP_FILTER_PRESENT:
432                 printf( "%s=*", f->f_type );
433                 break;
434
435         case LDAP_FILTER_AND:
436         case LDAP_FILTER_OR:
437         case LDAP_FILTER_NOT:
438                 printf( "(%c", f->f_choice == LDAP_FILTER_AND ? '&' :
439                     f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
440                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
441                         filter_print( p );
442                 }
443                 printf( ")" );
444                 break;
445
446         default:
447                 printf( "unknown type %d", f->f_choice );
448                 break;
449         }
450 }
451
452 #endif /* ldap_debug */