component.c 31.4 KB
Newer Older
1
2
3
4
/* component.c -- Component Filter Match Routines */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
5
 * Copyright 2003-2020 The OpenLDAP Foundation.
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 * Portions Copyright 2004 by IBM Corporation.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */

#include "portable.h"

#include <ac/string.h>
#include <ac/socket.h>

#include "lutil.h"
#include <ldap.h>
#include "slap.h"

#ifdef LDAP_COMP_MATCH

Sang Seok Lim's avatar
Sang Seok Lim committed
29
#include "component.h"
30

Sang Seok Lim's avatar
Sang Seok Lim committed
31
/*
32
 * Following function pointers are initialized
Sang Seok Lim's avatar
Sang Seok Lim committed
33
34
 * when a component module is loaded
 */
35
36
alloc_nibble_func* nibble_mem_allocator = NULL;
free_nibble_func* nibble_mem_free = NULL;
37
convert_attr_to_comp_func* attr_converter = NULL;
Sang Seok Lim's avatar
Sang Seok Lim committed
38
39
convert_assert_to_comp_func* assert_converter = NULL ;
free_component_func* component_destructor = NULL ;
40
41
test_component_func* test_components = NULL;
test_membership_func* is_aliased_attribute = NULL;
42
43
component_encoder_func* component_encoder = NULL;
get_component_info_func* get_component_description = NULL;
Sang Seok Lim's avatar
Sang Seok Lim committed
44
45
46
#define OID_ALL_COMP_MATCH "1.2.36.79672281.1.13.6"
#define OID_COMP_FILTER_MATCH "1.2.36.79672281.1.13.2"
#define MAX_LDAP_STR_LEN 128
47

48
49
50
51
52
53
54
55
56
57
58
59
60
static int
peek_componentId_type( ComponentAssertionValue* cav );

static int
strip_cav_str( ComponentAssertionValue* cav, char* str);

static int
peek_cav_str( ComponentAssertionValue* cav, char* str );

static int
parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
				ComponentFilter** filt, const char** text );

61
62
63
static void
free_comp_filter( ComponentFilter* f );

64
static int
65
test_comp_filter( Syntax *syn, ComponentSyntaxInfo *a, ComponentFilter *f );
66

67
int
Sang Seok Lim's avatar
Sang Seok Lim committed
68
69
70
71
72
73
74
componentCertificateValidate(
	Syntax *syntax,
	struct berval *val )
{
	return LDAP_SUCCESS;
}

75
int
76
77
78
79
80
81
82
componentFilterValidate(
	Syntax *syntax,
	struct berval *val )
{
	return LDAP_SUCCESS;
}

Sang Seok Lim's avatar
Sang Seok Lim committed
83
84
85
86
87
88
89
90
int
allComponentsValidate(
	Syntax *syntax,
	struct berval *val )
{
	return LDAP_SUCCESS;
}

91
92
93
94
95
96
97
98
99
int
componentFilterMatch ( 
	int *matchp, 
	slap_mask_t flags, 
	Syntax *syntax, 
	MatchingRule *mr,
	struct berval *value, 
	void *assertedValue )
{
100
	ComponentSyntaxInfo *csi_attr = (ComponentSyntaxInfo*)value;
Sang Seok Lim's avatar
Sang Seok Lim committed
101
	MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue;
102
	int rc;
Sang Seok Lim's avatar
Sang Seok Lim committed
103

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
104
	if ( !mr || !ma->ma_cf ) return LDAP_INAPPROPRIATE_MATCHING;
105

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
106
107
108
109
	/* Check if the component module is loaded */
	if ( !attr_converter || !nibble_mem_allocator ) {
		return LDAP_OTHER;
	}
Sang Seok Lim's avatar
Bug fix    
Sang Seok Lim committed
110

111
	rc = test_comp_filter( syntax, csi_attr, ma->ma_cf );
Sang Seok Lim's avatar
Bug fix    
Sang Seok Lim committed
112

113
114
115
116
117
118
119
120
121
122
	if ( rc == LDAP_COMPARE_TRUE ) {
		*matchp = 0;
		return LDAP_SUCCESS;
	}
	else if ( rc == LDAP_COMPARE_FALSE ) {
		*matchp = 1;
		return LDAP_SUCCESS;
	}
	else {
		return LDAP_INAPPROPRIATE_MATCHING;
Sang Seok Lim's avatar
Sang Seok Lim committed
123
124
	}
}
Sang Seok Lim's avatar
Bug fix    
Sang Seok Lim committed
125

126
127
128
129
130
131
132
133
134
int
directoryComponentsMatch( 
	int *matchp, 
	slap_mask_t flags, 
	Syntax *syntax, 
	MatchingRule *mr,
	struct berval *value, 
	void *assertedValue )
{
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
135
	/* Only for registration */
136
137
138
	*matchp = 0;
	return LDAP_SUCCESS;
}
Sang Seok Lim's avatar
Sang Seok Lim committed
139
140
141
142
143
144
145
146
147
148

int
allComponentsMatch( 
	int *matchp, 
	slap_mask_t flags, 
	Syntax *syntax, 
	MatchingRule *mr,
	struct berval *value, 
	void *assertedValue )
{
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
149
	/* Only for registration */
150
151
152
153
154
	*matchp = 0;
	return LDAP_SUCCESS;
}

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

