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