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