]> git.sur5r.net Git - openldap/blob - servers/slapd/component.c
bb66c4cee7bc23a1f230db690e5f664bf5a3c3bd
[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 [%d]\n", type, 0, 0 );
451         len = 0;
452         _cid.ci_type = type;
453         _cid.ci_next = NULL;
454         switch ( type ) {
455         case LDAP_COMPREF_IDENTIFIER :
456                 _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
457                 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
458                         cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
459                 _cid.ci_val.ci_identifier.bv_len = len;
460                 cav->cav_ptr += len;
461                 break;
462         case LDAP_COMPREF_FROM_BEGINNING :
463                 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
464                         cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
465                 _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
466                 cav->cav_ptr += len;
467                 break;
468         case LDAP_COMPREF_FROM_END :
469                 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
470                         cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
471                 _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
472                 cav->cav_ptr += len;
473                 break;
474         case LDAP_COMPREF_COUNT :
475                 _cid.ci_val.ci_count = 0;
476                 cav->cav_ptr++;
477                 break;
478         case LDAP_COMPREF_CONTENT :
479                 _cid.ci_val.ci_content = 1;
480                 cav->cav_ptr += strlen("content");
481                 break;
482         case LDAP_COMPREF_SELECT :
483                 if ( cav->cav_ptr[len] != '(' ) return LDAP_COMPREF_UNDEFINED;
484                 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
485                       cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
486                         ; len++ );
487                 _cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
488                 _cid.ci_val.ci_select_value.bv_len = len - 1 ;
489                 cav->cav_ptr += len + 1;
490                 break;
491         case LDAP_COMPREF_ALL :
492                 _cid.ci_val.ci_all = '*';
493                 cav->cav_ptr++;
494                 break;
495         default :
496                 return LDAP_COMPREF_UNDEFINED;
497         }
498
499         if ( op ) {
500                 *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
501         } else {
502                 *cid = malloc( sizeof( ComponentId ) );
503         }
504         **cid = _cid;
505         return LDAP_SUCCESS;
506 }
507
508 static int
509 peek_componentId_type( ComponentAssertionValue* cav )
510 {
511         eat_whsp( cav );
512
513         if ( cav->cav_ptr[0] == '-' ) {
514                 return LDAP_COMPREF_FROM_END;
515
516         } else if ( cav->cav_ptr[0] == '(' ) {
517                 return LDAP_COMPREF_SELECT;
518
519         } else if ( cav->cav_ptr[0] == '*' ) {
520                 return LDAP_COMPREF_ALL;
521
522         } else if ( cav->cav_ptr[0] == '0' ) {
523                 return LDAP_COMPREF_COUNT;
524
525         } else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' ) {
526                 return LDAP_COMPREF_FROM_BEGINNING;
527
528         } else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
529                 strncmp(cav->cav_ptr,"content",7) == 0 )
530         {
531                 return LDAP_COMPREF_CONTENT;
532         } else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
533                         (cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
534         {
535                 return LDAP_COMPREF_IDENTIFIER;
536         }
537
538         return LDAP_COMPREF_UNDEFINED;
539 }
540
541 static ber_tag_t
542 comp_next_id( ComponentAssertionValue* cav )
543 {
544         if ( *(cav->cav_ptr) == '.' ) {
545                 cav->cav_ptr++;
546                 return LDAP_COMPREF_DEFINED;
547         }
548
549         return LDAP_COMPREF_UNDEFINED;
550 }
551
552
553
554 static int
555 get_component_reference(
556         Operation *op,
557         ComponentAssertionValue* cav,
558         ComponentReference** cr,
559         const char** text )
560 {
561         int rc, count = 0;
562         ber_int_t type;
563         ComponentReference* ca_comp_ref;
564         ComponentId** cr_list;
565         char* start, *end;
566
567         eat_whsp( cav );
568
569         start = cav->cav_ptr;
570         if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) return rc;
571         if ( op ) {
572                 ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ),
573                         op->o_tmpmemctx );
574         } else {
575                 ca_comp_ref = malloc( sizeof( ComponentReference ) );
576         }
577
578         if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
579
580         cr_list = &ca_comp_ref->cr_list;
581
582         for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
583                 ; type = comp_next_id( cav ), count++ )
584         {
585                 rc = get_componentId( op, cav, cr_list, text );
586                 if ( rc == LDAP_SUCCESS ) {
587                         if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
588                         cr_list = &(*cr_list)->ci_next;
589
590                 } else if ( rc == LDAP_COMPREF_UNDEFINED ) {
591                         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         if ( rc == LDAP_SUCCESS ) {     
606                 *cr = ca_comp_ref;
607                 **cr = *ca_comp_ref;    
608
609         } else if ( op ) {
610                  op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
611
612         } else {
613                  free( ca_comp_ref ) ;
614         }
615
616         (*cr)->cr_string.bv_val = start;
617         (*cr)->cr_string.bv_len = end - start + 1;
618         
619         return rc;
620 }
621
622 int
623 insert_component_reference(
624         ComponentReference *cr,
625         ComponentReference** cr_list)
626 {
627         if ( !cr ) return LDAP_PARAM_ERROR;
628
629         if ( !(*cr_list) ) {
630                 *cr_list = cr;
631                 cr->cr_next = NULL;
632         } else {
633                 cr->cr_next = *cr_list;
634                 *cr_list = cr;
635         }
636         return LDAP_SUCCESS;
637 }
638
639 /*
640  * If there is '.' in the name of a given attribute
641  * the first '.'- following characters are considered
642  * as a component reference of the attribute
643  * EX) userCertificate.toBeSigned.serialNumber
644  * attribute : userCertificate
645  * component reference : toBeSigned.serialNumber
646  */
647 int
648 is_component_reference( char* attr ) {
649         int i;
650         for ( i=0; attr[i] != '\0' ; i++ ) {
651                 if ( attr[i] == '.' ) return (1);
652         }
653         return (0);
654 }
655
656 int
657 extract_component_reference(
658         char* attr,
659         ComponentReference** cr )
660 {
661         int i, rc;
662         char* cr_ptr;
663         int cr_len;
664         ComponentAssertionValue cav;
665         char text[1][128];
666
667         for ( i=0; attr[i] != '\0' ; i++ ) {
668                 if ( attr[i] == '.' ) break;
669         }
670
671         if (attr[i] != '.' ) return LDAP_PARAM_ERROR;
672         attr[i] = '\0';
673
674         cr_ptr = attr + i + 1 ;
675         cr_len = strlen ( cr_ptr );
676         if ( cr_len <= 0 ) return LDAP_PARAM_ERROR;
677
678         /* enclosed between double quotes*/
679         cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
680         memcpy( cav.cav_buf+1, cr_ptr, cr_len );
681         cav.cav_buf[0] = '"';
682         cav.cav_buf[cr_len+1] = '"';
683         cav.cav_end = cr_ptr + cr_len + 2;
684
685         rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
686         if ( rc != LDAP_SUCCESS ) return rc;
687         (*cr)->cr_string.bv_val = cav.cav_buf;
688         (*cr)->cr_string.bv_len = cr_len + 2;
689
690         return LDAP_SUCCESS;
691 }
692
693 static int
694 get_ca_use_default( Operation *op,
695         ComponentAssertionValue* cav,
696         int* ca_use_def, const char**  text )
697 {
698         strip_cav_str( cav, "useDefaultValues" );
699
700         if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
701                 strip_cav_str( cav, "TRUE" );
702                 *ca_use_def = 1;
703
704         } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
705                 strip_cav_str( cav, "FALSE" );
706                 *ca_use_def = 0;
707
708         } else {
709                 return LDAP_INVALID_SYNTAX;
710         }
711
712         return LDAP_SUCCESS;
713 }
714
715 static int
716 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
717                 MatchingRule** mr, const char**  text )
718 {
719         int count = 0;
720         struct berval rule_text = { 0L, NULL };
721
722         eat_whsp( cav );
723
724         for ( ; ; count++ ) {
725                 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
726                         cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
727                         cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
728                 {
729                         break;
730                 }
731         }
732
733         if ( count == 0 ) {
734                 *text = "component matching rule not recognized";
735                 return LDAP_INAPPROPRIATE_MATCHING;
736         }
737         
738         rule_text.bv_len = count;
739         rule_text.bv_val = cav->cav_ptr;
740         *mr = mr_bvfind( &rule_text );
741         cav->cav_ptr += count;
742         Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n",
743                 (*mr)->smr_mrule.mr_oid, 0, 0 );
744         if ( *mr == NULL ) {
745                 *text = "component matching rule not recognized";
746                 return LDAP_INAPPROPRIATE_MATCHING;
747         }
748         return LDAP_SUCCESS;
749 }
750
751 static int
752 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
753 {
754         int count, sequent_dquote, unclosed_brace, succeed;
755
756         eat_whsp( cav );
757         /*
758          * Four cases of GSER <Values>
759          * 1) "..." :
760          *      StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
761          * 2) '...'B or '...'H :
762          *      BitStringVal, OctetStringVal
763          * 3) {...} :
764          *      SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
765          * 4) Between two white spaces
766          *      INTEGER, BOOLEAN, NULL,ENUMERATE, etc
767          */
768
769         succeed = 0;
770         if ( cav->cav_ptr[0] == '"' ) {
771                 for( count = 1, sequent_dquote = 0 ; ; count++ ) {
772                         /* In order to find escaped double quote */
773                         if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
774                         else sequent_dquote = 0;
775
776                         if ( cav->cav_ptr[count] == '\0' ||
777                                 (cav->cav_ptr+count) > cav->cav_end )
778                         {
779                                 break;
780                         }
781                                 
782                         if ( ( cav->cav_ptr[count] == '"' &&
783                                 cav->cav_ptr[count-1] != '"') ||
784                                 ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) )
785                         {
786                                 succeed = 1;
787                                 break;
788                         }
789                 }
790                 
791                 if ( !succeed || cav->cav_ptr[count] != '"' ) {
792                         return LDAP_FILTER_ERROR;
793                 }
794
795                 bv->bv_val = cav->cav_ptr + 1;
796                 bv->bv_len = count - 1; /* exclude '"' */
797
798         } else if ( cav->cav_ptr[0] == '\'' ) {
799                 for( count = 1 ; ; count++ ) {
800                         if ( cav->cav_ptr[count] == '\0' ||
801                                 (cav->cav_ptr+count) > cav->cav_end )
802                         {
803                                 break;
804                         }
805                         if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B') ||
806                                 (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') )
807                         {
808                                 succeed = 1;
809                                 break;
810                         }
811                 }
812
813                 if ( !succeed ||
814                         !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
815                 {
816                         return LDAP_FILTER_ERROR;
817                 }
818
819                 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
820                 bv->bv_len = count - 2;/* exclude "'H" or "'B" */
821                                 
822         } else if ( cav->cav_ptr[0] == '{' ) {
823                 for( count = 1, unclosed_brace = 1 ; ; count++ ) {
824                         if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
825                         if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
826
827                         if ( cav->cav_ptr[count] == '\0' ||
828                                 (cav->cav_ptr+count) > cav->cav_end )
829                         {
830                                 break;
831                         }
832                         if ( unclosed_brace == 0 ) {
833                                 succeed = 1;
834                                 break;
835                         }
836                 }
837
838                 if ( !succeed || cav->cav_ptr[count] != '}' ) return LDAP_FILTER_ERROR;
839
840                 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
841                 bv->bv_len = count - 1;/* exclude  "'B" */
842
843         } else {
844                 succeed = 1;
845                 /*Find  following white space where the value is ended*/
846                 for( count = 1 ; ; count++ ) {
847                         if ( cav->cav_ptr[count] == '\0' ||
848                                 cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' ||
849                                 cav->cav_ptr[count] == '{' ||
850                                 (cav->cav_ptr+count) > cav->cav_end )
851                         {
852                                 break;
853                         }
854                 }
855                 bv->bv_val = cav->cav_ptr;
856                 bv->bv_len = count;
857         }
858
859         cav->cav_ptr += bv->bv_len;
860         return LDAP_SUCCESS;
861 }
862
863 static int
864 get_matching_value( Operation *op, ComponentAssertion* ca,
865         ComponentAssertionValue* cav, struct berval* bv,
866         const char**  text )
867 {
868         if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
869                 if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
870                         return LDAP_FILTER_ERROR;
871                 }
872
873         } else {
874                 /* embeded componentFilterMatch Description */
875                 bv->bv_val = cav->cav_ptr;
876                 bv->bv_len = cav_cur_len( cav );
877         }
878
879         return LDAP_SUCCESS;
880 }
881
882 /* Don't move the position pointer, just peek given string */
883 static int
884 peek_cav_str( ComponentAssertionValue* cav, char* str )
885 {
886         eat_whsp( cav );
887         if ( cav_cur_len( cav ) >= strlen( str ) &&
888                 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
889         {
890                 return LDAP_SUCCESS;
891         }
892
893         return LDAP_INVALID_SYNTAX;
894 }
895
896 static int
897 strip_cav_str( ComponentAssertionValue* cav, char* str)
898 {
899         eat_whsp( cav );
900         if ( cav_cur_len( cav ) >= strlen( str ) &&
901                 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
902         {
903                 cav->cav_ptr += strlen( str );
904                 return LDAP_SUCCESS;
905         }
906
907         return LDAP_INVALID_SYNTAX;
908 }
909
910 /*
911  * TAG : "item", "and", "or", "not"
912  */
913 static int
914 strip_cav_tag( ComponentAssertionValue* cav )
915 {
916
917         eat_whsp( cav );
918         if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
919                 strip_cav_str( cav , "item:" );
920                 return LDAP_COMP_FILTER_ITEM;
921
922         } else if ( cav_cur_len( cav ) >= 7 &&
923                 strncmp( cav->cav_ptr, "and", 3 ) == 0 )
924         {
925                 strip_cav_str( cav , "and:" );
926                 return LDAP_COMP_FILTER_AND;
927
928         } else if ( cav_cur_len( cav ) >= 6 &&
929                 strncmp( cav->cav_ptr, "or" , 2 ) == 0 )
930         {
931                 strip_cav_str( cav , "or:" );
932                 return LDAP_COMP_FILTER_OR;
933
934         } else if ( cav_cur_len( cav ) >= 7 &&
935                 strncmp( cav->cav_ptr, "not", 3 ) == 0 )
936         {
937                 strip_cav_str( cav , "not:" );
938                 return LDAP_COMP_FILTER_NOT;
939         }
940
941         return LBER_ERROR;
942 }
943
944 /*
945  * when encoding, "item" is denotation of ComponentAssertion
946  * ComponentAssertion :: SEQUENCE {
947  *      component               ComponentReference (SIZE(1..MAX)) OPTIONAL,
948  *      useDefaultValues        BOOLEAN DEFAULT TRUE,
949  *      rule                    MATCHING-RULE.&id,
950  *      value                   MATCHING-RULE.&AssertionType }
951  */
952 static int
953 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
954                 const char** text )
955 {
956         int rc;
957         ComponentAssertion* _ca;
958         struct berval t_bv;
959         struct berval value;
960         MatchingRule* mr;
961
962         Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
963         if ( op )
964                 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
965         else
966                 _ca = malloc( sizeof( ComponentAssertion ) );
967
968         if ( !_ca ) return LDAP_NO_MEMORY;
969
970         _ca->ca_comp_data.cd_tree = NULL;
971         _ca->ca_comp_data.cd_mem_op = NULL;
972
973         rc = peek_cav_str( cav, "component" );
974         if ( rc == LDAP_SUCCESS ) {
975                 strip_cav_str( cav, "component" );
976                 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
977                 if ( rc != LDAP_SUCCESS ) {
978                         if ( op )
979                                 op->o_tmpfree( _ca, op->o_tmpmemctx );
980                         else
981                                 free( _ca );
982                         return LDAP_INVALID_SYNTAX;
983                 }
984                 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
985                         return rc;
986         } else {
987                 _ca->ca_comp_ref = NULL;
988         }
989
990         rc = peek_cav_str( cav, "useDefaultValues");
991         if ( rc == LDAP_SUCCESS ) {
992                 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
993                 if ( rc != LDAP_SUCCESS ) {
994                         if ( op )
995                                 op->o_tmpfree( _ca, op->o_tmpmemctx );
996                         else
997                                 free( _ca );
998                         return LDAP_INVALID_SYNTAX;
999                 }
1000                 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
1001                         return rc;
1002         }
1003         else _ca->ca_use_def = 1;
1004
1005         if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
1006                 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
1007                 if ( op )
1008                         op->o_tmpfree( _ca, op->o_tmpmemctx );
1009                 else
1010                         free( _ca );
1011                 return LDAP_INAPPROPRIATE_MATCHING;
1012         }
1013         
1014         if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
1015                 return rc;
1016         if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
1017                 get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
1018                 if ( op )
1019                         op->o_tmpfree( _ca, op->o_tmpmemctx );
1020                 else
1021                         free( _ca );
1022                 return LDAP_INVALID_SYNTAX;
1023         }
1024
1025         /*
1026          * Normalize the value of this component assertion when the matching
1027          * rule is one of existing matching rules
1028          */
1029         mr = _ca->ca_ma_rule;
1030         if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
1031
1032                 value.bv_val[value.bv_len] = '\0';
1033                 rc = mr->smr_normalize (
1034                         SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
1035                         NULL, mr,
1036                         &value, &_ca->ca_ma_value, op->o_tmpmemctx );
1037                 if ( rc != LDAP_SUCCESS )
1038                         return rc;
1039         }
1040         else
1041                 _ca->ca_ma_value = value;
1042         /*
1043          * Validate the value of this component assertion
1044          */
1045         if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
1046                 return LDAP_INVALID_SYNTAX;
1047         }
1048
1049
1050         /* componentFilterMatch contains componentFilterMatch in it */
1051         if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
1052                 struct berval bv;
1053                 bv.bv_val = cav->cav_ptr;
1054                 bv.bv_len = cav_cur_len( cav );
1055                 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
1056                 if ( rc != LDAP_SUCCESS ) {
1057                         if ( op )
1058                                 op->o_tmpfree( _ca, op->o_tmpmemctx );
1059                         else
1060                                 free( _ca );
1061                         return rc;
1062                 }
1063                 cav->cav_ptr = bv.bv_val;
1064                 assert( cav->cav_end >= bv.bv_val );
1065         }
1066
1067         *ca = _ca;
1068         return LDAP_SUCCESS;
1069 }
1070
1071 static int
1072 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
1073                                 ComponentFilter** filt, const char** text )
1074 {
1075         /*
1076          * A component filter looks like this coming in:
1077          *      Filter ::= CHOICE {
1078          *              item    [0]     ComponentAssertion,
1079          *              and     [1]     SEQUENCE OF ComponentFilter,
1080          *              or      [2]     SEQUENCE OF ComponentFilter,
1081          *              not     [3]     ComponentFilter,
1082          *      }
1083          */
1084
1085         ber_tag_t       tag;
1086         int             err;
1087         ComponentFilter f;
1088         /* TAG : item, and, or, not in RFC 2254 */
1089         tag = strip_cav_tag( cav );
1090
1091         if ( tag == LBER_ERROR ) {
1092                 *text = "error decoding comp filter";
1093                 return LDAP_PROTOCOL_ERROR;
1094         }
1095
1096         if ( tag != LDAP_COMP_FILTER_NOT )
1097                 strip_cav_str( cav, "{");
1098
1099         err = LDAP_SUCCESS;
1100
1101         f.cf_next = NULL;
1102         f.cf_choice = tag; 
1103
1104         switch ( f.cf_choice ) {
1105         case LDAP_COMP_FILTER_AND:
1106         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
1107                 err = get_comp_filter_list( op, cav, &f.cf_and, text );
1108                 if ( err != LDAP_SUCCESS ) {
1109                         break;
1110                 }
1111                 if ( f.cf_and == NULL ) {
1112                         f.cf_choice = SLAPD_FILTER_COMPUTED;
1113                         f.cf_result = LDAP_COMPARE_TRUE;
1114                 }
1115                 break;
1116
1117         case LDAP_COMP_FILTER_OR:
1118         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
1119                 err = get_comp_filter_list( op, cav, &f.cf_or, text );
1120                 if ( err != LDAP_SUCCESS ) {
1121                         break;
1122                 }
1123                 if ( f.cf_or == NULL ) {
1124                         f.cf_choice = SLAPD_FILTER_COMPUTED;
1125                         f.cf_result = LDAP_COMPARE_FALSE;
1126                 }
1127                 /* no assert - list could be empty */
1128                 break;
1129
1130         case LDAP_COMP_FILTER_NOT:
1131         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
1132                 err = parse_comp_filter( op, cav, &f.cf_not, text );
1133                 if ( err != LDAP_SUCCESS ) {
1134                         break;
1135                 }
1136
1137                 assert( f.cf_not != NULL );
1138                 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
1139                         int fresult = f.cf_not->cf_result;
1140                         f.cf_choice = SLAPD_FILTER_COMPUTED;
1141                         op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
1142                         f.cf_not = NULL;
1143
1144                         switch ( fresult ) {
1145                         case LDAP_COMPARE_TRUE:
1146                                 f.cf_result = LDAP_COMPARE_FALSE;
1147                                 break;
1148                         case LDAP_COMPARE_FALSE:
1149                                 f.cf_result = LDAP_COMPARE_TRUE;
1150                                 break;
1151                         default: ;
1152                                 /* (!Undefined) is Undefined */
1153                         }
1154                 }
1155                 break;
1156
1157         case LDAP_COMP_FILTER_ITEM:
1158         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1159                 err = get_item( op, cav, &f.cf_ca, text );
1160                 if ( err != LDAP_SUCCESS ) {
1161                         break;
1162                 }
1163
1164                 assert( f.cf_ca != NULL );
1165                 break;
1166
1167         default:
1168                 f.cf_choice = SLAPD_FILTER_COMPUTED;
1169                 f.cf_result = SLAPD_COMPARE_UNDEFINED;
1170                 break;
1171         }
1172
1173         if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1174                 *text = "Component Filter Syntax Error";
1175                 return err;
1176         }
1177
1178         if ( tag != LDAP_COMP_FILTER_NOT )
1179                 strip_cav_str( cav, "}");
1180
1181         if ( err == LDAP_SUCCESS ) {
1182                 if ( op ) {
1183                         *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1184                 } else {
1185                         *filt = malloc( sizeof(f) );
1186                 }
1187                 **filt = f;
1188         }
1189
1190         return( err );
1191 }
1192
1193 static int
1194 test_comp_filter_and(
1195         Syntax *syn,
1196         ComponentSyntaxInfo *a,
1197         ComponentFilter *flist )
1198 {
1199         ComponentFilter *f;
1200         int rtn = LDAP_COMPARE_TRUE;
1201
1202         for ( f = flist ; f != NULL; f = f->cf_next ) {
1203                 int rc = test_comp_filter( syn, a, f );
1204                 if ( rc == LDAP_COMPARE_FALSE ) {
1205                         rtn = rc;
1206                         break;
1207                 }
1208         
1209                 if ( rc != LDAP_COMPARE_TRUE ) {
1210                         rtn = rc;
1211                 }
1212         }
1213
1214         return rtn;
1215 }
1216
1217 static int
1218 test_comp_filter_or(
1219         Syntax *syn,
1220         ComponentSyntaxInfo *a,
1221         ComponentFilter *flist )
1222 {
1223         ComponentFilter *f;
1224         int rtn = LDAP_COMPARE_TRUE;
1225
1226         for ( f = flist ; f != NULL; f = f->cf_next ) {
1227                 int rc = test_comp_filter( syn, a, f );
1228                 if ( rc == LDAP_COMPARE_TRUE ) {
1229                         rtn = rc;
1230                         break;
1231                 }
1232         
1233                 if ( rc != LDAP_COMPARE_FALSE ) {
1234                         rtn = rc;
1235                 }
1236         }
1237
1238         return rtn;
1239 }
1240
1241 int
1242 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1243         struct berval* bv_assert )
1244 {
1245         int rc;
1246         int match;
1247
1248         assert( mr != NULL );
1249         assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1250
1251         if( !mr->smr_match ) return LDAP_INAPPROPRIATE_MATCHING;
1252
1253         rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1254                 mr, bv_attr, bv_assert );
1255
1256         if ( rc != LDAP_SUCCESS ) return rc;
1257
1258         return match ? LDAP_COMPARE_FALSE : LDAP_COMPARE_TRUE;
1259 }
1260
1261 /*
1262  * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1263  */
1264 static int
1265 test_comp_filter_item(
1266         Syntax *syn,
1267         ComponentSyntaxInfo *csi_attr,
1268         ComponentAssertion *ca )
1269 {
1270         int rc, len;
1271         void *attr_nm, *assert_nm;
1272
1273         if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1274                 OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1275                 /* componentFilterMatch inside of componentFilterMatch */
1276                 rc = test_comp_filter( syn, csi_attr, ca->ca_cf );
1277                 return rc;
1278         }
1279
1280         /* Memory for storing will-be-extracted attribute values */
1281         attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1282         if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
1283
1284         /* Memory for storing component assertion values */
1285         if( !ca->ca_comp_data.cd_mem_op ) {
1286                 assert_nm = nibble_mem_allocator ( 256, 64 );
1287                 if ( !assert_nm ) {
1288                         nibble_mem_free ( attr_nm );
1289                         return LDAP_PROTOCOL_ERROR;
1290                 }
1291                 ca->ca_comp_data.cd_mem_op = assert_nm;
1292
1293         } else {
1294                 assert_nm = ca->ca_comp_data.cd_mem_op;
1295         }
1296
1297         /* component reference initialization */
1298         if ( ca->ca_comp_ref ) {
1299                 ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1300         }
1301         rc = test_components( attr_nm, assert_nm, csi_attr, ca );
1302
1303         /* free memory used for storing extracted attribute value */
1304         nibble_mem_free ( attr_nm );
1305         return rc;
1306 }
1307
1308 static int
1309 test_comp_filter(
1310     Syntax *syn,
1311     ComponentSyntaxInfo *a,
1312     ComponentFilter *f )
1313 {
1314         int     rc;
1315
1316         if ( !f ) return LDAP_PROTOCOL_ERROR;
1317
1318         Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
1319         switch ( f->cf_choice ) {
1320         case SLAPD_FILTER_COMPUTED:
1321                 rc = f->cf_result;
1322                 break;
1323         case LDAP_COMP_FILTER_AND:
1324                 rc = test_comp_filter_and( syn, a, f->cf_and );
1325                 break;
1326         case LDAP_COMP_FILTER_OR:
1327                 rc = test_comp_filter_or( syn, a, f->cf_or );
1328                 break;
1329         case LDAP_COMP_FILTER_NOT:
1330                 rc = test_comp_filter( syn, a, f->cf_not );
1331
1332                 switch ( rc ) {
1333                 case LDAP_COMPARE_TRUE:
1334                         rc = LDAP_COMPARE_FALSE;
1335                         break;
1336                 case LDAP_COMPARE_FALSE:
1337                         rc = LDAP_COMPARE_TRUE;
1338                         break;
1339                 }
1340                 break;
1341         case LDAP_COMP_FILTER_ITEM:
1342                 rc = test_comp_filter_item( syn, a, f->cf_ca );
1343                 break;
1344         default:
1345                 rc = LDAP_PROTOCOL_ERROR;
1346         }
1347
1348         return( rc );
1349 }
1350
1351 static void
1352 free_comp_filter_list( ComponentFilter* f )
1353 {
1354         ComponentFilter* tmp;
1355         for ( tmp = f; tmp; tmp = tmp->cf_next ) {
1356                 free_comp_filter( tmp );
1357         }
1358 }
1359
1360 static void
1361 free_comp_filter( ComponentFilter* f )
1362 {
1363         if ( !f ) {
1364                 Debug( LDAP_DEBUG_FILTER,
1365                         "free_comp_filter: Invalid filter so failed to release memory\n",
1366                         0, 0, 0 );
1367                 return;
1368         }
1369         switch ( f->cf_choice ) {
1370         case LDAP_COMP_FILTER_AND:
1371         case LDAP_COMP_FILTER_OR:
1372                 free_comp_filter_list( f->cf_any );
1373                 break;
1374         case LDAP_COMP_FILTER_NOT:
1375                 free_comp_filter( f->cf_any );
1376                 break;
1377         case LDAP_COMP_FILTER_ITEM:
1378                 if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op ) {
1379                         nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1380                 }
1381                 break;
1382         default:
1383                 break;
1384         }
1385 }
1386
1387 void
1388 component_free( ComponentFilter *f ) {
1389         free_comp_filter( f );
1390 }
1391
1392 void
1393 free_ComponentData( Attribute *a ) {
1394         if ( a->a_comp_data->cd_mem_op )
1395                 component_destructor( a->a_comp_data->cd_mem_op );
1396         free ( a->a_comp_data );
1397         a->a_comp_data = NULL;
1398 }
1399 #endif