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