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