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