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