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