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