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