]> git.sur5r.net Git - openldap/blob - servers/slapd/filter.c
8d225049f0d603587a563919432d2da33f71eddf
[openldap] / servers / slapd / filter.c
1 /* filter.c - routines for parsing and dealing with filters */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-1999 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11
12 #include <ac/socket.h>
13 #include <ac/string.h>
14
15 #include "slap.h"
16
17 static int      get_filter_list(Connection *conn, BerElement *ber, Filter **f, char **fstr);
18 static int      get_substring_filter(Connection *conn, BerElement *ber, Filter *f, char **fstr);
19
20 int
21 get_filter( Connection *conn, BerElement *ber, Filter **filt, char **fstr )
22 {
23         ber_len_t       len;
24         int             err;
25         Filter          *f;
26         char            *ftmp;
27
28         Debug( LDAP_DEBUG_FILTER, "begin get_filter\n", 0, 0, 0 );
29
30         /*
31          * A filter looks like this coming in:
32          *      Filter ::= CHOICE {
33          *              and             [0]     SET OF Filter,
34          *              or              [1]     SET OF Filter,
35          *              not             [2]     Filter,
36          *              equalityMatch   [3]     AttributeValueAssertion,
37          *              substrings      [4]     SubstringFilter,
38          *              greaterOrEqual  [5]     AttributeValueAssertion,
39          *              lessOrEqual     [6]     AttributeValueAssertion,
40          *              present         [7]     AttributeType,,
41          *              approxMatch     [8]     AttributeValueAssertion
42          *              extensibleMatch [9] MatchingRuleAssertion
43          *      }
44          *
45          *      SubstringFilter ::= SEQUENCE {
46          *              type               AttributeType,
47          *              SEQUENCE OF CHOICE {
48          *                      initial          [0] IA5String,
49          *                      any              [1] IA5String,
50          *                      final            [2] IA5String
51          *              }
52          *      }
53          *
54      *  MatchingRuleAssertion ::= SEQUENCE {
55      *          matchingRule    [1] MatchingRuleId OPTIONAL,
56      *          type            [2] AttributeDescription OPTIONAL,
57      *          matchValue      [3] AssertionValue,
58      *          dnAttributes    [4] BOOLEAN DEFAULT FALSE
59          *      }
60          *
61          */
62
63         f = (Filter *) ch_malloc( sizeof(Filter) );
64         f->f_next = NULL;
65
66         err = LDAP_SUCCESS;
67         *fstr = NULL;
68         f->f_choice = ber_peek_tag( ber, &len );
69
70         switch ( f->f_choice ) {
71 #ifndef SLAPD_SCHEMA_NOT_COMPAT
72         case LDAP_FILTER_EQUALITY:
73                 Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
74                 if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) {
75                         *fstr = ch_malloc(4 + strlen( f->f_avtype ) +
76                             f->f_avvalue.bv_len);
77                         sprintf( *fstr, "(%s=%s)", f->f_avtype,
78                             f->f_avvalue.bv_val );
79                 }
80                 break;
81
82         case LDAP_FILTER_SUBSTRINGS:
83                 Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
84                 err = get_substring_filter( conn, ber, f, fstr );
85                 break;
86
87         case LDAP_FILTER_GE:
88                 Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
89                 if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) {
90                         *fstr = ch_malloc(5 + strlen( f->f_avtype ) +
91                             f->f_avvalue.bv_len);
92                         sprintf( *fstr, "(%s>=%s)", f->f_avtype,
93                             f->f_avvalue.bv_val );
94                 }
95                 break;
96
97         case LDAP_FILTER_LE:
98                 Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
99                 if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) {
100                         *fstr = ch_malloc(5 + strlen( f->f_avtype ) +
101                             f->f_avvalue.bv_len);
102                         sprintf( *fstr, "(%s<=%s)", f->f_avtype,
103                             f->f_avvalue.bv_val );
104                 }
105                 break;
106
107         case LDAP_FILTER_PRESENT:
108                 Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
109                 if ( ber_scanf( ber, "a", &f->f_type ) == LBER_ERROR ) {
110                         err = -1;
111                 } else {
112                         err = LDAP_SUCCESS;
113                         attr_normalize( f->f_type );
114                         *fstr = ch_malloc( 5 + strlen( f->f_type ) );
115                         sprintf( *fstr, "(%s=*)", f->f_type );
116                 }
117                 break;
118
119         case LDAP_FILTER_APPROX:
120                 Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
121                 if ( (err = get_ava( ber, &f->f_ava )) == LDAP_SUCCESS ) {
122                         *fstr = ch_malloc(5 + strlen( f->f_avtype ) +
123                             f->f_avvalue.bv_len);
124                         sprintf( *fstr, "(%s~=%s)", f->f_avtype,
125                             f->f_avvalue.bv_val );
126                 }
127                 break;
128 #endif
129
130         case LDAP_FILTER_AND:
131                 Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
132                 if ( (err = get_filter_list( conn, ber, &f->f_and, &ftmp ))
133                     == LDAP_SUCCESS ) {
134                         if (ftmp == NULL) ftmp = ch_strdup("");
135                         *fstr = ch_malloc( 4 + strlen( ftmp ) );
136                         sprintf( *fstr, "(&%s)", ftmp );
137                         free( ftmp );
138                 }
139                 break;
140
141         case LDAP_FILTER_OR:
142                 Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
143                 if ( (err = get_filter_list( conn, ber, &f->f_or, &ftmp ))
144                     == LDAP_SUCCESS ) {
145                         if (ftmp == NULL) ftmp = ch_strdup("");
146                         *fstr = ch_malloc( 4 + strlen( ftmp ) );
147                         sprintf( *fstr, "(|%s)", ftmp );
148                         free( ftmp );
149                 }
150                 break;
151
152         case LDAP_FILTER_NOT:
153                 Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
154                 (void) ber_skip_tag( ber, &len );
155                 if ( (err = get_filter( conn, ber, &f->f_not, &ftmp )) == LDAP_SUCCESS ) {
156                         if (ftmp == NULL) ftmp = ch_strdup("");
157                         *fstr = ch_malloc( 4 + strlen( ftmp ) );
158                         sprintf( *fstr, "(!%s)", ftmp );
159                         free( ftmp );
160                 }
161                 break;
162
163         case LDAP_FILTER_EXT:
164                 /* not yet implemented */
165                 Debug( LDAP_DEBUG_ANY, "extensible match not yet implemented.\n",
166                        f->f_choice, 0, 0 );
167                 err = -1;
168                 break;
169
170         case LBER_DEFAULT:
171                 Debug( LDAP_DEBUG_ANY, "decoding filter error\n",
172                        0, 0, 0 );
173                 err = -1;
174                 break;
175
176         default:
177                 Debug( LDAP_DEBUG_ANY, "unknown filter type %lu\n",
178                        f->f_choice, 0, 0 );
179                 err = LDAP_PROTOCOL_ERROR;
180                 break;
181         }
182
183         if ( err != LDAP_SUCCESS ) {
184                 free( (char *) f );
185                 if ( *fstr != NULL ) {
186                         free( *fstr );
187                 }
188         } else {
189                 *filt = f;
190         }
191
192         Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
193         return( err );
194 }
195
196 static int
197 get_filter_list( Connection *conn, BerElement *ber, Filter **f, char **fstr )
198 {
199         Filter          **new;
200         int             err;
201         ber_tag_t       tag;
202         ber_len_t       len;
203         char            *last, *ftmp;
204
205         Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
206
207         *fstr = NULL;
208         new = f;
209         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
210             tag = ber_next_element( ber, &len, last ) )
211         {
212                 if ( (err = get_filter( conn, ber, new, &ftmp )) != LDAP_SUCCESS )
213                         return( err );
214                 if ( *fstr == NULL ) {
215                         *fstr = ftmp;
216                 } else {
217                         *fstr = ch_realloc( *fstr, strlen( *fstr ) +
218                             strlen( ftmp ) + 1 );
219                         strcat( *fstr, ftmp );
220                         free( ftmp );
221                 }
222                 new = &(*new)->f_next;
223         }
224         *new = NULL;
225
226         Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
227         return( LDAP_SUCCESS );
228 }
229
230 #ifndef SLAPD_SCHEMA_NOT_COMPAT
231
232 static int
233 get_substring_filter(
234     Connection  *conn,
235     BerElement  *ber,
236     Filter      *f,
237     char        **fstr
238 )
239 {
240         ber_tag_t       tag;
241         ber_len_t       len;
242         ber_tag_t       rc;
243         struct berval *val;
244         char            *last;
245         int             syntax;
246
247         Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
248
249         if ( ber_scanf( ber, "{a" /*}*/, &f->f_sub_type ) == LBER_ERROR ) {
250                 return( -1 );
251         }
252
253         attr_normalize( f->f_sub_type );
254
255 #ifdef SLAPD_SCHEMA_NOT_COMPAT
256         /* not yet implemented */
257 #else
258         /* should get real syntax and see if we have a substring matching rule */
259         syntax = attr_syntax( f->f_sub_type );
260 #endif
261
262         f->f_sub_initial = NULL;
263         f->f_sub_any = NULL;
264         f->f_sub_final = NULL;
265
266         if( fstr ) {
267                 *fstr = ch_malloc( strlen( f->f_sub_type ) + 3 );
268                 sprintf( *fstr, "(%s=", f->f_sub_type );
269         }
270
271         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
272             tag = ber_next_element( ber, &len, last ) )
273         {
274                 rc = ber_scanf( ber, "O", &val );
275                 if ( rc == LBER_ERROR ) {
276                         rc = -1;
277                         goto return_error;
278                 }
279
280                 if ( val == NULL || val->bv_len == 0 ) {
281                         ber_bvfree( val );
282                         rc = LDAP_INVALID_SYNTAX;
283                         goto return_error;
284                 } 
285
286                 rc = LDAP_PROTOCOL_ERROR;
287
288 #ifdef SLAPD_SCHEMA_NOT_COMPAT
289                 /* not yet implemented */
290 #else
291                 /* we should call a substring syntax normalization routine */
292                 value_normalize( val->bv_val, syntax );
293                 /* this is bogus, value_normalize should take a berval */
294                 val->bv_len = strlen( val->bv_val );
295 #endif
296
297                 switch ( tag ) {
298                 case LDAP_SUBSTRING_INITIAL:
299                         Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
300                         if ( f->f_sub_initial != NULL ) {
301                                 ber_bvfree( val );
302                                 goto return_error;
303                         }
304                         f->f_sub_initial = val;
305
306                         if( fstr ) {
307                                 *fstr = ch_realloc( *fstr,
308                                         strlen( *fstr ) + val->bv_len + 1 );
309                                 strcat( *fstr, val->bv_val );
310                         }
311                         break;
312
313                 case LDAP_SUBSTRING_ANY:
314                         Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
315                         if( ber_bvecadd( &f->f_sub_any, val ) < 0 ) {
316                                 ber_bvfree( val );
317                                 goto return_error;
318                         }
319
320                         if( fstr ) {
321                                 *fstr = ch_realloc( *fstr,
322                                         strlen( *fstr ) + val->bv_len + 2 );
323                                 strcat( *fstr, "*" );
324                                 strcat( *fstr, val->bv_val );
325                         }
326                         break;
327
328                 case LDAP_SUBSTRING_FINAL:
329                         Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
330                         if ( f->f_sub_final != NULL ) {
331                                 ber_bvfree( val );
332                                 goto return_error;
333                         }
334                         f->f_sub_final = val;
335
336                         if( fstr ) {
337                                 *fstr = ch_realloc( *fstr,
338                                         strlen( *fstr ) + val->bv_len + 2 );
339                                 strcat( *fstr, "*" );
340                                 strcat( *fstr, val->bv_val );
341                         }
342                         break;
343
344                 default:
345                         Debug( LDAP_DEBUG_FILTER, "  unknown type\n", tag, 0,
346                             0 );
347
348                         ber_bvfree( val );
349
350 return_error:
351                         Debug( LDAP_DEBUG_FILTER, "  error=%d\n", rc, 0, 0 );
352
353                         if( fstr ) {
354                                 free( *fstr );
355                                 *fstr = NULL;
356                         }
357
358                         ch_free( f->f_sub_type );
359                         ber_bvfree( f->f_sub_initial );
360                         ber_bvecfree( f->f_sub_any );
361                         ber_bvfree( f->f_sub_final );
362                         return rc;
363                 }
364         }
365
366         if( fstr ) {
367                 *fstr = ch_realloc( *fstr, strlen( *fstr ) + 3 );
368                 if ( f->f_sub_final == NULL ) {
369                         strcat( *fstr, "*" );
370                 }
371                 strcat( *fstr, ")" );
372         }
373
374         Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
375         return( LDAP_SUCCESS );
376 }
377
378 #endif /* not compat */
379
380 void
381 filter_free( Filter *f )
382 {
383         Filter  *p, *next;
384
385         if ( f == NULL ) {
386                 return;
387         }
388
389         switch ( f->f_choice ) {
390         case LDAP_FILTER_PRESENT:
391 #ifdef SLAPD_SCHEMA_NOT_COMPAT
392                 ad_free( f->f_desc, 1 );
393 #else
394                 if ( f->f_type != NULL ) {
395                         free( f->f_type );
396                 }
397 #endif
398                 break;
399
400         case LDAP_FILTER_EQUALITY:
401         case LDAP_FILTER_GE:
402         case LDAP_FILTER_LE:
403         case LDAP_FILTER_APPROX:
404 #ifdef SLAPD_SCHEMA_NOT_COMPAT
405                 ava_free( f->f_ava, 1 );
406 #else
407                 ava_free( &f->f_ava, 0 );
408 #endif
409                 break;
410
411         case LDAP_FILTER_SUBSTRINGS:
412 #ifdef SLAPD_SCHEMA_NOT_COMPAT
413                 ad_free( f->f_sub_desc, 1 );
414                 if ( f->f_sub_initial != NULL ) {
415                         ber_bvfree( f->f_sub_initial );
416                 }
417                 ber_bvecfree( f->f_sub_any );
418                 if ( f->f_sub_final != NULL ) {
419                         ber_bvfree( f->f_sub_final );
420                 }
421 #else
422                 if ( f->f_sub_type != NULL ) {
423                         free( f->f_sub_type );
424                 }
425                 if ( f->f_sub_initial != NULL ) {
426                         ber_bvfree( f->f_sub_initial );
427                 }
428                 ber_bvecfree( f->f_sub_any );
429                 if ( f->f_sub_final != NULL ) {
430                         ber_bvfree( f->f_sub_final );
431                 }
432 #endif
433                 break;
434
435         case LDAP_FILTER_AND:
436         case LDAP_FILTER_OR:
437         case LDAP_FILTER_NOT:
438                 for ( p = f->f_list; p != NULL; p = next ) {
439                         next = p->f_next;
440                         filter_free( p );
441                 }
442                 break;
443
444         default:
445                 Debug( LDAP_DEBUG_ANY, "unknown filter type %lu\n",
446                        f->f_choice, 0, 0 );
447                 break;
448         }
449
450         free( f );
451 }
452
453 #ifdef LDAP_DEBUG
454
455 void
456 filter_print( Filter *f )
457 {
458         int     i;
459         Filter  *p;
460
461         if ( f == NULL ) {
462                 fprintf( stderr, "NULL" );
463         }
464
465         switch ( f->f_choice ) {
466         case LDAP_FILTER_EQUALITY:
467 #ifdef SLAPD_SCHEMA_NOT_COMPAT
468                 fprintf( stderr, "(%s=%s)",
469                         f->f_ava->aa_desc->ad_cname,
470                     f->f_ava->aa_value->bv_val );
471 #else
472                 fprintf( stderr, "(%s=%s)", f->f_ava.ava_type,
473                     f->f_ava.ava_value.bv_val );
474 #endif
475                 break;
476
477         case LDAP_FILTER_GE:
478 #ifdef SLAPD_SCHEMA_NOT_COMPAT
479                 fprintf( stderr, "(%s>=%s)",
480                         f->f_ava->aa_desc->ad_cname,
481                     f->f_ava->aa_value->bv_val );
482 #else
483                 fprintf( stderr, "(%s>=%s)", f->f_ava.ava_type,
484                     f->f_ava.ava_value.bv_val );
485 #endif
486                 break;
487
488         case LDAP_FILTER_LE:
489 #ifdef SLAPD_SCHEMA_NOT_COMPAT
490                 fprintf( stderr, "(%s<=%s)",
491                         f->f_ava->aa_desc->ad_cname,
492                     f->f_ava->aa_value->bv_val );
493 #else
494                 fprintf( stderr, "(%s<=%s)", f->f_ava.ava_type,
495                     f->f_ava.ava_value.bv_val );
496 #endif
497                 break;
498
499         case LDAP_FILTER_APPROX:
500 #ifdef SLAPD_SCHEMA_NOT_COMPAT
501                 fprintf( stderr, "(%s~=%s)",
502                         f->f_ava->aa_desc->ad_cname,
503                     f->f_ava->aa_value->bv_val );
504 #else
505                 fprintf( stderr, "(%s~=%s)", f->f_ava.ava_type,
506                     f->f_ava.ava_value.bv_val );
507 #endif
508                 break;
509
510         case LDAP_FILTER_SUBSTRINGS:
511 #ifdef SLAPD_SCHEMA_NOT_COMPAT
512                 fprintf( stderr, "(%s=" /*)*/, f->f_sub_desc->ad_cname );
513 #else
514                 fprintf( stderr, "(%s=" /*)*/, f->f_sub_type );
515 #endif
516                 if ( f->f_sub_initial != NULL ) {
517                         fprintf( stderr, "%s", f->f_sub_initial->bv_val );
518                 }
519                 if ( f->f_sub_any != NULL ) {
520                         for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
521                                 fprintf( stderr, "*%s", f->f_sub_any[i]->bv_val );
522                         }
523                 }
524                 if ( f->f_sub_final != NULL ) {
525                         fprintf( stderr, "*%s", f->f_sub_final->bv_val );
526                 }
527                 fprintf( stderr, /*(*/ ")" );
528                 break;
529
530         case LDAP_FILTER_PRESENT:
531 #ifdef SLAPD_SCHEMA_NOT_COMPAT
532                 fprintf( stderr, "(%s=*)",
533                         f->f_desc->ad_cname );
534 #else
535                 fprintf( stderr, "%s=*", f->f_type );
536 #endif
537                 break;
538
539         case LDAP_FILTER_AND:
540         case LDAP_FILTER_OR:
541         case LDAP_FILTER_NOT:
542                 fprintf( stderr, "(%c" /*)*/,
543                         f->f_choice == LDAP_FILTER_AND ? '&' :
544                     f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
545                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
546                         filter_print( p );
547                 }
548                 fprintf( stderr, /*(*/ ")" );
549                 break;
550
551         default:
552                 fprintf( stderr, "(unknown filter %lu)", f->f_choice );
553                 break;
554         }
555 }
556
557 #endif /* ldap_debug */