]> git.sur5r.net Git - openldap/blob - servers/slapd/filter.c
7b108931553b5e4c0d807ddb660212f3474b4aff
[openldap] / servers / slapd / filter.c
1 /* filter.c - routines for parsing and dealing with filters */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2003 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         const char **text );
22
23 static int      get_substring_filter(
24         Connection *conn,
25         BerElement *ber,
26         Filter *f,
27         const char **text );
28
29 static void simple_vrFilter2bv(
30         ValuesReturnFilter *f,
31         struct berval *fstr );
32
33 static int      get_simple_vrFilter(
34         Connection *conn,
35         BerElement *ber,
36         ValuesReturnFilter **f,
37         const char **text );
38
39 #ifdef SLAP_NVALUES
40 #define XXX 1
41 #endif
42
43 int
44 get_filter(
45         Connection *conn,
46         BerElement *ber,
47         Filter **filt,
48         const char **text )
49 {
50         ber_tag_t       tag;
51         ber_len_t       len;
52         int             err;
53         Filter          *f;
54
55 #ifdef NEW_LOGGING
56         LDAP_LOG( FILTER, ENTRY, "get_filter: conn %d\n", conn->c_connid, 0, 0 );
57 #else
58         Debug( LDAP_DEBUG_FILTER, "begin get_filter\n", 0, 0, 0 );
59 #endif
60         /*
61          * A filter looks like this coming in:
62          *      Filter ::= CHOICE {
63          *              and             [0]     SET OF Filter,
64          *              or              [1]     SET OF Filter,
65          *              not             [2]     Filter,
66          *              equalityMatch   [3]     AttributeValueAssertion,
67          *              substrings      [4]     SubstringFilter,
68          *              greaterOrEqual  [5]     AttributeValueAssertion,
69          *              lessOrEqual     [6]     AttributeValueAssertion,
70          *              present         [7]     AttributeType,,
71          *              approxMatch     [8]     AttributeValueAssertion
72          *              extensibleMatch [9]     MatchingRuleAssertion
73          *      }
74          *
75          *      SubstringFilter ::= SEQUENCE {
76          *              type               AttributeType,
77          *              SEQUENCE OF CHOICE {
78          *                      initial          [0] IA5String,
79          *                      any              [1] IA5String,
80          *                      final            [2] IA5String
81          *              }
82          *      }
83          *
84          *      MatchingRuleAssertion ::= SEQUENCE {
85          *              matchingRule    [1] MatchingRuleId OPTIONAL,
86          *              type            [2] AttributeDescription OPTIONAL,
87          *              matchValue      [3] AssertionValue,
88          *              dnAttributes    [4] BOOLEAN DEFAULT FALSE
89          *      }
90          *
91          */
92
93         tag = ber_peek_tag( ber, &len );
94
95         if( tag == LBER_ERROR ) {
96                 *text = "error decoding filter";
97                 return SLAPD_DISCONNECT;
98         }
99
100         f = (Filter *) ch_malloc( sizeof(Filter) );
101         f->f_next = NULL;
102
103         err = LDAP_SUCCESS;
104         f->f_choice = tag; 
105
106         switch ( f->f_choice ) {
107         case LDAP_FILTER_EQUALITY:
108 #ifdef NEW_LOGGING
109                 LDAP_LOG( FILTER, DETAIL2, 
110                         "get_filter: conn %d  EQUALITY\n", conn->c_connid, 0, 0 );
111 #else
112                 Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
113 #endif
114                 err = get_ava( ber, &f->f_ava, SLAP_MR_EQUALITY, text );
115                 if ( err != LDAP_SUCCESS ) {
116                         break;
117                 }
118
119                 assert( f->f_ava != NULL );
120                 break;
121
122         case LDAP_FILTER_SUBSTRINGS:
123 #ifdef NEW_LOGGING
124                 LDAP_LOG( FILTER, DETAIL1, 
125                         "get_filter: conn %d  SUBSTRINGS\n", conn->c_connid, 0, 0 );
126 #else
127                 Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
128 #endif
129                 err = get_substring_filter( conn, ber, f, text );
130                 if( err != LDAP_SUCCESS ) {
131                         break;
132                 }
133                 assert( f->f_sub != NULL );
134                 break;
135
136         case LDAP_FILTER_GE:
137 #ifdef NEW_LOGGING
138                 LDAP_LOG( FILTER, DETAIL1, 
139                         "get_filter: conn %d  GE\n", conn->c_connid, 0, 0 );
140 #else
141                 Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
142 #endif
143                 err = get_ava( ber, &f->f_ava, SLAP_MR_ORDERING, text );
144                 if ( err != LDAP_SUCCESS ) {
145                         break;
146                 }
147                 assert( f->f_ava != NULL );
148                 break;
149
150         case LDAP_FILTER_LE:
151 #ifdef NEW_LOGGING
152                 LDAP_LOG( FILTER, DETAIL1, 
153                         "get_filter: conn %d  LE\n", conn->c_connid, 0, 0 );
154 #else
155                 Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
156 #endif
157                 err = get_ava( ber, &f->f_ava, SLAP_MR_ORDERING, text );
158                 if ( err != LDAP_SUCCESS ) {
159                         break;
160                 }
161                 assert( f->f_ava != NULL );
162                 break;
163
164         case LDAP_FILTER_PRESENT: {
165                 struct berval type;
166
167 #ifdef NEW_LOGGING
168                 LDAP_LOG( FILTER, DETAIL1, 
169                         "get_filter: conn %d PRESENT\n", conn->c_connid, 0, 0 );
170 #else
171                 Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
172 #endif
173                 if ( ber_scanf( ber, "m", &type ) == LBER_ERROR ) {
174                         err = SLAPD_DISCONNECT;
175                         *text = "error decoding filter";
176                         break;
177                 }
178
179                 f->f_desc = NULL;
180                 err = slap_bv2ad( &type, &f->f_desc, text );
181
182                 if( err != LDAP_SUCCESS ) {
183                         /* unrecognized attribute description or other error */
184                         f->f_choice = SLAPD_FILTER_COMPUTED;
185                         f->f_result = LDAP_COMPARE_FALSE;
186                         err = LDAP_SUCCESS;
187                         break;
188                 }
189                 } break;
190
191         case LDAP_FILTER_APPROX:
192 #ifdef NEW_LOGGING
193                 LDAP_LOG( FILTER, DETAIL1, 
194                         "get_filter: conn %d  APPROX\n", conn->c_connid, 0, 0 );
195 #else
196                 Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
197 #endif
198                 err = get_ava( ber, &f->f_ava, SLAP_MR_EQUALITY_APPROX, text );
199                 if ( err != LDAP_SUCCESS ) {
200                         break;
201                 }
202                 assert( f->f_ava != NULL );
203                 break;
204
205         case LDAP_FILTER_AND:
206 #ifdef NEW_LOGGING
207                 LDAP_LOG( FILTER, DETAIL1, 
208                         "get_filter: conn %d  AND\n", conn->c_connid, 0, 0 );
209 #else
210                 Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
211 #endif
212                 err = get_filter_list( conn, ber, &f->f_and, text );
213                 if ( err != LDAP_SUCCESS ) {
214                         break;
215                 }
216 #ifdef XXX
217                 assert( f->f_and != NULL );
218 #endif
219                 break;
220
221         case LDAP_FILTER_OR:
222 #ifdef NEW_LOGGING
223                 LDAP_LOG( FILTER, DETAIL1, 
224                         "get_filter: conn %d  OR\n", conn->c_connid, 0, 0  );
225 #else
226                 Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
227 #endif
228                 err = get_filter_list( conn, ber, &f->f_or, text );
229                 if ( err != LDAP_SUCCESS ) {
230                         break;
231                 }
232                 break;
233
234         case LDAP_FILTER_NOT:
235 #ifdef NEW_LOGGING
236                 LDAP_LOG( FILTER, DETAIL1, 
237                         "get_filter: conn %d  NOT\n", conn->c_connid, 0, 0 );
238 #else
239                 Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
240 #endif
241                 (void) ber_skip_tag( ber, &len );
242                 err = get_filter( conn, ber, &f->f_not, text );
243                 if ( err != LDAP_SUCCESS ) {
244                         break;
245                 }
246                 break;
247
248         case LDAP_FILTER_EXT:
249 #ifdef NEW_LOGGING
250                 LDAP_LOG( FILTER, DETAIL1, 
251                         "get_filter: conn %d  EXTENSIBLE\n", conn->c_connid, 0, 0 );
252 #else
253                 Debug( LDAP_DEBUG_FILTER, "EXTENSIBLE\n", 0, 0, 0 );
254 #endif
255
256                 err = get_mra( ber, &f->f_mra, text );
257                 if ( err != LDAP_SUCCESS ) {
258                         break;
259                 }
260
261 #ifdef XXX
262                 assert( f->f_mra != NULL );
263 #endif
264                 break;
265
266         default:
267                 (void) ber_scanf( ber, "x" ); /* skip the element */
268 #ifdef NEW_LOGGING
269                 LDAP_LOG( FILTER, ERR, 
270                         "get_filter: conn %d unknown filter type=%lu\n",
271                         conn->c_connid, f->f_choice, 0 );
272 #else
273                 Debug( LDAP_DEBUG_ANY, "get_filter: unknown filter type=%lu\n",
274                         f->f_choice, 0, 0 );
275 #endif
276                 f->f_choice = SLAPD_FILTER_COMPUTED;
277                 f->f_result = SLAPD_COMPARE_UNDEFINED;
278                 break;
279         }
280
281         if ( err != LDAP_SUCCESS ) {
282                 if( err != SLAPD_DISCONNECT ) {
283                         /* ignore error */
284                         f->f_choice = SLAPD_FILTER_COMPUTED;
285                         f->f_result = SLAPD_COMPARE_UNDEFINED;
286                         err = LDAP_SUCCESS;
287                         *filt = f;
288
289                 } else {
290                         free(f);
291                 }
292
293         } else {
294                 *filt = f;
295         }
296
297 #ifdef NEW_LOGGING
298         LDAP_LOG( FILTER, DETAIL2, 
299                 "get_filter: conn %d exit\n", conn->c_connid, 0, 0 );
300 #else
301         Debug( LDAP_DEBUG_FILTER, "end get_filter %d\n", err, 0, 0 );
302 #endif
303         return( err );
304 }
305
306 static int
307 get_filter_list( Connection *conn, BerElement *ber,
308         Filter **f,
309         const char **text )
310 {
311         Filter          **new;
312         int             err;
313         ber_tag_t       tag;
314         ber_len_t       len;
315         char            *last;
316
317 #ifdef NEW_LOGGING
318         LDAP_LOG( FILTER, ENTRY, 
319                 "get_filter_list: conn %d start\n", conn->c_connid, 0, 0 );
320 #else
321         Debug( LDAP_DEBUG_FILTER, "begin get_filter_list\n", 0, 0, 0 );
322 #endif
323         new = f;
324         for ( tag = ber_first_element( ber, &len, &last );
325                 tag != LBER_DEFAULT;
326                 tag = ber_next_element( ber, &len, last ) )
327         {
328                 err = get_filter( conn, ber, new, text );
329                 if ( err != LDAP_SUCCESS )
330                         return( err );
331                 new = &(*new)->f_next;
332         }
333         *new = NULL;
334
335 #ifdef NEW_LOGGING
336         LDAP_LOG( FILTER, ENTRY, 
337                 "get_filter_list: conn %d exit\n", conn->c_connid, 0, 0 );
338 #else
339         Debug( LDAP_DEBUG_FILTER, "end get_filter_list\n", 0, 0, 0 );
340 #endif
341         return( LDAP_SUCCESS );
342 }
343
344 static int
345 get_substring_filter(
346         Connection      *conn,
347         BerElement      *ber,
348         Filter  *f,
349         const char      **text )
350 {
351         ber_tag_t       tag;
352         ber_len_t       len;
353         ber_tag_t       rc;
354         struct berval value;
355         char            *last;
356         struct berval bv;
357         AttributeDescription *ad;
358
359         *text = "error decoding filter";
360
361 #ifdef NEW_LOGGING
362         LDAP_LOG( FILTER, ENTRY, 
363                 "get_substring_filter: conn %d  begin\n", conn->c_connid, 0, 0 );
364 #else
365         Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
366 #endif
367         if ( ber_scanf( ber, "{m" /*}*/, &bv ) == LBER_ERROR ) {
368                 return SLAPD_DISCONNECT;
369         }
370
371         ad = NULL;
372         rc = slap_bv2ad( &bv, &ad, text );
373
374         if( rc != LDAP_SUCCESS ) {
375                 text = NULL;
376                 f->f_choice = SLAPD_FILTER_COMPUTED;
377                 f->f_result = SLAPD_COMPARE_UNDEFINED;
378                 return LDAP_SUCCESS;
379         }
380
381         f->f_sub = ch_calloc( 1, sizeof(SubstringsAssertion) );
382         f->f_sub_desc = ad;
383         f->f_sub_initial.bv_val = NULL;
384         f->f_sub_any = NULL;
385         f->f_sub_final.bv_val = NULL;
386
387         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
388                 tag = ber_next_element( ber, &len, last ) )
389         {
390                 unsigned usage;
391
392                 rc = ber_scanf( ber, "m", &value );
393                 if ( rc == LBER_ERROR ) {
394                         rc = SLAPD_DISCONNECT;
395                         goto return_error;
396                 }
397
398                 if ( value.bv_val == NULL || value.bv_len == 0 ) {
399                         rc = LDAP_INVALID_SYNTAX;
400                         goto return_error;
401                 } 
402
403                 switch ( tag ) {
404                 case LDAP_SUBSTRING_INITIAL:
405                         usage = SLAP_MR_SUBSTR_INITIAL;
406                         break;
407
408                 case LDAP_SUBSTRING_ANY:
409                         usage = SLAP_MR_SUBSTR_ANY;
410                         break;
411
412                 case LDAP_SUBSTRING_FINAL:
413                         usage = SLAP_MR_SUBSTR_FINAL;
414                         break;
415
416                 default:
417                         rc = LDAP_PROTOCOL_ERROR;
418
419 #ifdef NEW_LOGGING
420                         LDAP_LOG( FILTER, ERR,
421                                 "get_filter_substring: conn %d  unknown substring choice=%ld\n",
422                                 conn->c_connid, (long)tag, 0 );
423 #else
424                         Debug( LDAP_DEBUG_FILTER,
425                                 "  unknown substring choice=%ld\n",
426                                 (long) tag, 0, 0 );
427 #endif
428                         goto return_error;
429                 }
430
431 #ifdef SLAP_NVALUES
432                 /* validate/normalize using equality matching rule validator! */
433                 rc = asserted_value_validate_normalize(
434                         f->f_sub_desc, f->f_sub_desc->ad_type->sat_equality,
435                         usage, &value, &bv, text );
436                 if( rc != LDAP_SUCCESS ) {
437                         goto return_error;
438                 }
439 #else
440                 /* validate using equality matching rule validator! */
441                 rc = value_validate( f->f_sub_desc->ad_type->sat_equality,
442                         &value, text );
443                 if( rc != LDAP_SUCCESS ) {
444                         goto return_error;
445                 }
446
447                 rc = value_normalize( f->f_sub_desc, usage,
448                         &value, &bv, text );
449                 if( rc != LDAP_SUCCESS ) {
450                         goto return_error;
451                 }
452 #endif
453
454                 value = bv;
455                 rc = LDAP_PROTOCOL_ERROR;
456
457                 switch ( tag ) {
458                 case LDAP_SUBSTRING_INITIAL:
459 #ifdef NEW_LOGGING
460                         LDAP_LOG( FILTER, DETAIL1,
461                                 "get_substring_filter: conn %d  INITIAL\n", conn->c_connid, 0, 0 );
462 #else
463                         Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
464 #endif
465
466                         if ( f->f_sub_initial.bv_val != NULL
467                                 || f->f_sub_any != NULL 
468                                 || f->f_sub_final.bv_val != NULL )
469                         {
470                                 free( value.bv_val );
471                                 goto return_error;
472                         }
473
474                         f->f_sub_initial = value;
475                         break;
476
477                 case LDAP_SUBSTRING_ANY:
478 #ifdef NEW_LOGGING
479                         LDAP_LOG( FILTER, DETAIL1,
480                                 "get_substring_filter: conn %d  ANY\n", conn->c_connid, 0, 0 );
481 #else
482                         Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
483 #endif
484
485                         if ( f->f_sub_final.bv_val != NULL ) {
486                                 free( value.bv_val );
487                                 goto return_error;
488                         }
489
490                         ber_bvarray_add( &f->f_sub_any, &value );
491                         break;
492
493                 case LDAP_SUBSTRING_FINAL:
494 #ifdef NEW_LOGGING
495                         LDAP_LOG( FILTER, DETAIL1, 
496                                 "get_substring_filter: conn %d  FINAL\n", conn->c_connid, 0, 0 );
497 #else
498                         Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
499 #endif
500
501                         if ( f->f_sub_final.bv_val != NULL ) {
502                                 free( value.bv_val );
503                                 goto return_error;
504                         }
505
506                         f->f_sub_final = value;
507                         break;
508
509                 default:
510 #ifdef NEW_LOGGING
511                         LDAP_LOG( FILTER, INFO, 
512                                 "get_substring_filter: conn %d  unknown substring type %ld\n",
513                                 conn->c_connid, (long)tag, 0 );
514 #else
515                         Debug( LDAP_DEBUG_FILTER,
516                                 "  unknown substring type=%ld\n",
517                                 (long) tag, 0, 0 );
518 #endif
519
520                         free( value.bv_val );
521
522 return_error:
523 #ifdef NEW_LOGGING
524                         LDAP_LOG( FILTER, INFO, 
525                                 "get_substring_filter: conn %d  error %ld\n",
526                                 conn->c_connid, (long)rc, 0 );
527 #else
528                         Debug( LDAP_DEBUG_FILTER, "  error=%ld\n",
529                                 (long) rc, 0, 0 );
530 #endif
531                         free( f->f_sub_initial.bv_val );
532                         ber_bvarray_free( f->f_sub_any );
533                         free( f->f_sub_final.bv_val );
534                         ch_free( f->f_sub );
535                         f->f_sub = NULL;
536                         return rc;
537                 }
538         }
539
540 #ifdef NEW_LOGGING
541         LDAP_LOG( FILTER, ENTRY, 
542                 "get_substring_filter: conn %d exit\n", conn->c_connid, 0, 0 );
543 #else
544         Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
545 #endif
546         return( LDAP_SUCCESS );
547 }
548
549 void
550 filter_free( Filter *f )
551 {
552         Filter  *p, *next;
553
554         if ( f == NULL ) {
555                 return;
556         }
557
558         switch ( f->f_choice ) {
559         case LDAP_FILTER_PRESENT:
560                 break;
561
562         case LDAP_FILTER_EQUALITY:
563         case LDAP_FILTER_GE:
564         case LDAP_FILTER_LE:
565         case LDAP_FILTER_APPROX:
566                 ava_free( f->f_ava, 1 );
567                 break;
568
569         case LDAP_FILTER_SUBSTRINGS:
570                 if ( f->f_sub_initial.bv_val != NULL ) {
571                         free( f->f_sub_initial.bv_val );
572                 }
573                 ber_bvarray_free( f->f_sub_any );
574                 if ( f->f_sub_final.bv_val != NULL ) {
575                         free( f->f_sub_final.bv_val );
576                 }
577                 ch_free( f->f_sub );
578                 break;
579
580         case LDAP_FILTER_AND:
581         case LDAP_FILTER_OR:
582         case LDAP_FILTER_NOT:
583                 for ( p = f->f_list; p != NULL; p = next ) {
584                         next = p->f_next;
585                         filter_free( p );
586                 }
587                 break;
588
589         case LDAP_FILTER_EXT:
590                 mra_free( f->f_mra, 1 );
591                 break;
592
593         case SLAPD_FILTER_COMPUTED:
594                 break;
595
596         default:
597 #ifdef NEW_LOGGING
598                 LDAP_LOG( FILTER, ERR, 
599                         "filter_free: unknown filter type %lu\n", f->f_choice, 0, 0 );
600 #else
601                 Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
602                         f->f_choice, 0, 0 );
603 #endif
604                 break;
605         }
606
607         free( f );
608 }
609
610 void
611 filter2bv( Filter *f, struct berval *fstr )
612 {
613         int     i;
614         Filter  *p;
615         struct berval tmp;
616         ber_len_t len;
617
618         if ( f == NULL ) {
619                 ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
620                 return;
621         }
622
623         switch ( f->f_choice ) {
624         case LDAP_FILTER_EQUALITY:
625                 filter_escape_value( &f->f_av_value, &tmp );
626
627                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
628                         tmp.bv_len + ( sizeof("(=)") - 1 );
629                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
630
631                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
632                         f->f_av_desc->ad_cname.bv_val,
633                         tmp.bv_val );
634
635                 ber_memfree( tmp.bv_val );
636                 break;
637
638         case LDAP_FILTER_GE:
639                 filter_escape_value( &f->f_av_value, &tmp );
640
641                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
642                         tmp.bv_len + ( sizeof("(>=)") - 1 );
643                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
644
645                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
646                         f->f_av_desc->ad_cname.bv_val,
647                         tmp.bv_val );
648
649                 ber_memfree( tmp.bv_val );
650                 break;
651
652         case LDAP_FILTER_LE:
653                 filter_escape_value( &f->f_av_value, &tmp );
654
655                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
656                         tmp.bv_len + ( sizeof("(<=)") - 1 );
657                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
658
659                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
660                         f->f_av_desc->ad_cname.bv_val,
661                         tmp.bv_val );
662
663                 ber_memfree( tmp.bv_val );
664                 break;
665
666         case LDAP_FILTER_APPROX:
667                 filter_escape_value( &f->f_av_value, &tmp );
668
669                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
670                         tmp.bv_len + ( sizeof("(~=)") - 1 );
671                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
672
673                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
674                         f->f_av_desc->ad_cname.bv_val,
675                         tmp.bv_val );
676                 ber_memfree( tmp.bv_val );
677                 break;
678
679         case LDAP_FILTER_SUBSTRINGS:
680                 fstr->bv_len = f->f_sub_desc->ad_cname.bv_len +
681                         ( sizeof("(=*)") - 1 );
682                 fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
683
684                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
685                         f->f_sub_desc->ad_cname.bv_val );
686
687                 if ( f->f_sub_initial.bv_val != NULL ) {
688                         len = fstr->bv_len;
689
690                         filter_escape_value( &f->f_sub_initial, &tmp );
691
692                         fstr->bv_len += tmp.bv_len;
693                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
694
695                         snprintf( &fstr->bv_val[len-2], tmp.bv_len+3,
696                                 /* "(attr=" */ "%s*)",
697                                 tmp.bv_val );
698
699                         ber_memfree( tmp.bv_val );
700                 }
701
702                 if ( f->f_sub_any != NULL ) {
703                         for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
704                                 len = fstr->bv_len;
705                                 filter_escape_value( &f->f_sub_any[i], &tmp );
706
707                                 fstr->bv_len += tmp.bv_len + 1;
708                                 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
709
710                                 snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
711                                         /* "(attr=[init]*[any*]" */ "%s*)",
712                                         tmp.bv_val );
713                                 ber_memfree( tmp.bv_val );
714                         }
715                 }
716
717                 if ( f->f_sub_final.bv_val != NULL ) {
718                         len = fstr->bv_len;
719
720                         filter_escape_value( &f->f_sub_final, &tmp );
721
722                         fstr->bv_len += tmp.bv_len;
723                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
724
725                         snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
726                                 /* "(attr=[init*][any*]" */ "%s)",
727                                 tmp.bv_val );
728
729                         ber_memfree( tmp.bv_val );
730                 }
731
732                 break;
733
734         case LDAP_FILTER_PRESENT:
735                 fstr->bv_len = f->f_desc->ad_cname.bv_len +
736                         ( sizeof("(=*)") - 1 );
737                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
738
739                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
740                         f->f_desc->ad_cname.bv_val );
741                 break;
742
743         case LDAP_FILTER_AND:
744         case LDAP_FILTER_OR:
745         case LDAP_FILTER_NOT:
746                 fstr->bv_len = sizeof("(%)") - 1;
747                 fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
748
749                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
750                         f->f_choice == LDAP_FILTER_AND ? '&' :
751                         f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
752
753                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
754                         len = fstr->bv_len;
755
756                         filter2bv( p, &tmp );
757                         
758                         fstr->bv_len += tmp.bv_len;
759                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
760
761                         snprintf( &fstr->bv_val[len-1], tmp.bv_len + 2, 
762                                 /*"("*/ "%s)", tmp.bv_val );
763
764                         ch_free( tmp.bv_val );
765                 }
766
767                 break;
768
769         case LDAP_FILTER_EXT: {
770                 struct berval ad;
771                 filter_escape_value( &f->f_mr_value, &tmp );
772
773                 if ( f->f_mr_desc ) {
774                         ad = f->f_mr_desc->ad_cname;
775                 } else {
776                         ad.bv_len = 0;
777                         ad.bv_val = "";
778                 }
779                         
780                 fstr->bv_len = ad.bv_len +
781                         ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
782                         ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
783                         tmp.bv_len + ( sizeof("(:=)") - 1 );
784                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
785
786                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
787                         ad.bv_val,
788                         f->f_mr_dnattrs ? ":dn" : "",
789                         f->f_mr_rule_text.bv_len ? ":" : "",
790                         f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
791                         tmp.bv_val );
792                 ber_memfree( tmp.bv_val );
793                 } break;
794
795         case SLAPD_FILTER_COMPUTED:
796                 ber_str2bv(
797                         f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
798                         f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
799                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
800                         "(?=error)",
801                         f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
802                         f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
803                         f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
804                         sizeof("(?=error)")-1,
805                         1, fstr );
806                 break;
807
808         default:
809                 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
810                 break;
811         }
812 }
813
814 int
815 filter_escape_value(
816         struct berval *in,
817         struct berval *out )
818 {
819         ber_len_t i;
820         assert( in );
821         assert( out );
822
823         out->bv_val = (char *) ch_malloc( ( in->bv_len * 3 ) + 1 );
824         out->bv_len = 0;
825
826         for( i=0; i < in->bv_len ; i++ ) {
827                 if( FILTER_ESCAPE(in->bv_val[i]) ) {
828                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_CHAR;
829                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_HI( in->bv_val[i] );
830                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_LO( in->bv_val[i] );
831                 } else {
832                         out->bv_val[out->bv_len++] = in->bv_val[i];
833                 }
834         }
835
836         out->bv_val[out->bv_len] = '\0';
837         return LDAP_SUCCESS;
838 }
839
840 static int
841 get_simple_vrFilter(
842         Connection *conn,
843         BerElement *ber,
844         ValuesReturnFilter **filt,
845         const char **text )
846 {
847         ber_tag_t       tag;
848         ber_len_t       len;
849         int             err;
850         ValuesReturnFilter *vrf;
851
852 #ifdef NEW_LOGGING
853         LDAP_LOG( FILTER, ENTRY, 
854                 "get_simple_vrFilter: conn %d\n", conn->c_connid, 0, 0 );
855 #else
856         Debug( LDAP_DEBUG_FILTER, "begin get_simple_vrFilter\n", 0, 0, 0 );
857 #endif
858
859         tag = ber_peek_tag( ber, &len );
860
861         if( tag == LBER_ERROR ) {
862                 *text = "error decoding filter";
863                 return SLAPD_DISCONNECT;
864         }
865
866         vrf = (ValuesReturnFilter *) ch_malloc( sizeof(ValuesReturnFilter) );
867         vrf->vrf_next = NULL;
868
869         err = LDAP_SUCCESS;
870         vrf->vrf_choice = tag; 
871
872         switch ( vrf->vrf_choice ) {
873         case LDAP_FILTER_EQUALITY:
874 #ifdef NEW_LOGGING
875                 LDAP_LOG( FILTER, DETAIL2, 
876                         "get_simple_vrFilter: conn %d  EQUALITY\n", conn->c_connid, 0, 0 );
877 #else
878                 Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
879 #endif
880                 err = get_ava( ber, &vrf->vrf_ava, SLAP_MR_EQUALITY, text );
881                 if ( err != LDAP_SUCCESS ) {
882                         break;
883                 }
884
885                 assert( vrf->vrf_ava != NULL );
886                 break;
887
888         case LDAP_FILTER_SUBSTRINGS:
889 #ifdef NEW_LOGGING
890                 LDAP_LOG( FILTER, DETAIL1, 
891                         "get_simple_vrFilter: conn %d  SUBSTRINGS\n", conn->c_connid, 0, 0 );
892 #else
893                 Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
894 #endif
895                 err = get_substring_filter( conn, ber, (Filter *)vrf, text );
896                 break;
897
898         case LDAP_FILTER_GE:
899 #ifdef NEW_LOGGING
900                 LDAP_LOG( FILTER, DETAIL1, 
901                         "get_simple_vrFilter: conn %d  GE\n", conn->c_connid, 0, 0 );
902 #else
903                 Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
904 #endif
905                 err = get_ava( ber, &vrf->vrf_ava, SLAP_MR_ORDERING, text );
906                 if ( err != LDAP_SUCCESS ) {
907                         break;
908                 }
909                 break;
910
911         case LDAP_FILTER_LE:
912 #ifdef NEW_LOGGING
913                 LDAP_LOG( FILTER, DETAIL1, 
914                         "get_simple_vrFilter: conn %d  LE\n", conn->c_connid, 0, 0 );
915 #else
916                 Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
917 #endif
918                 err = get_ava( ber, &vrf->vrf_ava, SLAP_MR_ORDERING, text );
919                 if ( err != LDAP_SUCCESS ) {
920                         break;
921                 }
922                 break;
923
924         case LDAP_FILTER_PRESENT: {
925                 struct berval type;
926
927 #ifdef NEW_LOGGING
928                 LDAP_LOG( FILTER, DETAIL1, 
929                         "get_simple_vrFilter: conn %d PRESENT\n", conn->c_connid, 0, 0 );
930 #else
931                 Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
932 #endif
933                 if ( ber_scanf( ber, "m", &type ) == LBER_ERROR ) {
934                         err = SLAPD_DISCONNECT;
935                         *text = "error decoding filter";
936                         break;
937                 }
938
939                 vrf->vrf_desc = NULL;
940                 err = slap_bv2ad( &type, &vrf->vrf_desc, text );
941
942                 if( err != LDAP_SUCCESS ) {
943                         /* unrecognized attribute description or other error */
944                         vrf->vrf_choice = SLAPD_FILTER_COMPUTED;
945                         vrf->vrf_result = LDAP_COMPARE_FALSE;
946                         err = LDAP_SUCCESS;
947                         break;
948                 }
949                 } break;
950
951         case LDAP_FILTER_APPROX:
952 #ifdef NEW_LOGGING
953                 LDAP_LOG( FILTER, DETAIL1, 
954                         "get_simple_vrFilter: conn %d  APPROX\n", conn->c_connid, 0, 0 );
955 #else
956                 Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
957 #endif
958                 err = get_ava( ber, &vrf->vrf_ava, SLAP_MR_EQUALITY_APPROX, text );
959                 if ( err != LDAP_SUCCESS ) {
960                         break;
961                 }
962                 break;
963
964         case LDAP_FILTER_EXT:
965 #ifdef NEW_LOGGING
966                 LDAP_LOG( FILTER, DETAIL1, 
967                         "get_simple_vrFilter: conn %d  EXTENSIBLE\n", conn->c_connid, 0, 0 );
968 #else
969                 Debug( LDAP_DEBUG_FILTER, "EXTENSIBLE\n", 0, 0, 0 );
970 #endif
971
972                 err = get_mra( ber, &vrf->vrf_mra, text );
973                 if ( err != LDAP_SUCCESS ) {
974                         break;
975                 }
976
977                 assert( vrf->vrf_mra != NULL );
978                 break;
979
980         default:
981                 (void) ber_scanf( ber, "x" ); /* skip the element */
982 #ifdef NEW_LOGGING
983                 LDAP_LOG( FILTER, ERR, 
984                         "get_simple_vrFilter: conn %d unknown filter type=%lu\n",
985                         conn->c_connid, vrf->vrf_choice, 0 );
986 #else
987                 Debug( LDAP_DEBUG_ANY, "get_simple_vrFilter: unknown filter type=%lu\n",
988                         vrf->vrf_choice, 0, 0 );
989 #endif
990                 vrf->vrf_choice = SLAPD_FILTER_COMPUTED;
991                 vrf->vrf_result = SLAPD_COMPARE_UNDEFINED;
992                 break;
993         }
994
995         if ( err != LDAP_SUCCESS ) {
996                 if( err != SLAPD_DISCONNECT ) {
997                         /* ignore error */
998                         vrf->vrf_choice = SLAPD_FILTER_COMPUTED;
999                         vrf->vrf_result = SLAPD_COMPARE_UNDEFINED;
1000                         err = LDAP_SUCCESS;
1001                         *filt = vrf;
1002
1003                 } else {
1004                         free(vrf);
1005                 }
1006
1007         } else {
1008                 *filt = vrf;
1009         }
1010
1011 #ifdef NEW_LOGGING
1012         LDAP_LOG( FILTER, DETAIL2, 
1013                 "get_simple_vrFilter: conn %d exit\n", conn->c_connid, 0, 0 );
1014 #else
1015         Debug( LDAP_DEBUG_FILTER, "end get_simple_vrFilter %d\n", err, 0, 0 );
1016 #endif
1017         return( err );
1018 }
1019
1020 int
1021 get_vrFilter( Connection *conn, BerElement *ber,
1022         ValuesReturnFilter **vrf,
1023         const char **text )
1024 {
1025         /*
1026          * A ValuesReturnFilter looks like this:
1027          *
1028          *      ValuesReturnFilter ::= SEQUENCE OF SimpleFilterItem
1029          *      SimpleFilterItem ::= CHOICE {
1030          *              equalityMatch   [3]     AttributeValueAssertion,
1031          *              substrings      [4]     SubstringFilter,
1032          *              greaterOrEqual  [5]     AttributeValueAssertion,
1033          *              lessOrEqual     [6]     AttributeValueAssertion,
1034          *              present         [7]     AttributeType,
1035          *              approxMatch     [8]     AttributeValueAssertion,
1036          *              extensibleMatch [9]     SimpleMatchingAssertion -- LDAPv3
1037          *      }
1038          *
1039          *      SubstringFilter ::= SEQUENCE {
1040          *              type               AttributeType,
1041          *              SEQUENCE OF CHOICE {
1042          *                      initial          [0] IA5String,
1043          *                      any              [1] IA5String,
1044          *                      final            [2] IA5String
1045          *              }
1046          *      }
1047          *
1048          *      SimpleMatchingAssertion ::= SEQUENCE {  -- LDAPv3
1049          *              matchingRule    [1] MatchingRuleId OPTIONAL,
1050          *              type            [2] AttributeDescription OPTIONAL,
1051          *              matchValue      [3] AssertionValue }
1052          */
1053
1054         ValuesReturnFilter **n;
1055         ber_tag_t       tag;
1056         ber_len_t       len;
1057         char            *last;
1058
1059 #ifdef NEW_LOGGING
1060         LDAP_LOG( FILTER, ENTRY, 
1061                 "get_vrFilter: conn %d start\n", conn->c_connid, 0, 0 );
1062 #else
1063         Debug( LDAP_DEBUG_FILTER, "begin get_vrFilter\n", 0, 0, 0 );
1064 #endif
1065
1066         tag = ber_peek_tag( ber, &len );
1067
1068         if( tag == LBER_ERROR ) {
1069                 *text = "error decoding vrFilter";
1070                 return SLAPD_DISCONNECT;
1071         }
1072
1073         if( tag != LBER_SEQUENCE ) {
1074                 *text = "error decoding vrFilter, expect SEQUENCE tag";
1075                 return SLAPD_DISCONNECT;
1076         }
1077
1078         n = vrf;
1079         for ( tag = ber_first_element( ber, &len, &last );
1080                 tag != LBER_DEFAULT;
1081                 tag = ber_next_element( ber, &len, last ) )
1082         {
1083                 int err = get_simple_vrFilter( conn, ber, n, text );
1084                 if ( err != LDAP_SUCCESS )
1085                         return( err );
1086                 n = &(*n)->vrf_next;
1087         }
1088         *n = NULL;
1089
1090 #ifdef NEW_LOGGING
1091         LDAP_LOG( FILTER, ENTRY, 
1092                 "get_vrFilter: conn %d exit\n", conn->c_connid, 0, 0 );
1093 #else
1094         Debug( LDAP_DEBUG_FILTER, "end get_vrFilter\n", 0, 0, 0 );
1095 #endif
1096         return( LDAP_SUCCESS );
1097 }
1098
1099 void
1100 vrFilter_free( ValuesReturnFilter *vrf )
1101 {
1102         ValuesReturnFilter      *p, *next;
1103
1104         if ( vrf == NULL ) {
1105                 return;
1106         }
1107
1108         for ( p = vrf; p != NULL; p = next ) {
1109                 next = p->vrf_next;
1110
1111                 switch ( vrf->vrf_choice ) {
1112                 case LDAP_FILTER_PRESENT:
1113                         break;
1114
1115                 case LDAP_FILTER_EQUALITY:
1116                 case LDAP_FILTER_GE:
1117                 case LDAP_FILTER_LE:
1118                 case LDAP_FILTER_APPROX:
1119                         ava_free( vrf->vrf_ava, 1 );
1120                         break;
1121
1122                 case LDAP_FILTER_SUBSTRINGS:
1123                         if ( vrf->vrf_sub_initial.bv_val != NULL ) {
1124                                 free( vrf->vrf_sub_initial.bv_val );
1125                         }
1126                         ber_bvarray_free( vrf->vrf_sub_any );
1127                         if ( vrf->vrf_sub_final.bv_val != NULL ) {
1128                                 free( vrf->vrf_sub_final.bv_val );
1129                         }
1130                         ch_free( vrf->vrf_sub );
1131                         break;
1132
1133                 case LDAP_FILTER_EXT:
1134                         mra_free( vrf->vrf_mra, 1 );
1135                         break;
1136
1137                 case SLAPD_FILTER_COMPUTED:
1138                         break;
1139
1140                 default:
1141 #ifdef NEW_LOGGING
1142                         LDAP_LOG( FILTER, ERR, 
1143                                 "filter_free: unknown filter type %lu\n", vrf->vrf_choice, 0, 0 );
1144 #else
1145                         Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
1146                                 vrf->vrf_choice, 0, 0 );
1147 #endif
1148                         break;
1149                 }
1150
1151                 free( vrf );
1152         }
1153 }
1154
1155
1156 void
1157 vrFilter2bv( ValuesReturnFilter *vrf, struct berval *fstr )
1158 {
1159         ValuesReturnFilter      *p;
1160         struct berval tmp;
1161         ber_len_t len;
1162
1163         if ( vrf == NULL ) {
1164                 ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
1165                 return;
1166         }
1167
1168         fstr->bv_len = sizeof("()") - 1;
1169         fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
1170
1171         snprintf( fstr->bv_val, fstr->bv_len + 1, "()");
1172
1173         for ( p = vrf; p != NULL; p = p->vrf_next ) {
1174                 len = fstr->bv_len;
1175
1176                 simple_vrFilter2bv( p, &tmp );
1177                         
1178                 fstr->bv_len += tmp.bv_len;
1179                 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
1180
1181                 snprintf( &fstr->bv_val[len-1], tmp.bv_len + 2, 
1182                         /*"("*/ "%s)", tmp.bv_val );
1183
1184                 ch_free( tmp.bv_val );
1185         }
1186 }
1187
1188 static void
1189 simple_vrFilter2bv( ValuesReturnFilter *vrf, struct berval *fstr )
1190 {
1191         struct berval tmp;
1192         ber_len_t len;
1193
1194         if ( vrf == NULL ) {
1195                 ber_str2bv( "No filter!", sizeof("No filter!")-1, 1, fstr );
1196                 return;
1197         }
1198
1199         switch ( vrf->vrf_choice ) {
1200         case LDAP_FILTER_EQUALITY:
1201                 filter_escape_value( &vrf->vrf_av_value, &tmp );
1202
1203                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1204                         tmp.bv_len + ( sizeof("(=)") - 1 );
1205                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
1206
1207                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
1208                         vrf->vrf_av_desc->ad_cname.bv_val,
1209                         tmp.bv_val );
1210
1211                 ber_memfree( tmp.bv_val );
1212                 break;
1213
1214         case LDAP_FILTER_GE:
1215                 filter_escape_value( &vrf->vrf_av_value, &tmp );
1216
1217                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1218                         tmp.bv_len + ( sizeof("(>=)") - 1 );
1219                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
1220
1221                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
1222                         vrf->vrf_av_desc->ad_cname.bv_val,
1223                         tmp.bv_val );
1224
1225                 ber_memfree( tmp.bv_val );
1226                 break;
1227
1228         case LDAP_FILTER_LE:
1229                 filter_escape_value( &vrf->vrf_av_value, &tmp );
1230
1231                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1232                         tmp.bv_len + ( sizeof("(<=)") - 1 );
1233                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
1234
1235                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
1236                         vrf->vrf_av_desc->ad_cname.bv_val,
1237                         tmp.bv_val );
1238
1239                 ber_memfree( tmp.bv_val );
1240                 break;
1241
1242         case LDAP_FILTER_APPROX:
1243                 filter_escape_value( &vrf->vrf_av_value, &tmp );
1244
1245                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1246                         tmp.bv_len + ( sizeof("(~=)") - 1 );
1247                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
1248
1249                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
1250                         vrf->vrf_av_desc->ad_cname.bv_val,
1251                         tmp.bv_val );
1252                 ber_memfree( tmp.bv_val );
1253                 break;
1254
1255         case LDAP_FILTER_SUBSTRINGS:
1256                 fstr->bv_len = vrf->vrf_sub_desc->ad_cname.bv_len +
1257                         ( sizeof("(=*)") - 1 );
1258                 fstr->bv_val = ch_malloc( fstr->bv_len + 128 );
1259
1260                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
1261                         vrf->vrf_sub_desc->ad_cname.bv_val );
1262
1263                 if ( vrf->vrf_sub_initial.bv_val != NULL ) {
1264                         len = fstr->bv_len;
1265
1266                         filter_escape_value( &vrf->vrf_sub_initial, &tmp );
1267
1268                         fstr->bv_len += tmp.bv_len;
1269                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
1270
1271                         snprintf( &fstr->bv_val[len-2], tmp.bv_len+3,
1272                                 /* "(attr=" */ "%s*)",
1273                                 tmp.bv_val );
1274
1275                         ber_memfree( tmp.bv_val );
1276                 }
1277
1278                 if ( vrf->vrf_sub_any != NULL ) {
1279                         int i;
1280                         for ( i = 0; vrf->vrf_sub_any[i].bv_val != NULL; i++ ) {
1281                                 len = fstr->bv_len;
1282                                 filter_escape_value( &vrf->vrf_sub_any[i], &tmp );
1283
1284                                 fstr->bv_len += tmp.bv_len + 1;
1285                                 fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
1286
1287                                 snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
1288                                         /* "(attr=[init]*[any*]" */ "%s*)",
1289                                         tmp.bv_val );
1290                                 ber_memfree( tmp.bv_val );
1291                         }
1292                 }
1293
1294                 if ( vrf->vrf_sub_final.bv_val != NULL ) {
1295                         len = fstr->bv_len;
1296
1297                         filter_escape_value( &vrf->vrf_sub_final, &tmp );
1298
1299                         fstr->bv_len += tmp.bv_len;
1300                         fstr->bv_val = ch_realloc( fstr->bv_val, fstr->bv_len + 1 );
1301
1302                         snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
1303                                 /* "(attr=[init*][any*]" */ "%s)",
1304                                 tmp.bv_val );
1305
1306                         ber_memfree( tmp.bv_val );
1307                 }
1308
1309                 break;
1310
1311         case LDAP_FILTER_PRESENT:
1312                 fstr->bv_len = vrf->vrf_desc->ad_cname.bv_len +
1313                         ( sizeof("(=*)") - 1 );
1314                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
1315
1316                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
1317                         vrf->vrf_desc->ad_cname.bv_val );
1318                 break;
1319
1320         case LDAP_FILTER_EXT: {
1321                 struct berval ad;
1322                 filter_escape_value( &vrf->vrf_mr_value, &tmp );
1323
1324                 if ( vrf->vrf_mr_desc ) {
1325                         ad = vrf->vrf_mr_desc->ad_cname;
1326                 } else {
1327                         ad.bv_len = 0;
1328                         ad.bv_val = "";
1329                 }
1330                         
1331                 fstr->bv_len = ad.bv_len +
1332                         ( vrf->vrf_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
1333                         ( vrf->vrf_mr_rule_text.bv_len ? vrf->vrf_mr_rule_text.bv_len+1 : 0 ) +
1334                         tmp.bv_len + ( sizeof("(:=)") - 1 );
1335                 fstr->bv_val = ch_malloc( fstr->bv_len + 1 );
1336
1337                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
1338                         ad.bv_val,
1339                         vrf->vrf_mr_dnattrs ? ":dn" : "",
1340                         vrf->vrf_mr_rule_text.bv_len ? ":" : "",
1341                         vrf->vrf_mr_rule_text.bv_len ? vrf->vrf_mr_rule_text.bv_val : "",
1342                         tmp.bv_val );
1343
1344                 ber_memfree( tmp.bv_val );
1345                 } break;
1346
1347         case SLAPD_FILTER_COMPUTED:
1348                 ber_str2bv(
1349                         vrf->vrf_result == LDAP_COMPARE_FALSE ? "(?=false)" :
1350                         vrf->vrf_result == LDAP_COMPARE_TRUE ? "(?=true)" :
1351                         vrf->vrf_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
1352                         "(?=error)",
1353                         vrf->vrf_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
1354                         vrf->vrf_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
1355                         vrf->vrf_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
1356                         sizeof("(?=error)")-1,
1357                         1, fstr );
1358                 break;
1359
1360         default:
1361                 ber_str2bv( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr );
1362                 break;
1363         }
1364 }
1365
1366 static int
1367 get_substring_vrFilter(
1368         Connection      *conn,
1369         BerElement      *ber,
1370         ValuesReturnFilter      *vrf,
1371         const char      **text )
1372 {
1373         ber_tag_t       tag;
1374         ber_len_t       len;
1375         ber_tag_t       rc;
1376         struct berval value;
1377         char            *last;
1378         struct berval bv;
1379         *text = "error decoding filter";
1380
1381 #ifdef NEW_LOGGING
1382         LDAP_LOG( FILTER, ENTRY, 
1383                 "get_substring_filter: conn %d  begin\n", conn->c_connid, 0, 0 );
1384 #else
1385         Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
1386 #endif
1387         if ( ber_scanf( ber, "{m" /*}*/, &bv ) == LBER_ERROR ) {
1388                 return SLAPD_DISCONNECT;
1389         }
1390
1391         vrf->vrf_sub = ch_calloc( 1, sizeof(SubstringsAssertion) );
1392         vrf->vrf_sub_desc = NULL;
1393         rc = slap_bv2ad( &bv, &vrf->vrf_sub_desc, text );
1394
1395         if( rc != LDAP_SUCCESS ) {
1396                 text = NULL;
1397                 ch_free( vrf->vrf_sub );
1398                 vrf->vrf_choice = SLAPD_FILTER_COMPUTED;
1399                 vrf->vrf_result = SLAPD_COMPARE_UNDEFINED;
1400                 return LDAP_SUCCESS;
1401         }
1402
1403         vrf->vrf_sub_initial.bv_val = NULL;
1404         vrf->vrf_sub_any = NULL;
1405         vrf->vrf_sub_final.bv_val = NULL;
1406
1407         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
1408                 tag = ber_next_element( ber, &len, last ) )
1409         {
1410                 unsigned usage;
1411
1412                 rc = ber_scanf( ber, "m", &value );
1413                 if ( rc == LBER_ERROR ) {
1414                         rc = SLAPD_DISCONNECT;
1415                         goto return_error;
1416                 }
1417
1418                 if ( value.bv_val == NULL || value.bv_len == 0 ) {
1419                         rc = LDAP_INVALID_SYNTAX;
1420                         goto return_error;
1421                 } 
1422
1423                 switch ( tag ) {
1424                 case LDAP_SUBSTRING_INITIAL:
1425                         usage = SLAP_MR_SUBSTR_INITIAL;
1426                         break;
1427
1428                 case LDAP_SUBSTRING_ANY:
1429                         usage = SLAP_MR_SUBSTR_ANY;
1430                         break;
1431
1432                 case LDAP_SUBSTRING_FINAL:
1433                         usage = SLAP_MR_SUBSTR_FINAL;
1434                         break;
1435
1436                 default:
1437                         rc = LDAP_PROTOCOL_ERROR;
1438
1439 #ifdef NEW_LOGGING
1440                         LDAP_LOG( FILTER, ERR, 
1441                                 "get_filter_substring: conn %d  unknown substring choice=%ld\n",
1442                                 conn->c_connid, (long)tag, 0 );
1443 #else
1444                         Debug( LDAP_DEBUG_FILTER,
1445                                 "  unknown substring choice=%ld\n",
1446                                 (long) tag, 0, 0 );
1447 #endif
1448                         goto return_error;
1449                 }
1450
1451 #ifdef SLAP_NVALUES
1452                 /* validate/normalize using equality matching rule validator! */
1453                 rc = asserted_value_validate_normalize(
1454                         vrf->vrf_sub_desc, vrf->vrf_sub_desc->ad_type->sat_equality,
1455                         usage, &value, &bv, text );
1456                 if( rc != LDAP_SUCCESS ) {
1457                         goto return_error;
1458                 }
1459 #else
1460                 /* valiate using equality matching rule validator! */
1461                 rc = value_validate( vrf->vrf_sub_desc->ad_type->sat_equality,
1462                         &value, text );
1463                 if( rc != LDAP_SUCCESS ) {
1464                         goto return_error;
1465                 }
1466
1467                 rc = value_normalize( vrf->vrf_sub_desc, usage,
1468                         &value, &bv, text );
1469                 if( rc != LDAP_SUCCESS ) {
1470                         goto return_error;
1471                 }
1472 #endif
1473
1474                 value = bv;
1475
1476                 rc = LDAP_PROTOCOL_ERROR;
1477
1478                 switch ( tag ) {
1479                 case LDAP_SUBSTRING_INITIAL:
1480 #ifdef NEW_LOGGING
1481                         LDAP_LOG( FILTER, DETAIL1, 
1482                                 "get_substring_filter: conn %d  INITIAL\n", 
1483                                 conn->c_connid, 0, 0 );
1484 #else
1485                         Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
1486 #endif
1487
1488                         if ( vrf->vrf_sub_initial.bv_val != NULL
1489                                 || vrf->vrf_sub_any != NULL 
1490                                 || vrf->vrf_sub_final.bv_val != NULL )
1491                         {
1492                                 free( value.bv_val );
1493                                 goto return_error;
1494                         }
1495
1496                         vrf->vrf_sub_initial = value;
1497                         break;
1498
1499                 case LDAP_SUBSTRING_ANY:
1500 #ifdef NEW_LOGGING
1501                         LDAP_LOG( FILTER, DETAIL1, 
1502                                 "get_substring_filter: conn %d  ANY\n", conn->c_connid, 0, 0 );
1503 #else
1504                         Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
1505 #endif
1506
1507                         if ( vrf->vrf_sub_final.bv_val != NULL ) {
1508                                 free( value.bv_val );
1509                                 goto return_error;
1510                         }
1511
1512                         ber_bvarray_add( &vrf->vrf_sub_any, &value );
1513                         break;
1514
1515                 case LDAP_SUBSTRING_FINAL:
1516 #ifdef NEW_LOGGING
1517                         LDAP_LOG( FILTER, DETAIL1, 
1518                                 "get_substring_filter: conn %d  FINAL\n", conn->c_connid, 0, 0 );
1519 #else
1520                         Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
1521 #endif
1522
1523                         if ( vrf->vrf_sub_final.bv_val != NULL ) {
1524                                 free( value.bv_val );
1525                                 goto return_error;
1526                         }
1527
1528                         vrf->vrf_sub_final = value;
1529                         break;
1530
1531                 default:
1532 #ifdef NEW_LOGGING
1533                         LDAP_LOG( FILTER, INFO, 
1534                                 "get_substring_filter: conn %d  unknown substring type %ld\n",
1535                                 conn->c_connid, (long)tag, 0 );
1536 #else
1537                         Debug( LDAP_DEBUG_FILTER,
1538                                 "  unknown substring type=%ld\n",
1539                                 (long) tag, 0, 0 );
1540 #endif
1541
1542                         free( value.bv_val );
1543
1544 return_error:
1545 #ifdef NEW_LOGGING
1546                         LDAP_LOG( FILTER, INFO, 
1547                                 "get_substring_filter: conn %d  error %ld\n",
1548                                 conn->c_connid, (long)rc, 0 );
1549 #else
1550                         Debug( LDAP_DEBUG_FILTER, "  error=%ld\n",
1551                                 (long) rc, 0, 0 );
1552 #endif
1553                         free( vrf->vrf_sub_initial.bv_val );
1554                         ber_bvarray_free( vrf->vrf_sub_any );
1555                         free( vrf->vrf_sub_final.bv_val );
1556                         ch_free( vrf->vrf_sub );
1557                         return rc;
1558                 }
1559         }
1560
1561 #ifdef NEW_LOGGING
1562         LDAP_LOG( FILTER, ENTRY, 
1563                 "get_substring_filter: conn %d exit\n", conn->c_connid, 0, 0 );
1564 #else
1565         Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
1566 #endif
1567         return( LDAP_SUCCESS );
1568 }
1569