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