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