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