Sang Seok Lim's avatar
Sang Seok Lim committed
160
	return LDAP_SUCCESS;
161
162
}

163
ComponentReference*
164
165
166
167
168
169
170
171
172
173
174
175
176
177
dup_comp_ref ( Operation* op, ComponentReference* cr )
{
	ComponentReference* dup_cr;
	ComponentId* ci_curr;
	ComponentId** ci_temp;

	dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );

	dup_cr->cr_len = cr->cr_len;
	dup_cr->cr_string = cr->cr_string;

	ci_temp = &dup_cr->cr_list;
	ci_curr = cr->cr_list;

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
178
179
180
	for ( ; ci_curr != NULL ;
		ci_curr = ci_curr->ci_next, ci_temp = &(*ci_temp)->ci_next )
	{
181
		*ci_temp = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
Howard Chu's avatar
Cleanup    
Howard Chu committed
182
		if ( !*ci_temp ) return NULL;
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
		**ci_temp = *ci_curr;
	}

	dup_cr->cr_curr = dup_cr->cr_list;

	return dup_cr;
}

static int
dup_comp_filter_list (
	Operation *op,
	struct berval *bv,
	ComponentFilter* in_f,
	ComponentFilter** out_f )
{
	ComponentFilter **new, *f;
	int		rc;

	new = out_f;
	for ( f = in_f; f != NULL; f = f->cf_next ) {
		rc = dup_comp_filter( op, bv, f, new );
		if ( rc != LDAP_SUCCESS ) {
			return rc;
		}
		new = &(*new)->cf_next;
	}
	return LDAP_SUCCESS;
}

int
get_len_of_next_assert_value ( struct berval* bv, char separator )
{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
215
	ber_len_t i = 0;
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
	while (1) {
		if ( (bv->bv_val[ i ] == separator) || ( i >= bv->bv_len) )
			break;
		i++;
	}
	bv->bv_val += (i + 1);
	bv->bv_len -= (i + 1);
	return i;
}

int
dup_comp_filter_item (
	Operation *op,
	struct berval* assert_bv,
	ComponentAssertion* in_ca,
	ComponentAssertion** out_ca )
{
	int len;

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
235
	if ( !in_ca->ca_comp_ref ) return SLAPD_DISCONNECT;
236
237

	*out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
238
	if ( !(*out_ca) ) return LDAP_NO_MEMORY;
239
240
241
242
243
244
245
246
247
248

	(*out_ca)->ca_comp_data.cd_tree = NULL;
	(*out_ca)->ca_comp_data.cd_mem_op = NULL;

	(*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref );
	(*out_ca)->ca_use_def = 0;
	(*out_ca)->ca_ma_rule = in_ca->ca_ma_rule;

	(*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val;
	len = get_len_of_next_assert_value ( assert_bv, '$' );
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
249
	if ( len <= 0 ) return SLAPD_DISCONNECT;
250
251
252
253
254
255
256
257
258
259
260
261
262
	(*out_ca)->ca_ma_value.bv_len = len;
	
	return LDAP_SUCCESS;
}

int
dup_comp_filter (
	Operation* op,
	struct berval *bv,
	ComponentFilter *in_f,
	ComponentFilter **out_f )
{
	int	rc;
Howard Chu's avatar
Howard Chu committed
263
	ComponentFilter dup_f = {0};
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295

	if ( !in_f ) return LDAP_PROTOCOL_ERROR;

	switch ( in_f->cf_choice ) {
	case LDAP_COMP_FILTER_AND:
		rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and);
		dup_f.cf_choice = LDAP_COMP_FILTER_AND;
		break;
	case LDAP_COMP_FILTER_OR:
		rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or);
		dup_f.cf_choice = LDAP_COMP_FILTER_OR;
		break;
	case LDAP_COMP_FILTER_NOT:
		rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not);
		dup_f.cf_choice = LDAP_COMP_FILTER_NOT;
		break;
	case LDAP_COMP_FILTER_ITEM:
		rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca );
		dup_f.cf_choice = LDAP_COMP_FILTER_ITEM;
		break;
	default:
		rc = LDAP_PROTOCOL_ERROR;
	}

	if ( rc == LDAP_SUCCESS ) {
		*out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx );
		**out_f = dup_f;
	}

	return( rc );
}

296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
int
get_aliased_filter_aa ( Operation* op, AttributeAssertion* a_assert, AttributeAliasing* aa, const char** text )
{
	struct berval assert_bv;

	Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );

	if ( !aa->aa_cf  )
		return LDAP_PROTOCOL_ERROR;

	assert_bv = a_assert->aa_value;
	/*
	 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
	 * the component assertion value in assert_bv
	 * Multiple values may be separated with '$'
	 */
	return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &a_assert->aa_cf );
}
314
315

int
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
316
317
318
get_aliased_filter( Operation* op,
	MatchingRuleAssertion* ma, AttributeAliasing* aa,
	const char** text )
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
{
	struct berval assert_bv;

	Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );

	if ( !aa->aa_cf  ) return LDAP_PROTOCOL_ERROR;

	assert_bv = ma->ma_value;
	/* Attribute Description is replaced with aliased one */
	ma->ma_desc = aa->aa_aliased_ad;
	ma->ma_rule = aa->aa_mr;
	/*
	 * Duplicate aa->aa_cf to ma->ma_cf by replacing the
	 * the component assertion value in assert_bv
	 * Multiple values may be separated with '$'
	 */
