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