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