]> git.sur5r.net Git - openldap/blob - servers/slapd/component.c
d0b7e0af61d6f15813977f50914fb9e03bd9eb2c
[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 "ldap_pvt.h"
24 #include "lutil.h"
25 #include <ldap.h>
26 #include "slap.h"
27
28 #ifdef LDAP_COMP_MATCH
29
30 #include "asn.h"
31
32 static int
33 peek_componentId_type( ComponentAssertionValue* cav );
34
35 static int
36 strip_cav_str( ComponentAssertionValue* cav, char* str);
37
38 static int
39 peek_cav_str( ComponentAssertionValue* cav, char* str );
40
41 static int
42 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
43                                 ComponentFilter** filt, const char** text );
44
45 static int
46 test_comp_filter_attr( Operation *op, Attribute *a, struct berval *bv,
47                         ComponentFilter *f );
48
49 int
50 componentFilterValidate(
51         Syntax *syntax,
52         struct berval *val )
53 {
54         return LDAP_SUCCESS;
55 }
56
57 int
58 componentFilterMatch ( 
59         int *matchp, 
60         slap_mask_t flags, 
61         Syntax *syntax, 
62         MatchingRule *mr,
63         struct berval *value, 
64         void *assertedValue )
65 {
66         /* FIXME: to be implemented */
67         *matchp = 0;
68         return LDAP_SUCCESS;
69 }
70
71
72 static int
73 slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav)
74 {
75         int len;
76
77         len = ldap_pvt_filter_value_unescape( bv->bv_val );
78         cav->cav_ptr = cav->cav_buf = bv->bv_val;
79         cav->cav_end = bv->bv_val + len;
80 }
81
82 int
83 get_comp_filter ( Operation* op, struct berval* bv, ComponentFilter** filt,
84                                  const char **text )
85 {
86         ComponentAssertionValue cav;
87         int len, rc;
88         Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
89         slapd_ber2cav(bv, &cav);
90         rc = parse_comp_filter( op, &cav, filt, text );
91         bv->bv_val = cav.cav_ptr;
92         return rc;
93 }
94
95 static void
96 eat_whsp( ComponentAssertionValue* cav )
97 {
98         while ( ( cav->cav_ptr <= cav->cav_end ) && ( *cav->cav_ptr == ' ' ) )
99                cav->cav_ptr++;
100 }
101
102 static int
103 cav_cur_len( ComponentAssertionValue* cav )
104 {
105         return cav->cav_end - cav->cav_ptr;
106 }
107
108 static ber_tag_t
109 comp_first_element( ComponentAssertionValue* cav )
110 {
111         eat_whsp( cav );
112         if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
113                 return LDAP_COMP_FILTER_ITEM;
114         }
115         else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
116                 return LDAP_COMP_FILTER_AND;
117         }
118         else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
119                 return LDAP_COMP_FILTER_OR;
120         }
121         else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
122                 return LDAP_COMP_FILTER_NOT;
123         }
124         else
125                 return LDAP_COMP_FILTER_UNDEFINED;
126 }
127
128 static ber_tag_t
129 comp_next_element( ComponentAssertionValue* cav )
130 {
131
132         eat_whsp( cav );
133         if ( *(cav->cav_ptr) == ',' ) {
134                 /* move pointer to the next CA */
135                 cav->cav_ptr++;
136                 return comp_first_element( cav );
137         }
138         else return LDAP_COMP_FILTER_UNDEFINED;
139 }
140
141 static int
142 get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
143                         ComponentFilter** f, const char** text )
144 {
145         ComponentFilter **new;
146         int             err;
147         ber_tag_t       tag;
148         ber_len_t       len;
149         char            *last;
150
151         Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
152         new = f;
153         for ( tag = comp_first_element( cav ); tag != LDAP_COMP_FILTER_UNDEFINED;
154                 tag = comp_next_element( cav ) )
155         {
156                 err = parse_comp_filter( op, cav, new, text );
157                 if ( err != LDAP_SUCCESS )
158                         return ( err );
159                 new = &(*new)->cf_next;
160         }
161         *new = NULL;
162
163
164         return( LDAP_SUCCESS );
165 }
166
167 static int
168 get_componentId( Operation *op, ComponentAssertionValue* cav,
169                         ComponentId ** cid, const char** text )
170 {
171         ber_tag_t type;
172         ComponentId _cid;
173         int len;
174
175         type = peek_componentId_type( cav );
176
177         Debug( LDAP_DEBUG_FILTER, "get_compId [%d]\n", type, 0, 0 );
178         len = 0;
179         _cid.ci_type = type;
180         _cid.ci_next = NULL;
181         switch ( type ) {
182         case LDAP_COMPREF_IDENTIFIER :
183                 _cid.ci_val.ci_identifier.bv_val = cav->cav_ptr;
184                 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
185                         cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
186                 _cid.ci_val.ci_identifier.bv_len = len;
187                 cav->cav_ptr += len;
188                 break;
189         case LDAP_COMPREF_FROM_BEGINNING :
190                 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
191                         cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
192                 _cid.ci_val.ci_from_beginning = strtol( cav->cav_ptr, NULL, 0 );
193                 cav->cav_ptr += len;
194                 break;
195         case LDAP_COMPREF_FROM_END :
196                 for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
197                         cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' ; len++ );
198                 _cid.ci_val.ci_from_end = strtol( cav->cav_ptr, NULL, 0 );
199                 cav->cav_ptr += len;
200                 break;
201         case LDAP_COMPREF_COUNT :
202                 _cid.ci_val.ci_count = 0;
203                 cav->cav_ptr++;
204                 break;
205         case LDAP_COMPREF_CONTENT :
206                 /* FIXEME: yet to be implemented */
207                 break;
208         case LDAP_COMPREF_SELECT :
209                 /* FIXEME: yet to be implemented */
210                 break;
211         case LDAP_COMPREF_ALL :
212                 _cid.ci_val.ci_all = '*';
213                 cav->cav_ptr++;
214         Debug( LDAP_DEBUG_FILTER, "get_compId : ALL\n", 0, 0, 0 );
215                 break;
216         default :
217                 return LDAP_COMPREF_UNDEFINED;
218         }
219
220         *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
221         **cid = _cid;
222         return LDAP_SUCCESS;
223 }
224
225 static int
226 peek_componentId_type( ComponentAssertionValue* cav )
227 {
228         eat_whsp( cav );
229         if ( cav->cav_ptr[0] == '-' )
230                 return LDAP_COMPREF_FROM_END;
231         else if ( cav->cav_ptr[0] == '(' )
232                 return LDAP_COMPREF_SELECT;
233         else if ( cav->cav_ptr[0] == '*' )
234                 return LDAP_COMPREF_ALL;
235         else if ( cav->cav_ptr[0] == '0' )
236                 return LDAP_COMPREF_COUNT;
237         else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' )
238                 return LDAP_COMPREF_FROM_BEGINNING;
239         else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
240                 strncmp(cav->cav_ptr,"content",7) == 0 )
241                 return LDAP_COMPREF_CONTENT;
242         else if ( cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z' )
243                 return LDAP_COMPREF_IDENTIFIER;
244         else
245                 return LDAP_COMPREF_UNDEFINED;
246 }
247
248 static ber_tag_t
249 comp_next_id( ComponentAssertionValue* cav )
250 {
251
252         if ( *(cav->cav_ptr) == '.' ) {
253                 cav->cav_ptr++;
254                 return LDAP_COMPREF_DEFINED;
255         }
256         else return LDAP_COMPREF_UNDEFINED;
257 }
258
259 static int
260 get_component_reference( Operation *op, ComponentAssertionValue* cav,
261                         ComponentReference** cr, const char** text )
262 {
263         int rc,count=0;
264         ber_int_t type;
265         ComponentReference* ca_comp_ref;
266         ComponentId** cr_list;
267
268         eat_whsp( cav );
269         ca_comp_ref =
270                 op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
271
272         cr_list = &ca_comp_ref->cr_list;
273         strip_cav_str( cav, "\"");
274         for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
275                 ; type = comp_next_id( cav ), count++ ) {
276                 rc = get_componentId( op, cav, cr_list, text );
277                 if ( rc == LDAP_SUCCESS ) {
278                         if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
279                         cr_list = &(*cr_list)->ci_next;
280                 }
281         }
282         ca_comp_ref->cr_len = count;
283         strip_cav_str( cav, "\"");
284
285         if ( rc == LDAP_SUCCESS ) {     
286                 *cr = ca_comp_ref;
287                 **cr = *ca_comp_ref;    
288         }
289         else op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
290
291         return rc;
292 }
293
294 static int
295 get_ca_use_default( Operation *op, ComponentAssertionValue* cav,
296                 int* ca_use_def, const char**  text )
297 {
298         int rc;
299         if ( peek_cav_str( cav, "useDefaultValues" ) == LDAP_SUCCESS ) {
300                 strip_cav_str( cav, "useDefaultValues" );
301                 if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
302                         strip_cav_str( cav, "TRUE" );
303                         *ca_use_def = 1;
304                 }
305                 else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
306                         strip_cav_str( cav, "FALSE" );
307                         *ca_use_def = 0;
308                 }
309                 else
310                         return LDAP_INVALID_SYNTAX;
311         }
312         else /* If not defined, default value is TRUE */
313                 *ca_use_def = 1;
314         return LDAP_SUCCESS;
315 }
316
317 static int
318 get_matching_rule( Operation *op, ComponentAssertionValue* cav,
319                 MatchingRule** mr, const char**  text )
320 {
321         int count = 0;
322         char temp;
323         struct berval rule_text = { 0L, NULL };
324
325         eat_whsp( cav );
326
327         for ( ; ; count++ ) {
328                 if ( cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == ',' ||
329                         cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == '{' ||
330                         cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '\n' )
331                         break;
332         }
333
334         if ( count == 0 ) {
335                 *text = "component matching rule not recognized";
336                 return LDAP_INAPPROPRIATE_MATCHING;
337         }
338         
339         rule_text.bv_len = count;
340         rule_text.bv_val = cav->cav_ptr;
341         *mr = mr_bvfind( &rule_text );
342         cav->cav_ptr += count;
343         Debug( LDAP_DEBUG_FILTER, "get_matching_rule: %s\n", (*mr)->smr_mrule.mr_oid, 0, 0 );
344         if ( *mr == NULL ) {
345                 *text = "component matching rule not recognized";
346                 return LDAP_INAPPROPRIATE_MATCHING;
347         }
348         return LDAP_SUCCESS;
349 }
350
351 static void
352 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
353 {
354         int count;
355
356         eat_whsp( cav );
357         /*
358          * Four cases of GSER <Values>
359          * 1) "..." :
360          *      StringVal, GeneralizedTimeVal, UTCTimeVal, ObjectDescriptorVal
361          * 2) '...'B or '...'H :
362          *      BitStringVal, OctetStringVal
363          * 3) {...} :
364          *      SEQUENCE, SEQUENCEOF, SETOF, SET, CHOICE
365          * 4) Between two white spaces
366          *      INTEGER, BOOLEAN, NULL,ENUMERATE, etc
367          */
368
369         if ( cav->cav_ptr[0] == '"' ) {
370                 for( count = 0 ; ; count++ ) {
371                         if ( cav->cav_ptr[count] == '\0' ||
372                         ( cav->cav_ptr[count] == '"' && cav->cav_ptr[count-1] != '"') )
373                                 break;
374                 }
375         }
376         else if ( cav->cav_ptr[0] == '\'' ) {
377                 for( count = 0 ; ; count++ ) {
378                         if ( cav->cav_ptr[count] == '\0' ||
379                         (cav->cav_ptr[count] == '\'' && cav->cav_ptr[count] == 'B')||
380                         (cav->cav_ptr[count] == '\'' && cav->cav_ptr[count] == 'H') )
381                                 break;
382                 }
383                                 
384         }
385         else if ( cav->cav_ptr[0] == '{' ) {
386                 for( count = 0 ; ; count++ ) {
387                         if ( cav->cav_ptr[count] == '\0' ||
388                         (cav->cav_ptr[count] == '}' && cav->cav_ptr[count] == ' ') )
389                                 break;
390                 }
391         }
392         else {
393                 for( count = 0 ; ; count++ ) {
394                         if ( cav->cav_ptr[count] == ' ')
395                                 break;
396                 }
397         }
398
399         bv->bv_val = cav->cav_ptr;
400         bv->bv_len = count;
401         cav->cav_ptr += count;
402 }
403
404 static int
405 get_matching_value( Operation *op, ComponentAssertion* ca,
406                         ComponentAssertionValue* cav, struct berval* bv,
407                         const char**  text )
408 {
409         int count;
410         ber_tag_t tag;
411
412         if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
413                 get_GSER_value( cav, bv );
414         }
415         else {
416                 /* embeded componentFilterMatch Description */
417                 bv->bv_val = cav->cav_ptr;
418                 bv->bv_len = cav_cur_len( cav );
419         }
420
421         return LDAP_SUCCESS;
422 }
423
424 /* Don't move the position pointer, just peek given string */
425 static int
426 peek_cav_str( ComponentAssertionValue* cav, char* str )
427 {
428         eat_whsp( cav );
429         if ( cav_cur_len( cav ) >= strlen( str ) &&
430                 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 )
431                 return LDAP_SUCCESS;
432         else 
433                 return LDAP_INVALID_SYNTAX;
434 }
435
436 static int
437 strip_cav_str( ComponentAssertionValue* cav, char* str)
438 {
439         eat_whsp( cav );
440         if ( cav_cur_len( cav ) >= strlen( str ) &&
441                 strncmp( cav->cav_ptr, str, strlen( str ) ) == 0 ) {
442                 cav->cav_ptr += strlen( str );
443                 return LDAP_SUCCESS;
444         }
445         else 
446                 return LDAP_INVALID_SYNTAX;
447 }
448
449 /*
450  * TAG : "item", "and", "or", "not"
451  */
452 static int
453 strip_cav_tag( ComponentAssertionValue* cav )
454 {
455
456         eat_whsp( cav );
457         if ( cav_cur_len( cav ) >= 8 && strncmp( cav->cav_ptr, "item", 4 ) == 0 ) {
458                 strip_cav_str( cav , "item:" );
459                 return LDAP_COMP_FILTER_ITEM;
460         }
461         else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "and", 3 ) == 0 ) {
462                 strip_cav_str( cav , "and:" );
463                 return LDAP_COMP_FILTER_AND;
464         }
465         else if ( cav_cur_len( cav ) >= 6 && strncmp( cav->cav_ptr, "or" , 2 ) == 0 ) {
466                 strip_cav_str( cav , "or:" );
467                 return LDAP_COMP_FILTER_OR;
468         }
469         else if ( cav_cur_len( cav ) >= 7 && strncmp( cav->cav_ptr, "not", 3 ) == 0 ) {
470                 strip_cav_str( cav , "not:" );
471                 return LDAP_COMP_FILTER_NOT;
472         }
473         else
474                 return LBER_ERROR;
475 }
476
477 /*
478  * when encoding, "item" is denotation of ComponentAssertion
479  * ComponentAssertion :: SEQUENCE {
480  *      component               ComponentReference (SIZE(1..MAX)) OPTIONAL,
481  *      useDefaultValues        BOOLEAN DEFAULT TRUE,
482  *      rule                    MATCHING-RULE.&id,
483  *      value                   MATCHING-RULE.&AssertionType }
484  */
485 static int
486 get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
487                 const char** text )
488 {
489         int rc;
490         ComponentAssertion* _ca;
491
492         Debug( LDAP_DEBUG_FILTER, "get_item: %s\n", 0, 0, 0 );
493         _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
494
495         rc = peek_cav_str( cav, "component" );
496         if ( rc == LDAP_SUCCESS ) {
497                 strip_cav_str( cav, "component" );
498                 rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
499                 if ( rc != LDAP_SUCCESS ) {
500                         rc = LDAP_INVALID_SYNTAX;
501                         op->o_tmpfree( _ca, op->o_tmpmemctx );
502                         return rc;
503                 }
504         }
505
506         strip_cav_str( cav,",");
507         rc = peek_cav_str( cav, "useDefaultValues");
508         if ( rc == LDAP_SUCCESS ) {
509                 rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
510                 if ( rc != LDAP_SUCCESS ) {
511                         rc = LDAP_INVALID_SYNTAX;
512                         op->o_tmpfree( _ca, op->o_tmpmemctx );
513                         return rc;
514                 }
515         }
516
517         if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
518                 get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
519                 rc = LDAP_INAPPROPRIATE_MATCHING;
520                 op->o_tmpfree( _ca, op->o_tmpmemctx );
521                 return rc;
522         }
523         
524         strip_cav_str( cav,",");
525         if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
526                 get_matching_value( op, _ca, cav, &_ca->ca_ma_value,text ) == LDAP_SUCCESS )) {
527                 rc = LDAP_INVALID_SYNTAX;
528                 op->o_tmpfree( _ca, op->o_tmpmemctx );
529                 return rc;
530         }
531
532         /* componentFilterMatch contains componentFilterMatch in it */
533         if ( _ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT) ) {
534                 struct berval bv;
535                 bv.bv_val = cav->cav_ptr;
536                 bv.bv_len = cav_cur_len( cav );
537                 rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
538                 if ( rc != LDAP_SUCCESS ) {
539                         op->o_tmpfree( _ca, op->o_tmpmemctx );
540                         return rc;
541                 }
542                 cav->cav_ptr = bv.bv_val;
543                 assert( cav->cav_end >= bv.bv_val );
544         }
545
546         *ca = _ca;
547         return LDAP_SUCCESS;
548 }
549
550 static int
551 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
552                                 ComponentFilter** filt, const char** text )
553 {
554         /*
555          * A component filter looks like this coming in:
556          *      Filter ::= CHOICE {
557          *              item    [0]     ComponentAssertion,
558          *              and     [1]     SEQUENCE OF ComponentFilter,
559          *              or      [2]     SEQUENCE OF ComponentFilter,
560          *              not     [3]     ComponentFilter,
561          *      }
562          */
563
564         ber_tag_t       tag;
565         ber_len_t       len;
566         int             err;
567         ComponentFilter f;
568         /* TAG : item, and, or, not in RFC 2254 */
569         tag = strip_cav_tag( cav );
570
571         if ( tag == LBER_ERROR ) {
572                 *text = "error decoding comp filter";
573                 return LDAP_PROTOCOL_ERROR;
574         }
575
576         if ( tag != LDAP_COMP_FILTER_NOT )
577                 strip_cav_str( cav, "{");
578
579         err = LDAP_SUCCESS;
580
581         f.cf_next = NULL;
582         f.cf_choice = tag; 
583
584         switch ( f.cf_choice ) {
585         case LDAP_COMP_FILTER_AND:
586         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_AND\n", 0, 0, 0 );
587                 err = get_comp_filter_list( op, cav, &f.cf_and, text );
588                 if ( err != LDAP_SUCCESS ) {
589                         break;
590                 }
591                 if ( f.cf_and == NULL ) {
592                         f.cf_choice = SLAPD_FILTER_COMPUTED;
593                         f.cf_result = LDAP_COMPARE_TRUE;
594                 }
595                 break;
596
597         case LDAP_COMP_FILTER_OR:
598         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_OR\n", 0, 0, 0 );
599                 err = get_comp_filter_list( op, cav, &f.cf_or, text );
600                 if ( err != LDAP_SUCCESS ) {
601                         break;
602                 }
603                 if ( f.cf_or == NULL ) {
604                         f.cf_choice = SLAPD_FILTER_COMPUTED;
605                         f.cf_result = LDAP_COMPARE_FALSE;
606                 }
607                 /* no assert - list could be empty */
608                 break;
609
610         case LDAP_COMP_FILTER_NOT:
611         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_NOT\n", 0, 0, 0 );
612                 err = parse_comp_filter( op, cav, &f.cf_not, text );
613                 if ( err != LDAP_SUCCESS ) {
614                         break;
615                 }
616
617                 assert( f.cf_not != NULL );
618                 if ( f.cf_not->cf_choice == SLAPD_FILTER_COMPUTED ) {
619                         int fresult = f.cf_not->cf_result;
620                         f.cf_choice = SLAPD_FILTER_COMPUTED;
621                         op->o_tmpfree( f.cf_not, op->o_tmpmemctx );
622                         f.cf_not = NULL;
623
624                         switch ( fresult ) {
625                         case LDAP_COMPARE_TRUE:
626                                 f.cf_result = LDAP_COMPARE_FALSE;
627                                 break;
628                         case LDAP_COMPARE_FALSE:
629                                 f.cf_result = LDAP_COMPARE_TRUE;
630                                 break;
631                         default: ;
632                                 /* (!Undefined) is Undefined */
633                         }
634                 }
635                 break;
636
637         case LDAP_COMP_FILTER_ITEM:
638         Debug( LDAP_DEBUG_FILTER, "LDAP_COMP_FILTER_ITEM\n", 0, 0, 0 );
639                 err = get_item( op, cav, &f.cf_ca, text );
640                 if ( err != LDAP_SUCCESS ) {
641                         break;
642                 }
643
644                 assert( f.cf_ca != NULL );
645                 break;
646
647         default:
648                 f.cf_choice = SLAPD_FILTER_COMPUTED;
649                 f.cf_result = SLAPD_COMPARE_UNDEFINED;
650                 break;
651         }
652
653         if ( tag != LDAP_COMP_FILTER_NOT )
654                 strip_cav_str( cav, "}");
655
656         if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
657                 *text = NULL;
658                 f.cf_choice = SLAPD_FILTER_COMPUTED;
659                 f.cf_result = SLAPD_COMPARE_UNDEFINED;
660                 err = LDAP_SUCCESS;
661         }
662
663         if ( err == LDAP_SUCCESS ) {
664                 *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
665                 **filt = f;
666         }
667
668         return( err );
669 }
670
671 static int
672 test_comp_filter_and(
673         Operation *op,
674         Attribute *a,
675         struct berval  *bv,
676         ComponentFilter *flist )
677 {
678         ComponentFilter *f;
679         int rtn = LDAP_COMPARE_TRUE;
680
681         for ( f = flist ; f != NULL; f = f->cf_next ) {
682                 int rc = test_comp_filter_attr( op, a, bv, f );
683                 if ( rc == LDAP_COMPARE_FALSE ) {
684                         rtn = rc;
685                         break;
686                 }
687         
688                 if ( rc != LDAP_COMPARE_TRUE ) {
689                         rtn = rc;
690                 }
691         }
692
693         return rtn;
694 }
695
696 static int
697 test_comp_filter_or(
698         Operation *op,
699         Attribute *a,
700         struct berval     *bv,
701         ComponentFilter *flist )
702 {
703         ComponentFilter *f;
704         int rtn = LDAP_COMPARE_TRUE;
705
706         for ( f = flist ; f != NULL; f = f->cf_next ) {
707                 int rc = test_comp_filter_attr( op, a, bv, f );
708                 if ( rc == LDAP_COMPARE_TRUE ) {
709                         rtn = rc;
710                         break;
711                 }
712         
713                 if ( rc != LDAP_COMPARE_FALSE ) {
714                         rtn = rc;
715                 }
716         }
717
718         return rtn;
719 }
720
721 /*
722  * Convert attribute value to C internal data structure
723  * This function has an associated ASN.1 type
724  * bv must contain the value for the type( type name is T1 )
725  * This function is linked to ssyn_attr2comp
726  */
727
728 /*
729  * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
730  */
731 static int
732 test_comp_filter_item(
733         Operation       *op,
734         Attribute       *a,
735         struct berval   *bv,
736         ComponentAssertion *ca )
737 {
738         int rc = LDAP_COMPARE_TRUE;
739         int len;
740         ComponentSyntaxInfo* csi_attr, *csi_assert;
741
742         if ( (ca->ca_ma_rule->smr_usage & SLAP_MR_COMPONENT) && ca->ca_cf ) {
743                 /* componentFilterMatch inside of componentFilterMatch */
744                 rc = test_comp_filter_attr( op, a, bv, ca->ca_cf );
745                 return rc;
746         }
747
748         assert( !(ca->ca_ma_rule->smr_usage & SLAP_MR_COMPONENT) );
749         /* FIXME : Return ALWAYS true */
750         return LDAP_COMPARE_TRUE;
751 }
752
753 /*
754  * If matched, LDAP_COMPARE_TRUE is returned
755  */
756 int
757 test_comp_filter_entry(
758     Operation   *op,
759     Entry       *e,
760     MatchingRuleAssertion *mra )
761 {
762         Attribute *a;
763         void    *memctx;
764
765         mra->ma_cf->cf_ca->ca_mra = mra;
766
767         Debug( LDAP_DEBUG_FILTER, "test_comp_filter_entry\n", 0, 0, 0 );
768         if ( mra->ma_desc ) {
769                 /*
770                  * ma_desc is available, so filtering for one attribute
771                  * SEARCH permissionc can be checked directly
772                  */
773                 if ( !access_allowed( op, e, mra->ma_desc,
774                         &mra->ma_value, ACL_SEARCH, NULL ) )
775                 {
776                         return LDAP_INSUFFICIENT_ACCESS;
777                 }
778                 /* Find attributes that componentFilter Match can be applied to */
779                 for( a=attrs_find( e->e_attrs, mra->ma_desc );
780                         a != NULL ;
781                         a = attrs_find( a->a_next, mra->ma_desc ) )
782                 {
783                         struct berval *bv = a->a_vals;
784
785                         for ( ; bv->bv_val != NULL ; bv++ ) {
786                                 int ret, rc;
787                                 const char *text;
788                                 rc = test_comp_filter_attr( op, a, bv, mra->ma_cf );
789                                 if ( rc == LDAP_COMPARE_TRUE ) return rc;
790                         }
791                 }
792
793         } else {
794                 /*
795                  * No attribute description : test all
796                  */
797                 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
798                         struct berval   *bv, value;
799                         const char      *text = NULL;
800                         int             rc;
801                                                                                   
802                         /* check if matching is appropriate */
803                         if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type
804 )) {
805                                 continue;
806                         }
807                                                                                   
808                         /* check search access */
809                         if ( !access_allowed( op, e,
810                                 a->a_desc, &value, ACL_SEARCH, NULL ) ) {
811                                 continue;
812                         }
813                                                                                   
814                         bv = a->a_vals;
815
816                         for ( ; bv->bv_val != NULL ; bv++ ) {
817                                 int ret, rc;
818                                 const char *text;
819                                 rc = test_comp_filter_attr( op, a, bv, mra->ma_cf );
820                                 if ( rc == LDAP_COMPARE_TRUE ) break;
821                         }
822                         if ( rc != LDAP_SUCCESS ) return rc;
823                 }
824         }
825
826         return LDAP_COMPARE_FALSE;
827 }
828
829 static int
830 test_comp_filter_attr(
831     Operation   *op,
832     Attribute   *a,
833     struct berval *bv,
834     ComponentFilter *f )
835 {
836         int     rc;
837
838         Debug( LDAP_DEBUG_FILTER, "test_comp_filter_attr\n", 0, 0, 0 );
839         switch ( f->cf_choice ) {
840         case SLAPD_FILTER_COMPUTED:
841                 rc = f->cf_result;
842                 break;
843         case LDAP_COMP_FILTER_AND:
844                 rc = test_comp_filter_and( op, a, bv, f->cf_and );
845                 break;
846         case LDAP_COMP_FILTER_OR:
847                 rc = test_comp_filter_or( op, a, bv, f->cf_or );
848                 break;
849         case LDAP_COMP_FILTER_NOT:
850                 rc = test_comp_filter_attr( op, a, bv, f->cf_not );
851
852                 switch ( rc ) {
853                 case LDAP_COMPARE_TRUE:
854                         rc = LDAP_COMPARE_FALSE;
855                         break;
856                 case LDAP_COMPARE_FALSE:
857                         rc = LDAP_COMPARE_TRUE;
858                         break;
859                 }
860                 break;
861         case LDAP_COMP_FILTER_ITEM:
862                 rc = test_comp_filter_item( op, a, bv, f->cf_ca );
863                 break;
864         default:
865                 rc = LDAP_PROTOCOL_ERROR;
866         }
867
868         return( rc );
869 }
870 #endif