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