Sang Seok Lim's avatar
Sang Seok Lim committed
335
	return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf );
336
337
}

338
int
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
339
340
get_comp_filter( Operation* op, struct berval* bv,
	ComponentFilter** filt, const char **text )
341
342
{
	ComponentAssertionValue cav;
343
344
	int rc;

345
	Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
Sang Seok Lim's avatar
Sang Seok Lim committed
346
347
348
	if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) {
		return rc;
	}
349
	rc = parse_comp_filter( op, &cav, filt, text );
350
	/* bv->bv_val = cav.cav_ptr; */
351

352
353
354
355
356
357
	return rc;
}

static void
eat_whsp( ComponentAssertionValue* cav )
{
Sang Seok Lim's avatar
Sang Seok Lim committed
358
359
360
	for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) {
		cav->cav_ptr++;
	}
361
362
363
364
365
366
367
368
369
370
371
372
373
374
}

static int
cav_cur_len( ComponentAssertionValue* cav )
{
	return cav->cav_end - cav->cav_ptr;
}

static ber_tag_t
comp_first_element( ComponentAssertionValue* cav )
{
	eat_whsp( cav );
	if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
		return LDAP_COMP_FILTER_ITEM;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
375
376
377
378

	} else if ( cav_cur_len( cav ) >= 7 &&
		strncmp( cav->cav_ptr, "and", 3 ) == 0 )
	{
379
		return LDAP_COMP_FILTER_AND;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
380
381
382
383

	} else if ( cav_cur_len( cav ) >= 6 &&
		strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
	{
384
		return LDAP_COMP_FILTER_OR;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
385
386
387
388

	} else if ( cav_cur_len( cav ) >= 7 &&
		strncmp( cav->cav_ptr, "not", 3 ) == 0 )
	{
389
		return LDAP_COMP_FILTER_NOT;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
390
391

	} else {
392
		return LDAP_COMP_FILTER_UNDEFINED;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
393
	}
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
}

static ber_tag_t
comp_next_element( ComponentAssertionValue* cav )
{
	eat_whsp( cav );
	if ( *(cav->cav_ptr) == ',' ) {
		/* move pointer to the next CA */
		cav->cav_ptr++;
		return comp_first_element( cav );
	}
	else return LDAP_COMP_FILTER_UNDEFINED;
}

static int
get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
410
	ComponentFilter** f, const char** text )
411
412
413
414
415
416
417
{
	ComponentFilter **new;
	int		err;
	ber_tag_t	tag;

	Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
	new = f;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
418
419
	for ( tag = comp_first_element( cav );
		tag != LDAP_COMP_FILTER_UNDEFINED;
420
421
422
		tag = comp_next_element( cav ) )
	{
		err = parse_comp_filter( op, cav, new, text );
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
423
		if ( err != LDAP_SUCCESS ) return ( err );
424
425
426
427
428
429
430
431
432
		new = &(*new)->cf_next;
	}
	*new = NULL;

	return( LDAP_SUCCESS );
}

static int
get_componentId( Operation *op, ComponentAssertionValue* cav,
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
433
	ComponentId ** cid, const char** text )
434
435
436
437
438
439
440
{
	ber_tag_t type;
	ComponentId _cid;
	int len;

	type = peek_componentId_type( cav );

441
442
	Debug( LDAP_DEBUG_FILTER, "get_compId [%lu]\n",
		(unsigned long) type, 0, 0 );
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
	len = 0;
	_cid.ci_type = type;
	_cid.ci_next = NULL;
	switch ( type ) {
	case LDAP_COMPREF_IDENTIFIER :
		_cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
			cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
		_cid.ci_val.ci_identifier.bv_len = len;
		cav->cav_ptr += len;
		break;
	case LDAP_COMPREF_FROM_BEGINNING :
		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
			cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
		_cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
		cav->cav_ptr += len;
		break;
	case LDAP_COMPREF_FROM_END :
		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
			cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
		_cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
		cav->cav_ptr += len;
		break;
	case LDAP_COMPREF_COUNT :
		_cid.ci_val.ci_count = 0;
		cav->cav_ptr++;
		break;
	case LDAP_COMPREF_CONTENT :
471
472
		_cid.ci_val.ci_content = 1;
		cav->cav_ptr += strlen("content");
473
474
		break;
	case LDAP_COMPREF_SELECT :
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
475
		if ( cav->cav_ptr[len] != '(' ) return LDAP_COMPREF_UNDEFINED;
476
		for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
477
478
	  	      cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
			; len++ );
479
480
		_cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
		_cid.ci_val.ci_select_value.bv_len = len - 1 ;
481
		cav->cav_ptr += len + 1;
482
483
484
485
486
487
488
489
490
		break;
	case LDAP_COMPREF_ALL :
		_cid.ci_val.ci_all = '*';
		cav->cav_ptr++;
		break;
	default :
		return LDAP_COMPREF_UNDEFINED;
	}

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
491
	if ( op ) {
492
		*cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
493
	} else {
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
494
495
496
497
		*cid = SLAP_MALLOC( sizeof( ComponentId ) );
	}
	if (*cid == NULL) {
		return LDAP_NO_MEMORY;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
498
	}
499
500
501
502
503
504
505
506
	**cid = _cid;
	return LDAP_SUCCESS;
}

