Home | History | Annotate | Line # | Download | only in slapd
      1 /*	$NetBSD: filter.c,v 1.9 2025/09/05 21:16:25 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-2024 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.9 2025/09/05 21:16:25 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
     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
     84 filter_destroy( void )
     85 {
     86 	return;
     87 }
     88 
     89 static int
     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
    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
    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
    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
    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
    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
    611 filter2bv_x( Operation *op, Filter *f, struct berval *fstr )
    612 {
    613 	filter2bv_undef_x( op, f, 0, fstr );
    614 }
    615 
    616 void
    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
    873 filter2bv( Filter *f, struct berval *fstr )
    874 {
    875 	filter2bv_undef( f, 0, fstr );
    876 }
    877 
    878 void
    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 *
    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 		n->f_ava = ava_dup( f->f_ava, memctx );
    919 		break;
    920 	case LDAP_FILTER_SUBSTRINGS:
    921 		n->f_sub = mf->bmf_calloc( 1, sizeof(SubstringsAssertion), memctx );
    922 		if ( f->f_sub_desc->ad_flags & SLAP_DESC_TEMPORARY )
    923 			n->f_sub_desc = slap_bv2tmp_ad( &f->f_sub_desc->ad_cname, memctx );
    924 		else
    925 			n->f_sub_desc = f->f_sub_desc;
    926 		if ( !BER_BVISNULL( &f->f_sub_initial ))
    927 			ber_dupbv_x( &n->f_sub_initial, &f->f_sub_initial, memctx );
    928 		if ( f->f_sub_any ) {
    929 			int i;
    930 			for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ );
    931 			n->f_sub_any = mf->bmf_malloc(( i+1 )*sizeof( struct berval ),
    932 				memctx );
    933 			for ( i = 0; !BER_BVISNULL( &f->f_sub_any[i] ); i++ ) {
    934 				ber_dupbv_x( &n->f_sub_any[i], &f->f_sub_any[i], memctx );
    935 			}
    936 			BER_BVZERO( &n->f_sub_any[i] );
    937 		}
    938 		if ( !BER_BVISNULL( &f->f_sub_final ))
    939 			ber_dupbv_x( &n->f_sub_final, &f->f_sub_final, memctx );
    940 		break;
    941 	case LDAP_FILTER_EXT: {
    942 		/* Should this be mra_dup() ? */
    943 		ber_len_t length;
    944 		length = sizeof(MatchingRuleAssertion);
    945 		if ( !BER_BVISNULL( &f->f_mr_rule_text ))
    946 			length += f->f_mr_rule_text.bv_len + 1;
    947 		n->f_mra = mf->bmf_calloc( 1, length, memctx );
    948 		*n->f_mra = *f->f_mra;
    949 		if ( f->f_mr_desc && ( f->f_sub_desc->ad_flags & SLAP_DESC_TEMPORARY ))
    950 			n->f_mr_desc = slap_bv2tmp_ad( &f->f_mr_desc->ad_cname, memctx );
    951 		ber_dupbv_x( &n->f_mr_value, &f->f_mr_value, memctx );
    952 		if ( !BER_BVISNULL( &f->f_mr_rule_text )) {
    953 			n->f_mr_rule_text.bv_val = (char *)(n->f_mra+1);
    954 			AC_MEMCPY(n->f_mr_rule_text.bv_val,
    955 				f->f_mr_rule_text.bv_val, f->f_mr_rule_text.bv_len );
    956 		}
    957 		} break;
    958 	case LDAP_FILTER_AND:
    959 	case LDAP_FILTER_OR:
    960 	case LDAP_FILTER_NOT: {
    961 		Filter **p;
    962 		for ( p = &n->f_list, f = f->f_list; f; f = f->f_next ) {
    963 			*p = filter_dup( f, memctx );
    964 			p = &(*p)->f_next;
    965 		}
    966 		} break;
    967 	}
    968 	return n;
    969 }
    970 
    971 static int
    972 get_simple_vrFilter(
    973 	Operation *op,
    974 	BerElement *ber,
    975 	ValuesReturnFilter **filt,
    976 	const char **text )
    977 {
    978 	ber_tag_t	tag;
    979 	ber_len_t	len;
    980 	int		err;
    981 	ValuesReturnFilter vrf;
    982 
    983 	Debug( LDAP_DEBUG_FILTER, "begin get_simple_vrFilter\n" );
    984 
    985 	tag = ber_peek_tag( ber, &len );
    986 
    987 	if( tag == LBER_ERROR ) {
    988 		*text = "error decoding filter";
    989 		return SLAPD_DISCONNECT;
    990 	}
    991 
    992 	vrf.vrf_next = NULL;
    993 
    994 	err = LDAP_SUCCESS;
    995 	vrf.vrf_choice = tag;
    996 
    997 	switch ( vrf.vrf_choice ) {
    998 	case LDAP_FILTER_EQUALITY:
    999 		Debug( LDAP_DEBUG_FILTER, "EQUALITY\n" );
   1000 		err = get_ava( op, ber, (Filter *)&vrf, SLAP_MR_EQUALITY, text );
   1001 		if ( err != LDAP_SUCCESS ) {
   1002 			break;
   1003 		}
   1004 
   1005 		assert( vrf.vrf_ava != NULL );
   1006 		break;
   1007 
   1008 	case LDAP_FILTER_SUBSTRINGS:
   1009 		Debug( LDAP_DEBUG_FILTER, "SUBSTRINGS\n" );
   1010 		err = get_ssa( op, ber, (Filter *)&vrf, text );
   1011 		break;
   1012 
   1013 	case LDAP_FILTER_GE:
   1014 		Debug( LDAP_DEBUG_FILTER, "GE\n" );
   1015 		err = get_ava( op, ber, (Filter *)&vrf, SLAP_MR_ORDERING, text );
   1016 		if ( err != LDAP_SUCCESS ) {
   1017 			break;
   1018 		}
   1019 		break;
   1020 
   1021 	case LDAP_FILTER_LE:
   1022 		Debug( LDAP_DEBUG_FILTER, "LE\n" );
   1023 		err = get_ava( op, ber, (Filter *)&vrf, SLAP_MR_ORDERING, text );
   1024 		if ( err != LDAP_SUCCESS ) {
   1025 			break;
   1026 		}
   1027 		break;
   1028 
   1029 	case LDAP_FILTER_PRESENT: {
   1030 		struct berval type;
   1031 
   1032 		Debug( LDAP_DEBUG_FILTER, "PRESENT\n" );
   1033 		if ( ber_scanf( ber, "m", &type ) == LBER_ERROR ) {
   1034 			err = SLAPD_DISCONNECT;
   1035 			*text = "error decoding filter";
   1036 			break;
   1037 		}
   1038 
   1039 		vrf.vrf_desc = NULL;
   1040 		err = slap_bv2ad( &type, &vrf.vrf_desc, text );
   1041 
   1042 		if( err != LDAP_SUCCESS ) {
   1043 			vrf.vrf_choice |= SLAPD_FILTER_UNDEFINED;
   1044 			err = slap_bv2undef_ad( &type, &vrf.vrf_desc, text,
   1045 				SLAP_AD_PROXIED);
   1046 
   1047 			if( err != LDAP_SUCCESS ) {
   1048 				/* unrecognized attribute description or other error */
   1049 				Debug( LDAP_DEBUG_ANY,
   1050 					"get_simple_vrFilter: conn %lu unknown "
   1051 					"attribute type=%s (%d)\n",
   1052 					op->o_connid, type.bv_val, err );
   1053 
   1054 				vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
   1055 				vrf.vrf_result = LDAP_COMPARE_FALSE;
   1056 				err = LDAP_SUCCESS;
   1057 				break;
   1058 			}
   1059 		}
   1060 		} break;
   1061 
   1062 	case LDAP_FILTER_APPROX:
   1063 		Debug( LDAP_DEBUG_FILTER, "APPROX\n" );
   1064 		err = get_ava( op, ber, (Filter *)&vrf, SLAP_MR_EQUALITY_APPROX, text );
   1065 		if ( err != LDAP_SUCCESS ) {
   1066 			break;
   1067 		}
   1068 		break;
   1069 
   1070 	case LDAP_FILTER_EXT:
   1071 		Debug( LDAP_DEBUG_FILTER, "EXTENSIBLE\n" );
   1072 
   1073 		err = get_mra( op, ber, (Filter *)&vrf, text );
   1074 		if ( err != LDAP_SUCCESS ) {
   1075 			break;
   1076 		}
   1077 
   1078 		assert( vrf.vrf_mra != NULL );
   1079 		break;
   1080 
   1081 	default:
   1082 		(void) ber_scanf( ber, "x" ); /* skip the element */
   1083 		Debug( LDAP_DEBUG_ANY, "get_simple_vrFilter: unknown filter type=%lu\n",
   1084 			vrf.vrf_choice );
   1085 		vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
   1086 		vrf.vrf_result = SLAPD_COMPARE_UNDEFINED;
   1087 		break;
   1088 	}
   1089 
   1090 	if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
   1091 		/* ignore error */
   1092 		vrf.vrf_choice = SLAPD_FILTER_COMPUTED;
   1093 		vrf.vrf_result = SLAPD_COMPARE_UNDEFINED;
   1094 		err = LDAP_SUCCESS;
   1095 	}
   1096 
   1097 	if ( err == LDAP_SUCCESS ) {
   1098 		*filt = op->o_tmpalloc( sizeof vrf, op->o_tmpmemctx );
   1099 		**filt = vrf;
   1100 	}
   1101 
   1102 	Debug( LDAP_DEBUG_FILTER, "end get_simple_vrFilter %d\n", err );
   1103 
   1104 	return err;
   1105 }
   1106 
   1107 int
   1108 get_vrFilter( Operation *op, BerElement *ber,
   1109 	ValuesReturnFilter **vrf,
   1110 	const char **text )
   1111 {
   1112 	/*
   1113 	 * A ValuesReturnFilter looks like this:
   1114 	 *
   1115 	 *	ValuesReturnFilter ::= SEQUENCE OF SimpleFilterItem
   1116 	 *      SimpleFilterItem ::= CHOICE {
   1117 	 *              equalityMatch   [3]     AttributeValueAssertion,
   1118 	 *              substrings      [4]     SubstringFilter,
   1119 	 *              greaterOrEqual  [5]     AttributeValueAssertion,
   1120 	 *              lessOrEqual     [6]     AttributeValueAssertion,
   1121 	 *              present         [7]     AttributeType,
   1122 	 *              approxMatch     [8]     AttributeValueAssertion,
   1123 	 *		extensibleMatch [9]	SimpleMatchingAssertion -- LDAPv3
   1124 	 *      }
   1125 	 *
   1126 	 *      SubstringFilter ::= SEQUENCE {
   1127 	 *              type               AttributeType,
   1128 	 *              SEQUENCE OF CHOICE {
   1129 	 *                      initial          [0] IA5String,
   1130 	 *                      any              [1] IA5String,
   1131 	 *                      final            [2] IA5String
   1132 	 *              }
   1133 	 *      }
   1134 	 *
   1135 	 *	SimpleMatchingAssertion ::= SEQUENCE {	-- LDAPv3
   1136 	 *		matchingRule    [1] MatchingRuleId OPTIONAL,
   1137 	 *		type            [2] AttributeDescription OPTIONAL,
   1138 	 *		matchValue      [3] AssertionValue }
   1139 	 */
   1140 
   1141 	ValuesReturnFilter **n;
   1142 	ber_tag_t	tag;
   1143 	ber_len_t	len;
   1144 	char		*last;
   1145 
   1146 	Debug( LDAP_DEBUG_FILTER, "begin get_vrFilter\n" );
   1147 
   1148 	tag = ber_peek_tag( ber, &len );
   1149 
   1150 	if( tag == LBER_ERROR ) {
   1151 		*text = "error decoding vrFilter";
   1152 		return SLAPD_DISCONNECT;
   1153 	}
   1154 
   1155 	if( tag != LBER_SEQUENCE ) {
   1156 		*text = "error decoding vrFilter, expect SEQUENCE tag";
   1157 		return SLAPD_DISCONNECT;
   1158 	}
   1159 
   1160 	n = vrf;
   1161 	for ( tag = ber_first_element( ber, &len, &last );
   1162 		tag != LBER_DEFAULT;
   1163 		tag = ber_next_element( ber, &len, last ) )
   1164 	{
   1165 		int err = get_simple_vrFilter( op, ber, n, text );
   1166 
   1167 		if ( err != LDAP_SUCCESS ) return( err );
   1168 
   1169 		n = &(*n)->vrf_next;
   1170 	}
   1171 	*n = NULL;
   1172 
   1173 	Debug( LDAP_DEBUG_FILTER, "end get_vrFilter\n" );
   1174 	return( LDAP_SUCCESS );
   1175 }
   1176 
   1177 void
   1178 vrFilter_free( Operation *op, ValuesReturnFilter *vrf )
   1179 {
   1180 	ValuesReturnFilter	*next;
   1181 
   1182 	for ( ; vrf != NULL; vrf = next ) {
   1183 		next = vrf->vrf_next;
   1184 
   1185 		switch ( vrf->vrf_choice & SLAPD_FILTER_MASK ) {
   1186 		case LDAP_FILTER_PRESENT:
   1187 			break;
   1188 
   1189 		case LDAP_FILTER_EQUALITY:
   1190 		case LDAP_FILTER_GE:
   1191 		case LDAP_FILTER_LE:
   1192 		case LDAP_FILTER_APPROX:
   1193 			ava_free( op, vrf->vrf_ava, 1 );
   1194 			break;
   1195 
   1196 		case LDAP_FILTER_SUBSTRINGS:
   1197 			if ( vrf->vrf_sub_initial.bv_val != NULL ) {
   1198 				op->o_tmpfree( vrf->vrf_sub_initial.bv_val, op->o_tmpmemctx );
   1199 			}
   1200 			ber_bvarray_free_x( vrf->vrf_sub_any, op->o_tmpmemctx );
   1201 			if ( vrf->vrf_sub_final.bv_val != NULL ) {
   1202 				op->o_tmpfree( vrf->vrf_sub_final.bv_val, op->o_tmpmemctx );
   1203 			}
   1204 			op->o_tmpfree( vrf->vrf_sub, op->o_tmpmemctx );
   1205 			break;
   1206 
   1207 		case LDAP_FILTER_EXT:
   1208 			mra_free( op, vrf->vrf_mra, 1 );
   1209 			break;
   1210 
   1211 		case SLAPD_FILTER_COMPUTED:
   1212 			break;
   1213 
   1214 		default:
   1215 			Debug( LDAP_DEBUG_ANY, "filter_free: unknown filter type=%lu\n",
   1216 				vrf->vrf_choice );
   1217 			break;
   1218 		}
   1219 
   1220 		op->o_tmpfree( vrf, op->o_tmpmemctx );
   1221 	}
   1222 }
   1223 
   1224 void
   1225 vrFilter2bv( Operation *op, ValuesReturnFilter *vrf, struct berval *fstr )
   1226 {
   1227 	ValuesReturnFilter	*p;
   1228 	struct berval tmp;
   1229 	ber_len_t len;
   1230 
   1231 	if ( vrf == NULL ) {
   1232 		ber_str2bv_x( "No filter!", STRLENOF("No filter!"),
   1233 			1, fstr, op->o_tmpmemctx );
   1234 		return;
   1235 	}
   1236 
   1237 	fstr->bv_len = STRLENOF("()");
   1238 	fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
   1239 
   1240 	snprintf( fstr->bv_val, fstr->bv_len + 1, "()");
   1241 
   1242 	for ( p = vrf; p != NULL; p = p->vrf_next ) {
   1243 		len = fstr->bv_len;
   1244 
   1245 		simple_vrFilter2bv( op, p, &tmp );
   1246 
   1247 		fstr->bv_len += tmp.bv_len;
   1248 		fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
   1249 			op->o_tmpmemctx );
   1250 
   1251 		snprintf( &fstr->bv_val[len-1], tmp.bv_len + 2,
   1252 			/*"("*/ "%s)", tmp.bv_val );
   1253 
   1254 		op->o_tmpfree( tmp.bv_val, op->o_tmpmemctx );
   1255 	}
   1256 }
   1257 
   1258 static void
   1259 simple_vrFilter2bv( Operation *op, ValuesReturnFilter *vrf, struct berval *fstr )
   1260 {
   1261 	struct berval tmp;
   1262 	ber_len_t len;
   1263 	int undef;
   1264 
   1265 	if ( vrf == NULL ) {
   1266 		ber_str2bv_x( "No filter!", STRLENOF("No filter!"), 1, fstr,
   1267 			op->o_tmpmemctx );
   1268 		return;
   1269 	}
   1270 	undef = vrf->vrf_choice & SLAPD_FILTER_UNDEFINED;
   1271 
   1272 	switch ( vrf->vrf_choice & SLAPD_FILTER_MASK ) {
   1273 	case LDAP_FILTER_EQUALITY:
   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_GE:
   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 
   1300 		ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
   1301 		break;
   1302 
   1303 	case LDAP_FILTER_LE:
   1304 		filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
   1305 
   1306 		fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
   1307 			tmp.bv_len + STRLENOF("(<=)");
   1308 		if ( undef ) fstr->bv_len++;
   1309 		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
   1310 
   1311 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s<=%s)",
   1312 			vrf->vrf_av_desc->ad_cname.bv_val,
   1313 			tmp.bv_val );
   1314 
   1315 		ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
   1316 		break;
   1317 
   1318 	case LDAP_FILTER_APPROX:
   1319 		filter_escape_value_x( &vrf->vrf_av_value, &tmp, op->o_tmpmemctx );
   1320 
   1321 		fstr->bv_len = vrf->vrf_av_desc->ad_cname.bv_len +
   1322 			tmp.bv_len + STRLENOF("(~=)");
   1323 		if ( undef ) fstr->bv_len++;
   1324 		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
   1325 
   1326 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s~=%s)",
   1327 			vrf->vrf_av_desc->ad_cname.bv_val,
   1328 			tmp.bv_val );
   1329 		ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
   1330 		break;
   1331 
   1332 	case LDAP_FILTER_SUBSTRINGS:
   1333 		fstr->bv_len = vrf->vrf_sub_desc->ad_cname.bv_len +
   1334 			STRLENOF("(=*)");
   1335 		if ( undef ) fstr->bv_len++;
   1336 		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 128, op->o_tmpmemctx );
   1337 
   1338 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
   1339 			vrf->vrf_sub_desc->ad_cname.bv_val );
   1340 
   1341 		if ( vrf->vrf_sub_initial.bv_val != NULL ) {
   1342 			len = fstr->bv_len;
   1343 
   1344 			filter_escape_value_x( &vrf->vrf_sub_initial, &tmp, op->o_tmpmemctx );
   1345 
   1346 			fstr->bv_len += tmp.bv_len;
   1347 			fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
   1348 				op->o_tmpmemctx );
   1349 
   1350 			snprintf( &fstr->bv_val[len-2], tmp.bv_len+3,
   1351 				/* "(attr=" */ "%s*)",
   1352 				tmp.bv_val );
   1353 
   1354 			ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
   1355 		}
   1356 
   1357 		if ( vrf->vrf_sub_any != NULL ) {
   1358 			int i;
   1359 			for ( i = 0; vrf->vrf_sub_any[i].bv_val != NULL; i++ ) {
   1360 				len = fstr->bv_len;
   1361 				filter_escape_value_x( &vrf->vrf_sub_any[i], &tmp,
   1362 					op->o_tmpmemctx );
   1363 
   1364 				fstr->bv_len += tmp.bv_len + 1;
   1365 				fstr->bv_val = op->o_tmprealloc( fstr->bv_val,
   1366 					fstr->bv_len + 1, op->o_tmpmemctx );
   1367 
   1368 				snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
   1369 					/* "(attr=[init]*[any*]" */ "%s*)",
   1370 					tmp.bv_val );
   1371 				ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
   1372 			}
   1373 		}
   1374 
   1375 		if ( vrf->vrf_sub_final.bv_val != NULL ) {
   1376 			len = fstr->bv_len;
   1377 
   1378 			filter_escape_value_x( &vrf->vrf_sub_final, &tmp, op->o_tmpmemctx );
   1379 
   1380 			fstr->bv_len += tmp.bv_len;
   1381 			fstr->bv_val = op->o_tmprealloc( fstr->bv_val, fstr->bv_len + 1,
   1382 				op->o_tmpmemctx );
   1383 
   1384 			snprintf( &fstr->bv_val[len-1], tmp.bv_len+3,
   1385 				/* "(attr=[init*][any*]" */ "%s)",
   1386 				tmp.bv_val );
   1387 
   1388 			ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
   1389 		}
   1390 
   1391 		break;
   1392 
   1393 	case LDAP_FILTER_PRESENT:
   1394 		fstr->bv_len = vrf->vrf_desc->ad_cname.bv_len +
   1395 			STRLENOF("(=*)");
   1396 		if ( undef ) fstr->bv_len++;
   1397 		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
   1398 
   1399 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s=*)",
   1400 			vrf->vrf_desc->ad_cname.bv_val );
   1401 		break;
   1402 
   1403 	case LDAP_FILTER_EXT: {
   1404 		struct berval ad;
   1405 		filter_escape_value_x( &vrf->vrf_mr_value, &tmp, op->o_tmpmemctx );
   1406 
   1407 		if ( vrf->vrf_mr_desc ) {
   1408 			ad = vrf->vrf_mr_desc->ad_cname;
   1409 		} else {
   1410 			ad.bv_len = 0;
   1411 			ad.bv_val = "";
   1412 		}
   1413 
   1414 		fstr->bv_len = ad.bv_len +
   1415 			( vrf->vrf_mr_dnattrs ? STRLENOF(":dn") : 0 ) +
   1416 			( vrf->vrf_mr_rule_text.bv_len
   1417 				? vrf->vrf_mr_rule_text.bv_len+1 : 0 ) +
   1418 			tmp.bv_len + STRLENOF("(:=)");
   1419 		if ( undef ) fstr->bv_len++;
   1420 		fstr->bv_val = op->o_tmpalloc( fstr->bv_len + 1, op->o_tmpmemctx );
   1421 
   1422 		snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
   1423 			ad.bv_val,
   1424 			vrf->vrf_mr_dnattrs ? ":dn" : "",
   1425 			vrf->vrf_mr_rule_text.bv_len ? ":" : "",
   1426 			vrf->vrf_mr_rule_text.bv_len ? vrf->vrf_mr_rule_text.bv_val : "",
   1427 			tmp.bv_val );
   1428 
   1429 		ber_memfree_x( tmp.bv_val, op->o_tmpmemctx );
   1430 		} break;
   1431 
   1432 	case SLAPD_FILTER_COMPUTED:
   1433 		ber_str2bv_x(
   1434 			vrf->vrf_result == LDAP_COMPARE_FALSE ? "(?=false)" :
   1435 			vrf->vrf_result == LDAP_COMPARE_TRUE ? "(?=true)" :
   1436 			vrf->vrf_result == SLAPD_COMPARE_UNDEFINED
   1437 				? "(?=undefined)" : "(?=error)",
   1438 			vrf->vrf_result == LDAP_COMPARE_FALSE ? STRLENOF("(?=false)") :
   1439 			vrf->vrf_result == LDAP_COMPARE_TRUE ? STRLENOF("(?=true)") :
   1440 			vrf->vrf_result == SLAPD_COMPARE_UNDEFINED
   1441 				? STRLENOF("(?=undefined)") : STRLENOF("(?=error)"),
   1442 			1, fstr, op->o_tmpmemctx );
   1443 		break;
   1444 
   1445 	default:
   1446 		ber_str2bv_x( "(?=unknown)", STRLENOF("(?=unknown)"),
   1447 			1, fstr, op->o_tmpmemctx );
   1448 		break;
   1449 	}
   1450 }
   1451