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