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