]> git.sur5r.net Git - openldap/blob - servers/slapd/filter.c
8de5d6e94e3d38b973302932c0faf4d685c1191a
[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_tmpfree = (BER_MEMFREE_FN *)ch_free;
619         filter_free_x( &op, f );
620 }
621
622 void
623 filter2bv_x( Filter *f, struct berval *fstr, void *ctx )
624 {
625         int     i;
626         Filter  *p;
627         struct berval tmp;
628         ber_len_t len;
629         BER_MEMALLOC_FN *alloc = ctx ? sl_malloc : (BER_MEMALLOC_FN *)ch_malloc;
630         BER_MEMREALLOC_FN *reallo = ctx ? sl_realloc : (BER_MEMREALLOC_FN *)ch_realloc;
631
632         if ( f == NULL ) {
633                 ber_str2bv_x( "No filter!", sizeof("No filter!")-1, 1, fstr, ctx );
634                 return;
635         }
636
637         switch ( f->f_choice ) {
638         case LDAP_FILTER_EQUALITY:
639                 filter_escape_value_x( &f->f_av_value, &tmp, ctx );
640
641                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
642                         tmp.bv_len + ( sizeof("(=)") - 1 );
643                 fstr->bv_val = alloc( fstr->bv_len + 1, ctx );
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_x( tmp.bv_val, ctx );
650                 break;
651
652         case LDAP_FILTER_GE:
653                 filter_escape_value_x( &f->f_av_value, &tmp, ctx );
654
655                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
656                         tmp.bv_len + ( sizeof("(>=)") - 1 );
657                 fstr->bv_val = alloc( fstr->bv_len + 1, ctx );
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_x( tmp.bv_val, ctx );
664                 break;
665
666         case LDAP_FILTER_LE:
667                 filter_escape_value_x( &f->f_av_value, &tmp, ctx );
668
669                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
670                         tmp.bv_len + ( sizeof("(<=)") - 1 );
671                 fstr->bv_val = alloc( fstr->bv_len + 1, ctx );
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
677                 ber_memfree_x( tmp.bv_val, ctx );
678                 break;
679
680         case LDAP_FILTER_APPROX:
681                 filter_escape_value_x( &f->f_av_value, &tmp, ctx );
682
683                 fstr->bv_len = f->f_av_desc->ad_cname.bv_len +
684                         tmp.bv_len + ( sizeof("(~=)") - 1 );
685                 fstr->bv_val = alloc( fstr->bv_len + 1, ctx );
686
687                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
688                         f->f_av_desc->ad_cname.bv_val,
689                         tmp.bv_val );
690                 ber_memfree_x( tmp.bv_val, ctx );
691                 break;
692
693         case LDAP_FILTER_SUBSTRINGS:
694                 fstr->bv_len = f->f_sub_desc->ad_cname.bv_len +
695                         ( sizeof("(=*)") - 1 );
696                 fstr->bv_val = alloc( fstr->bv_len + 128, ctx );
697
698                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
699                         f->f_sub_desc->ad_cname.bv_val );
700
701                 if ( f->f_sub_initial.bv_val != NULL ) {
702                         len = fstr->bv_len;
703
704                         filter_escape_value_x( &f->f_sub_initial, &tmp, ctx );
705
706                         fstr->bv_len += tmp.bv_len;
707                         fstr->bv_val = reallo( fstr->bv_val, fstr->bv_len + 1, ctx );
708
709                         snprintf( &fstr->bv_val[len-2], tmp.bv_len+3,
710                                 /* "(attr=" */ "%s*)",
711                                 tmp.bv_val );
712
713                         ber_memfree_x( tmp.bv_val, ctx );
714                 }
715
716                 if ( f->f_sub_any != NULL ) {
717                         for ( i = 0; f->f_sub_any[i].bv_val != NULL; i++ ) {
718                                 len = fstr->bv_len;
719                                 filter_escape_value_x( &f->f_sub_any[i], &tmp, ctx );
720
721                                 fstr->bv_len += tmp.bv_len + 1;
722                                 fstr->bv_val = reallo( fstr->bv_val, fstr->bv_len + 1, ctx );
723
724                                 snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
725                                         /* "(attr=[init]*[any*]" */ "%s*)",
726                                         tmp.bv_val );
727                                 ber_memfree_x( tmp.bv_val, ctx );
728                         }
729                 }
730
731                 if ( f->f_sub_final.bv_val != NULL ) {
732                         len = fstr->bv_len;
733
734                         filter_escape_value_x( &f->f_sub_final, &tmp, ctx );
735
736                         fstr->bv_len += tmp.bv_len;
737                         fstr->bv_val = reallo( fstr->bv_val, fstr->bv_len + 1, ctx );
738
739                         snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
740                                 /* "(attr=[init*][any*]" */ "%s)",
741                                 tmp.bv_val );
742
743                         ber_memfree_x( tmp.bv_val, ctx );
744                 }
745
746                 break;
747
748         case LDAP_FILTER_PRESENT:
749                 fstr->bv_len = f->f_desc->ad_cname.bv_len +
750                         ( sizeof("(=*)") - 1 );
751                 fstr->bv_val = alloc( fstr->bv_len + 1, ctx );
752
753                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
754                         f->f_desc->ad_cname.bv_val );
755                 break;
756
757         case LDAP_FILTER_AND:
758         case LDAP_FILTER_OR:
759         case LDAP_FILTER_NOT:
760                 fstr->bv_len = sizeof("(%)") - 1;
761                 fstr->bv_val = alloc( fstr->bv_len + 128, ctx );
762
763                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%c)",
764                         f->f_choice == LDAP_FILTER_AND ? '&' :
765                         f->f_choice == LDAP_FILTER_OR ? '|' : '!' );
766
767                 for ( p = f->f_list; p != NULL; p = p->f_next ) {
768                         len = fstr->bv_len;
769
770                         filter2bv( p, &tmp );
771                         
772                         fstr->bv_len += tmp.bv_len;
773                         fstr->bv_val = reallo( fstr->bv_val, fstr->bv_len + 1, ctx );
774
775                         snprintf( &fstr->bv_val[len-1], tmp.bv_len + 2, 
776                                 /*"("*/ "%s)", tmp.bv_val );
777
778                         ch_free( tmp.bv_val );
779                 }
780
781                 break;
782
783         case LDAP_FILTER_EXT: {
784                 struct berval ad;
785                 filter_escape_value_x( &f->f_mr_value, &tmp, ctx );
786
787                 if ( f->f_mr_desc ) {
788                         ad = f->f_mr_desc->ad_cname;
789                 } else {
790                         ad.bv_len = 0;
791                         ad.bv_val = "";
792                 }
793                         
794                 fstr->bv_len = ad.bv_len +
795                         ( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
796                         ( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
797                         tmp.bv_len + ( sizeof("(:=)") - 1 );
798                 fstr->bv_val = alloc( fstr->bv_len + 1, ctx );
799
800                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
801                         ad.bv_val,
802                         f->f_mr_dnattrs ? ":dn" : "",
803                         f->f_mr_rule_text.bv_len ? ":" : "",
804                         f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
805                         tmp.bv_val );
806                 ber_memfree_x( tmp.bv_val, ctx );
807                 } break;
808
809         case SLAPD_FILTER_COMPUTED:
810                 ber_str2bv_x(
811                         f->f_result == LDAP_COMPARE_FALSE ? "(?=false)" :
812                         f->f_result == LDAP_COMPARE_TRUE ? "(?=true)" :
813                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
814                         "(?=error)",
815                         f->f_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
816                         f->f_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
817                         f->f_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
818                         sizeof("(?=error)")-1,
819                         1, fstr, ctx );
820                 break;
821
822         default:
823                 ber_str2bv_x( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr, ctx );
824                 break;
825         }
826 }
827
828 void
829 filter2bv( Filter *f, struct berval *fstr )
830 {
831         filter2bv_x( f, fstr, NULL );
832 }
833
834 int
835 filter_escape_value_x(
836         struct berval *in,
837         struct berval *out,
838         void *ctx )
839 {
840         ber_len_t i;
841         assert( in );
842         assert( out );
843
844         i = in->bv_len * 3 + 1;
845         out->bv_val = ctx ? sl_malloc( i, ctx ) : ch_malloc( i );
846         out->bv_len = 0;
847
848         for( i=0; i < in->bv_len ; i++ ) {
849                 if( FILTER_ESCAPE(in->bv_val[i]) ) {
850                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_CHAR;
851                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_HI( in->bv_val[i] );
852                         out->bv_val[out->bv_len++] = SLAP_ESCAPE_LO( in->bv_val[i] );
853                 } else {
854                         out->bv_val[out->bv_len++] = in->bv_val[i];
855                 }
856         }
857
858         out->bv_val[out->bv_len] = '\0';
859         return LDAP_SUCCESS;
860 }
861
862 int
863 filter_escape_value(
864         struct berval *in,
865         struct berval *out )
866 {
867         return filter_escape_value_x( in, out, NULL );
868 }
869
870 static int
871 get_simple_vrFilter(
872         Operation *op,
873         BerElement *ber,
874         ValuesReturnFilter **filt,
875         const char **text )
876 {
877         ber_tag_t       tag;
878         ber_len_t       len;
879         int             err;
880         ValuesReturnFilter vrf;
881
882 #ifdef NEW_LOGGING
883         LDAP_LOG( FILTER, ENTRY, 
884                 "get_simple_vrFilter: conn %d\n", op->o_connid, 0, 0 );
885 #else
886         Debug( LDAP_DEBUG_FILTER, "begin get_simple_vrFilter\n", 0, 0, 0 );
887 #endif
888
889         tag = ber_peek_tag( ber, &len );
890
891         if( tag == LBER_ERROR ) {
892                 *text = "error decoding filter";
893                 return SLAPD_DISCONNECT;
894         }
895
896         vrf.vrf_next = NULL;
897
898         err = LDAP_SUCCESS;
899         vrf.vrf_choice = tag; 
900
901         switch ( vrf.vrf_choice ) {
902         case LDAP_FILTER_EQUALITY:
903 #ifdef NEW_LOGGING
904                 LDAP_LOG( FILTER, DETAIL2, 
905                         "get_simple_vrFilter: conn %d  EQUALITY\n", op->o_connid, 0, 0 );
906 #else
907                 Debug( LDAP_DEBUG_FILTER, "EQUALITY\n", 0, 0, 0 );
908 #endif
909                 err = get_ava( op, ber, &vrf.vrf_ava, SLAP_MR_EQUALITY, text );
910                 if ( err != LDAP_SUCCESS ) {
911                         break;
912                 }
913
914                 assert( vrf.vrf_ava != NULL );
915                 break;
916
917         case LDAP_FILTER_SUBSTRINGS:
918 #ifdef NEW_LOGGING
919                 LDAP_LOG( FILTER, DETAIL1, 
920                         "get_simple_vrFilter: conn %d  SUBSTRINGS\n", op->o_connid, 0, 0 );
921 #else
922                 Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n", 0, 0, 0 );
923 #endif
924                 err = get_ssa( op, ber, &vrf.vrf_sub, text );
925                 break;
926
927         case LDAP_FILTER_GE:
928 #ifdef NEW_LOGGING
929                 LDAP_LOG( FILTER, DETAIL1, 
930                         "get_simple_vrFilter: conn %d  GE\n", op->o_connid, 0, 0 );
931 #else
932                 Debug( LDAP_DEBUG_FILTER, "GE\n", 0, 0, 0 );
933 #endif
934                 err = get_ava( op, ber, &vrf.vrf_ava, SLAP_MR_ORDERING, text );
935                 if ( err != LDAP_SUCCESS ) {
936                         break;
937                 }
938                 break;
939
940         case LDAP_FILTER_LE:
941 #ifdef NEW_LOGGING
942                 LDAP_LOG( FILTER, DETAIL1, 
943                         "get_simple_vrFilter: conn %d  LE\n", op->o_connid, 0, 0 );
944 #else
945                 Debug( LDAP_DEBUG_FILTER, "LE\n", 0, 0, 0 );
946 #endif
947                 err = get_ava( op, ber, &vrf.vrf_ava, SLAP_MR_ORDERING, text );
948                 if ( err != LDAP_SUCCESS ) {
949                         break;
950                 }
951                 break;
952
953         case LDAP_FILTER_PRESENT: {
954                 struct berval type;
955
956 #ifdef NEW_LOGGING
957                 LDAP_LOG( FILTER, DETAIL1, 
958                         "get_simple_vrFilter: conn %d PRESENT\n", op->o_connid, 0, 0 );
959 #else
960                 Debug( LDAP_DEBUG_FILTER, "PRESENT\n", 0, 0, 0 );
961 #endif
962                 if ( ber_scanf( ber, "m", &type ) == LBER_ERROR ) {
963                         err = SLAPD_DISCONNECT;
964                         *text = "error decoding filter";
965                         break;
966                 }
967
968                 vrf.vrf_desc = NULL;
969                 err = slap_bv2ad( &type, &vrf.vrf_desc, text );
970
971                 if( err != LDAP_SUCCESS ) {
972                         /* unrecognized attribute description or other error */
973                         vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
974                         vrf.vrf_result = LDAP_COMPARE_FALSE;
975                         err = LDAP_SUCCESS;
976                         break;
977                 }
978                 } break;
979
980         case LDAP_FILTER_APPROX:
981 #ifdef NEW_LOGGING
982                 LDAP_LOG( FILTER, DETAIL1, 
983                         "get_simple_vrFilter: conn %d  APPROX\n", op->o_connid, 0, 0 );
984 #else
985                 Debug( LDAP_DEBUG_FILTER, "APPROX\n", 0, 0, 0 );
986 #endif
987                 err = get_ava( op, ber, &vrf.vrf_ava, SLAP_MR_EQUALITY_APPROX, text );
988                 if ( err != LDAP_SUCCESS ) {
989                         break;
990                 }
991                 break;
992
993         case LDAP_FILTER_EXT:
994 #ifdef NEW_LOGGING
995                 LDAP_LOG( FILTER, DETAIL1, 
996                         "get_simple_vrFilter: conn %d  EXTENSIBLE\n", op->o_connid, 0, 0 );
997 #else
998                 Debug( LDAP_DEBUG_FILTER, "EXTENSIBLE\n", 0, 0, 0 );
999 #endif
1000
1001                 err = get_mra( op, ber, &vrf.vrf_mra, text );
1002                 if ( err != LDAP_SUCCESS ) {
1003                         break;
1004                 }
1005
1006                 assert( vrf.vrf_mra != NULL );
1007                 break;
1008
1009         default:
1010                 (void) ber_scanf( ber, "x" ); /* skip the element */
1011 #ifdef NEW_LOGGING
1012                 LDAP_LOG( FILTER, ERR, 
1013                         "get_simple_vrFilter: conn %d unknown filter type=%lu\n",
1014                         op->o_connid, vrf.vrf_choice, 0 );
1015 #else
1016                 Debug( LDAP_DEBUG_ANY, "get_simple_vrFilter: unknown filter type=%lu\n",
1017                         vrf.vrf_choice, 0, 0 );
1018 #endif
1019                 vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
1020                 vrf.vrf_result = SLAPD_COMPARE_UNDEFINED;
1021                 break;
1022         }
1023
1024         if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1025                 /* ignore error */
1026                 vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
1027                 vrf.vrf_result = SLAPD_COMPARE_UNDEFINED;
1028                 err = LDAP_SUCCESS;
1029         }
1030
1031         if ( err == LDAP_SUCCESS ) {
1032                 *filt = ch_malloc( sizeof vrf );
1033                 **filt = vrf;
1034         }
1035
1036 #ifdef NEW_LOGGING
1037         LDAP_LOG( FILTER, DETAIL2, 
1038                 "get_simple_vrFilter: conn %d exit\n", op->o_connid, 0, 0 );
1039 #else
1040         Debug( LDAP_DEBUG_FILTER, "end get_simple_vrFilter %d\n", err, 0, 0 );
1041 #endif
1042
1043         return err;
1044 }
1045
1046 int
1047 get_vrFilter( Operation *op, BerElement *ber,
1048         ValuesReturnFilter **vrf,
1049         const char **text )
1050 {
1051         /*
1052          * A ValuesReturnFilter looks like this:
1053          *
1054          *      ValuesReturnFilter ::= SEQUENCE OF SimpleFilterItem
1055          *      SimpleFilterItem ::= CHOICE {
1056          *              equalityMatch   [3]     AttributeValueAssertion,
1057          *              substrings      [4]     SubstringFilter,
1058          *              greaterOrEqual  [5]     AttributeValueAssertion,
1059          *              lessOrEqual     [6]     AttributeValueAssertion,
1060          *              present         [7]     AttributeType,
1061          *              approxMatch     [8]     AttributeValueAssertion,
1062          *              extensibleMatch [9]     SimpleMatchingAssertion -- LDAPv3
1063          *      }
1064          *
1065          *      SubstringFilter ::= SEQUENCE {
1066          *              type               AttributeType,
1067          *              SEQUENCE OF CHOICE {
1068          *                      initial          [0] IA5String,
1069          *                      any              [1] IA5String,
1070          *                      final            [2] IA5String
1071          *              }
1072          *      }
1073          *
1074          *      SimpleMatchingAssertion ::= SEQUENCE {  -- LDAPv3
1075          *              matchingRule    [1] MatchingRuleId OPTIONAL,
1076          *              type            [2] AttributeDescription OPTIONAL,
1077          *              matchValue      [3] AssertionValue }
1078          */
1079
1080         ValuesReturnFilter **n;
1081         ber_tag_t       tag;
1082         ber_len_t       len;
1083         char            *last;
1084
1085 #ifdef NEW_LOGGING
1086         LDAP_LOG( FILTER, ENTRY, 
1087                 "get_vrFilter: conn %d start\n", op->o_connid, 0, 0 );
1088 #else
1089         Debug( LDAP_DEBUG_FILTER, "begin get_vrFilter\n", 0, 0, 0 );
1090 #endif
1091
1092         tag = ber_peek_tag( ber, &len );
1093
1094         if( tag == LBER_ERROR ) {
1095                 *text = "error decoding vrFilter";
1096                 return SLAPD_DISCONNECT;
1097         }
1098
1099         if( tag != LBER_SEQUENCE ) {
1100                 *text = "error decoding vrFilter, expect SEQUENCE tag";
1101                 return SLAPD_DISCONNECT;
1102         }
1103
1104         n = vrf;
1105         for ( tag = ber_first_element( ber, &len, &last );
1106                 tag != LBER_DEFAULT;
1107                 tag = ber_next_element( ber, &len, last ) )
1108         {
1109                 int err = get_simple_vrFilter( op, ber, n, text );
1110
1111                 if ( err != LDAP_SUCCESS ) return( err );
1112
1113                 n = &(*n)->vrf_next;
1114         }
1115         *n = NULL;
1116
1117 #ifdef NEW_LOGGING
1118         LDAP_LOG( FILTER, ENTRY, 
1119                 "get_vrFilter: conn %d exit\n", op->o_connid, 0, 0 );
1120 #else
1121         Debug( LDAP_DEBUG_FILTER, "end get_vrFilter\n", 0, 0, 0 );
1122 #endif
1123         return( LDAP_SUCCESS );
1124 }
1125
1126 void
1127 vrFilter_free( Operation *op, ValuesReturnFilter *vrf )
1128 {
1129         ValuesReturnFilter      *p, *next;
1130
1131         if ( vrf == NULL ) {
1132                 return;
1133         }
1134
1135         for ( p = vrf; p != NULL; p = next ) {
1136                 next = p->vrf_next;
1137
1138                 switch ( vrf->vrf_choice ) {
1139                 case LDAP_FILTER_PRESENT:
1140                         break;
1141
1142                 case LDAP_FILTER_EQUALITY:
1143                 case LDAP_FILTER_GE:
1144                 case LDAP_FILTER_LE:
1145                 case LDAP_FILTER_APPROX:
1146                         ava_free( op, vrf->vrf_ava, 1 );
1147                         break;
1148
1149                 case LDAP_FILTER_SUBSTRINGS:
1150                         if ( vrf->vrf_sub_initial.bv_val != NULL ) {
1151 #ifdef notyet
1152                                 op->o_tmpfree( vrf->vrf_sub_initial.bv_val, op->o_tmpmemctx );
1153 #else
1154                                 ch_free( vrf->vrf_sub_initial.bv_val );
1155 #endif
1156                         }
1157                         ber_bvarray_free_x( vrf->vrf_sub_any, op->o_tmpmemctx );
1158                         if ( vrf->vrf_sub_final.bv_val != NULL ) {
1159 #ifdef notyet
1160                                 op->o_tmpfree( vrf->vrf_sub_final.bv_val, op->o_tmpmemctx );
1161 #else
1162                                 ch_free( vrf->vrf_sub_final.bv_val );
1163 #endif
1164                         }
1165                         op->o_tmpfree( vrf->vrf_sub, op->o_tmpmemctx );
1166                         break;
1167
1168                 case LDAP_FILTER_EXT:
1169                         mra_free( op, vrf->vrf_mra, 1 );
1170                         break;
1171
1172                 case SLAPD_FILTER_COMPUTED:
1173                         break;
1174
1175                 default:
1176 #ifdef NEW_LOGGING
1177                         LDAP_LOG( FILTER, ERR, 
1178                                 "filter_free: unknown filter type %lu\n", vrf->vrf_choice, 0, 0 );
1179 #else
1180                         Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
1181                                 vrf->vrf_choice, 0, 0 );
1182 #endif
1183                         break;
1184                 }
1185
1186                 op->o_tmpfree( vrf, op->o_tmpmemctx );
1187         }
1188 }
1189
1190 void
1191 vrFilter2bv( Operation *op, ValuesReturnFilter *vrf, struct berval *fstr )
1192 {
1193         ValuesReturnFilter      *p;
1194         struct berval tmp;
1195         ber_len_t len;
1196         BER_MEMREALLOC_FN *reallo = op->o_tmpmemctx ? sl_realloc :
1197                 (BER_MEMREALLOC_FN *)ch_realloc;
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 = reallo( 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         BER_MEMREALLOC_FN *reallo = op->o_tmpmemctx ? sl_realloc :
1230                 (BER_MEMREALLOC_FN *) ch_realloc;
1231
1232         if ( vrf == NULL ) {
1233                 ber_str2bv_x( "No filter!", sizeof("No filter!")-1, 1, fstr, op->o_tmpmemctx );
1234                 return;
1235         }
1236
1237         switch ( vrf->vrf_choice ) {
1238         case LDAP_FILTER_EQUALITY:
1239                 filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
1240
1241                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1242                         tmp.bv_len + ( sizeof("(=)") - 1 );
1243                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1244
1245                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=%s)",
1246                         vrf->vrf_av_desc->ad_cname.bv_val,
1247                         tmp.bv_val );
1248
1249                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1250                 break;
1251
1252         case LDAP_FILTER_GE:
1253                 filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
1254
1255                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1256                         tmp.bv_len + ( sizeof("(>=)") - 1 );
1257                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1258
1259                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s>=%s)",
1260                         vrf->vrf_av_desc->ad_cname.bv_val,
1261                         tmp.bv_val );
1262
1263                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1264                 break;
1265
1266         case LDAP_FILTER_LE:
1267                 filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
1268
1269                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1270                         tmp.bv_len + ( sizeof("(<=)") - 1 );
1271                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1272
1273                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
1274                         vrf->vrf_av_desc->ad_cname.bv_val,
1275                         tmp.bv_val );
1276
1277                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1278                 break;
1279
1280         case LDAP_FILTER_APPROX:
1281                 filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
1282
1283                 fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
1284                         tmp.bv_len + ( sizeof("(~=)") - 1 );
1285                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1286
1287                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
1288                         vrf->vrf_av_desc->ad_cname.bv_val,
1289                         tmp.bv_val );
1290                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1291                 break;
1292
1293         case LDAP_FILTER_SUBSTRINGS:
1294                 fstr->bv_len = vrf->vrf_sub_desc->ad_cname.bv_len +
1295                         ( sizeof("(=*)") - 1 );
1296                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
1297
1298                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
1299                         vrf->vrf_sub_desc->ad_cname.bv_val );
1300
1301                 if ( vrf->vrf_sub_initial.bv_val != NULL ) {
1302                         len = fstr->bv_len;
1303
1304                         filter_escape_value_x( &vrf->vrf_sub_initial, &tmp, op->o_tmpmemctx );
1305
1306                         fstr->bv_len += tmp.bv_len;
1307                         fstr->bv_val = reallo( fstr->bv_val, fstr->bv_len + 1, op->o_tmpmemctx );
1308
1309                         snprintf( &fstr->bv_val[len-2], tmp.bv_len+3,
1310                                 /* "(attr=" */ "%s*)",
1311                                 tmp.bv_val );
1312
1313                         ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1314                 }
1315
1316                 if ( vrf->vrf_sub_any != NULL ) {
1317                         int i;
1318                         for ( i = 0; vrf->vrf_sub_any[i].bv_val != NULL; i++ ) {
1319                                 len = fstr->bv_len;
1320                                 filter_escape_value_x( &vrf->vrf_sub_any[i], &tmp, op->o_tmpmemctx );
1321
1322                                 fstr->bv_len += tmp.bv_len + 1;
1323                                 fstr->bv_val = reallo( fstr->bv_val, fstr->bv_len + 1, op->o_tmpmemctx );
1324
1325                                 snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
1326                                         /* "(attr=[init]*[any*]" */ "%s*)",
1327                                         tmp.bv_val );
1328                                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1329                         }
1330                 }
1331
1332                 if ( vrf->vrf_sub_final.bv_val != NULL ) {
1333                         len = fstr->bv_len;
1334
1335                         filter_escape_value_x( &vrf->vrf_sub_final, &tmp, op->o_tmpmemctx );
1336
1337                         fstr->bv_len += tmp.bv_len;
1338                         fstr->bv_val = reallo( fstr->bv_val, fstr->bv_len + 1, op->o_tmpmemctx );
1339
1340                         snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
1341                                 /* "(attr=[init*][any*]" */ "%s)",
1342                                 tmp.bv_val );
1343
1344                         ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1345                 }
1346
1347                 break;
1348
1349         case LDAP_FILTER_PRESENT:
1350                 fstr->bv_len = vrf->vrf_desc->ad_cname.bv_len +
1351                         ( sizeof("(=*)") - 1 );
1352                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1353
1354                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
1355                         vrf->vrf_desc->ad_cname.bv_val );
1356                 break;
1357
1358         case LDAP_FILTER_EXT: {
1359                 struct berval ad;
1360                 filter_escape_value_x( &vrf->vrf_mr_value, &tmp, op->o_tmpmemctx );
1361
1362                 if ( vrf->vrf_mr_desc ) {
1363                         ad = vrf->vrf_mr_desc->ad_cname;
1364                 } else {
1365                         ad.bv_len = 0;
1366                         ad.bv_val = "";
1367                 }
1368                         
1369                 fstr->bv_len = ad.bv_len +
1370                         ( vrf->vrf_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
1371                         ( vrf->vrf_mr_rule_text.bv_len ? vrf->vrf_mr_rule_text.bv_len+1 : 0 ) +
1372                         tmp.bv_len + ( sizeof("(:=)") - 1 );
1373                 fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
1374
1375                 snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
1376                         ad.bv_val,
1377                         vrf->vrf_mr_dnattrs ? ":dn" : "",
1378                         vrf->vrf_mr_rule_text.bv_len ? ":" : "",
1379                         vrf->vrf_mr_rule_text.bv_len ? vrf->vrf_mr_rule_text.bv_val : "",
1380                         tmp.bv_val );
1381
1382                 ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
1383                 } break;
1384
1385         case SLAPD_FILTER_COMPUTED:
1386                 ber_str2bv_x(
1387                         vrf->vrf_result == LDAP_COMPARE_FALSE ? "(?=false)" :
1388                         vrf->vrf_result == LDAP_COMPARE_TRUE ? "(?=true)" :
1389                         vrf->vrf_result == SLAPD_COMPARE_UNDEFINED ? "(?=undefined)" :
1390                         "(?=error)",
1391                         vrf->vrf_result == LDAP_COMPARE_FALSE ? sizeof("(?=false)")-1 :
1392                         vrf->vrf_result == LDAP_COMPARE_TRUE ? sizeof("(?=true)")-1 :
1393                         vrf->vrf_result == SLAPD_COMPARE_UNDEFINED ? sizeof("(?=undefined)")-1 :
1394                         sizeof("(?=error)")-1,
1395                         1, fstr, op->o_tmpmemctx );
1396                 break;
1397
1398         default:
1399                 ber_str2bv_x( "(?=unknown)", sizeof("(?=unknown)")-1, 1, fstr, op->o_tmpmemctx );
1400                 break;
1401         }
1402 }
1403
1404 #if 0 /* unused */
1405 static int
1406 get_substring_vrFilter(
1407         Operation *op,
1408         BerElement      *ber,
1409         ValuesReturnFilter      *vrf,
1410         const char      **text )
1411 {
1412         ber_tag_t       tag;
1413         ber_len_t       len;
1414         ber_tag_t       rc;
1415         struct berval value;
1416         char            *last;
1417         struct berval bv;
1418         *text = "error decoding filter";
1419
1420 #ifdef NEW_LOGGING
1421         LDAP_LOG( FILTER, ENTRY, 
1422                 "get_substring_filter: conn %d  begin\n", op->o_connid, 0, 0 );
1423 #else
1424         Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
1425 #endif
1426         if ( ber_scanf( ber, "{m" /*}*/, &bv ) == LBER_ERROR ) {
1427                 return SLAPD_DISCONNECT;
1428         }
1429
1430         vrf->vrf_sub = ch_calloc( 1, sizeof(SubstringsAssertion) );
1431         vrf->vrf_sub_desc = NULL;
1432         rc = slap_bv2ad( &bv, &vrf->vrf_sub_desc, text );
1433
1434         if( rc != LDAP_SUCCESS ) {
1435                 text = NULL;
1436                 ch_free( vrf->vrf_sub );
1437                 vrf->vrf_choice = SLAPD_FILTER_COMPUTED;
1438                 vrf->vrf_result = SLAPD_COMPARE_UNDEFINED;
1439                 return LDAP_SUCCESS;
1440         }
1441
1442         vrf->vrf_sub_initial.bv_val = NULL;
1443         vrf->vrf_sub_any = NULL;
1444         vrf->vrf_sub_final.bv_val = NULL;
1445
1446         for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
1447                 tag = ber_next_element( ber, &len, last ) )
1448         {
1449                 unsigned usage;
1450
1451                 rc = ber_scanf( ber, "m", &value );
1452                 if ( rc == LBER_ERROR ) {
1453                         rc = SLAPD_DISCONNECT;
1454                         goto return_error;
1455                 }
1456
1457                 if ( value.bv_val == NULL || value.bv_len == 0 ) {
1458                         rc = LDAP_INVALID_SYNTAX;
1459                         goto return_error;
1460                 } 
1461
1462                 switch ( tag ) {
1463                 case LDAP_SUBSTRING_INITIAL:
1464                         usage = SLAP_MR_SUBSTR_INITIAL;
1465                         break;
1466
1467                 case LDAP_SUBSTRING_ANY:
1468                         usage = SLAP_MR_SUBSTR_ANY;
1469                         break;
1470
1471                 case LDAP_SUBSTRING_FINAL:
1472                         usage = SLAP_MR_SUBSTR_FINAL;
1473                         break;
1474
1475                 default:
1476                         rc = LDAP_PROTOCOL_ERROR;
1477
1478 #ifdef NEW_LOGGING
1479                         LDAP_LOG( FILTER, ERR, 
1480                                 "get_filter_substring: conn %d  unknown substring choice=%ld\n",
1481                                 op->o_connid, (long)tag, 0 );
1482 #else
1483                         Debug( LDAP_DEBUG_FILTER,
1484                                 "  unknown substring choice=%ld\n",
1485                                 (long) tag, 0, 0 );
1486 #endif
1487                         goto return_error;
1488                 }
1489
1490                 /* validate/normalize using equality matching rule validator! */
1491                 rc = asserted_value_validate_normalize(
1492                         vrf->vrf_sub_desc, vrf->vrf_sub_desc->ad_type->sat_equality,
1493                         usage, &value, &bv, text );
1494                 if( rc != LDAP_SUCCESS ) {
1495                         goto return_error;
1496                 }
1497
1498                 value = bv;
1499
1500                 rc = LDAP_PROTOCOL_ERROR;
1501
1502                 switch ( tag ) {
1503                 case LDAP_SUBSTRING_INITIAL:
1504 #ifdef NEW_LOGGING
1505                         LDAP_LOG( FILTER, DETAIL1, 
1506                                 "get_substring_filter: conn %d  INITIAL\n", 
1507                                 op->o_connid, 0, 0 );
1508 #else
1509                         Debug( LDAP_DEBUG_FILTER, "  INITIAL\n", 0, 0, 0 );
1510 #endif
1511
1512                         if ( vrf->vrf_sub_initial.bv_val != NULL
1513                                 || vrf->vrf_sub_any != NULL 
1514                                 || vrf->vrf_sub_final.bv_val != NULL )
1515                         {
1516                                 free( value.bv_val );
1517                                 goto return_error;
1518                         }
1519
1520                         vrf->vrf_sub_initial = value;
1521                         break;
1522
1523                 case LDAP_SUBSTRING_ANY:
1524 #ifdef NEW_LOGGING
1525                         LDAP_LOG( FILTER, DETAIL1, 
1526                                 "get_substring_filter: conn %d  ANY\n", op->o_connid, 0, 0 );
1527 #else
1528                         Debug( LDAP_DEBUG_FILTER, "  ANY\n", 0, 0, 0 );
1529 #endif
1530
1531                         if ( vrf->vrf_sub_final.bv_val != NULL ) {
1532                                 free( value.bv_val );
1533                                 goto return_error;
1534                         }
1535
1536                         ber_bvarray_add( &vrf->vrf_sub_any, &value );
1537                         break;
1538
1539                 case LDAP_SUBSTRING_FINAL:
1540 #ifdef NEW_LOGGING
1541                         LDAP_LOG( FILTER, DETAIL1, 
1542                                 "get_substring_filter: conn %d  FINAL\n", op->o_connid, 0, 0 );
1543 #else
1544                         Debug( LDAP_DEBUG_FILTER, "  FINAL\n", 0, 0, 0 );
1545 #endif
1546
1547                         if ( vrf->vrf_sub_final.bv_val != NULL ) {
1548                                 free( value.bv_val );
1549                                 goto return_error;
1550                         }
1551
1552                         vrf->vrf_sub_final = value;
1553                         break;
1554
1555                 default:
1556 #ifdef NEW_LOGGING
1557                         LDAP_LOG( FILTER, INFO, 
1558                                 "get_substring_filter: conn %d  unknown substring type %ld\n",
1559                                 op->o_connid, (long)tag, 0 );
1560 #else
1561                         Debug( LDAP_DEBUG_FILTER,
1562                                 "  unknown substring type=%ld\n",
1563                                 (long) tag, 0, 0 );
1564 #endif
1565
1566                         free( value.bv_val );
1567
1568 return_error:
1569 #ifdef NEW_LOGGING
1570                         LDAP_LOG( FILTER, INFO, 
1571                                 "get_substring_filter: conn %d  error %ld\n",
1572                                 op->o_connid, (long)rc, 0 );
1573 #else
1574                         Debug( LDAP_DEBUG_FILTER, "  error=%ld\n",
1575                                 (long) rc, 0, 0 );
1576 #endif
1577                         free( vrf->vrf_sub_initial.bv_val );
1578                         ber_bvarray_free( vrf->vrf_sub_any );
1579                         free( vrf->vrf_sub_final.bv_val );
1580                         ch_free( vrf->vrf_sub );
1581                         return rc;
1582                 }
1583         }
1584
1585 #ifdef NEW_LOGGING
1586         LDAP_LOG( FILTER, ENTRY, 
1587                 "get_substring_filter: conn %d exit\n", op->o_connid, 0, 0 );
1588 #else
1589         Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
1590 #endif
1591         return( LDAP_SUCCESS );
1592 }
1593 #endif /* unused */