1 /* component.c -- Component Filter Match Routines */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2021 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
componentCertificateValidate(Syntax * syntax,struct berval * val)68 componentCertificateValidate(
69 	Syntax *syntax,
70 	struct berval *val )
71 {
72 	return LDAP_SUCCESS;
73 }
74 
75 int
componentFilterValidate(Syntax * syntax,struct berval * val)76 componentFilterValidate(
77 	Syntax *syntax,
78 	struct berval *val )
79 {
80 	return LDAP_SUCCESS;
81 }
82 
83 int
allComponentsValidate(Syntax * syntax,struct berval * val)84 allComponentsValidate(
85 	Syntax *syntax,
86 	struct berval *val )
87 {
88 	return LDAP_SUCCESS;
89 }
90 
91 int
componentFilterMatch(int * matchp,slap_mask_t flags,Syntax * syntax,MatchingRule * mr,struct berval * value,void * assertedValue)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
directoryComponentsMatch(int * matchp,slap_mask_t flags,Syntax * syntax,MatchingRule * mr,struct berval * value,void * assertedValue)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
allComponentsMatch(int * matchp,slap_mask_t flags,Syntax * syntax,MatchingRule * mr,struct berval * value,void * assertedValue)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
slapd_ber2cav(struct berval * bv,ComponentAssertionValue * cav)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*
dup_comp_ref(Operation * op,ComponentReference * cr)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
dup_comp_filter_list(Operation * op,struct berval * bv,ComponentFilter * in_f,ComponentFilter ** out_f)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
get_len_of_next_assert_value(struct berval * bv,char separator)213 get_len_of_next_assert_value ( struct berval* bv, char separator )
214 {
215 	ber_len_t 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
dup_comp_filter_item(Operation * op,struct berval * assert_bv,ComponentAssertion * in_ca,ComponentAssertion ** out_ca)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
dup_comp_filter(Operation * op,struct berval * bv,ComponentFilter * in_f,ComponentFilter ** out_f)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
get_aliased_filter_aa(Operation * op,AttributeAssertion * a_assert,AttributeAliasing * aa,const char ** text)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" );
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
get_aliased_filter(Operation * op,MatchingRuleAssertion * ma,AttributeAliasing * aa,const char ** text)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" );
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
get_comp_filter(Operation * op,struct berval * bv,ComponentFilter ** filt,const char ** text)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" );
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
eat_whsp(ComponentAssertionValue * cav)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
cav_cur_len(ComponentAssertionValue * cav)364 cav_cur_len( ComponentAssertionValue* cav )
365 {
366 	return cav->cav_end - cav->cav_ptr;
367 }
368 
369 static ber_tag_t
comp_first_element(ComponentAssertionValue * cav)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
comp_next_element(ComponentAssertionValue * cav)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
get_comp_filter_list(Operation * op,ComponentAssertionValue * cav,ComponentFilter ** f,const char ** text)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" );
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
get_componentId(Operation * op,ComponentAssertionValue * cav,ComponentId ** cid,const char ** text)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 );
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 = SLAP_MALLOC( sizeof( ComponentId ) );
495 	}
496 	if (*cid == NULL) {
497 		return LDAP_NO_MEMORY;
498 	}
499 	**cid = _cid;
500 	return LDAP_SUCCESS;
501 }
502 
503 static int
peek_componentId_type(ComponentAssertionValue * cav)504 peek_componentId_type( ComponentAssertionValue* cav )
505 {
506 	eat_whsp( cav );
507 
508 	if ( cav->cav_ptr[0] == '-' ) {
509 		return LDAP_COMPREF_FROM_END;
510 
511 	} else if ( cav->cav_ptr[0] == '(' ) {
512 		return LDAP_COMPREF_SELECT;
513 
514 	} else if ( cav->cav_ptr[0] == '*' ) {
515 		return LDAP_COMPREF_ALL;
516 
517 	} else if ( cav->cav_ptr[0] == '0' ) {
518 		return LDAP_COMPREF_COUNT;
519 
520 	} else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' ) {
521 		return LDAP_COMPREF_FROM_BEGINNING;
522 
523 	} else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
524 		strncmp(cav->cav_ptr,"content",7) == 0 )
525 	{
526 		return LDAP_COMPREF_CONTENT;
527 	} else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
528 			(cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
529 	{
530 		return LDAP_COMPREF_IDENTIFIER;
531 	}
532 
533 	return LDAP_COMPREF_UNDEFINED;
534 }
535 
536 static ber_tag_t
comp_next_id(ComponentAssertionValue * cav)537 comp_next_id( ComponentAssertionValue* cav )
538 {
539 	if ( *(cav->cav_ptr) == '.' ) {
540 		cav->cav_ptr++;
541 		return LDAP_COMPREF_DEFINED;
542 	}
543 
544 	return LDAP_COMPREF_UNDEFINED;
545 }
546 
547 
548 
549 static int
get_component_reference(Operation * op,ComponentAssertionValue * cav,ComponentReference ** cr,const char ** text)550 get_component_reference(
551 	Operation *op,
552 	ComponentAssertionValue* cav,
553 	ComponentReference** cr,
554 	const char** text )
555 {
556 	int rc, count = 0;
557 	ber_int_t type;
558 	ComponentReference* ca_comp_ref;
559 	ComponentId** cr_list;
560 	char* start, *end;
561 
562 	eat_whsp( cav );
563 
564 	start = cav->cav_ptr;
565 	if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) return rc;
566 	if ( op ) {
567 		ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ),
568 			op->o_tmpmemctx );
569 	} else {
570 		ca_comp_ref = SLAP_MALLOC( sizeof( ComponentReference ) );
571 	}
572 
573 	if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
574 
575 	cr_list = &ca_comp_ref->cr_list;
576 
577 	for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
578 		; type = comp_next_id( cav ), count++ )
579 	{
580 		rc = get_componentId( op, cav, cr_list, text );
581 		if ( rc == LDAP_SUCCESS ) {
582 			if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
583 			cr_list = &(*cr_list)->ci_next;
584 
585 		} else if ( rc == LDAP_COMPREF_UNDEFINED ) {
586 			if ( op ) {
587 				op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
588 			} else {
589 				free( ca_comp_ref );
590 			}
591 			return rc;
592 		}
593 	}
594 	ca_comp_ref->cr_len = count;
595 	end = cav->cav_ptr;
596 	if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
597 		if ( op ) {
598 			op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
599 		} else {
600 			free( ca_comp_ref );
601 		}
602 		return rc;
603 	}
604 
605 	*cr = ca_comp_ref;
606 	**cr = *ca_comp_ref;
607 
608 	(*cr)->cr_string.bv_val = start;
609 	(*cr)->cr_string.bv_len = end - start + 1;
610 
611 	return rc;
612 }
613 
614 int
insert_component_reference(ComponentReference * cr,ComponentReference ** cr_list)615 insert_component_reference(
616 	ComponentReference *cr,
617 	ComponentReference** cr_list)
618 {
619 	if ( !cr ) return LDAP_PARAM_ERROR;
620 
621 	if ( !(*cr_list) ) {
622 		*cr_list = cr;
623 		cr->cr_next = NULL;
624 	} else {
625 		cr->cr_next = *cr_list;
626 		*cr_list = cr;
627 	}
628 	return LDAP_SUCCESS;
629 }
630 
631 /*
632  * If there is '.' in the name of a given attribute
633  * the first '.'- following characters are considered
634  * as a component reference of the attribute
635  * EX) userCertificate.toBeSigned.serialNumber
636  * attribute : userCertificate
637  * component reference : toBeSigned.serialNumber
638  */
639 int
is_component_reference(char * attr)640 is_component_reference( char* attr ) {
641 	int i;
642 	for ( i=0; attr[i] != '\0' ; i++ ) {
643 		if ( attr[i] == '.' ) return (1);
644 	}
645 	return (0);
646 }
647 
648 int
extract_component_reference(char * attr,ComponentReference ** cr)649 extract_component_reference(
650 	char* attr,
651 	ComponentReference** cr )
652 {
653 	int i, rc;
654 	char* cr_ptr;
655 	int cr_len;
656 	ComponentAssertionValue cav;
657 	char text[1][128];
658 
659 	for ( i=0; attr[i] != '\0' ; i++ ) {
660 		if ( attr[i] == '.' ) break;
661 	}
662 
663 	if (attr[i] != '.' ) return LDAP_PARAM_ERROR;
664 	attr[i] = '\0';
665 
666 	cr_ptr = attr + i + 1 ;
667 	cr_len = strlen ( cr_ptr );
668 	if ( cr_len <= 0 ) return LDAP_PARAM_ERROR;
669 
670 	/* enclosed between double quotes*/
671 	cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
672 	memcpy( cav.cav_buf+1, cr_ptr, cr_len );
673 	cav.cav_buf[0] = '"';
674 	cav.cav_buf[cr_len+1] = '"';
675 	cav.cav_end = cr_ptr + cr_len + 2;
676 
677 	rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
678 	if ( rc != LDAP_SUCCESS ) return rc;
679 	(*cr)->cr_string.bv_val = cav.cav_buf;
680 	(*cr)->cr_string.bv_len = cr_len + 2;
681 
682 	return LDAP_SUCCESS;
683 }
684 
685 static int
get_ca_use_default(Operation * op,ComponentAssertionValue * cav,int * ca_use_def,const char ** text)686 get_ca_use_default( Operation *op,
687 	ComponentAssertionValue* cav,
688 	int* ca_use_def, const char**  text )
689 {
690 	strip_cav_str( cav, "useDefaultValues" );
691 
692 	if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
693 		strip_cav_str( cav, "TRUE" );
694 		*ca_use_def = 1;
695 
696 	} else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
697 		strip_cav_str( cav, "FALSE" );
698 		*ca_use_def = 0;
699 
700 	} else {
701 		return LDAP_INVALID_SYNTAX;
702 	}
703 
704 	return LDAP_SUCCESS;
705 }
706 
707 static int
get_matching_rule(Operation * op,ComponentAssertionValue * cav,MatchingRule ** mr,const char ** text)708 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
709 		MatchingRule** mr, const char**  text )
710 {
711 	int count = 0;
712 	struct berval rule_text = { 0L, NULL };
713 
714 	eat_whsp( cav );
715 
716 	for ( ; ; count++ ) {
717 		if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
718 			cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
719 			cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
720 		{
721 			break;
722 		}
723 	}
724 
725 	if ( count == 0 ) {
726 		*text = "component matching rule not recognized";
727 		return LDAP_INAPPROPRIATE_MATCHING;
728 	}
729 
730 	rule_text.bv_len = count;
731 	rule_text.bv_val = cav->cav_ptr;
732 	*mr = mr_bvfind( &rule_text );
733 	cav->cav_ptr += count;
734 	Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n",
735 		(*mr)->smr_mrule.mr_oid );
736 	if ( *mr == NULL ) {
737 		*text = "component matching rule not recognized";
738 		return LDAP_INAPPROPRIATE_MATCHING;
739 	}
740 	return LDAP_SUCCESS;
741 }
742 
743 static int
get_GSER_value(ComponentAssertionValue * cav,struct berval * bv)744 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
745 {
746 	int count, sequent_dquote, unclosed_brace, succeed;
747 
748 	eat_whsp( cav );
749 	/*
750 	 * Four cases of GSER <Values>
751 	 * 1) "..." :
752 	 *	StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
753 	 * 2) '...'B or '...'H :
754 	 *	BitStringVal, OctetStringVal
755 	 * 3) {...} :
756 	 *	SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
757 	 * 4) Between two white spaces
758 	 *	INTEGER, BOOLEAN, NULL,ENUMERATE, etc
759 	 */
760 
761 	succeed = 0;
762 	if ( cav->cav_ptr[0] == '"' ) {
763 		for( count = 1, sequent_dquote = 0 ; ; count++ ) {
764 			/* In order to find escaped double quote */
765 			if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
766 			else sequent_dquote = 0;
767 
768 			if ( cav->cav_ptr[count] == '\0' ||
769 				(cav->cav_ptr+count) > cav->cav_end )
770 			{
771 				break;
772 			}
773 
774 			if ( ( cav->cav_ptr[count] == '"' &&
775 				cav->cav_ptr[count-1] != '"') ||
776 				( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) )
777 			{
778 				succeed = 1;
779 				break;
780 			}
781 		}
782 
783 		if ( !succeed || cav->cav_ptr[count] != '"' ) {
784 			return LDAP_FILTER_ERROR;
785 		}
786 
787 		bv->bv_val = cav->cav_ptr + 1;
788 		bv->bv_len = count - 1; /* exclude '"' */
789 
790 	} else if ( cav->cav_ptr[0] == '\'' ) {
791 		for( count = 1 ; ; count++ ) {
792 			if ( cav->cav_ptr[count] == '\0' ||
793 				(cav->cav_ptr+count) > cav->cav_end )
794 			{
795 				break;
796 			}
797 			if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B') ||
798 				(cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') )
799 			{
800 				succeed = 1;
801 				break;
802 			}
803 		}
804 
805 		if ( !succeed ||
806 			!(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
807 		{
808 			return LDAP_FILTER_ERROR;
809 		}
810 
811 		bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
812 		bv->bv_len = count - 2;/* exclude "'H" or "'B" */
813 
814 	} else if ( cav->cav_ptr[0] == '{' ) {
815 		for( count = 1, unclosed_brace = 1 ; ; count++ ) {
816 			if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
817 			if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
818 
819 			if ( cav->cav_ptr[count] == '\0' ||
820 				(cav->cav_ptr+count) > cav->cav_end )
821 			{
822 				break;
823 			}
824 			if ( unclosed_brace == 0 ) {
825 				succeed = 1;
826 				break;
827 			}
828 		}
829 
830 		if ( !succeed || cav->cav_ptr[count] != '}' ) return LDAP_FILTER_ERROR;
831 
832 		bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
833 		bv->bv_len = count - 1;/* exclude  "'B" */
834 
835 	} else {
836 		succeed = 1;
837 		/*Find  following white space where the value is ended*/
838 		for( count = 1 ; ; count++ ) {
839 			if ( cav->cav_ptr[count] == '\0' ||
840 				cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' ||
841 				cav->cav_ptr[count] == '{' ||
842 				(cav->cav_ptr+count) > cav->cav_end )
843 			{
844 				break;
845 			}
846 		}
847 		bv->bv_val = cav->cav_ptr;
848 		bv->bv_len = count;
849 	}
850 
851 	cav->cav_ptr += bv->bv_len;
852 	return LDAP_SUCCESS;
853 }
854 
855 static int
get_matching_value(Operation * op,ComponentAssertion * ca,ComponentAssertionValue * cav,struct berval * bv,const char ** text)856 get_matching_value( Operation *op, ComponentAssertion* ca,
857 	ComponentAssertionValue* cav, struct berval* bv,
858 	const char**  text )
859 {
860 	if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
861 		if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
862 			return LDAP_FILTER_ERROR;
863 		}
864 
865 	} else {
866 		/* embedded componentFilterMatch Description */
867 		bv->bv_val = cav->cav_ptr;
868 		bv->bv_len = cav_cur_len( cav );
869 	}
870 
871 	return LDAP_SUCCESS;
872 }
873 
874 /* Don't move the position pointer, just peek given string */
875 static int
peek_cav_str(ComponentAssertionValue * cav,char * str)876 peek_cav_str( ComponentAssertionValue* cav, char* str )
877 {
878 	eat_whsp( cav );
879 	if ( cav_cur_len( cav ) >= strlen( str ) &&
880 		strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
881 	{
882 		return LDAP_SUCCESS;
883 	}
884 
885 	return LDAP_INVALID_SYNTAX;
886 }
887 
888 static int
strip_cav_str(ComponentAssertionValue * cav,char * str)889 strip_cav_str( ComponentAssertionValue* cav, char* str)
890 {
891 	eat_whsp( cav );
892 	if ( cav_cur_len( cav ) >= strlen( str ) &&
893 		strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
894 	{
895 		cav->cav_ptr += strlen( str );
896 		return LDAP_SUCCESS;
897 	}
898 
899 	return LDAP_INVALID_SYNTAX;
900 }
901 
902 /*
903  * TAG : "item", "and", "or", "not"
904  */
905 static ber_tag_t
strip_cav_tag(ComponentAssertionValue * cav)906 strip_cav_tag( ComponentAssertionValue* cav )
907 {
908 	int rc;
909 
910 	eat_whsp( cav );
911 	if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
912 		if ( strip_cav_str( cav , "item:" ))
913 			goto fail;
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 		if ( strip_cav_str( cav , "and:" ))
920 			goto fail;
921 		return LDAP_COMP_FILTER_AND;
922 
923 	} else if ( cav_cur_len( cav ) >= 6 &&
924 		strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
925 	{
926 		if ( strip_cav_str( cav , "or:" ))
927 			goto fail;
928 		return LDAP_COMP_FILTER_OR;
929 
930 	} else if ( cav_cur_len( cav ) >= 7 &&
931 		strncmp( cav->cav_ptr, "not", 3 ) == 0 )
932 	{
933 		if ( strip_cav_str( cav , "not:" ))
934 			goto fail;
935 		return LDAP_COMP_FILTER_NOT;
936 	}
937 
938 fail:
939 	return LBER_ERROR;
940 }
941 
942 /*
943  * when encoding, "item" is denotation of ComponentAssertion
944  * ComponentAssertion :: SEQUENCE {
945  *	component		ComponentReference (SIZE(1..MAX)) OPTIONAL,
946  *	useDefaultValues	BOOLEAN DEFAULT TRUE,
947  *	rule			MATCHING-RULE.&id,
948  *	value			MATCHING-RULE.&AssertionType }
949  */
950 static int
get_item(Operation * op,ComponentAssertionValue * cav,ComponentAssertion ** ca,const char ** text)951 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
952 		const char** text )
953 {
954 	int rc, freeval = 0;
955 	ComponentAssertion* _ca;
956 	struct berval value;
957 	MatchingRule* mr;
958 
959 	Debug( LDAP_DEBUG_FILTER, "get_item \n" );
960 	if ( op )
961 		_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
962 	else
963 		_ca = SLAP_MALLOC( sizeof( ComponentAssertion ) );
964 
965 	if ( !_ca ) return LDAP_NO_MEMORY;
966 
967 	_ca->ca_comp_data.cd_tree = NULL;
968 	_ca->ca_comp_data.cd_mem_op = NULL;
969 	BER_BVZERO( &_ca->ca_ma_value );
970 
971 	rc = peek_cav_str( cav, "component" );
972 	if ( rc == LDAP_SUCCESS ) {
973 		strip_cav_str( cav, "component" );
974 		rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
975 		if ( rc != LDAP_SUCCESS ) {
976 			rc = LDAP_INVALID_SYNTAX;
977 fail:
978 			if ( freeval )
979 				op->o_tmpfree( _ca->ca_ma_value.bv_val, op->o_tmpmemctx );
980 			if ( op )
981 				op->o_tmpfree( _ca, op->o_tmpmemctx );
982 			else
983 				free( _ca );
984 			return rc;
985 		}
986 		if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
987 			goto fail;
988 	} else {
989 		_ca->ca_comp_ref = NULL;
990 	}
991 
992 	rc = peek_cav_str( cav, "useDefaultValues");
993 	if ( rc == LDAP_SUCCESS ) {
994 		rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
995 		if ( rc != LDAP_SUCCESS ) {
996 			rc = LDAP_INVALID_SYNTAX;
997 			goto fail;
998 		}
999 		if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
1000 			goto fail;
1001 	}
1002 	else _ca->ca_use_def = 1;
1003 
1004 	if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
1005 		get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
1006 		rc = LDAP_INAPPROPRIATE_MATCHING;
1007 		goto fail;
1008 	}
1009 
1010 	if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
1011 		goto fail;
1012 	if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
1013 		get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
1014 		rc = LDAP_INVALID_SYNTAX;
1015 		goto fail;
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 			goto fail;
1032 		freeval = 1;
1033 	}
1034 	else
1035 		_ca->ca_ma_value = value;
1036 	/*
1037 	 * Validate the value of this component assertion
1038 	 */
1039 	if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
1040 		rc = LDAP_INVALID_SYNTAX;
1041 		goto fail;
1042 	}
1043 
1044 
1045 	/* componentFilterMatch contains componentFilterMatch in it */
1046 	if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
1047 		struct berval bv;
1048 		bv.bv_val = cav->cav_ptr;
1049 		bv.bv_len = cav_cur_len( cav );
1050 		rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
1051 		if ( rc != LDAP_SUCCESS )
1052 			goto fail;
1053 		cav->cav_ptr = bv.bv_val;
1054 		assert( cav->cav_end >= bv.bv_val );
1055 	}
1056 
1057 	*ca = _ca;
1058 	return LDAP_SUCCESS;
1059 }
1060 
1061 static int
parse_comp_filter(Operation * op,ComponentAssertionValue * cav,ComponentFilter ** filt,const char ** text)1062 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
1063 				ComponentFilter** filt, const char** text )
1064 {
1065 	/*
1066 	 * A component filter looks like this coming in:
1067 	 *	Filter ::= CHOICE {
1068 	 *		item	[0]	ComponentAssertion,
1069 	 *		and	[1]	SEQUENCE OF ComponentFilter,
1070 	 *		or	[2]	SEQUENCE OF ComponentFilter,
1071 	 *		not	[3]	ComponentFilter,
1072 	 *	}
1073 	 */
1074 
1075 	ber_tag_t	tag;
1076 	int		err = LDAP_SUCCESS;
1077 	ComponentFilter	f;
1078 	/* TAG : item, and, or, not in RFC 4515 */
1079 	tag = strip_cav_tag( cav );
1080 
1081 	if ( tag == LBER_ERROR ) {
1082 		*text = "error decoding comp filter";
1083 		return LDAP_PROTOCOL_ERROR;
1084 	}
1085 
1086 	if ( tag != LDAP_COMP_FILTER_NOT ) {
1087 		err = strip_cav_str( cav, "{");
1088 		if ( err )
1089 			goto invalid;
1090 	}
1091 
1092 	f.cf_next = NULL;
1093 	f.cf_choice = tag;
1094 
1095 	switch ( f.cf_choice ) {
1096 	case LDAP_COMP_FILTER_AND:
1097 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n" );
1098 		err = get_comp_filter_list( op, cav, &f.cf_and, text );
1099 		if ( err != LDAP_SUCCESS ) {
1100 			break;
1101 		}
1102 		if ( f.cf_and == NULL ) {
1103 			f.cf_choice = SLAPD_FILTER_COMPUTED;
1104 			f.cf_result = LDAP_COMPARE_TRUE;
1105 		}
1106 		break;
1107 
1108 	case LDAP_COMP_FILTER_OR:
1109 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n" );
1110 		err = get_comp_filter_list( op, cav, &f.cf_or, text );
1111 		if ( err != LDAP_SUCCESS ) {
1112 			break;
1113 		}
1114 		if ( f.cf_or == NULL ) {
1115 			f.cf_choice = SLAPD_FILTER_COMPUTED;
1116 			f.cf_result = LDAP_COMPARE_FALSE;
1117 		}
1118 		/* no assert - list could be empty */
1119 		break;
1120 
1121 	case LDAP_COMP_FILTER_NOT:
1122 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n" );
1123 		err = parse_comp_filter( op, cav, &f.cf_not, text );
1124 		if ( err != LDAP_SUCCESS ) {
1125 			break;
1126 		}
1127 
1128 		assert( f.cf_not != NULL );
1129 		if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
1130 			int fresult = f.cf_not->cf_result;
1131 			f.cf_choice = SLAPD_FILTER_COMPUTED;
1132 			op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
1133 			f.cf_not = NULL;
1134 
1135 			switch ( fresult ) {
1136 			case LDAP_COMPARE_TRUE:
1137 				f.cf_result = LDAP_COMPARE_FALSE;
1138 				break;
1139 			case LDAP_COMPARE_FALSE:
1140 				f.cf_result = LDAP_COMPARE_TRUE;
1141 				break;
1142 			default: ;
1143 				/* (!Undefined) is Undefined */
1144 			}
1145 		}
1146 		break;
1147 
1148 	case LDAP_COMP_FILTER_ITEM:
1149 	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n" );
1150 		err = get_item( op, cav, &f.cf_ca, text );
1151 		if ( err != LDAP_SUCCESS ) {
1152 			break;
1153 		}
1154 
1155 		assert( f.cf_ca != NULL );
1156 		break;
1157 
1158 	default:
1159 		f.cf_choice = SLAPD_FILTER_COMPUTED;
1160 		f.cf_result = SLAPD_COMPARE_UNDEFINED;
1161 		break;
1162 	}
1163 
1164 invalid:
1165 	if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1166 		*text = "Component Filter Syntax Error";
1167 		return err;
1168 	}
1169 
1170 	if ( tag != LDAP_COMP_FILTER_NOT )
1171 		err = strip_cav_str( cav, "}");
1172 
1173 	if ( err == LDAP_SUCCESS ) {
1174 		if ( op ) {
1175 			*filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1176 		} else {
1177 			*filt = SLAP_MALLOC( sizeof(f) );
1178 		}
1179 		if ( *filt == NULL ) {
1180 			return LDAP_NO_MEMORY;
1181 		}
1182 		**filt = f;
1183 	}
1184 
1185 	return( err );
1186 }
1187 
1188 static int
test_comp_filter_and(Syntax * syn,ComponentSyntaxInfo * a,ComponentFilter * flist)1189 test_comp_filter_and(
1190 	Syntax *syn,
1191 	ComponentSyntaxInfo *a,
1192 	ComponentFilter *flist )
1193 {
1194 	ComponentFilter *f;
1195 	int rtn = LDAP_COMPARE_TRUE;
1196 
1197 	for ( f = flist ; f != NULL; f = f->cf_next ) {
1198 		int rc = test_comp_filter( syn, a, f );
1199 		if ( rc == LDAP_COMPARE_FALSE ) {
1200 			rtn = rc;
1201 			break;
1202 		}
1203 
1204 		if ( rc != LDAP_COMPARE_TRUE ) {
1205 			rtn = rc;
1206 		}
1207 	}
1208 
1209 	return rtn;
1210 }
1211 
1212 static int
test_comp_filter_or(Syntax * syn,ComponentSyntaxInfo * a,ComponentFilter * flist)1213 test_comp_filter_or(
1214 	Syntax *syn,
1215 	ComponentSyntaxInfo *a,
1216 	ComponentFilter *flist )
1217 {
1218 	ComponentFilter *f;
1219 	int rtn = LDAP_COMPARE_TRUE;
1220 
1221 	for ( f = flist ; f != NULL; f = f->cf_next ) {
1222 		int rc = test_comp_filter( syn, a, f );
1223 		if ( rc == LDAP_COMPARE_TRUE ) {
1224 			rtn = rc;
1225 			break;
1226 		}
1227 
1228 		if ( rc != LDAP_COMPARE_FALSE ) {
1229 			rtn = rc;
1230 		}
1231 	}
1232 
1233 	return rtn;
1234 }
1235 
1236 int
csi_value_match(MatchingRule * mr,struct berval * bv_attr,struct berval * bv_assert)1237 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1238 	struct berval* bv_assert )
1239 {
1240 	int rc;
1241 	int match;
1242 
1243 	assert( mr != NULL );
1244 	assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1245 
1246 	if( !mr->smr_match ) return LDAP_INAPPROPRIATE_MATCHING;
1247 
1248 	rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1249 		mr, bv_attr, bv_assert );
1250 
1251 	if ( rc != LDAP_SUCCESS ) return rc;
1252 
1253 	return match ? LDAP_COMPARE_FALSE : LDAP_COMPARE_TRUE;
1254 }
1255 
1256 /*
1257  * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1258  */
1259 static int
test_comp_filter_item(Syntax * syn,ComponentSyntaxInfo * csi_attr,ComponentAssertion * ca)1260 test_comp_filter_item(
1261 	Syntax *syn,
1262 	ComponentSyntaxInfo *csi_attr,
1263 	ComponentAssertion *ca )
1264 {
1265 	int rc;
1266 	void *attr_nm, *assert_nm;
1267 
1268 	if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1269 		OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1270 		/* componentFilterMatch inside of componentFilterMatch */
1271 		rc = test_comp_filter( syn, csi_attr, ca->ca_cf );
1272 		return rc;
1273 	}
1274 
1275 	/* Memory for storing will-be-extracted attribute values */
1276 	attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1277 	if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
1278 
1279 	/* Memory for storing component assertion values */
1280 	if( !ca->ca_comp_data.cd_mem_op ) {
1281 		assert_nm = nibble_mem_allocator ( 256, 64 );
1282 		if ( !assert_nm ) {
1283 			nibble_mem_free ( attr_nm );
1284 			return LDAP_PROTOCOL_ERROR;
1285 		}
1286 		ca->ca_comp_data.cd_mem_op = assert_nm;
1287 
1288 	} else {
1289 		assert_nm = ca->ca_comp_data.cd_mem_op;
1290 	}
1291 
1292 	/* component reference initialization */
1293 	if ( ca->ca_comp_ref ) {
1294 		ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1295 	}
1296 	rc = test_components( attr_nm, assert_nm, csi_attr, ca );
1297 
1298 	/* free memory used for storing extracted attribute value */
1299 	nibble_mem_free ( attr_nm );
1300 	return rc;
1301 }
1302 
1303 static int
test_comp_filter(Syntax * syn,ComponentSyntaxInfo * a,ComponentFilter * f)1304 test_comp_filter(
1305     Syntax *syn,
1306     ComponentSyntaxInfo *a,
1307     ComponentFilter *f )
1308 {
1309 	int	rc;
1310 
1311 	if ( !f ) return LDAP_PROTOCOL_ERROR;
1312 
1313 	Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n" );
1314 	switch ( f->cf_choice ) {
1315 	case SLAPD_FILTER_COMPUTED:
1316 		rc = f->cf_result;
1317 		break;
1318 	case LDAP_COMP_FILTER_AND:
1319 		rc = test_comp_filter_and( syn, a, f->cf_and );
1320 		break;
1321 	case LDAP_COMP_FILTER_OR:
1322 		rc = test_comp_filter_or( syn, a, f->cf_or );
1323 		break;
1324 	case LDAP_COMP_FILTER_NOT:
1325 		rc = test_comp_filter( syn, a, f->cf_not );
1326 
1327 		switch ( rc ) {
1328 		case LDAP_COMPARE_TRUE:
1329 			rc = LDAP_COMPARE_FALSE;
1330 			break;
1331 		case LDAP_COMPARE_FALSE:
1332 			rc = LDAP_COMPARE_TRUE;
1333 			break;
1334 		}
1335 		break;
1336 	case LDAP_COMP_FILTER_ITEM:
1337 		rc = test_comp_filter_item( syn, a, f->cf_ca );
1338 		break;
1339 	default:
1340 		rc = LDAP_PROTOCOL_ERROR;
1341 	}
1342 
1343 	return( rc );
1344 }
1345 
1346 static void
free_comp_filter_list(ComponentFilter * f)1347 free_comp_filter_list( ComponentFilter* f )
1348 {
1349 	ComponentFilter* tmp;
1350 	for ( tmp = f; tmp; tmp = tmp->cf_next ) {
1351 		free_comp_filter( tmp );
1352 	}
1353 }
1354 
1355 static void
free_comp_filter(ComponentFilter * f)1356 free_comp_filter( ComponentFilter* f )
1357 {
1358 	if ( !f ) {
1359 		Debug( LDAP_DEBUG_FILTER,
1360 			"free_comp_filter: Invalid filter so failed to release memory\n" );
1361 		return;
1362 	}
1363 	switch ( f->cf_choice ) {
1364 	case LDAP_COMP_FILTER_AND:
1365 	case LDAP_COMP_FILTER_OR:
1366 		free_comp_filter_list( f->cf_any );
1367 		break;
1368 	case LDAP_COMP_FILTER_NOT:
1369 		free_comp_filter( f->cf_any );
1370 		break;
1371 	case LDAP_COMP_FILTER_ITEM:
1372 		if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op ) {
1373 			nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1374 		}
1375 		break;
1376 	default:
1377 		break;
1378 	}
1379 }
1380 
1381 void
component_free(ComponentFilter * f)1382 component_free( ComponentFilter *f ) {
1383 	free_comp_filter( f );
1384 }
1385 
1386 void
free_ComponentData(Attribute * a)1387 free_ComponentData( Attribute *a ) {
1388 	if ( a->a_comp_data->cd_mem_op )
1389 		component_destructor( a->a_comp_data->cd_mem_op );
1390 	free ( a->a_comp_data );
1391 	a->a_comp_data = NULL;
1392 }
1393 #endif
1394