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