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