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