static int
peek_componentId_type( ComponentAssertionValue* cav )
{
	eat_whsp( cav );
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
507
508

	if ( cav->cav_ptr[0] == '-' ) {
509
		return LDAP_COMPREF_FROM_END;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
510
511

	} else if ( cav->cav_ptr[0] == '(' ) {
512
		return LDAP_COMPREF_SELECT;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
513
514

	} else if ( cav->cav_ptr[0] == '*' ) {
515
		return LDAP_COMPREF_ALL;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
516
517

	} else if ( cav->cav_ptr[0] == '0' ) {
518
		return LDAP_COMPREF_COUNT;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
519
520

	} else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' ) {
521
		return LDAP_COMPREF_FROM_BEGINNING;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
522
523

	} else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
524
		strncmp(cav->cav_ptr,"content",7) == 0 )
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
525
	{
526
		return LDAP_COMPREF_CONTENT;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
527
	} else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
Sang Seok Lim's avatar
Sang Seok Lim committed
528
			(cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
529
	{
530
		return LDAP_COMPREF_IDENTIFIER;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
531
532
533
	}

	return LDAP_COMPREF_UNDEFINED;
534
535
536
537
538
539
540
541
542
}

static ber_tag_t
comp_next_id( ComponentAssertionValue* cav )
{
	if ( *(cav->cav_ptr) == '.' ) {
		cav->cav_ptr++;
		return LDAP_COMPREF_DEFINED;
	}
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
543
544

	return LDAP_COMPREF_UNDEFINED;
545
546
}

547
548


549
static int
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
550
551
552
553
554
get_component_reference(
	Operation *op,
	ComponentAssertionValue* cav,
	ComponentReference** cr,
	const char** text )
555
{
556
	int rc, count = 0;
557
558
559
	ber_int_t type;
	ComponentReference* ca_comp_ref;
	ComponentId** cr_list;
560
	char* start, *end;
561
562

	eat_whsp( cav );
563

564
	start = cav->cav_ptr;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
565
566
567
568
569
	if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) return rc;
	if ( op ) {
		ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ),
			op->o_tmpmemctx );
	} else {
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
570
		ca_comp_ref = SLAP_MALLOC( sizeof( ComponentReference ) );
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
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
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
578
579
		; type = comp_next_id( cav ), count++ )
	{
580
581
582
583
		rc = get_componentId( op, cav, cr_list, text );
		if ( rc == LDAP_SUCCESS ) {
			if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
			cr_list = &(*cr_list)->ci_next;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
584
585

		} else if ( rc == LDAP_COMPREF_UNDEFINED ) {
Howard Chu's avatar
Howard Chu committed
586
587
588
589
590
			if ( op ) {
				op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
			} else {
				free( ca_comp_ref );
			}
Sang Seok Lim's avatar
Sang Seok Lim committed
591
			return rc;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
592
		}
593
594
	}
	ca_comp_ref->cr_len = count;
595
	end = cav->cav_ptr;
596
	if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
597
		if ( op ) {
598
			op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
599
		} else {
600
			free( ca_comp_ref );
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
601
		}
602
603
		return rc;
	}
604

Howard Chu's avatar
Cleanup    
Howard Chu committed
605
606
	*cr = ca_comp_ref;
	**cr = *ca_comp_ref;	
607

608
609
610
	(*cr)->cr_string.bv_val = start;
	(*cr)->cr_string.bv_len = end - start + 1;
	
611
612
613
	return rc;
}

614
int
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
615
616
617
618
619
620
insert_component_reference(
	ComponentReference *cr,
	ComponentReference** cr_list)
{
	if ( !cr ) return LDAP_PARAM_ERROR;

621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
	if ( !(*cr_list) ) {
		*cr_list = cr;
		cr->cr_next = NULL;
	} else {
		cr->cr_next = *cr_list;
		*cr_list = cr;
	}
	return LDAP_SUCCESS;
}

/*
 * If there is '.' in the name of a given attribute
 * the first '.'- following characters are considered
 * as a component reference of the attribute
 * EX) userCertificate.toBeSigned.serialNumber
 * attribute : userCertificate
 * component reference : toBeSigned.serialNumber
 */
int
is_component_reference( char* attr ) {
	int i;
	for ( i=0; attr[i] != '\0' ; i++ ) {
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
643
		if ( attr[i] == '.' ) return (1);
644
645
646
647
648
	}
	return (0);
}

int
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
649
650
651
652
653
654
655
656
extract_component_reference(
	char* attr,
	ComponentReference** cr )
{
	int i, rc;
	char* cr_ptr;
	int cr_len;
	ComponentAssertionValue cav;
657
658
	char text[1][128];

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
659
660
661
662
663
664
	for ( i=0; attr[i] != '\0' ; i++ ) {
		if ( attr[i] == '.' ) break;
	}

	if (attr[i] != '.' ) return LDAP_PARAM_ERROR;
	attr[i] = '\0';
665

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
666
667
668
	cr_ptr = attr + i + 1 ;
	cr_len = strlen ( cr_ptr );
	if ( cr_len <= 0 ) return LDAP_PARAM_ERROR;
669
670
671
672
673
674

	/* enclosed between double quotes*/
	cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
	memcpy( cav.cav_buf+1, cr_ptr, cr_len );
	cav.cav_buf[0] = '"';
	cav.cav_buf[cr_len+1] = '"';
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
675
	cav.cav_end = cr_ptr + cr_len + 2;
676

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
677
678
	rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
	if ( rc != LDAP_SUCCESS ) return rc;
679
680
681
682
683
	(*cr)->cr_string.bv_val = cav.cav_buf;
	(*cr)->cr_string.bv_len = cr_len + 2;

	return LDAP_SUCCESS;
}
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
684

