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