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