685
static int
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
686
687
688
get_ca_use_default( Operation *op,
	ComponentAssertionValue* cav,
	int* ca_use_def, const char**  text )
689
{
690
	strip_cav_str( cav, "useDefaultValues" );
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
691

692
693
	if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
		strip_cav_str( cav, "TRUE" );
694
		*ca_use_def = 1;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
695

696
697
698
	} else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
		strip_cav_str( cav, "FALSE" );
		*ca_use_def = 0;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
699

700
701
	} else {
		return LDAP_INVALID_SYNTAX;
702
703
	}

704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
	return LDAP_SUCCESS;
}

static int
get_matching_rule( Operation *op, ComponentAssertionValue* cav,
		MatchingRule** mr, const char**  text )
{
	int count = 0;
	struct berval rule_text = { 0L, NULL };

	eat_whsp( cav );

	for ( ; ; count++ ) {
		if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
			cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
			cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
720
		{
721
			break;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
722
		}
723
724
725
726
727
728
729
730
731
732
733
	}

	if ( count == 0 ) {
		*text = "component matching rule not recognized";
		return LDAP_INAPPROPRIATE_MATCHING;
	}
	
	rule_text.bv_len = count;
	rule_text.bv_val = cav->cav_ptr;
	*mr = mr_bvfind( &rule_text );
	cav->cav_ptr += count;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
734
735
	Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n",
		(*mr)->smr_mrule.mr_oid, 0, 0 );
736
737
738
739
740
741
742
	if ( *mr == NULL ) {
		*text = "component matching rule not recognized";
		return LDAP_INAPPROPRIATE_MATCHING;
	}
	return LDAP_SUCCESS;
}

