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