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