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