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