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