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