]> git.sur5r.net Git - openldap/blob - servers/slapd/component.c
ced9d9baea81155751c2fe3570d1d622269bfd40
[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;
267         bzero( &dup_f, sizeof(dup_f));
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         rc = 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 static int
516 get_component_reference( Operation *op, ComponentAssertionValue* cav,
517                         ComponentReference** cr, const char** text )
518 {
519         int rc, count = 0;
520         ber_int_t type;
521         ComponentReference* ca_comp_ref;
522         ComponentId** cr_list;
523
524         eat_whsp( cav );
525
526         if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS )
527                 return rc;
528
529         if ( op )
530                 ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
531         else
532                 ca_comp_ref = malloc( sizeof( ComponentReference ) );
533
534         if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
535
536         cr_list = &ca_comp_ref->cr_list;
537
538         for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
539                 ; type = comp_next_id( cav ), count++ ) {
540                 rc = get_componentId( op, cav, cr_list, text );
541                 if ( rc == LDAP_SUCCESS ) {
542                         if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
543                         cr_list = &(*cr_list)->ci_next;
544                 }
545                 else if ( rc == LDAP_COMPREF_UNDEFINED )
546                         return rc;
547         }
548         ca_comp_ref->cr_len = count;
549
550         if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
551                 if ( op )
552                         op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
553                 else
554                         free( ca_comp_ref );
555                 return rc;
556         }
557
558         if ( rc == LDAP_SUCCESS ) {     
559                 *cr = ca_comp_ref;
560                 **cr = *ca_comp_ref;    
561         }
562         else if ( op )
563                  op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
564         else
565                  free( ca_comp_ref ) ;
566
567         return rc;
568 }
569
570 static int
571 get_ca_use_default( Operation *op, ComponentAssertionValue* cav,
572                 int* ca_use_def, const char**  text )
573 {
574         strip_cav_str( cav, "useDefaultValues" );
575         if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
576                 strip_cav_str( cav, "TRUE" );
577                 *ca_use_def = 1;
578         } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
579                 strip_cav_str( cav, "FALSE" );
580                 *ca_use_def = 0;
581         } else {
582                 return LDAP_INVALID_SYNTAX;
583         }
584
585         return LDAP_SUCCESS;
586 }
587
588 static int
589 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
590                 MatchingRule** mr, const char**  text )
591 {
592         int count = 0;
593         struct berval rule_text = { 0L, NULL };
594
595         eat_whsp( cav );
596
597         for ( ; ; count++ ) {
598                 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
599                         cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
600                         cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
601                         break;
602         }
603
604         if ( count == 0 ) {
605                 *text = "component matching rule not recognized";
606                 return LDAP_INAPPROPRIATE_MATCHING;
607         }
608         
609         rule_text.bv_len = count;
610         rule_text.bv_val = cav->cav_ptr;
611         *mr = mr_bvfind( &rule_text );
612         cav->cav_ptr += count;
613         Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n", (*mr)->smr_mrule.mr_oid, 0, 0 );
614         if ( *mr == NULL ) {
615                 *text = "component matching rule not recognized";
616                 return LDAP_INAPPROPRIATE_MATCHING;
617         }
618         return LDAP_SUCCESS;
619 }
620
621 static int
622 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
623 {
624         int count, sequent_dquote, unclosed_brace, succeed;
625
626         eat_whsp( cav );
627         /*
628          * Four cases of GSER <Values>
629          * 1) "..." :
630          *      StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
631          * 2) '...'B or '...'H :
632          *      BitStringVal, OctetStringVal
633          * 3) {...} :
634          *      SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
635          * 4) Between two white spaces
636          *      INTEGER, BOOLEAN, NULL,ENUMERATE, etc
637          */
638
639         succeed = 0;
640         if ( cav->cav_ptr[0] == '"' ) {
641                 for( count = 1, sequent_dquote = 0 ; ; count++ ) {
642                         /* In order to find escaped double quote */
643                         if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
644                         else sequent_dquote = 0;
645
646                         if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
647                                 break;
648                         }
649                                 
650                         if ( ( cav->cav_ptr[count] == '"' && cav->cav_ptr[count-1] != '"') ||
651                         ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) ) {
652                                 succeed = 1;
653                                 break;
654                         }
655                 }
656                 
657                 if ( !succeed || cav->cav_ptr[count] != '"' )
658                         return LDAP_FILTER_ERROR;
659
660                 bv->bv_val = cav->cav_ptr + 1;
661                 bv->bv_len = count - 1; /* exclude '"' */
662         }
663         else if ( cav->cav_ptr[0] == '\'' ) {
664                 for( count = 1 ; ; count++ ) {
665                         if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
666                                 break;
667                         }
668                         if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B')||
669                         (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') ) {
670                                 succeed = 1;
671                                 break;
672                         }
673                 }
674
675                 if ( !succeed || !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
676                         return LDAP_FILTER_ERROR;
677
678                 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
679                 bv->bv_len = count - 2;/* exclude "'H" or "'B" */
680                                 
681         }
682         else if ( cav->cav_ptr[0] == '{' ) {
683                 for( count = 1, unclosed_brace = 1 ; ; count++ ) {
684                         if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
685                         if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
686
687                         if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end )
688                                 break;
689                         if ( unclosed_brace == 0 ) {
690                                 succeed = 1;
691                                 break;
692                         }
693                 }
694
695                 if ( !succeed || cav->cav_ptr[count] != '}' )
696                         return LDAP_FILTER_ERROR;
697
698                 bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
699                 bv->bv_len = count - 1;/* exclude  "'B" */
700         }
701         else {
702                 succeed = 1;
703                 /*Find  following white space where the value is ended*/
704                 for( count = 1 ; ; count++ ) {
705                         if ( cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == ' ' || (cav->cav_ptr+count) > cav->cav_end ) {
706                                 break;
707                         }
708                 }
709                 bv->bv_val = cav->cav_ptr;
710                 bv->bv_len = count;
711         }
712
713         cav->cav_ptr += bv->bv_len;
714
715         return LDAP_SUCCESS;
716 }
717
718 static int
719 get_matching_value( Operation *op, ComponentAssertion* ca,
720                         ComponentAssertionValue* cav, struct berval* bv,
721                         const char**  text )
722 {
723         if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
724                 if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
725                         return LDAP_FILTER_ERROR;
726                 }
727
728         } else {
729                 /* embeded componentFilterMatch Description */
730                 bv->bv_val = cav->cav_ptr;
731                 bv->bv_len = cav_cur_len( cav );
732         }
733
734         return LDAP_SUCCESS;
735 }
736
737 /* Don't move the position pointer, just peek given string */
738 static int
739 peek_cav_str( ComponentAssertionValue* cav, char* str )
740 {
741         eat_whsp( cav );
742         if ( cav_cur_len( cav ) >= strlen( str ) &&
743                 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
744                 return LDAP_SUCCESS;
745         else 
746                 return LDAP_INVALID_SYNTAX;
747 }
748
749 static int
750 strip_cav_str( ComponentAssertionValue* cav, char* str)
751 {
752         eat_whsp( cav );
753         if ( cav_cur_len( cav ) >= strlen( str ) &&
754                 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 ) {
755                 cav->cav_ptr += strlen( str );
756                 return LDAP_SUCCESS;
757         }
758         else 
759                 return LDAP_INVALID_SYNTAX;
760 }
761
762 /*
763  * TAG : "item", "and", "or", "not"
764  */
765 static int
766 strip_cav_tag( ComponentAssertionValue* cav )
767 {
768
769         eat_whsp( cav );
770         if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
771                 strip_cav_str( cav , "item:" );
772                 return LDAP_COMP_FILTER_ITEM;
773         }
774         else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
775                 strip_cav_str( cav , "and:" );
776                 return LDAP_COMP_FILTER_AND;
777         }
778         else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
779                 strip_cav_str( cav , "or:" );
780                 return LDAP_COMP_FILTER_OR;
781         }
782         else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
783                 strip_cav_str( cav , "not:" );
784                 return LDAP_COMP_FILTER_NOT;
785         }
786         else
787                 return LBER_ERROR;
788 }
789
790 /*
791  * when encoding, "item" is denotation of ComponentAssertion
792  * ComponentAssertion :: SEQUENCE {
793  *      component               ComponentReference (SIZE(1..MAX)) OPTIONAL,
794  *      useDefaultValues        BOOLEAN DEFAULT TRUE,
795  *      rule                    MATCHING-RULE.&id,
796  *      value                   MATCHING-RULE.&AssertionType }
797  */
798 static int
799 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
800                 const char** text )
801 {
802         int rc;
803         ComponentAssertion* _ca;
804         struct berval t_bv;
805         struct berval value;
806         MatchingRule* mr;
807
808         Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
809         if ( op )
810                 _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
811         else
812                 _ca = malloc( sizeof( ComponentAssertion ) );
813
814         if ( !_ca ) return LDAP_NO_MEMORY;
815
816         _ca->ca_comp_data.cd_tree = NULL;
817         _ca->ca_comp_data.cd_mem_op = NULL;
818
819         rc = peek_cav_str( cav, "component" );
820         if ( rc == LDAP_SUCCESS ) {
821                 strip_cav_str( cav, "component" );
822                 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
823                 if ( rc != LDAP_SUCCESS ) {
824                         if ( op )
825                                 op->o_tmpfree( _ca, op->o_tmpmemctx );
826                         else
827                                 free( _ca );
828                         return LDAP_INVALID_SYNTAX;
829                 }
830         }
831
832         if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
833                 return rc;
834
835         rc = peek_cav_str( cav, "useDefaultValues");
836         if ( rc == LDAP_SUCCESS ) {
837                 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
838                 if ( rc != LDAP_SUCCESS ) {
839                         if ( op )
840                                 op->o_tmpfree( _ca, op->o_tmpmemctx );
841                         else
842                                 free( _ca );
843                         return LDAP_INVALID_SYNTAX;
844                 }
845                 if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
846                         return rc;
847         }
848         else _ca->ca_use_def = 1;
849
850         if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
851                 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
852                 if ( op )
853                         op->o_tmpfree( _ca, op->o_tmpmemctx );
854                 else
855                         free( _ca );
856                 return LDAP_INAPPROPRIATE_MATCHING;
857         }
858         
859         if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
860                 return rc;
861         if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
862                 get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
863                 if ( op )
864                         op->o_tmpfree( _ca, op->o_tmpmemctx );
865                 else
866                         free( _ca );
867                 return LDAP_INVALID_SYNTAX;
868         }
869
870         /*
871          * Normalize the value of this component assertion when the matching
872          * rule is one of existing matching rules
873          */
874         mr = _ca->ca_ma_rule;
875         if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
876
877                 value.bv_val[value.bv_len] = '\0';
878                 rc = mr->smr_normalize (
879                 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
880                 NULL, mr,
881                 &value, &_ca->ca_ma_value, op->o_tmpmemctx );
882                 if ( rc != LDAP_SUCCESS )
883                         return rc;
884         }
885         else
886                 _ca->ca_ma_value = value;
887         /*
888          * Validate the value of this component assertion
889          */
890         if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
891                 return LDAP_INVALID_SYNTAX;
892         }
893
894
895         /* componentFilterMatch contains componentFilterMatch in it */
896         if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
897                 struct berval bv;
898                 bv.bv_val = cav->cav_ptr;
899                 bv.bv_len = cav_cur_len( cav );
900                 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
901                 if ( rc != LDAP_SUCCESS ) {
902                         if ( op )
903                                 op->o_tmpfree( _ca, op->o_tmpmemctx );
904                         else
905                                 free( _ca );
906                         return rc;
907                 }
908                 cav->cav_ptr = bv.bv_val;
909                 assert( cav->cav_end >= bv.bv_val );
910         }
911
912         *ca = _ca;
913         return LDAP_SUCCESS;
914 }
915
916 static int
917 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
918                                 ComponentFilter** filt, const char** text )
919 {
920         /*
921          * A component filter looks like this coming in:
922          *      Filter ::= CHOICE {
923          *              item    [0]     ComponentAssertion,
924          *              and     [1]     SEQUENCE OF ComponentFilter,
925          *              or      [2]     SEQUENCE OF ComponentFilter,
926          *              not     [3]     ComponentFilter,
927          *      }
928          */
929
930         ber_tag_t       tag;
931         int             err;
932         ComponentFilter f;
933         /* TAG : item, and, or, not in RFC 2254 */
934         tag = strip_cav_tag( cav );
935
936         if ( tag == LBER_ERROR ) {
937                 *text = "error decoding comp filter";
938                 return LDAP_PROTOCOL_ERROR;
939         }
940
941         if ( tag != LDAP_COMP_FILTER_NOT )
942                 strip_cav_str( cav, "{");
943
944         err = LDAP_SUCCESS;
945
946         f.cf_next = NULL;
947         f.cf_choice = tag; 
948
949         switch ( f.cf_choice ) {
950         case LDAP_COMP_FILTER_AND:
951         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
952                 err = get_comp_filter_list( op, cav, &f.cf_and, text );
953                 if ( err != LDAP_SUCCESS ) {
954                         break;
955                 }
956                 if ( f.cf_and == NULL ) {
957                         f.cf_choice = SLAPD_FILTER_COMPUTED;
958                         f.cf_result = LDAP_COMPARE_TRUE;
959                 }
960                 break;
961
962         case LDAP_COMP_FILTER_OR:
963         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
964                 err = get_comp_filter_list( op, cav, &f.cf_or, text );
965                 if ( err != LDAP_SUCCESS ) {
966                         break;
967                 }
968                 if ( f.cf_or == NULL ) {
969                         f.cf_choice = SLAPD_FILTER_COMPUTED;
970                         f.cf_result = LDAP_COMPARE_FALSE;
971                 }
972                 /* no assert - list could be empty */
973                 break;
974
975         case LDAP_COMP_FILTER_NOT:
976         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
977                 err = parse_comp_filter( op, cav, &f.cf_not, text );
978                 if ( err != LDAP_SUCCESS ) {
979                         break;
980                 }
981
982                 assert( f.cf_not != NULL );
983                 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
984                         int fresult = f.cf_not->cf_result;
985                         f.cf_choice = SLAPD_FILTER_COMPUTED;
986                         op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
987                         f.cf_not = NULL;
988
989                         switch ( fresult ) {
990                         case LDAP_COMPARE_TRUE:
991                                 f.cf_result = LDAP_COMPARE_FALSE;
992                                 break;
993                         case LDAP_COMPARE_FALSE:
994                                 f.cf_result = LDAP_COMPARE_TRUE;
995                                 break;
996                         default: ;
997                                 /* (!Undefined) is Undefined */
998                         }
999                 }
1000                 break;
1001
1002         case LDAP_COMP_FILTER_ITEM:
1003         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
1004                 err = get_item( op, cav, &f.cf_ca, text );
1005                 if ( err != LDAP_SUCCESS ) {
1006                         break;
1007                 }
1008
1009                 assert( f.cf_ca != NULL );
1010                 break;
1011
1012         default:
1013                 f.cf_choice = SLAPD_FILTER_COMPUTED;
1014                 f.cf_result = SLAPD_COMPARE_UNDEFINED;
1015                 break;
1016         }
1017
1018         if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
1019                 *text = "Component Filter Syntax Error";
1020                 return err;
1021         }
1022
1023         if ( tag != LDAP_COMP_FILTER_NOT )
1024                 strip_cav_str( cav, "}");
1025
1026         if ( err == LDAP_SUCCESS ) {
1027                 if ( op ) {
1028                         *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
1029                 } else {
1030                         *filt = malloc( sizeof(f) );
1031                 }
1032                 **filt = f;
1033         }
1034
1035         return( err );
1036 }
1037
1038 static int
1039 test_comp_filter_and(
1040         Syntax *syn,
1041         Attribute *a,
1042         struct berval  *bv,
1043         ComponentFilter *flist )
1044 {
1045         ComponentFilter *f;
1046         int rtn = LDAP_COMPARE_TRUE;
1047
1048         for ( f = flist ; f != NULL; f = f->cf_next ) {
1049                 int rc = test_comp_filter( syn, a, bv, f );
1050                 if ( rc == LDAP_COMPARE_FALSE ) {
1051                         rtn = rc;
1052                         break;
1053                 }
1054         
1055                 if ( rc != LDAP_COMPARE_TRUE ) {
1056                         rtn = rc;
1057                 }
1058         }
1059
1060         return rtn;
1061 }
1062
1063 static int
1064 test_comp_filter_or(
1065         Syntax *syn,
1066         Attribute *a,
1067         struct berval     *bv,
1068         ComponentFilter *flist )
1069 {
1070         ComponentFilter *f;
1071         int rtn = LDAP_COMPARE_TRUE;
1072
1073         for ( f = flist ; f != NULL; f = f->cf_next ) {
1074                 int rc = test_comp_filter( syn, a, bv, f );
1075                 if ( rc == LDAP_COMPARE_TRUE ) {
1076                         rtn = rc;
1077                         break;
1078                 }
1079         
1080                 if ( rc != LDAP_COMPARE_FALSE ) {
1081                         rtn = rc;
1082                 }
1083         }
1084
1085         return rtn;
1086 }
1087
1088 int
1089 csi_value_match( MatchingRule *mr, struct berval* bv_attr,
1090                 struct berval* bv_assert )
1091 {
1092         int rc;
1093         int match;
1094
1095         assert( mr != NULL );
1096         assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
1097
1098         if( !mr->smr_match ) {
1099                 return LDAP_INAPPROPRIATE_MATCHING;
1100         }
1101
1102         rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
1103                                 mr, bv_attr, bv_assert );
1104         if ( rc == LDAP_SUCCESS )
1105                 return match? LDAP_COMPARE_FALSE:LDAP_COMPARE_TRUE;
1106         else
1107                 return rc;
1108 }
1109
1110 /*
1111  * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
1112  */
1113 static int
1114 test_comp_filter_item(
1115         Syntax *syn,
1116         Attribute       *a,
1117         struct berval   *bv,
1118         ComponentAssertion *ca )
1119 {
1120         int rc, len;
1121         ComponentSyntaxInfo* csi_attr, *csi_assert=NULL;
1122         void *attr_nm, *assert_nm;
1123
1124         if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
1125                 OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
1126                 /* componentFilterMatch inside of componentFilterMatch */
1127                 rc = test_comp_filter( syn, a, bv, ca->ca_cf );
1128                 return rc;
1129         }
1130
1131         /* load attribute containg components */
1132         if ( !a->a_comp_data && attr_converter && nibble_mem_allocator ) {
1133                 a->a_comp_data = malloc( sizeof( ComponentData ) );
1134                 /* Memory chunk pre-allocation for decoders */
1135                 a->a_comp_data->cd_mem_op = (void*) nibble_mem_allocator ( 1024, 128 );
1136                 a->a_comp_data->cd_tree = attr_converter (a, syn, bv);
1137         }
1138
1139         if ( a->a_comp_data->cd_tree == NULL ) {
1140                 nibble_mem_free( a->a_comp_data->cd_mem_op );
1141                 free ( a->a_comp_data );
1142                 a->a_comp_data = NULL;
1143                 return LDAP_PROTOCOL_ERROR;
1144         }
1145
1146         /* Memory for storing will-be-extracted attribute values */
1147         attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
1148         if ( !attr_nm )return LDAP_PROTOCOL_ERROR;
1149
1150         /* Memory for storing component assertion values */
1151         if( !ca->ca_comp_data.cd_mem_op ) {
1152                 assert_nm = nibble_mem_allocator ( 256, 64 );
1153                 if ( !assert_nm ) {
1154                         nibble_mem_free ( attr_nm );
1155                         return LDAP_PROTOCOL_ERROR;
1156                 }
1157                 ca->ca_comp_data.cd_mem_op = assert_nm;
1158         }
1159         else {
1160                 assert_nm = ca->ca_comp_data.cd_mem_op;
1161         }
1162
1163         /* component reference initialization */
1164         ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
1165         rc = test_components( attr_nm, assert_nm, (ComponentSyntaxInfo*)a->a_comp_data->cd_tree, ca );
1166
1167         /* free memory used for storing extracted attribute value */
1168         nibble_mem_free ( attr_nm );
1169         return rc;
1170 }
1171
1172 static int
1173 test_comp_filter(
1174     Syntax *syn,
1175     Attribute   *a,
1176     struct berval *bv,
1177     ComponentFilter *f )
1178 {
1179         int     rc;
1180
1181         if ( !f ) return LDAP_PROTOCOL_ERROR;
1182
1183         Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
1184         switch ( f->cf_choice ) {
1185         case SLAPD_FILTER_COMPUTED:
1186                 rc = f->cf_result;
1187                 break;
1188         case LDAP_COMP_FILTER_AND:
1189                 rc = test_comp_filter_and( syn, a, bv, f->cf_and );
1190                 break;
1191         case LDAP_COMP_FILTER_OR:
1192                 rc = test_comp_filter_or( syn, a, bv, f->cf_or );
1193                 break;
1194         case LDAP_COMP_FILTER_NOT:
1195                 rc = test_comp_filter( syn, a, bv, f->cf_not );
1196
1197                 switch ( rc ) {
1198                 case LDAP_COMPARE_TRUE:
1199                         rc = LDAP_COMPARE_FALSE;
1200                         break;
1201                 case LDAP_COMPARE_FALSE:
1202                         rc = LDAP_COMPARE_TRUE;
1203                         break;
1204                 }
1205                 break;
1206         case LDAP_COMP_FILTER_ITEM:
1207                 rc = test_comp_filter_item( syn, a, bv, f->cf_ca );
1208                 break;
1209         default:
1210                 rc = LDAP_PROTOCOL_ERROR;
1211         }
1212
1213         return( rc );
1214 }
1215
1216 static void
1217 free_comp_filter_list( ComponentFilter* f )
1218 {
1219         ComponentFilter* tmp;
1220         for ( tmp = f ; tmp; tmp = tmp->cf_next );
1221         {
1222                 free_comp_filter( tmp );
1223         }
1224 }
1225
1226 static void
1227 free_comp_filter( ComponentFilter* f )
1228 {
1229         switch ( f->cf_choice ) {
1230         case LDAP_COMP_FILTER_AND:
1231         case LDAP_COMP_FILTER_OR:
1232                 free_comp_filter_list( f->cf_any );
1233                 break;
1234         case LDAP_COMP_FILTER_NOT:
1235                 free_comp_filter( f->cf_any );
1236                 break;
1237         case LDAP_COMP_FILTER_ITEM:
1238                 if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op )
1239                         nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );
1240                 break;
1241
1242         default:
1243                 break;
1244         }
1245 }
1246
1247 void
1248 component_free( ComponentFilter *f ) {
1249         free_comp_filter( f );
1250 }
1251
1252 #endif