]> git.sur5r.net Git - openldap/blob - servers/slapd/filter.c
Skip over unsupported tags
[openldap] / servers / slapd / filter.c
1 /* filter.c - routines for parsing and dealing with filters */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 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(
18         Connection *conn,
19         BerElement *ber,
20         Filter **f,
21         char **fstr,
22         const char **text );
23
24 static int      get_substring_filter(
25         Connection *conn,
26         BerElement *ber,
27         Filter *f,
28         char **fstr,
29         const char **text );
30
31 int
32 get_filter(
33         Connection *conn,
34         BerElement *ber,
35         Filter **filt,
36         char **fstr,
37         const char **text )
38 {
39         ber_tag_t       tag;
40         ber_len_t       len;
41         int             err;
42         Filter          *f;
43         char            *ftmp = NULL;
44
45         Debug( LDAP_DEBUG_FILTER, "begin get_filter\n", 0, 0, 0 );
46
47         /*
48          * A filter looks like this coming in:
49          *      Filter ::= CHOICE {
50          *              and             [0]     SET OF Filter,
51          *              or              [1]     SET OF Filter,
52          *              not             [2]     Filter,
53          *              equalityMatch   [3]     AttributeValueAssertion,
54          *              substrings      [4]     SubstringFilter,
55          *              greaterOrEqual  [5]     AttributeValueAssertion,
56          *              lessOrEqual     [6]     AttributeValueAssertion,
57          *              present         [7]     AttributeType,,
58          *              approxMatch     [8]     AttributeValueAssertion
59          *              extensibleMatch [9] MatchingRuleAssertion
60          *      }
61          *
62          *      SubstringFilter ::= SEQUENCE {
63          *              type               AttributeType,
64          *              SEQUENCE OF CHOICE {
65          *                      initial          [0] IA5String,
66          *                      any              [1] IA5String,
67          *                      final            [2] IA5String
68          *              }
69          *      }
70          *
71      *  MatchingRuleAssertion ::= SEQUENCE {
72      *          matchingRule    [1] MatchingRuleId OPTIONAL,
73      *          type            [2] AttributeDescription OPTIONAL,
74      *          matchValue      [3] AssertionValue,
75      *          dnAttributes    [4] BOOLEAN DEFAULT FALSE
76          *      }
77          *
78          */
79
80         tag = ber_peek_tag( ber, &len );
81
82         if( tag == LBER_ERROR ) {
83                 *text = "error decoding filter";
84                 return SLAPD_DISCONNECT;
85         }
86
87         f = (Filter *) ch_malloc( sizeof(Filter) );
88         f->f_next = NULL;
89
90         err = LDAP_SUCCESS;
91         *fstr = NULL;
92         f->f_choice = tag; 
93
94         switch ( f->f_choice ) {
95         case LDAP_FILTER_EQUALITY:
96                 Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
97
98                 err = get_ava( ber, &f->f_ava, SLAP_MR_EQUALITY, text );
99                 if ( err != LDAP_SUCCESS ) {
100                         break;
101                 }
102
103                 assert( f->f_ava != NULL );
104
105                 *fstr = ch_malloc( sizeof("(=)")
106                         + f->f_av_desc->ad_cname->bv_len
107                         + f->f_av_value->bv_len );
108
109                 sprintf( *fstr, "(%s=%s)",
110                         f->f_av_desc->ad_cname->bv_val,
111                     f->f_av_value->bv_val );
112
113                 break;
114
115         case LDAP_FILTER_SUBSTRINGS:
116                 Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
117                 err = get_substring_filter( conn, ber, f, fstr, text );
118                 break;
119
120         case LDAP_FILTER_GE:
121                 Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
122
123                 err = get_ava( ber, &f->f_ava, SLAP_MR_ORDERING, text );
124                 if ( err != LDAP_SUCCESS ) {
125                         break;
126                 }
127
128                 *fstr = ch_malloc( sizeof("(>=)")
129                         + f->f_av_desc->ad_cname->bv_len
130                         + f->f_av_value->bv_len );
131
132                 sprintf( *fstr, "(%s>=%s)",
133                         f->f_av_desc->ad_cname->bv_val,
134                     f->f_av_value->bv_val );
135
136                 break;
137
138         case LDAP_FILTER_LE:
139                 Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
140
141                 err = get_ava( ber, &f->f_ava, SLAP_MR_ORDERING, text );
142                 if ( err != LDAP_SUCCESS ) {
143                         break;
144                 }
145
146
147                 *fstr = ch_malloc( sizeof("(<=)")
148                         + f->f_av_desc->ad_cname->bv_len
149                         + f->f_av_value->bv_len );
150
151                 sprintf( *fstr, "(%s<=%s)",
152                         f->f_av_desc->ad_cname->bv_val,
153                     f->f_av_value->bv_val );
154
155                 break;
156
157         case LDAP_FILTER_PRESENT: {
158                 struct berval type;
159
160                 Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
161
162                 if ( ber_scanf( ber, "o", &type ) == LBER_ERROR ) {
163                         err = SLAPD_DISCONNECT;
164                         *text = "error decoding filter";
165                         break;
166                 }
167
168                 f->f_desc = NULL;
169                 err = slap_bv2ad( &type, &f->f_desc, text );
170
171                 if( err != LDAP_SUCCESS ) {
172                         ch_free( type.bv_val );
173                         break;
174                 }
175
176                 ch_free( type.bv_val );
177
178                 *fstr = ch_malloc( sizeof("(=*)")
179                         + f->f_desc->ad_cname->bv_len );
180                 sprintf( *fstr, "(%s=*)",
181                         f->f_desc->ad_cname->bv_val );
182
183                 } break;
184
185         case LDAP_FILTER_APPROX:
186                 Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
187
188                 err = get_ava( ber, &f->f_ava, SLAP_MR_EQUALITY_APPROX, text );
189                 if ( err != LDAP_SUCCESS ) {
190                         break;
191                 }
192
193                 *fstr = ch_malloc( sizeof("(~=)")
194                         + f->f_av_desc->ad_cname->bv_len
195                         + f->f_av_value->bv_len );
196
197                 sprintf( *fstr, "(%s~=%s)",
198                         f->f_av_desc->ad_cname->bv_val,
199                     f->f_av_value->bv_val );
200
201                 break;
202
203         case LDAP_FILTER_AND:
204                 Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
205                 err = get_filter_list( conn, ber, &f->f_and, &ftmp, text );
206                 if ( err != LDAP_SUCCESS ) {
207                         break;
208                 }
209                 *fstr = ch_malloc( sizeof("(&)")
210                         + ( ftmp == NULL ? 0 : strlen( ftmp ) ) );
211                 sprintf( *fstr, "(&%s)",
212                         ftmp == NULL ? "" : ftmp );
213                 break;
214
215         case LDAP_FILTER_OR:
216                 Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
217                 err = get_filter_list( conn, ber, &f->f_and, &ftmp, text );
218                 if ( err != LDAP_SUCCESS ) {
219                         break;
220                 }
221                 *fstr = ch_malloc( sizeof("(!)")
222                         + ( ftmp == NULL ? 0 : strlen( ftmp ) ) );
223                 sprintf( *fstr, "(|%s)",
224                         ftmp == NULL ? "" : ftmp );
225                 break;
226
227         case LDAP_FILTER_NOT:
228                 Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
229                 (void) ber_skip_tag( ber, &len );
230                 err = get_filter( conn, ber, &f->f_not, &ftmp, text );
231                 if ( err != LDAP_SUCCESS ) {
232                         break;
233                 }
234                 *fstr = ch_malloc( sizeof("(!)")
235                         + ( ftmp == NULL ? 0 : strlen( ftmp ) ) );
236                 sprintf( *fstr, "(!%s)",
237                         ftmp == NULL ? "" : ftmp );
238                 break;
239
240         case LDAP_FILTER_EXT:
241                 /* not yet implemented */
242                 Debug( LDAP_DEBUG_ANY, "extensible match not yet implemented.\n",
243                        f->f_choice, 0, 0 );
244                 (void) ber_skip_tag( ber, &len );
245                 f->f_choice = SLAPD_FILTER_COMPUTED;
246                 f->f_result = SLAPD_COMPARE_UNDEFINED;
247                 *fstr = ch_strdup( "(extended)" );
248                 break;
249
250         default:
251                 (void) ber_skip_tag( ber, &len );
252                 Debug( LDAP_DEBUG_ANY, "get_filter: unknown filter type=%lu\n",
253                        f->f_choice, 0, 0 );
254                 f->f_choice = SLAPD_FILTER_COMPUTED;
255                 f->f_result = SLAPD_COMPARE_UNDEFINED;
256                 *fstr = ch_strdup( "(undefined)" );
257                 break;
258         }
259
260         free( ftmp );
261
262         if ( err != LDAP_SUCCESS ) {
263                 if ( *fstr != NULL ) {
264                         free( *fstr );
265                 }
266
267                 if( err != SLAPD_DISCONNECT ) {
268                         /* ignore error */
269                         f->f_choice = SLAPD_FILTER_COMPUTED;
270                         f->f_result = SLAPD_COMPARE_UNDEFINED;
271                         *fstr = ch_strdup( "(badfilter)" );
272                         err = LDAP_SUCCESS;
273                         *filt = f;
274
275                 } else {
276                         free(f);
277                 }
278         } else {
279                 *filt = f;
280         }
281
282         Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
283         return( err );
284 }
285
286 static int
287 get_filter_list( Connection *conn, BerElement *ber,
288         Filter **f, char **fstr,
289         const char **text )
290 {
291         Filter          **new;
292         int             err;
293         ber_tag_t       tag;
294         ber_len_t       len;
295         char            *last, *ftmp;
296
297         Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
298
299         *fstr = NULL;
300         new = f;
301         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
302             tag = ber_next_element( ber, &len, last ) )
303         {
304                 err = get_filter( conn, ber, new, &ftmp, text );
305                 if ( err != LDAP_SUCCESS )
306                         return( err );
307
308                 if ( *fstr == NULL ) {
309                         *fstr = ftmp;
310                 } else {
311                         *fstr = ch_realloc( *fstr, strlen( *fstr ) +
312                             strlen( ftmp ) + 1 );
313                         strcat( *fstr, ftmp );
314                         free( ftmp );
315                 }
316                 new = &(*new)->f_next;
317         }
318         *new = NULL;
319
320         Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
321         return( LDAP_SUCCESS );
322 }
323
324 static int
325 get_substring_filter(
326     Connection  *conn,
327     BerElement  *ber,
328     Filter      *f,
329     char        **fstr,
330         const char      **text
331 )
332 {
333         ber_tag_t       tag;
334         ber_len_t       len;
335         ber_tag_t       rc;
336         struct berval *value;
337         char            *last;
338         struct berval type;
339         struct berval *nvalue;
340         *text = "error decoding filter";
341
342         Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
343
344         if ( ber_scanf( ber, "{o" /*}*/, &type ) == LBER_ERROR ) {
345                 return SLAPD_DISCONNECT;
346         }
347
348         f->f_sub = ch_calloc( 1, sizeof(SubstringsAssertion) );
349         f->f_sub_desc = NULL;
350         rc = slap_bv2ad( &type, &f->f_sub_desc, text );
351
352         ch_free( type.bv_val );
353
354         if( rc != LDAP_SUCCESS ) {
355                 text = NULL;
356                 ch_free( f->f_sub );
357                 f->f_choice = SLAPD_FILTER_COMPUTED;
358                 f->f_result = SLAPD_COMPARE_UNDEFINED;
359                 *fstr = ch_strdup( "(undefined)" );
360                 return LDAP_SUCCESS;
361         }
362
363         f->f_sub_initial = NULL;
364         f->f_sub_any = NULL;
365         f->f_sub_final = NULL;
366
367         if( fstr ) {
368                 *fstr = ch_malloc( sizeof("(=" /*)*/) +
369                         f->f_sub_desc->ad_cname->bv_len );
370                 sprintf( *fstr, "(%s=" /*)*/, f->f_sub_desc->ad_cname->bv_val );
371         }
372
373         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
374             tag = ber_next_element( ber, &len, last ) )
375         {
376                 unsigned usage;
377
378                 rc = ber_scanf( ber, "O", &value );
379                 if ( rc == LBER_ERROR ) {
380                         rc = SLAPD_DISCONNECT;
381                         goto return_error;
382                 }
383
384                 if ( value == NULL || value->bv_len == 0 ) {
385                         ber_bvfree( value );
386                         rc = LDAP_INVALID_SYNTAX;
387                         goto return_error;
388                 } 
389
390                 switch ( tag ) {
391                 case LDAP_SUBSTRING_INITIAL:
392                         usage = SLAP_MR_SUBSTR_INITIAL;
393                         break;
394
395                 case LDAP_SUBSTRING_ANY:
396                         usage = SLAP_MR_SUBSTR_ANY;
397                         break;
398
399                 case LDAP_SUBSTRING_FINAL:
400                         usage = SLAP_MR_SUBSTR_FINAL;
401                         break;
402
403                 default:
404                         rc = LDAP_PROTOCOL_ERROR;
405
406                         Debug( LDAP_DEBUG_FILTER,
407                                 "  unknown substring choice=%ld\n",
408                                 (long) tag, 0, 0 );
409
410                         ber_bvfree( value );
411                         goto return_error;
412                 }
413
414                 rc = value_normalize( f->f_sub_desc, usage, value, &nvalue, text );
415                 ber_bvfree( value );
416
417                 if( rc != LDAP_SUCCESS ) {
418                         goto return_error;
419                 }
420
421                 value = nvalue;
422
423                 rc = LDAP_PROTOCOL_ERROR;
424
425                 switch ( tag ) {
426                 case LDAP_SUBSTRING_INITIAL:
427                         Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
428                         if ( f->f_sub_initial != NULL ) {
429                                 ber_bvfree( value );
430                                 goto return_error;
431                         }
432
433                         f->f_sub_initial = value;
434
435                         if( fstr ) {
436                                 *fstr = ch_realloc( *fstr,
437                                         strlen( *fstr ) + value->bv_len + 1 );
438                                 strcat( *fstr, value->bv_val );
439                         }
440                         break;
441
442                 case LDAP_SUBSTRING_ANY:
443                         Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
444                         if( ber_bvecadd( &f->f_sub_any, value ) < 0 ) {
445                                 ber_bvfree( value );
446                                 goto return_error;
447                         }
448
449                         if( fstr ) {
450                                 *fstr = ch_realloc( *fstr,
451                                         strlen( *fstr ) + value->bv_len + 2 );
452                                 strcat( *fstr, "*" );
453                                 strcat( *fstr, value->bv_val );
454                         }
455                         break;
456
457                 case LDAP_SUBSTRING_FINAL:
458                         Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
459                         if ( f->f_sub_final != NULL ) {
460                                 ber_bvfree( value );
461                                 goto return_error;
462                         }
463                         f->f_sub_final = value;
464
465                         if( fstr ) {
466                                 *fstr = ch_realloc( *fstr,
467                                         strlen( *fstr ) + value->bv_len + 2 );
468                                 strcat( *fstr, "*" );
469                                 strcat( *fstr, value->bv_val );
470                         }
471                         break;
472
473                 default:
474                         Debug( LDAP_DEBUG_FILTER,
475                                 "  unknown substring type=%ld\n",
476                                 (long) tag, 0, 0 );
477
478                         ber_bvfree( value );
479
480 return_error:
481                         Debug( LDAP_DEBUG_FILTER, "  error=%ld\n",
482                                 (long) rc, 0, 0 );
483
484                         if( fstr ) {
485                                 free( *fstr );
486                                 *fstr = NULL;
487                         }
488
489                         ad_free( f->f_sub_desc, 1 );
490                         ber_bvfree( f->f_sub_initial );
491                         ber_bvecfree( f->f_sub_any );
492                         ber_bvfree( f->f_sub_final );
493                         ch_free( f->f_sub );
494                         return rc;
495                 }
496         }
497
498         if( fstr ) {
499                 *fstr = ch_realloc( *fstr, strlen( *fstr ) + 3 );
500                 if ( f->f_sub_final == NULL ) {
501                         strcat( *fstr, "*" );
502                 }
503                 strcat( *fstr, /*(*/ ")" );
504         }
505
506         Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
507         return( LDAP_SUCCESS );
508 }
509
510 void
511 filter_free( Filter *f )
512 {
513         Filter  *p, *next;
514
515         if ( f == NULL ) {
516                 return;
517         }
518
519         switch ( f->f_choice ) {
520         case LDAP_FILTER_PRESENT:
521                 ad_free( f->f_desc, 1 );
522                 break;
523
524         case LDAP_FILTER_EQUALITY:
525         case LDAP_FILTER_GE:
526         case LDAP_FILTER_LE:
527         case LDAP_FILTER_APPROX:
528                 ava_free( f->f_ava, 1 );
529                 break;
530
531         case LDAP_FILTER_SUBSTRINGS:
532                 ad_free( f->f_sub_desc, 1 );
533                 if ( f->f_sub_initial != NULL ) {
534                         ber_bvfree( f->f_sub_initial );
535                 }
536                 ber_bvecfree( f->f_sub_any );
537                 if ( f->f_sub_final != NULL ) {
538                         ber_bvfree( f->f_sub_final );
539                 }
540                 break;
541
542         case LDAP_FILTER_AND:
543         case LDAP_FILTER_OR:
544         case LDAP_FILTER_NOT:
545                 for ( p = f->f_list; p != NULL; p = next ) {
546                         next = p->f_next;
547                         filter_free( p );
548                 }
549                 break;
550
551         case SLAPD_FILTER_COMPUTED:
552                 break;
553
554         default:
555                 Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
556                        f->f_choice, 0, 0 );
557                 break;
558         }
559
560         free( f );
561 }
562
563 #ifdef LDAP_DEBUG
564
565 void
566 filter_print( Filter *f )
567 {
568         int     i;
569         Filter  *p;
570
571         if ( f == NULL ) {
572                 fprintf( stderr, "No filter!" );
573         }
574
575         switch ( f->f_choice ) {
576         case LDAP_FILTER_EQUALITY:
577                 fprintf( stderr, "(%s=%s)",
578                         f->f_av_desc->ad_cname->bv_val,
579                     f->f_av_value->bv_val );
580                 break;
581
582         case LDAP_FILTER_GE:
583                 fprintf( stderr, "(%s>=%s)",
584                         f->f_av_desc->ad_cname->bv_val,
585                     f->f_av_value->bv_val );
586                 break;
587
588         case LDAP_FILTER_LE:
589                 fprintf( stderr, "(%s<=%s)",
590                         f->f_ava->aa_desc->ad_cname->bv_val,
591                     f->f_ava->aa_value->bv_val );
592                 break;
593
594         case LDAP_FILTER_APPROX:
595                 fprintf( stderr, "(%s~=%s)",
596                         f->f_ava->aa_desc->ad_cname->bv_val,
597                     f->f_ava->aa_value->bv_val );
598                 break;
599
600         case LDAP_FILTER_SUBSTRINGS:
601                 fprintf( stderr, "(%s=" /*)*/,
602                         f->f_sub_desc->ad_cname->bv_val );
603                 if ( f->f_sub_initial != NULL ) {
604                         fprintf( stderr, "%s",
605                                 f->f_sub_initial->bv_val );
606                 }
607                 if ( f->f_sub_any != NULL ) {
608                         for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
609                                 fprintf( stderr, "*%s",
610                                         f->f_sub_any[i]->bv_val );
611                         }
612                 }
613                 if ( f->f_sub_final != NULL ) {
614                         fprintf( stderr,
615                                 "*%s", f->f_sub_final->bv_val );
616                 }
617                 fprintf( stderr, /*(*/ ")" );
618                 break;
619
620         case LDAP_FILTER_PRESENT:
621                 fprintf( stderr, "(%s=*)",
622                         f->f_desc->ad_cname->bv_val );
623                 break;
624
625         case LDAP_FILTER_AND:
626         case LDAP_FILTER_OR:
627         case LDAP_FILTER_NOT:
628                 fprintf( stderr, "(%c" /*)*/,
629                         f->f_choice == LDAP_FILTER_AND ? '&' :
630                     f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
631                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
632                         filter_print( p );
633                 }
634                 fprintf( stderr, /*(*/ ")" );
635                 break;
636
637         case SLAPD_FILTER_COMPUTED:
638                 fprintf( stderr, "(?=%s)",
639                         f->f_result == LDAP_COMPARE_FALSE ? "false" :
640                         f->f_result == LDAP_COMPARE_TRUE ? "true" :
641                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
642                         "error" );
643                 break;
644
645         default:
646                 fprintf( stderr, "(unknown-filter=%lu)", f->f_choice );
647                 break;
648         }
649 }
650
651 #endif /* ldap_debug */