]> git.sur5r.net Git - openldap/blob - servers/slapd/filter.c
DirectoryString syntaxes must have one or more octets to be valid.
[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                 f->f_choice = SLAPD_FILTER_COMPUTED;
245                 f->f_result = SLAPD_COMPARE_UNDEFINED;
246                 *fstr = ch_strdup( "(extended)" );
247                 break;
248
249         default:
250                 Debug( LDAP_DEBUG_ANY, "get_filter: unknown filter type=%lu\n",
251                        f->f_choice, 0, 0 );
252                 f->f_choice = SLAPD_FILTER_COMPUTED;
253                 f->f_result = SLAPD_COMPARE_UNDEFINED;
254                 *fstr = ch_strdup( "(undefined)" );
255                 break;
256         }
257
258         free( ftmp );
259
260         if ( err != LDAP_SUCCESS ) {
261                 if ( *fstr != NULL ) {
262                         free( *fstr );
263                 }
264
265                 if( err != SLAPD_DISCONNECT ) {
266                         /* ignore error */
267                         f->f_choice = SLAPD_FILTER_COMPUTED;
268                         f->f_result = SLAPD_COMPARE_UNDEFINED;
269                         *fstr = ch_strdup( "(badfilter)" );
270                         err = LDAP_SUCCESS;
271                         *filt = f;
272
273                 } else {
274                         free(f);
275                 }
276         } else {
277                 *filt = f;
278         }
279
280         Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
281         return( err );
282 }
283
284 static int
285 get_filter_list( Connection *conn, BerElement *ber,
286         Filter **f, char **fstr,
287         const char **text )
288 {
289         Filter          **new;
290         int             err;
291         ber_tag_t       tag;
292         ber_len_t       len;
293         char            *last, *ftmp;
294
295         Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
296
297         *fstr = NULL;
298         new = f;
299         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
300             tag = ber_next_element( ber, &len, last ) )
301         {
302                 err = get_filter( conn, ber, new, &ftmp, text );
303                 if ( err != LDAP_SUCCESS )
304                         return( err );
305
306                 if ( *fstr == NULL ) {
307                         *fstr = ftmp;
308                 } else {
309                         *fstr = ch_realloc( *fstr, strlen( *fstr ) +
310                             strlen( ftmp ) + 1 );
311                         strcat( *fstr, ftmp );
312                         free( ftmp );
313                 }
314                 new = &(*new)->f_next;
315         }
316         *new = NULL;
317
318         Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
319         return( LDAP_SUCCESS );
320 }
321
322 static int
323 get_substring_filter(
324     Connection  *conn,
325     BerElement  *ber,
326     Filter      *f,
327     char        **fstr,
328         const char      **text
329 )
330 {
331         ber_tag_t       tag;
332         ber_len_t       len;
333         ber_tag_t       rc;
334         struct berval *value;
335         char            *last;
336         struct berval type;
337         struct berval *nvalue;
338         *text = "error decoding filter";
339
340         Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
341
342         if ( ber_scanf( ber, "{o" /*}*/, &type ) == LBER_ERROR ) {
343                 return SLAPD_DISCONNECT;
344         }
345
346         f->f_sub = ch_calloc( 1, sizeof(SubstringsAssertion) );
347         f->f_sub_desc = NULL;
348         rc = slap_bv2ad( &type, &f->f_sub_desc, text );
349
350         ch_free( type.bv_val );
351
352         if( rc != LDAP_SUCCESS ) {
353                 text = NULL;
354                 ch_free( f->f_sub );
355                 f->f_choice = SLAPD_FILTER_COMPUTED;
356                 f->f_result = SLAPD_COMPARE_UNDEFINED;
357                 *fstr = ch_strdup( "(undefined)" );
358                 return LDAP_SUCCESS;
359         }
360
361         f->f_sub_initial = NULL;
362         f->f_sub_any = NULL;
363         f->f_sub_final = NULL;
364
365         if( fstr ) {
366                 *fstr = ch_malloc( sizeof("(=" /*)*/) +
367                         f->f_sub_desc->ad_cname->bv_len );
368                 sprintf( *fstr, "(%s=" /*)*/, f->f_sub_desc->ad_cname->bv_val );
369         }
370
371         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
372             tag = ber_next_element( ber, &len, last ) )
373         {
374                 unsigned usage;
375
376                 rc = ber_scanf( ber, "O", &value );
377                 if ( rc == LBER_ERROR ) {
378                         rc = SLAPD_DISCONNECT;
379                         goto return_error;
380                 }
381
382                 if ( value == NULL || value->bv_len == 0 ) {
383                         ber_bvfree( value );
384                         rc = LDAP_INVALID_SYNTAX;
385                         goto return_error;
386                 } 
387
388                 switch ( tag ) {
389                 case LDAP_SUBSTRING_INITIAL:
390                         usage = SLAP_MR_SUBSTR_INITIAL;
391                         break;
392
393                 case LDAP_SUBSTRING_ANY:
394                         usage = SLAP_MR_SUBSTR_ANY;
395                         break;
396
397                 case LDAP_SUBSTRING_FINAL:
398                         usage = SLAP_MR_SUBSTR_FINAL;
399                         break;
400
401                 default:
402                         rc = LDAP_PROTOCOL_ERROR;
403
404                         Debug( LDAP_DEBUG_FILTER,
405                                 "  unknown substring choice=%ld\n",
406                                 (long) tag, 0, 0 );
407
408                         ber_bvfree( value );
409                         goto return_error;
410                 }
411
412                 rc = value_normalize( f->f_sub_desc, usage, value, &nvalue, text );
413                 ber_bvfree( value );
414
415                 if( rc != LDAP_SUCCESS ) {
416                         goto return_error;
417                 }
418
419                 value = nvalue;
420
421                 rc = LDAP_PROTOCOL_ERROR;
422
423                 switch ( tag ) {
424                 case LDAP_SUBSTRING_INITIAL:
425                         Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
426                         if ( f->f_sub_initial != NULL ) {
427                                 ber_bvfree( value );
428                                 goto return_error;
429                         }
430
431                         f->f_sub_initial = value;
432
433                         if( fstr ) {
434                                 *fstr = ch_realloc( *fstr,
435                                         strlen( *fstr ) + value->bv_len + 1 );
436                                 strcat( *fstr, value->bv_val );
437                         }
438                         break;
439
440                 case LDAP_SUBSTRING_ANY:
441                         Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
442                         if( ber_bvecadd( &f->f_sub_any, value ) < 0 ) {
443                                 ber_bvfree( value );
444                                 goto return_error;
445                         }
446
447                         if( fstr ) {
448                                 *fstr = ch_realloc( *fstr,
449                                         strlen( *fstr ) + value->bv_len + 2 );
450                                 strcat( *fstr, "*" );
451                                 strcat( *fstr, value->bv_val );
452                         }
453                         break;
454
455                 case LDAP_SUBSTRING_FINAL:
456                         Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
457                         if ( f->f_sub_final != NULL ) {
458                                 ber_bvfree( value );
459                                 goto return_error;
460                         }
461                         f->f_sub_final = value;
462
463                         if( fstr ) {
464                                 *fstr = ch_realloc( *fstr,
465                                         strlen( *fstr ) + value->bv_len + 2 );
466                                 strcat( *fstr, "*" );
467                                 strcat( *fstr, value->bv_val );
468                         }
469                         break;
470
471                 default:
472                         Debug( LDAP_DEBUG_FILTER,
473                                 "  unknown substring type=%ld\n",
474                                 (long) tag, 0, 0 );
475
476                         ber_bvfree( value );
477
478 return_error:
479                         Debug( LDAP_DEBUG_FILTER, "  error=%ld\n",
480                                 (long) rc, 0, 0 );
481
482                         if( fstr ) {
483                                 free( *fstr );
484                                 *fstr = NULL;
485                         }
486
487                         ad_free( f->f_sub_desc, 1 );
488                         ber_bvfree( f->f_sub_initial );
489                         ber_bvecfree( f->f_sub_any );
490                         ber_bvfree( f->f_sub_final );
491                         ch_free( f->f_sub );
492                         return rc;
493                 }
494         }
495
496         if( fstr ) {
497                 *fstr = ch_realloc( *fstr, strlen( *fstr ) + 3 );
498                 if ( f->f_sub_final == NULL ) {
499                         strcat( *fstr, "*" );
500                 }
501                 strcat( *fstr, /*(*/ ")" );
502         }
503
504         Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
505         return( LDAP_SUCCESS );
506 }
507
508 void
509 filter_free( Filter *f )
510 {
511         Filter  *p, *next;
512
513         if ( f == NULL ) {
514                 return;
515         }
516
517         switch ( f->f_choice ) {
518         case LDAP_FILTER_PRESENT:
519                 ad_free( f->f_desc, 1 );
520                 break;
521
522         case LDAP_FILTER_EQUALITY:
523         case LDAP_FILTER_GE:
524         case LDAP_FILTER_LE:
525         case LDAP_FILTER_APPROX:
526                 ava_free( f->f_ava, 1 );
527                 break;
528
529         case LDAP_FILTER_SUBSTRINGS:
530                 ad_free( f->f_sub_desc, 1 );
531                 if ( f->f_sub_initial != NULL ) {
532                         ber_bvfree( f->f_sub_initial );
533                 }
534                 ber_bvecfree( f->f_sub_any );
535                 if ( f->f_sub_final != NULL ) {
536                         ber_bvfree( f->f_sub_final );
537                 }
538                 break;
539
540         case LDAP_FILTER_AND:
541         case LDAP_FILTER_OR:
542         case LDAP_FILTER_NOT:
543                 for ( p = f->f_list; p != NULL; p = next ) {
544                         next = p->f_next;
545                         filter_free( p );
546                 }
547                 break;
548
549         case SLAPD_FILTER_COMPUTED:
550                 break;
551
552         default:
553                 Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
554                        f->f_choice, 0, 0 );
555                 break;
556         }
557
558         free( f );
559 }
560
561 #ifdef LDAP_DEBUG
562
563 void
564 filter_print( Filter *f )
565 {
566         int     i;
567         Filter  *p;
568
569         if ( f == NULL ) {
570                 fprintf( stderr, "No filter!" );
571         }
572
573         switch ( f->f_choice ) {
574         case LDAP_FILTER_EQUALITY:
575                 fprintf( stderr, "(%s=%s)",
576                         f->f_av_desc->ad_cname->bv_val,
577                     f->f_av_value->bv_val );
578                 break;
579
580         case LDAP_FILTER_GE:
581                 fprintf( stderr, "(%s>=%s)",
582                         f->f_av_desc->ad_cname->bv_val,
583                     f->f_av_value->bv_val );
584                 break;
585
586         case LDAP_FILTER_LE:
587                 fprintf( stderr, "(%s<=%s)",
588                         f->f_ava->aa_desc->ad_cname->bv_val,
589                     f->f_ava->aa_value->bv_val );
590                 break;
591
592         case LDAP_FILTER_APPROX:
593                 fprintf( stderr, "(%s~=%s)",
594                         f->f_ava->aa_desc->ad_cname->bv_val,
595                     f->f_ava->aa_value->bv_val );
596                 break;
597
598         case LDAP_FILTER_SUBSTRINGS:
599                 fprintf( stderr, "(%s=" /*)*/,
600                         f->f_sub_desc->ad_cname->bv_val );
601                 if ( f->f_sub_initial != NULL ) {
602                         fprintf( stderr, "%s",
603                                 f->f_sub_initial->bv_val );
604                 }
605                 if ( f->f_sub_any != NULL ) {
606                         for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
607                                 fprintf( stderr, "*%s",
608                                         f->f_sub_any[i]->bv_val );
609                         }
610                 }
611                 if ( f->f_sub_final != NULL ) {
612                         fprintf( stderr,
613                                 "*%s", f->f_sub_final->bv_val );
614                 }
615                 fprintf( stderr, /*(*/ ")" );
616                 break;
617
618         case LDAP_FILTER_PRESENT:
619                 fprintf( stderr, "(%s=*)",
620                         f->f_desc->ad_cname->bv_val );
621                 break;
622
623         case LDAP_FILTER_AND:
624         case LDAP_FILTER_OR:
625         case LDAP_FILTER_NOT:
626                 fprintf( stderr, "(%c" /*)*/,
627                         f->f_choice == LDAP_FILTER_AND ? '&' :
628                     f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
629                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
630                         filter_print( p );
631                 }
632                 fprintf( stderr, /*(*/ ")" );
633                 break;
634
635         case SLAPD_FILTER_COMPUTED:
636                 fprintf( stderr, "(?=%s)",
637                         f->f_result == LDAP_COMPARE_FALSE ? "false" :
638                         f->f_result == LDAP_COMPARE_TRUE ? "true" :
639                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
640                         "error" );
641                 break;
642
643         default:
644                 fprintf( stderr, "(unknown-filter=%lu)", f->f_choice );
645                 break;
646         }
647 }
648
649 #endif /* ldap_debug */