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