Sang Seok Lim's avatar
Sang Seok Lim committed
743
static int
744
745
get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
{
Sang Seok Lim's avatar
Sang Seok Lim committed
746
	int count, sequent_dquote, unclosed_brace, succeed;
747
748
749
750
751
752
753
754
755
756
757
758
759
760

	eat_whsp( cav );
	/*
	 * Four cases of GSER <Values>
	 * 1) "..." :
	 *	StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
	 * 2) '...'B or '...'H :
	 *	BitStringVal, OctetStringVal
	 * 3) {...} :
	 *	SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
	 * 4) Between two white spaces
	 *	INTEGER, BOOLEAN, NULL,ENUMERATE, etc
	 */

Sang Seok Lim's avatar
Sang Seok Lim committed
761
	succeed = 0;
762
	if ( cav->cav_ptr[0] == '"' ) {
Sang Seok Lim's avatar
Sang Seok Lim committed
763
764
765
766
767
		for( count = 1, sequent_dquote = 0 ; ; count++ ) {
			/* In order to find escaped double quote */
			if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
			else sequent_dquote = 0;

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
768
769
770
			if ( cav->cav_ptr[count] == '\0' ||
				(cav->cav_ptr+count) > cav->cav_end )
			{
Sang Seok Lim's avatar
Sang Seok Lim committed
771
772
773
				break;
			}
				
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
774
775
776
777
			if ( ( cav->cav_ptr[count] == '"' &&
				cav->cav_ptr[count-1] != '"') ||
				( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) )
			{
Sang Seok Lim's avatar
Sang Seok Lim committed
778
				succeed = 1;
779
				break;
Sang Seok Lim's avatar
Sang Seok Lim committed
780
			}
781
		}
782
		
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
783
		if ( !succeed || cav->cav_ptr[count] != '"' ) {
784
			return LDAP_FILTER_ERROR;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
785
		}
786
787
788

		bv->bv_val = cav->cav_ptr + 1;
		bv->bv_len = count - 1; /* exclude '"' */
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
789
790

	} else if ( cav->cav_ptr[0] == '\'' ) {
Sang Seok Lim's avatar
Sang Seok Lim committed
791
		for( count = 1 ; ; count++ ) {
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
792
793
794
			if ( cav->cav_ptr[count] == '\0' ||
				(cav->cav_ptr+count) > cav->cav_end )
			{
Sang Seok Lim's avatar
Sang Seok Lim committed
795
796
				break;
			}
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
797
798
799
			if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B') ||
				(cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') )
			{
Sang Seok Lim's avatar
Sang Seok Lim committed
800
				succeed = 1;
801
				break;
Sang Seok Lim's avatar
Sang Seok Lim committed
802
			}
803
		}
804

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
805
806
807
808
809
		if ( !succeed ||
			!(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
		{
			return LDAP_FILTER_ERROR;
		}
810
811
812

		bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
		bv->bv_len = count - 2;/* exclude "'H" or "'B" */
813
				
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
814
	} else if ( cav->cav_ptr[0] == '{' ) {
Sang Seok Lim's avatar
Sang Seok Lim committed
815
816
817
818
		for( count = 1, unclosed_brace = 1 ; ; count++ ) {
			if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
			if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
819
820
821
			if ( cav->cav_ptr[count] == '\0' ||
				(cav->cav_ptr+count) > cav->cav_end )
			{
Sang Seok Lim's avatar
Sang Seok Lim committed
822
				break;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
823
			}
Sang Seok Lim's avatar
Sang Seok Lim committed
824
825
			if ( unclosed_brace == 0 ) {
				succeed = 1;
826
				break;
Sang Seok Lim's avatar
Sang Seok Lim committed
827
			}
828
		}
829

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
830
		if ( !succeed || cav->cav_ptr[count] != '}' ) return LDAP_FILTER_ERROR;
831
832
833

		bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
		bv->bv_len = count - 1;/* exclude  "'B" */
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
834
835

	} else {
Sang Seok Lim's avatar
Sang Seok Lim committed
836
		succeed = 1;
837
838
		/*Find  following white space where the value is ended*/
		for( count = 1 ; ; count++ ) {
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
839
840
841
842
843
			if ( cav->cav_ptr[count] == '\0' ||
				cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' ||
				cav->cav_ptr[count] == '{' ||
				(cav->cav_ptr+count) > cav->cav_end )
			{
844
845
846
				break;
			}
		}
847
848
		bv->bv_val = cav->cav_ptr;
		bv->bv_len = count;
849
850
	}

851
	cav->cav_ptr += bv->bv_len;
Sang Seok Lim's avatar
Sang Seok Lim committed
852
	return LDAP_SUCCESS;
853
854
855
856
}

static int
get_matching_value( Operation *op, ComponentAssertion* ca,
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
857
858
	ComponentAssertionValue* cav, struct berval* bv,
	const char**  text )
859
860
{
	if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
861
		if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
Sang Seok Lim's avatar
Sang Seok Lim committed
862
			return LDAP_FILTER_ERROR;
863
864
865
		}

	} else {
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
		/* embeded componentFilterMatch Description */
		bv->bv_val = cav->cav_ptr;
		bv->bv_len = cav_cur_len( cav );
	}

	return LDAP_SUCCESS;
}

/* Don't move the position pointer, just peek given string */
static int
peek_cav_str( ComponentAssertionValue* cav, char* str )
{
	eat_whsp( cav );
	if ( cav_cur_len( cav ) >= strlen( str ) &&
		strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
881
	{
882
		return LDAP_SUCCESS;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
883
884
885
	}

	return LDAP_INVALID_SYNTAX;
886
887
888
889
890
891
892
}

static int
strip_cav_str( ComponentAssertionValue* cav, char* str)
{
	eat_whsp( cav );
	if ( cav_cur_len( cav ) >= strlen( str ) &&
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
893
894
		strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
	{
895
896
897
		cav->cav_ptr += strlen( str );
		return LDAP_SUCCESS;
	}
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
898
899

	return LDAP_INVALID_SYNTAX;
900
901
902
903
904
}

/*
 * TAG : "item", "and", "or", "not"
 */
905
static ber_tag_t
906
907
strip_cav_tag( ComponentAssertionValue* cav )
{
908
	int rc;
909
910
911

	eat_whsp( cav );
	if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
912
913
		if ( strip_cav_str( cav , "item:" ))
			goto fail;
914
		return LDAP_COMP_FILTER_ITEM;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
915
916
917
918

	} else if ( cav_cur_len( cav ) >= 7 &&
		strncmp( cav->cav_ptr, "and", 3 ) == 0 )
	{
919
920
		if ( strip_cav_str( cav , "and:" ))
			goto fail;
921
		return LDAP_COMP_FILTER_AND;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
922
923
924
925

	} else if ( cav_cur_len( cav ) >= 6 &&
		strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
	{
926
927
		if ( strip_cav_str( cav , "or:" ))
			goto fail;
928
		return LDAP_COMP_FILTER_OR;
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
929
930
931
932

	} else if ( cav_cur_len( cav ) >= 7 &&
		strncmp( cav->cav_ptr, "not", 3 ) == 0 )
	{
933
934
		if ( strip_cav_str( cav , "not:" ))
			goto fail;
935
936
		return LDAP_COMP_FILTER_NOT;
	}
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
937

938
fail:
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
939
	return LBER_ERROR;
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
}

/*
 * when encoding, "item" is denotation of ComponentAssertion
 * ComponentAssertion :: SEQUENCE {
 *	component		ComponentReference (SIZE(1..MAX)) OPTIONAL,
 *	useDefaultValues	BOOLEAN DEFAULT TRUE,
 *	rule			MATCHING-RULE.&id,
 *	value			MATCHING-RULE.&AssertionType }
 */
static int
get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
		const char** text )
{
	int rc;
	ComponentAssertion* _ca;
956
957
	struct berval value;
	MatchingRule* mr;
958

959
960
961
962
	Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
	if ( op )
		_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
	else
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
963
		_ca = SLAP_MALLOC( sizeof( ComponentAssertion ) );
964
965

	if ( !_ca ) return LDAP_NO_MEMORY;
966

967
968
	_ca->ca_comp_data.cd_tree = NULL;
	_ca->ca_comp_data.cd_mem_op = NULL;
Sang Seok Lim's avatar
Sang Seok Lim committed
969

970
971
972
973
974
	rc = peek_cav_str( cav, "component" );
	if ( rc == LDAP_SUCCESS ) {
		strip_cav_str( cav, "component" );
		rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
		if ( rc != LDAP_SUCCESS ) {
975
976
977
978
979
			if ( op )
				op->o_tmpfree( _ca, op->o_tmpmemctx );
			else
				free( _ca );
			return LDAP_INVALID_SYNTAX;
980
		}
981
982
983
984
		if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
			return rc;
	} else {
		_ca->ca_comp_ref = NULL;
985
986
987
988
989
990
	}

	rc = peek_cav_str( cav, "useDefaultValues");
	if ( rc == LDAP_SUCCESS ) {
		rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
		if ( rc != LDAP_SUCCESS ) {
991
992
993
994
995
			if ( op )
				op->o_tmpfree( _ca, op->o_tmpmemctx );
			else
				free( _ca );
			return LDAP_INVALID_SYNTAX;
996
		}
997
998
		if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
			return rc;
999
	}
1000
	else _ca->ca_use_def = 1;
1001
1002
1003

	if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
		get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
1004
1005
1006
1007
1008
		if ( op )
			op->o_tmpfree( _ca, op->o_tmpmemctx );
		else
			free( _ca );
		return LDAP_INAPPROPRIATE_MATCHING;
1009
1010
	}
	
1011
1012
	if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
		return rc;
1013
	if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
1014
1015
1016
1017
1018
1019
		get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
		if ( op )
			op->o_tmpfree( _ca, op->o_tmpmemctx );
		else
			free( _ca );
		return LDAP_INVALID_SYNTAX;
1020
1021
	}

1022
1023
1024
1025
1026
1027
1028
1029
1030
	/*
	 * Normalize the value of this component assertion when the matching
	 * rule is one of existing matching rules
	 */
	mr = _ca->ca_ma_rule;
	if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {

		value.bv_val[value.bv_len] = '\0';
		rc = mr->smr_normalize (
1031
1032
1033
			SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
			NULL, mr,
			&value, &_ca->ca_ma_value, op->o_tmpmemctx );
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
		if ( rc != LDAP_SUCCESS )
			return rc;
	}
	else
		_ca->ca_ma_value = value;
	/*
	 * Validate the value of this component assertion
	 */
	if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
		return LDAP_INVALID_SYNTAX;
	}


