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