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