1047
	/* componentFilterMatch contains componentFilterMatch in it */
Sang Seok Lim's avatar
Sang Seok Lim committed
1048
	if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
1049
1050
1051
1052
1053
		struct berval bv;
		bv.bv_val = cav->cav_ptr;
		bv.bv_len = cav_cur_len( cav );
		rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
		if ( rc != LDAP_SUCCESS ) {
1054
1055
1056
1057
			if ( op )
				op->o_tmpfree( _ca, op->o_tmpmemctx );
			else
				free( _ca );
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
			return rc;
		}
		cav->cav_ptr = bv.bv_val;
		assert( cav->cav_end >= bv.bv_val );
	}

	*ca = _ca;
	return LDAP_SUCCESS;
}

static int
parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
				ComponentFilter** filt, const char** text )
{
	/*
	 * A component filter looks like this coming in:
	 *	Filter ::= CHOICE {
	 *		item	[0]	ComponentAssertion,
	 *		and	[1]	SEQUENCE OF ComponentFilter,
	 *		or	[2]	SEQUENCE OF ComponentFilter,
	 *		not	[3]	ComponentFilter,
	 *	}
	 */

	ber_tag_t	tag;
1083
	int		err = LDAP_SUCCESS;
1084
	ComponentFilter	f;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1085
	/* TAG : item, and, or, not in RFC 4515 */
1086
1087
1088
1089
1090
1091
1092
	tag = strip_cav_tag( cav );

	if ( tag == LBER_ERROR ) {
		*text = "error decoding comp filter";
		return LDAP_PROTOCOL_ERROR;
	}

1093
1094
1095
1096
1097
	if ( tag != LDAP_COMP_FILTER_NOT ) {
		err = strip_cav_str( cav, "{");
		if ( err )
			goto invalid;
	}
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170

	f.cf_next = NULL;
	f.cf_choice = tag; 

	switch ( f.cf_choice ) {
	case LDAP_COMP_FILTER_AND:
	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
		err = get_comp_filter_list( op, cav, &f.cf_and, text );
		if ( err != LDAP_SUCCESS ) {
			break;
		}
		if ( f.cf_and == NULL ) {
			f.cf_choice = SLAPD_FILTER_COMPUTED;
			f.cf_result = LDAP_COMPARE_TRUE;
		}
		break;

	case LDAP_COMP_FILTER_OR:
	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
		err = get_comp_filter_list( op, cav, &f.cf_or, text );
		if ( err != LDAP_SUCCESS ) {
			break;
		}
		if ( f.cf_or == NULL ) {
			f.cf_choice = SLAPD_FILTER_COMPUTED;
			f.cf_result = LDAP_COMPARE_FALSE;
		}
		/* no assert - list could be empty */
		break;

	case LDAP_COMP_FILTER_NOT:
	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
		err = parse_comp_filter( op, cav, &f.cf_not, text );
		if ( err != LDAP_SUCCESS ) {
			break;
		}

		assert( f.cf_not != NULL );
		if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
			int fresult = f.cf_not->cf_result;
			f.cf_choice = SLAPD_FILTER_COMPUTED;
			op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
			f.cf_not = NULL;

			switch ( fresult ) {
			case LDAP_COMPARE_TRUE:
				f.cf_result = LDAP_COMPARE_FALSE;
				break;
			case LDAP_COMPARE_FALSE:
				f.cf_result = LDAP_COMPARE_TRUE;
				break;
			default: ;
				/* (!Undefined) is Undefined */
			}
		}
		break;

	case LDAP_COMP_FILTER_ITEM:
	Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
		err = get_item( op, cav, &f.cf_ca, text );
		if ( err != LDAP_SUCCESS ) {
			break;
		}

		assert( f.cf_ca != NULL );
		break;

	default:
		f.cf_choice = SLAPD_FILTER_COMPUTED;
		f.cf_result = SLAPD_COMPARE_UNDEFINED;
		break;
	}

