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