xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/component.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: component.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* component.c -- Component Filter Match Routines */
4 /* OpenLDAP: pkg/ldap/servers/slapd/component.c,v 1.31.2.6 2009/01/22 00:01:00 kurt Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2003-2009 The OpenLDAP Foundation.
8  * Portions Copyright 2004 by IBM Corporation.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in the file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 
20 #include "portable.h"
21 
22 #include <ac/string.h>
23 #include <ac/socket.h>
24 
25 #include "lutil.h"
26 #include <ldap.h>
27 #include "slap.h"
28 
29 #ifdef LDAP_COMP_MATCH
30 
31 #include "component.h"
32 
33 /*
34  * Following function pointers are initialized
35  * when a component module is loaded
36  */
37 alloc_nibble_func* nibble_mem_allocator = NULL;
38 free_nibble_func* nibble_mem_free = NULL;
39 convert_attr_to_comp_func* attr_converter = NULL;
40 convert_assert_to_comp_func* assert_converter = NULL ;
41 free_component_func* component_destructor = NULL ;
42 test_component_func* test_components = NULL;
43 test_membership_func* is_aliased_attribute = NULL;
44 component_encoder_func* component_encoder = NULL;
45 get_component_info_func* get_component_description = NULL;
46 #define OID_ALL_COMP_MATCH "1.2.36.79672281.1.13.6"
47 #define OID_COMP_FILTER_MATCH "1.2.36.79672281.1.13.2"
48 #define MAX_LDAP_STR_LEN 128
49 
50 static int
51 peek_componentId_type( ComponentAssertionValue* cav );
52 
53 static int
54 strip_cav_str( ComponentAssertionValue* cav, char* str);
55 
56 static int
57 peek_cav_str( ComponentAssertionValue* cav, char* str );
58 
59 static int
60 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
61 				ComponentFilter** filt, const char** text );
62 
63 static void
64 free_comp_filter( ComponentFilter* f );
65 
66 static int
67 test_comp_filter( Syntax *syn, ComponentSyntaxInfo *a, ComponentFilter *f );
68 
69 int
70 componentCertificateValidate(
71 	Syntax *syntax,
72 	struct berval *val )
73 {
74 	return LDAP_SUCCESS;
75 }
76 
77 int
78 componentFilterValidate(
79 	Syntax *syntax,
80 	struct berval *val )
81 {
82 	return LDAP_SUCCESS;
83 }
84 
85 int
86 allComponentsValidate(
87 	Syntax *syntax,
88 	struct berval *val )
89 {
90 	return LDAP_SUCCESS;
91 }
92 
93 int
94 componentFilterMatch (
95 	int *matchp,
96 	slap_mask_t flags,
97 	Syntax *syntax,
98 	MatchingRule *mr,
99 	struct berval *value,
100 	void *assertedValue )
101 {
102 	ComponentSyntaxInfo *csi_attr = (ComponentSyntaxInfo*)value;
103 	MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue;
104 	int rc;
105 
106 	if ( !mr || !ma->ma_cf ) return LDAP_INAPPROPRIATE_MATCHING;
107 
108 	/* Check if the component module is loaded */
109 	if ( !attr_converter || !nibble_mem_allocator ) {
110 		return LDAP_OTHER;
111 	}
112 
113 	rc = test_comp_filter( syntax, csi_attr, ma->ma_cf );
114 
115 	if ( rc == LDAP_COMPARE_TRUE ) {
116 		*matchp = 0;
117 		return LDAP_SUCCESS;
118 	}
119 	else if ( rc == LDAP_COMPARE_FALSE ) {
120 		*matchp = 1;
121 		return LDAP_SUCCESS;
122 	}
123 	else {
124 		return LDAP_INAPPROPRIATE_MATCHING;
125 	}
126 }
127 
128 int
129 directoryComponentsMatch(
130 	int *matchp,
131 	slap_mask_t flags,
132 	Syntax *syntax,
133 	MatchingRule *mr,
134 	struct berval *value,
135 	void *assertedValue )
136 {
137 	/* Only for registration */
138 	*matchp = 0;
139 	return LDAP_SUCCESS;
140 }
141 
142 int
143 allComponentsMatch(
144 	int *matchp,
145 	slap_mask_t flags,
146 	Syntax *syntax,
147 	MatchingRule *mr,
148 	struct berval *value,
149 	void *assertedValue )
150 {
151 	/* Only for registration */
152 	*matchp = 0;
153 	return LDAP_SUCCESS;
154 }
155 
156 static int
157 slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav )
158 {
159 	cav->cav_ptr = cav->cav_buf = bv->bv_val;
160 	cav->cav_end = bv->bv_val + bv->bv_len;
161 
162 	return LDAP_SUCCESS;
163 }
164 
165 ComponentReference*
166 dup_comp_ref ( Operation* op, ComponentReference* cr )
167 {
168 	ComponentReference* dup_cr;
169 	ComponentId* ci_curr;
170 	ComponentId** ci_temp;
171 
172 	dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
173 
174 	dup_cr->cr_len = cr->cr_len;
175 	dup_cr->cr_string = cr->cr_string;
176 
177 	ci_temp = &dup_cr->cr_list;
178 	ci_curr = cr->cr_list;
179 
180 	for ( ; ci_curr != NULL ;
181 		ci_curr = ci_curr->ci_next, ci_temp = &(*ci_temp)->ci_next )
182 	{
183 		*ci_temp = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
184 		if ( !*ci_temp ) return NULL;
185 		**ci_temp = *ci_curr;
186 	}
187 
188 	dup_cr->cr_curr = dup_cr->cr_list;
189 
190 	return dup_cr;
191 }
192 
193 static int
194 dup_comp_filter_list (
195 	Operation *op,
196 	struct berval *bv,
197 	ComponentFilter* in_f,
198 	ComponentFilter** out_f )
199 {
200 	ComponentFilter **new, *f;
201 	int		rc;
202 
203 	new = out_f;
204 	for ( f = in_f; f != NULL; f = f->cf_next ) {
205 		rc = dup_comp_filter( op, bv, f, new );
206 		if ( rc != LDAP_SUCCESS ) {
207 			return rc;
208 		}
209 		new = &(*new)->cf_next;
210 	}
211 	return LDAP_SUCCESS;
212 }
213 
214 int
215 get_len_of_next_assert_value ( struct berval* bv, char separator )
216 {
217 	ber_len_t i = 0;
218 	while (1) {
219 		if ( (bv->bv_val[ i ] == separator) || ( i >= bv->bv_len) )
220 			break;
221 		i++;
222 	}
223 	bv->bv_val += (i + 1);
224 	bv->bv_len -= (i + 1);
225 	return i;
226 }
227 
228 int
229 dup_comp_filter_item (
230 	Operation *op,
231 	struct berval* assert_bv,
232 	ComponentAssertion* in_ca,
233 	ComponentAssertion** out_ca )
234 {
235 	int len;
236 
237 	if ( !in_ca->ca_comp_ref ) return SLAPD_DISCONNECT;
238 
239 	*out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
240 	if ( !(*out_ca) ) return LDAP_NO_MEMORY;
241 
242 	(*out_ca)->ca_comp_data.cd_tree = NULL;
243 	(*out_ca)->ca_comp_data.cd_mem_op = NULL;
244 
245 	(*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref );
246 	(*out_ca)->ca_use_def = 0;
247 	(*out_ca)->ca_ma_rule = in_ca->ca_ma_rule;
248 
249 	(*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val;
250 	len = get_len_of_next_assert_value ( assert_bv, '$' );
251 	if ( len <= 0 ) return SLAPD_DISCONNECT;
252 	(*out_ca)->ca_ma_value.bv_len = len;
253 
254 	return LDAP_SUCCESS;
255 }
256 
257 int
258 dup_comp_filter (
259 	Operation* op,
260 	struct berval *bv,
261 	ComponentFilter *in_f,
262 	ComponentFilter **out_f )
263 {
264 	int	rc;
265 	ComponentFilter dup_f = {0};
266 
267 	if ( !in_f ) return LDAP_PROTOCOL_ERROR;
268 
269 	switch ( in_f->cf_choice ) {
270 	case LDAP_COMP_FILTER_AND:
271 		rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and);
272 		dup_f.cf_choice = LDAP_COMP_FILTER_AND;
273 		break;
274 	case LDAP_COMP_FILTER_OR:
275 		rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or);
276 		dup_f.cf_choice = LDAP_COMP_FILTER_OR;
277 		break;
278 	case LDAP_COMP_FILTER_NOT:
279 		rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not);
280 		dup_f.cf_choice = LDAP_COMP_FILTER_NOT;
281 		break;
282 	case LDAP_COMP_FILTER_ITEM:
283 		rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca );
284 		dup_f.cf_choice = LDAP_COMP_FILTER_ITEM;
285 		break;
286 	default:
287 		rc = LDAP_PROTOCOL_ERROR;
288 	}
289 
290 	if ( rc == LDAP_SUCCESS ) {
291 		*out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx );
292 		**out_f = dup_f;
293 	}
294 
295 	return( rc );
296 }
297 
298 int
299 get_aliased_filter_aa ( Operation* op, AttributeAssertion* a_assert, AttributeAliasing* aa, const char** text )
300 {
301 	struct berval assert_bv;
302 
303 	Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
304 
305 	if ( !aa->aa_cf  )
306 		return LDAP_PROTOCOL_ERROR;
307 
308 	assert_bv = a_assert->aa_value;
309 	/*
310 	 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
311 	 * the component assertion value in assert_bv
312 	 * Multiple values may be separated with '$'
313 	 */
314 	return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &a_assert->aa_cf );
315 }
316 
317 int
318 get_aliased_filter( Operation* op,
319 	MatchingRuleAssertion* ma, AttributeAliasing* aa,
320 	const char** text )
321 {
322 	struct berval assert_bv;
323 
324 	Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
325 
326 	if ( !aa->aa_cf  ) return LDAP_PROTOCOL_ERROR;
327 
328 	assert_bv = ma->ma_value;
329 	/* Attribute Description is replaced with aliased one */
330 	ma->ma_desc = aa->aa_aliased_ad;
331 	ma->ma_rule = aa->aa_mr;
332 	/*
333 	 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
334 	 * the component assertion value in assert_bv
335 	 * Multiple values may be separated with '$'
336 	 */
337 	return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf );
338 }
339 
340 int
341 get_comp_filter( Operation* op, struct berval* bv,
342 	ComponentFilter** filt, const char **text )
343 {
344 	ComponentAssertionValue cav;
345 	int rc;
346 
347 	Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
348 	if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) {
349 		return rc;
350 	}
351 	rc = parse_comp_filter( op, &cav, filt, text );
352 	bv->bv_val = cav.cav_ptr;
353 
354 	return rc;
355 }
356 
357 static void
358 eat_whsp( ComponentAssertionValue* cav )
359 {
360 	for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) {
361 		cav->cav_ptr++;
362 	}
363 }
364 
365 static int
366 cav_cur_len( ComponentAssertionValue* cav )
367 {
368 	return cav->cav_end - cav->cav_ptr;
369 }
370 
371 static ber_tag_t
372 comp_first_element( ComponentAssertionValue* cav )
373 {
374 	eat_whsp( cav );
375 	if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
376 		return LDAP_COMP_FILTER_ITEM;
377 
378 	} else if ( cav_cur_len( cav ) >= 7 &&
379 		strncmp( cav->cav_ptr, "and", 3 ) == 0 )
380 	{
381 		return LDAP_COMP_FILTER_AND;
382 
383 	} else if ( cav_cur_len( cav ) >= 6 &&
384 		strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
385 	{
386 		return LDAP_COMP_FILTER_OR;
387 
388 	} else if ( cav_cur_len( cav ) >= 7 &&
389 		strncmp( cav->cav_ptr, "not", 3 ) == 0 )
390 	{
391 		return LDAP_COMP_FILTER_NOT;
392 
393 	} else {
394 		return LDAP_COMP_FILTER_UNDEFINED;
395 	}
396 }
397 
398 static ber_tag_t
399 comp_next_element( ComponentAssertionValue* cav )
400 {
401 	eat_whsp( cav );
402 	if ( *(cav->cav_ptr) == ',' ) {
403 		/* move pointer to the next CA */
404 		cav->cav_ptr++;
405 		return comp_first_element( cav );
406 	}
407 	else return LDAP_COMP_FILTER_UNDEFINED;
408 }
409 
410 static int
411 get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
412 	ComponentFilter** f, const char** text )
413 {
414 	ComponentFilter **new;
415 	int		err;
416 	ber_tag_t	tag;
417 
418 	Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
419 	new = f;
420 	for ( tag = comp_first_element( cav );
421 		tag != LDAP_COMP_FILTER_UNDEFINED;
422 		tag = comp_next_element( cav ) )
423 	{
424 		err = parse_comp_filter( op, cav, new, text );
425 		if ( err != LDAP_SUCCESS ) return ( err );
426 		new = &(*new)->cf_next;
427 	}
428 	*new = NULL;
429 
430 	return( LDAP_SUCCESS );
431 }
432 
433 static int
434 get_componentId( Operation *op, ComponentAssertionValue* cav,
435 	ComponentId ** cid, const char** text )
436 {
437 	ber_tag_t type;
438 	ComponentId _cid;
439 	int len;
440 
441 	type = peek_componentId_type( cav );
442 
443 	Debug( LDAP_DEBUG_FILTER, "get_compId [%lu]\n",
444 		(unsigned long) type, 0, 0 );
445 	len = 0;
446 	_cid.ci_type = type;
447 	_cid.ci_next = NULL;
448 	switch ( type ) {
449 	case LDAP_COMPREF_IDENTIFIER :
450 		_cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
451 		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
452 			cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
453 		_cid.ci_val.ci_identifier.bv_len = len;
454 		cav->cav_ptr += len;
455 		break;
456 	case LDAP_COMPREF_FROM_BEGINNING :
457 		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
458 			cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
459 		_cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
460 		cav->cav_ptr += len;
461 		break;
462 	case LDAP_COMPREF_FROM_END :
463 		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
464 			cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
465 		_cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
466 		cav->cav_ptr += len;
467 		break;
468 	case LDAP_COMPREF_COUNT :
469 		_cid.ci_val.ci_count = 0;
470 		cav->cav_ptr++;
471 		break;
472 	case LDAP_COMPREF_CONTENT :
473 		_cid.ci_val.ci_content = 1;
474 		cav->cav_ptr += strlen("content");
475 		break;
476 	case LDAP_COMPREF_SELECT :
477 		if ( cav->cav_ptr[len] != '(' ) return LDAP_COMPREF_UNDEFINED;
478 		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
479 	  	      cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
480 			; len++ );
481 		_cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
482 		_cid.ci_val.ci_select_value.bv_len = len - 1 ;
483 		cav->cav_ptr += len + 1;
484 		break;
485 	case LDAP_COMPREF_ALL :
486 		_cid.ci_val.ci_all = '*';
487 		cav->cav_ptr++;
488 		break;
489 	default :
490 		return LDAP_COMPREF_UNDEFINED;
491 	}
492 
493 	if ( op ) {
494 		*cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
495 	} else {
496 		*cid = SLAP_MALLOC( sizeof( ComponentId ) );
497 	}
498 	if (*cid == NULL) {
499 		return LDAP_NO_MEMORY;
500 	}
501 	**cid = _cid;
502 	return LDAP_SUCCESS;
503 }
504 
505 static int
506 peek_componentId_type( ComponentAssertionValue* cav )
507 {
508 	eat_whsp( cav );
509 
510 	if ( cav->cav_ptr[0] == '-' ) {
511 		return LDAP_COMPREF_FROM_END;
512 
513 	} else if ( cav->cav_ptr[0] == '(' ) {
514 		return LDAP_COMPREF_SELECT;
515 
516 	} else if ( cav->cav_ptr[0] == '*' ) {
517 		return LDAP_COMPREF_ALL;
518 
519 	} else if ( cav->cav_ptr[0] == '0' ) {
520 		return LDAP_COMPREF_COUNT;
521 
522 	} else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' ) {
523 		return LDAP_COMPREF_FROM_BEGINNING;
524 
525 	} else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
526 		strncmp(cav->cav_ptr,"content",7) == 0 )
527 	{
528 		return LDAP_COMPREF_CONTENT;
529 	} else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
530 			(cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
531 	{
532 		return LDAP_COMPREF_IDENTIFIER;
533 	}
534 
535 	return LDAP_COMPREF_UNDEFINED;
536 }
537 
538 static ber_tag_t
539 comp_next_id( ComponentAssertionValue* cav )
540 {
541 	if ( *(cav->cav_ptr) == '.' ) {
542 		cav->cav_ptr++;
543 		return LDAP_COMPREF_DEFINED;
544 	}
545 
546 	return LDAP_COMPREF_UNDEFINED;
547 }
548 
549 
550 
551 static int
552 get_component_reference(
553 	Operation *op,
554 	ComponentAssertionValue* cav,
555 	ComponentReference** cr,
556 	const char** text )
557 {
558 	int rc, count = 0;
559 	ber_int_t type;
560 	ComponentReference* ca_comp_ref;
561 	ComponentId** cr_list;
562 	char* start, *end;
563 
564 	eat_whsp( cav );
565 
566 	start = cav->cav_ptr;
567 	if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) return rc;
568 	if ( op ) {
569 		ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ),
570 			op->o_tmpmemctx );
571 	} else {
572 		ca_comp_ref = SLAP_MALLOC( sizeof( ComponentReference ) );
573 	}
574 
575 	if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
576 
577 	cr_list = &ca_comp_ref->cr_list;
578 
579 	for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
580 		; type = comp_next_id( cav ), count++ )
581 	{
582 		rc = get_componentId( op, cav, cr_list, text );
583 		if ( rc == LDAP_SUCCESS ) {
584 			if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
585 			cr_list = &(*cr_list)->ci_next;
586 
587 		} else if ( rc == LDAP_COMPREF_UNDEFINED ) {
588 			if ( op ) {
589 				op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
590 			} else {
591 				free( ca_comp_ref );
592 			}
593 			return rc;
594 		}
595 	}
596 	ca_comp_ref->cr_len = count;
597 	end = cav->cav_ptr;
598 	if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
599 		if ( op ) {
600 			op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
601 		} else {
602 			free( ca_comp_ref );
603 		}
604 		return rc;
605 	}
606 
607 	*cr = ca_comp_ref;
608 	**cr = *ca_comp_ref;
609 
610 	(*cr)->cr_string.bv_val = start;
611 	(*cr)->cr_string.bv_len = end - start + 1;
612 
613 	return rc;
614 }
615 
616 int
617 insert_component_reference(
618 	ComponentReference *cr,
619 	ComponentReference** cr_list)
620 {
621 	if ( !cr ) return LDAP_PARAM_ERROR;
622 
623 	if ( !(*cr_list) ) {
624 		*cr_list = cr;
625 		cr->cr_next = NULL;
626 	} else {
627 		cr->cr_next = *cr_list;
628 		*cr_list = cr;
629 	}
630 	return LDAP_SUCCESS;
631 }
632 
633 /*
634  * If there is '.' in the name of a given attribute
635  * the first '.'- following characters are considered
636  * as a component reference of the attribute
637  * EX) userCertificate.toBeSigned.serialNumber
638  * attribute : userCertificate
639  * component reference : toBeSigned.serialNumber
640  */
641 int
642 is_component_reference( char* attr ) {
643 	int i;
644 	for ( i=0; attr[i] != '\0' ; i++ ) {
645 		if ( attr[i] == '.' ) return (1);
646 	}
647 	return (0);
648 }
649 
650 int
651 extract_component_reference(
652 	char* attr,
653 	ComponentReference** cr )
654 {
655 	int i, rc;
656 	char* cr_ptr;
657 	int cr_len;
658 	ComponentAssertionValue cav;
659 	char text[1][128];
660 
661 	for ( i=0; attr[i] != '\0' ; i++ ) {
662 		if ( attr[i] == '.' ) break;
663 	}
664 
665 	if (attr[i] != '.' ) return LDAP_PARAM_ERROR;
666 	attr[i] = '\0';
667 
668 	cr_ptr = attr + i + 1 ;
669 	cr_len = strlen ( cr_ptr );
670 	if ( cr_len <= 0 ) return LDAP_PARAM_ERROR;
671 
672 	/* enclosed between double quotes*/
673 	cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
674 	memcpy( cav.cav_buf+1, cr_ptr, cr_len );
675 	cav.cav_buf[0] = '"';
676 	cav.cav_buf[cr_len+1] = '"';
677 	cav.cav_end = cr_ptr + cr_len + 2;
678 
679 	rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
680 	if ( rc != LDAP_SUCCESS ) return rc;
681 	(*cr)->cr_string.bv_val = cav.cav_buf;
682 	(*cr)->cr_string.bv_len = cr_len + 2;
683 
684 	return LDAP_SUCCESS;
685 }
686 
687 static int
688 get_ca_use_default( Operation *op,
689 	ComponentAssertionValue* cav,
690 	int* ca_use_def, const char**  text )
691 {
692 	strip_cav_str( cav, "useDefaultValues" );
693 
694 	if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
695 		strip_cav_str( cav, "TRUE" );
696 		*ca_use_def = 1;
697 
698 	} else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
699 		strip_cav_str( cav, "FALSE" );
700 		*ca_use_def = 0;
701 
702 	} else {
703 		return LDAP_INVALID_SYNTAX;
704 	}
705 
706 	return LDAP_SUCCESS;
707 }
708 
709 static int
710 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
711 		MatchingRule** mr, const char**  text )
712 {
713 	int count = 0;
714 	struct berval rule_text = { 0L, NULL };
715 
716 	eat_whsp( cav );
717 
718 	for ( ; ; count++ ) {
719 		if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
720 			cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
721 			cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
722 		{
723 			break;
724 		}
725 	}
726 
727 	if ( count == 0 ) {
728 		*text = "component matching rule not recognized";
729 		return LDAP_INAPPROPRIATE_MATCHING;
730 	}
731 
732 	rule_text.bv_len = count;
733 	rule_text.bv_val = cav->cav_ptr;
734 	*mr = mr_bvfind( &rule_text );
735 	cav->cav_ptr += count;
736 	Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n",
737 		(*mr)->smr_mrule.mr_oid, 0, 0 );
738 	if ( *mr == NULL ) {
739 		*text = "component matching rule not recognized";
740 		return LDAP_INAPPROPRIATE_MATCHING;
741 	}
742 	return LDAP_SUCCESS;
743 }
744 
745 static int
746 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
747 {
748 	int count, sequent_dquote, unclosed_brace, succeed;
749 
750 	eat_whsp( cav );
751 	/*
752 	 * Four cases of GSER <Values>
753 	 * 1) "..." :
754 	 *	StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
755 	 * 2) '...'B or '...'H :
756 	 *	BitStringVal, OctetStringVal
757 	 * 3) {...} :
758 	 *	SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
759 	 * 4) Between two white spaces
760 	 *	INTEGER, BOOLEAN, NULL,ENUMERATE, etc
761 	 */
762 
763 	succeed = 0;
764 	if ( cav->cav_ptr[0] == '"' ) {
765 		for( count = 1, sequent_dquote = 0 ; ; count++ ) {
766 			/* In order to find escaped double quote */
767 			if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
768 			else sequent_dquote = 0;
769 
770 			if ( cav->cav_ptr[count] == '\0' ||
771 				(cav->cav_ptr+count) > cav->cav_end )
772 			{
773 				break;
774 			}
775 
776 			if ( ( cav->cav_ptr[count] == '"' &&
777 				cav->cav_ptr[count-1] != '"') ||
778 				( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) )
779 			{
780 				succeed = 1;
781 				break;
782 			}
783 		}
784 
785 		if ( !succeed || cav->cav_ptr[count] != '"' ) {
786 			return LDAP_FILTER_ERROR;
787 		}
788 
789 		bv->bv_val = cav->cav_ptr + 1;
790 		bv->bv_len = count - 1; /* exclude '"' */
791 
792 	} else if ( cav->cav_ptr[0] == '\'' ) {
793 		for( count = 1 ; ; count++ ) {
794 			if ( cav->cav_ptr[count] == '\0' ||
795 				(cav->cav_ptr+count) > cav->cav_end )
796 			{
797 				break;
798 			}
799 			if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B') ||
800 				(cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') )
801 			{
802 				succeed = 1;
803 				break;
804 			}
805 		}
806 
807 		if ( !succeed ||
808 			!(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
809 		{
810 			return LDAP_FILTER_ERROR;
811 		}
812 
813 		bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
814 		bv->bv_len = count - 2;/* exclude "'H" or "'B" */
815 
816 	} else if ( cav->cav_ptr[0] == '{' ) {
817 		for( count = 1, unclosed_brace = 1 ; ; count++ ) {
818 			if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
819 			if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
820 
821 			if ( cav->cav_ptr[count] == '\0' ||
822 				(cav->cav_ptr+count) > cav->cav_end )
823 			{
824 				break;
825 			}
826 			if ( unclosed_brace == 0 ) {
827 				succeed = 1;
828 				break;
829 			}
830 		}
831 
832 		if ( !succeed || cav->cav_ptr[count] != '}' ) return LDAP_FILTER_ERROR;
833 
834 		bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
835 		bv->bv_len = count - 1;/* exclude  "'B" */
836 
837 	} else {
838 		succeed = 1;
839 		/*Find  following white space where the value is ended*/
840 		for( count = 1 ; ; count++ ) {
841 			if ( cav->cav_ptr[count] == '\0' ||
842 				cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' ||
843 				cav->cav_ptr[count] == '{' ||
844 				(cav->cav_ptr+count) > cav->cav_end )
845 			{
846 				break;
847 			}
848 		}
849 		bv->bv_val = cav->cav_ptr;
850 		bv->bv_len = count;
851 	}
852 
853 	cav->cav_ptr += bv->bv_len;
854 	return LDAP_SUCCESS;
855 }
856 
857 static int
858 get_matching_value( Operation *op, ComponentAssertion* ca,
859 	ComponentAssertionValue* cav, struct berval* bv,
860 	const char**  text )
861 {
862 	if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
863 		if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
864 			return LDAP_FILTER_ERROR;
865 		}
866 
867 	} else {
868 		/* embeded componentFilterMatch Description */
869 		bv->bv_val = cav->cav_ptr;
870 		bv->bv_len = cav_cur_len( cav );
871 	}
872 
873 	return LDAP_SUCCESS;
874 }
875 
876 /* Don't move the position pointer, just peek given string */
877 static int
878 peek_cav_str( ComponentAssertionValue* cav, char* str )
879 {
880 	eat_whsp( cav );
881 	if ( cav_cur_len( cav ) >= strlen( str ) &&
882 		strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
883 	{
884 		return LDAP_SUCCESS;
885 	}
886 
887 	return LDAP_INVALID_SYNTAX;
888 }
889 
890 static int
891 strip_cav_str( ComponentAssertionValue* cav, char* str)
892 {
893 	eat_whsp( cav );
894 	if ( cav_cur_len( cav ) >= strlen( str ) &&
895 		strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
896 	{
897 		cav->cav_ptr += strlen( str );
898 		return LDAP_SUCCESS;
899 	}
900 
901 	return LDAP_INVALID_SYNTAX;
902 }
903 
904 /*
905  * TAG : "item", "and", "or", "not"
906  */
907 static ber_tag_t
908 strip_cav_tag( ComponentAssertionValue* cav )
909 {
910 
911 	eat_whsp( cav );
912 	if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
913 		strip_cav_str( cav , "item:" );
914 		return LDAP_COMP_FILTER_ITEM;
915 
916 	} else if ( cav_cur_len( cav ) >= 7 &&
917 		strncmp( cav->cav_ptr, "and", 3 ) == 0 )
918 	{
919 		strip_cav_str( cav , "and:" );
920 		return LDAP_COMP_FILTER_AND;
921 
922 	} else if ( cav_cur_len( cav ) >= 6 &&
923 		strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
924 	{
925 		strip_cav_str( cav , "or:" );
926 		return LDAP_COMP_FILTER_OR;
927 
928 	} else if ( cav_cur_len( cav ) >= 7 &&
929 		strncmp( cav->cav_ptr, "not", 3 ) == 0 )
930 	{
931 		strip_cav_str( cav , "not:" );
932 		return LDAP_COMP_FILTER_NOT;
933 	}
934 
935 	return LBER_ERROR;
936 }
937 
938 /*
939  * when encoding, "item" is denotation of ComponentAssertion
940  * ComponentAssertion :: SEQUENCE {
941  *	component		ComponentReference (SIZE(1..MAX)) OPTIONAL,
942  *	useDefaultValues	BOOLEAN DEFAULT TRUE,
943  *	rule			MATCHING-RULE.&id,
944  *	value			MATCHING-RULE.&AssertionType }
945  */
946 static int
947 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
948 		const char** text )
949 {
950 	int rc;
951 	ComponentAssertion* _ca;
952 	struct berval value;
953 	MatchingRule* mr;
954 
955 	Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
956 	if ( op )
957 		_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
958 	else
959 		_ca = SLAP_MALLOC( sizeof( ComponentAssertion ) );
960 
961 	if ( !_ca ) return LDAP_NO_MEMORY;
962 
963 	_ca->ca_comp_data.cd_tree = NULL;
964 	_ca->ca_comp_data.cd_mem_op = NULL;
965 
966 	rc = peek_cav_str( cav, "component" );
967 	if ( rc == LDAP_SUCCESS ) {
968 		strip_cav_str( cav, "component" );
969 		rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
970 		if ( rc != LDAP_SUCCESS ) {
971 			if ( op )
972 				op->o_tmpfree( _ca, op->o_tmpmemctx );
973 			else
974 				free( _ca );
975 			return LDAP_INVALID_SYNTAX;
976 		}
977 		if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
978 			return rc;
979 	} else {
980 		_ca->ca_comp_ref = NULL;
981 	}
982 
983 	rc = peek_cav_str( cav, "useDefaultValues");
984 	if ( rc == LDAP_SUCCESS ) {
985 		rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
986 		if ( rc != LDAP_SUCCESS ) {
987 			if ( op )
988 				op->o_tmpfree( _ca, op->o_tmpmemctx );
989 			else
990 				free( _ca );
991 			return LDAP_INVALID_SYNTAX;
992 		}
993 		if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
994 			return rc;
995 	}
996 	else _ca->ca_use_def = 1;
997 
998 	if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
999 		get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
1000 		if ( op )
1001 			op->o_tmpfree( _ca, op->o_tmpmemctx );
1002 		else
1003 			free( _ca );
1004 		return LDAP_INAPPROPRIATE_MATCHING;
1005 	}
1006 
1007 	if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
1008 		return rc;
1009 	if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
1010 		get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
1011 		if ( op )
1012 			op->o_tmpfree( _ca, op->o_tmpmemctx );
1013 		else
1014 			free( _ca );
1015 		return LDAP_INVALID_SYNTAX;
1016 	}
1017 
1018 	/*
1019 	 * Normalize the value of this component assertion when the matching
1020 	 * rule is one of existing matching rules
1021 	 */
1022 	mr = _ca->ca_ma_rule;
1023 	if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
1024 
1025 		value.bv_val[value.bv_len] = '\0';
1026 		rc = mr->smr_normalize (
1027 			SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
1028 			NULL, mr,
1029 			&value, &_ca->ca_ma_value, op->o_tmpmemctx );
1030 		if ( rc != LDAP_SUCCESS )
1031 			return rc;
1032 	}
1033 	else
1034 		_ca->ca_ma_value = value;
1035 	/*
1036 	 * Validate the value of this component assertion
1037 	 */
1038 	if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
1039 		return LDAP_INVALID_SYNTAX;
1040 	}
1041 
1042 
1043 	/* componentFilterMatch contains componentFilterMatch in it */
1044 	if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
1045 		struct berval bv;
1046 		bv.bv_val = cav->cav_ptr;
1047 		bv.bv_len = cav_cur_len( cav );
1048 		rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
1049 		if ( rc != LDAP_SUCCESS ) {
1050 			if ( op )
1051 				op->o_tmpfree( _ca, op->o_tmpmemctx );
1052 			else
1053 				free( _ca );
1054 			return rc;
1055 		}
1056 		cav->cav_ptr = bv.bv_val;
1057 		assert( cav->cav_end >= bv.bv_val );
1058 	}
1059 
1060 	*ca = _ca;
1061 	return LDAP_SUCCESS;
1062 }
1063 
1064 static int
1065 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
1066 				ComponentFilter** filt, const char** text )
1067 {
1068 	/*
1069 	 * A component filter looks like this coming in:
1070 	 *	Filter ::= CHOICE {
1071 	 *		item	[0]	ComponentAssertion,
1072 	 *		and	[1]	SEQUENCE OF ComponentFilter,
1073 	 *		or	[2]	SEQUENCE OF ComponentFilter,
1074 	 *		not	[3]	ComponentFilter,
1075 	 *	}
1076 	 */
1077 
1078 	ber_tag_t	tag;
1079 	int		err;
1080 	ComponentFilter	f;
1081 	/* TAG : item, and, or, not in RFC 4515 */
1082 	tag = strip_cav_tag( cav );
1083 
1084 	if ( tag == LBER_ERROR ) {
1085 		*text = "error decoding comp filter";
1086 		return LDAP_PROTOCOL_ERROR;
1087 	}
1088 
1089 	if ( tag != LDAP_COMP_FILTER_NOT )
1090 		strip_cav_str( cav, "{");
1091 
1092 	err = LDAP_SUCCESS;
1093 
1094 	f.cf_next = NULL;
1095 	f.cf_choice = tag;
1096 
1097 	switch ( f.cf_choice ) {
1098 	case LDAP_COMP_FILTER_AND:
1099 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
1100 		err = get_comp_filter_list( op, cav, &f.cf_and, text );
1101 		if ( err != LDAP_SUCCESS ) {
1102 			break;
1103 		}
1104 		if ( f.cf_and == NULL ) {
1105 			f.cf_choice = SLAPD_FILTER_COMPUTED;
1106 			f.cf_result = LDAP_COMPARE_TRUE;
1107 		}
1108 		break;
1109 
1110 	case LDAP_COMP_FILTER_OR:
1111 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
1112 		err = get_comp_filter_list( op, cav, &f.cf_or, text );
1113 		if ( err != LDAP_SUCCESS ) {
1114 			break;
1115 		}
1116 		if ( f.cf_or == NULL ) {
1117 			f.cf_choice = SLAPD_FILTER_COMPUTED;
1118 			f.cf_result = LDAP_COMPARE_FALSE;
1119 		}
1120 		/* no assert - list could be empty */
1121 		break;
1122 
1123 	case LDAP_COMP_FILTER_NOT:
1124 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
1125 		err = parse_comp_filter( op, cav, &f.cf_not, text );
1126 		if ( err != LDAP_SUCCESS ) {
1127 			break;
1128 		}
1129 
1130 		assert( f.cf_not != NULL );
1131 		if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
1132 			int fresult = f.cf_not->cf_result;
1133 			f.cf_choice = SLAPD_FILTER_COMPUTED;
1134 			op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
1135 			f.cf_not = NULL;
1136 
1137 			switch ( fresult ) {
1138 			case LDAP_COMPARE_TRUE:
1139 				f.cf_result = LDAP_COMPARE_FALSE;
1140 				break;
1141 			case LDAP_COMPARE_FALSE:
1142 				f.cf_result = LDAP_COMPARE_TRUE;
1143 				break;
1144 			default: ;
1145 				/* (!Undefined) is Undefined */
1146 			}
1147 		}
1148 		break;
1149 
1150 	case LDAP_COMP_FILTER_ITEM:
1151 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1152 		err = get_item( op, cav, &f.cf_ca, text );
1153 		if ( err != LDAP_SUCCESS ) {
1154 			break;
1155 		}
1156 
1157 		assert( f.cf_ca != NULL );
1158 		break;
1159 
1160 	default:
1161 		f.cf_choice = SLAPD_FILTER_COMPUTED;
1162 		f.cf_result = SLAPD_COMPARE_UNDEFINED;
1163 		break;
1164 	}
1165 
1166 	if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1167 		*text = "Component Filter Syntax Error";
1168 		return err;
1169 	}
1170 
1171 	if ( tag != LDAP_COMP_FILTER_NOT )
1172 		strip_cav_str( cav, "}");
1173 
1174 	if ( err == LDAP_SUCCESS ) {
1175 		if ( op ) {
1176 			*filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1177 		} else {
1178 			*filt = SLAP_MALLOC( sizeof(f) );
1179 		}
1180 		if ( *filt == NULL ) {
1181 			return LDAP_NO_MEMORY;
1182 		}
1183 		**filt = f;
1184 	}
1185 
1186 	return( err );
1187 }
1188 
1189 static int
1190 test_comp_filter_and(
1191 	Syntax *syn,
1192 	ComponentSyntaxInfo *a,
1193 	ComponentFilter *flist )
1194 {
1195 	ComponentFilter *f;
1196 	int rtn = LDAP_COMPARE_TRUE;
1197 
1198 	for ( f = flist ; f != NULL; f = f->cf_next ) {
1199 		int rc = test_comp_filter( syn, a, f );
1200 		if ( rc == LDAP_COMPARE_FALSE ) {
1201 			rtn = rc;
1202 			break;
1203 		}
1204 
1205 		if ( rc != LDAP_COMPARE_TRUE ) {
1206 			rtn = rc;
1207 		}
1208 	}
1209 
1210 	return rtn;
1211 }
1212 
1213 static int
1214 test_comp_filter_or(
1215 	Syntax *syn,
1216 	ComponentSyntaxInfo *a,
1217 	ComponentFilter *flist )
1218 {
1219 	ComponentFilter *f;
1220 	int rtn = LDAP_COMPARE_TRUE;
1221 
1222 	for ( f = flist ; f != NULL; f = f->cf_next ) {
1223 		int rc = test_comp_filter( syn, a, f );
1224 		if ( rc == LDAP_COMPARE_TRUE ) {
1225 			rtn = rc;
1226 			break;
1227 		}
1228 
1229 		if ( rc != LDAP_COMPARE_FALSE ) {
1230 			rtn = rc;
1231 		}
1232 	}
1233 
1234 	return rtn;
1235 }
1236 
1237 int
1238 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1239 	struct berval* bv_assert )
1240 {
1241 	int rc;
1242 	int match;
1243 
1244 	assert( mr != NULL );
1245 	assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1246 
1247 	if( !mr->smr_match ) return LDAP_INAPPROPRIATE_MATCHING;
1248 
1249 	rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1250 		mr, bv_attr, bv_assert );
1251 
1252 	if ( rc != LDAP_SUCCESS ) return rc;
1253 
1254 	return match ? LDAP_COMPARE_FALSE : LDAP_COMPARE_TRUE;
1255 }
1256 
1257 /*
1258  * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1259  */
1260 static int
1261 test_comp_filter_item(
1262 	Syntax *syn,
1263 	ComponentSyntaxInfo *csi_attr,
1264 	ComponentAssertion *ca )
1265 {
1266 	int rc;
1267 	void *attr_nm, *assert_nm;
1268 
1269 	if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1270 		OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1271 		/* componentFilterMatch inside of componentFilterMatch */
1272 		rc = test_comp_filter( syn, csi_attr, ca->ca_cf );
1273 		return rc;
1274 	}
1275 
1276 	/* Memory for storing will-be-extracted attribute values */
1277 	attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1278 	if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
1279 
1280 	/* Memory for storing component assertion values */
1281 	if( !ca->ca_comp_data.cd_mem_op ) {
1282 		assert_nm = nibble_mem_allocator ( 256, 64 );
1283 		if ( !assert_nm ) {
1284 			nibble_mem_free ( attr_nm );
1285 			return LDAP_PROTOCOL_ERROR;
1286 		}
1287 		ca->ca_comp_data.cd_mem_op = assert_nm;
1288 
1289 	} else {
1290 		assert_nm = ca->ca_comp_data.cd_mem_op;
1291 	}
1292 
1293 	/* component reference initialization */
1294 	if ( ca->ca_comp_ref ) {
1295 		ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1296 	}
1297 	rc = test_components( attr_nm, assert_nm, csi_attr, ca );
1298 
1299 	/* free memory used for storing extracted attribute value */
1300 	nibble_mem_free ( attr_nm );
1301 	return rc;
1302 }
1303 
1304 static int
1305 test_comp_filter(
1306     Syntax *syn,
1307     ComponentSyntaxInfo *a,
1308     ComponentFilter *f )
1309 {
1310 	int	rc;
1311 
1312 	if ( !f ) return LDAP_PROTOCOL_ERROR;
1313 
1314 	Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
1315 	switch ( f->cf_choice ) {
1316 	case SLAPD_FILTER_COMPUTED:
1317 		rc = f->cf_result;
1318 		break;
1319 	case LDAP_COMP_FILTER_AND:
1320 		rc = test_comp_filter_and( syn, a, f->cf_and );
1321 		break;
1322 	case LDAP_COMP_FILTER_OR:
1323 		rc = test_comp_filter_or( syn, a, f->cf_or );
1324 		break;
1325 	case LDAP_COMP_FILTER_NOT:
1326 		rc = test_comp_filter( syn, a, f->cf_not );
1327 
1328 		switch ( rc ) {
1329 		case LDAP_COMPARE_TRUE:
1330 			rc = LDAP_COMPARE_FALSE;
1331 			break;
1332 		case LDAP_COMPARE_FALSE:
1333 			rc = LDAP_COMPARE_TRUE;
1334 			break;
1335 		}
1336 		break;
1337 	case LDAP_COMP_FILTER_ITEM:
1338 		rc = test_comp_filter_item( syn, a, f->cf_ca );
1339 		break;
1340 	default:
1341 		rc = LDAP_PROTOCOL_ERROR;
1342 	}
1343 
1344 	return( rc );
1345 }
1346 
1347 static void
1348 free_comp_filter_list( ComponentFilter* f )
1349 {
1350 	ComponentFilter* tmp;
1351 	for ( tmp = f; tmp; tmp = tmp->cf_next ) {
1352 		free_comp_filter( tmp );
1353 	}
1354 }
1355 
1356 static void
1357 free_comp_filter( ComponentFilter* f )
1358 {
1359 	if ( !f ) {
1360 		Debug( LDAP_DEBUG_FILTER,
1361 			"free_comp_filter: Invalid filter so failed to release memory\n",
1362 			0, 0, 0 );
1363 		return;
1364 	}
1365 	switch ( f->cf_choice ) {
1366 	case LDAP_COMP_FILTER_AND:
1367 	case LDAP_COMP_FILTER_OR:
1368 		free_comp_filter_list( f->cf_any );
1369 		break;
1370 	case LDAP_COMP_FILTER_NOT:
1371 		free_comp_filter( f->cf_any );
1372 		break;
1373 	case LDAP_COMP_FILTER_ITEM:
1374 		if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op ) {
1375 			nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1376 		}
1377 		break;
1378 	default:
1379 		break;
1380 	}
1381 }
1382 
1383 void
1384 component_free( ComponentFilter *f ) {
1385 	free_comp_filter( f );
1386 }
1387 
1388 void
1389 free_ComponentData( Attribute *a ) {
1390 	if ( a->a_comp_data->cd_mem_op )
1391 		component_destructor( a->a_comp_data->cd_mem_op );
1392 	free ( a->a_comp_data );
1393 	a->a_comp_data = NULL;
1394 }
1395 #endif
1396