1171
invalid:
1172
	if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1173
1174
		*text = "Component Filter Syntax Error";
		return err;
1175
1176
	}

1177
	if ( tag != LDAP_COMP_FILTER_NOT )
1178
		err = strip_cav_str( cav, "}");
1179

1180
	if ( err == LDAP_SUCCESS ) {
1181
1182
1183
		if ( op ) {
			*filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
		} else {
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
1184
1185
1186
1187
			*filt = SLAP_MALLOC( sizeof(f) );
		}
		if ( *filt == NULL ) {
			return LDAP_NO_MEMORY;
1188
		}
1189
1190
1191
1192
1193
1194
1195
1196
		**filt = f;
	}

	return( err );
}

static int
test_comp_filter_and(
Sang Seok Lim's avatar
Sang Seok Lim committed
1197
	Syntax *syn,
Sang Seok Lim's avatar
Bug fix    
Sang Seok Lim committed
1198
	ComponentSyntaxInfo *a,
1199
1200
1201
1202
1203
1204
	ComponentFilter *flist )
{
	ComponentFilter *f;
	int rtn = LDAP_COMPARE_TRUE;

	for ( f = flist ; f != NULL; f = f->cf_next ) {
1205
		int rc = test_comp_filter( syn, a, f );
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
		if ( rc == LDAP_COMPARE_FALSE ) {
			rtn = rc;
			break;
		}
	
		if ( rc != LDAP_COMPARE_TRUE ) {
			rtn = rc;
		}
	}

	return rtn;
}

static int
test_comp_filter_or(
Sang Seok Lim's avatar
Sang Seok Lim committed
1221
	Syntax *syn,
Sang Seok Lim's avatar
Bug fix    
Sang Seok Lim committed
1222
	ComponentSyntaxInfo *a,
1223
1224
1225
1226
1227
1228
	ComponentFilter *flist )
{
	ComponentFilter *f;
	int rtn = LDAP_COMPARE_TRUE;

	for ( f = flist ; f != NULL; f = f->cf_next ) {
1229
		int rc = test_comp_filter( syn, a, f );
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
		if ( rc == LDAP_COMPARE_TRUE ) {
			rtn = rc;
			break;
		}
	
		if ( rc != LDAP_COMPARE_FALSE ) {
			rtn = rc;
		}
	}

	return rtn;
}

1243
int
Sang Seok Lim's avatar
Sang Seok Lim committed
1244
csi_value_match( MatchingRule *mr, struct berval* bv_attr,
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
1245
	struct berval* bv_assert )
Sang Seok Lim's avatar
Sang Seok Lim committed
1246
1247
1248
1249
1250
1251
1252
{
	int rc;
	int match;

	assert( mr != NULL );
	assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );

Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
1253
	if( !mr->smr_match ) return LDAP_INAPPROPRIATE_MATCHING;
Sang Seok Lim's avatar
Sang Seok Lim committed
1254
1255

	rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
Kurt Zeilenga's avatar
Cleanup    
Kurt Zeilenga committed
1256
1257
1258
1259
1260
		mr, bv_attr, bv_assert );

	if ( rc != LDAP_SUCCESS ) return rc;

	return match ? LDAP_COMPARE_FALSE : LDAP_COMPARE_TRUE;
Sang Seok Lim's avatar
Sang Seok Lim committed
1261
1262
}

1263
1264
1265
1266
1267
/*
 * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
 */
static int
test_comp_filter_item(
Sang Seok Lim's avatar
Sang Seok Lim committed
1268
	Syntax *syn,
Sang Seok Lim's avatar
Bug fix    
Sang Seok Lim committed
1269
	ComponentSyntaxInfo *csi_attr,
1270
1271
	ComponentAssertion *ca )
{
1272
	int rc;
1273
	void *attr_nm, *assert_nm;
1274

Sang Seok Lim's avatar
Sang Seok Lim committed
1275
1276
	if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
		OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1277
		/* componentFilterMatch inside of componentFilterMatch */
1278
		rc = test_comp_filter( syn, csi_attr, ca->ca_cf );
1279
1280
1281
		return rc;
	}

1282
	/* Memory for storing will-be-extracted attribute values */
1283
	attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
Sang Seok Lim's avatar
Sang Seok Lim committed
1284
	if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
Sang Seok Lim's avatar
Sang Seok Lim committed
1285

1286
	/* Memory for storing component assertion values */
1287
1288
	if( !ca->ca_comp_data.cd_mem_op ) {
		assert_nm = nibble_mem_allocator ( 256, 64 );