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