]> git.sur5r.net Git - openldap/blob - servers/slapd/filterentry.c
initialize AttributeAssertion before using
[openldap] / servers / slapd / filterentry.c
1 /* filterentry.c - apply a filter to an entry */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 1998-2005 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
17  * All rights reserved.
18  *
19  * Redistribution and use in source and binary forms are permitted
20  * provided that this notice is preserved and that due credit is given
21  * to the University of Michigan at Ann Arbor. The name of the University
22  * may not be used to endorse or promote products derived from this
23  * software without specific prior written permission. This software
24  * is provided ``as is'' without express or implied warranty.
25  */
26
27 #include "portable.h"
28
29 #include <stdio.h>
30
31 #include <ac/socket.h>
32 #include <ac/string.h>
33
34 #include "slap.h"
35
36 #ifdef LDAP_COMP_MATCH
37 #include "component.h"
38 #endif
39
40 static int      test_filter_and( Operation *op, Entry *e, Filter *flist );
41 static int      test_filter_or( Operation *op, Entry *e, Filter *flist );
42 static int      test_substrings_filter( Operation *op, Entry *e, Filter *f);
43 static int      test_ava_filter( Operation *op,
44         Entry *e, AttributeAssertion *ava, int type );
45 static int      test_mra_filter( Operation *op,
46         Entry *e, MatchingRuleAssertion *mra );
47 static int      test_presence_filter( Operation *op,
48         Entry *e, AttributeDescription *desc );
49
50
51 /*
52  * test_filter - test a filter against a single entry.
53  * returns:
54  *              LDAP_COMPARE_TRUE               filter matched
55  *              LDAP_COMPARE_FALSE              filter did not match
56  *              SLAPD_COMPARE_UNDEFINED filter is undefined
57  *      or an ldap result code indicating error
58  */
59
60 int
61 test_filter(
62     Operation   *op,
63     Entry       *e,
64     Filter      *f )
65 {
66         int     rc;
67         Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
68
69         switch ( f->f_choice ) {
70         case SLAPD_FILTER_COMPUTED:
71                 Debug( LDAP_DEBUG_FILTER, "    COMPUTED %s (%d)\n",
72                         f->f_result == LDAP_COMPARE_FALSE ? "false" :
73                         f->f_result == LDAP_COMPARE_TRUE ? "true" :
74                         f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" : "error",
75                         f->f_result, 0 );
76
77                 rc = f->f_result;
78                 break;
79
80         case LDAP_FILTER_EQUALITY:
81                 Debug( LDAP_DEBUG_FILTER, "    EQUALITY\n", 0, 0, 0 );
82                 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_EQUALITY );
83                 break;
84
85         case LDAP_FILTER_SUBSTRINGS:
86                 Debug( LDAP_DEBUG_FILTER, "    SUBSTRINGS\n", 0, 0, 0 );
87                 rc = test_substrings_filter( op, e, f );
88                 break;
89
90         case LDAP_FILTER_GE:
91                 Debug( LDAP_DEBUG_FILTER, "    GE\n", 0, 0, 0 );
92                 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_GE );
93                 break;
94
95         case LDAP_FILTER_LE:
96                 Debug( LDAP_DEBUG_FILTER, "    LE\n", 0, 0, 0 );
97                 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_LE );
98                 break;
99
100         case LDAP_FILTER_PRESENT:
101                 Debug( LDAP_DEBUG_FILTER, "    PRESENT\n", 0, 0, 0 );
102                 rc = test_presence_filter( op, e, f->f_desc );
103                 break;
104
105         case LDAP_FILTER_APPROX:
106                 Debug( LDAP_DEBUG_FILTER, "    APPROX\n", 0, 0, 0 );
107                 rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_APPROX );
108                 break;
109
110         case LDAP_FILTER_AND:
111                 Debug( LDAP_DEBUG_FILTER, "    AND\n", 0, 0, 0 );
112                 rc = test_filter_and( op, e, f->f_and );
113                 break;
114
115         case LDAP_FILTER_OR:
116                 Debug( LDAP_DEBUG_FILTER, "    OR\n", 0, 0, 0 );
117                 rc = test_filter_or( op, e, f->f_or );
118                 break;
119
120         case LDAP_FILTER_NOT:
121                 Debug( LDAP_DEBUG_FILTER, "    NOT\n", 0, 0, 0 );
122                 rc = test_filter( op, e, f->f_not );
123
124                 /* Flip true to false and false to true
125                  * but leave Undefined alone.
126                  */
127                 switch( rc ) {
128                 case LDAP_COMPARE_TRUE:
129                         rc = LDAP_COMPARE_FALSE;
130                         break;
131                 case LDAP_COMPARE_FALSE:
132                         rc = LDAP_COMPARE_TRUE;
133                         break;
134                 }
135                 break;
136
137         case LDAP_FILTER_EXT:
138                 Debug( LDAP_DEBUG_FILTER, "    EXT\n", 0, 0, 0 );
139                 rc = test_mra_filter( op, e, f->f_mra );
140                 break;
141
142         default:
143                 Debug( LDAP_DEBUG_ANY, "    unknown filter type %lu\n",
144                     f->f_choice, 0, 0 );
145                 rc = LDAP_PROTOCOL_ERROR;
146         }
147
148         Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
149         return( rc );
150 }
151
152 static int test_mra_filter(
153         Operation *op,
154         Entry *e,
155         MatchingRuleAssertion *mra )
156 {
157         Attribute       *a;
158         void            *memctx;
159         BER_MEMFREE_FN  *memfree;
160 #ifdef LDAP_COMP_MATCH
161         int i, num_attr_vals;
162 #endif
163
164         if ( op == NULL ) {
165                 memctx = NULL;
166                 memfree = slap_sl_free;
167         } else {
168                 memctx = op->o_tmpmemctx;
169                 memfree = op->o_tmpfree;
170         }
171
172         if ( mra->ma_desc ) {
173                 /*
174                  * if ma_desc is available, then we're filtering for
175                  * one attribute, and SEARCH permissions can be checked
176                  * directly.
177                  */
178                 if ( !access_allowed( op, e,
179                         mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
180                 {
181                         return LDAP_INSUFFICIENT_ACCESS;
182                 }
183
184                 if ( mra->ma_desc == slap_schema.si_ad_entryDN ) {
185                         int ret, rc;
186                         const char *text;
187
188                         rc = value_match( &ret, slap_schema.si_ad_entryDN, mra->ma_rule,
189                                 0, &e->e_nname, &mra->ma_value, &text );
190         
191         
192                         if( rc != LDAP_SUCCESS ) return rc;
193                         if ( ret == 0 ) return LDAP_COMPARE_TRUE;
194                         return LDAP_COMPARE_FALSE;
195                 }
196
197                 for ( a = attrs_find( e->e_attrs, mra->ma_desc );
198                         a != NULL;
199                         a = attrs_find( a->a_next, mra->ma_desc ) )
200                 {
201                         struct berval   *bv;
202                         int             normalize_attribute = 0;
203
204 #ifdef LDAP_COMP_MATCH
205                         /* Component Matching */
206                         if ( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
207                                 num_attr_vals = 0;
208                                 if ( !a->a_comp_data ) {
209                                         for ( ;
210                                                 !BER_BVISNULL( &a->a_vals[num_attr_vals] );
211                                                 num_attr_vals++ )
212                                         {
213                                                 /* empty */;
214                                         }
215                                         if ( num_attr_vals <= 0 ) {
216                                                 /* no attribute value */
217                                                 return LDAP_INAPPROPRIATE_MATCHING;
218                                         }
219                                         num_attr_vals++;
220
221                                         /* following malloced will be freed by comp_tree_free () */
222                                         a->a_comp_data = malloc( sizeof( ComponentData ) +
223                                                 sizeof( ComponentSyntaxInfo* )*num_attr_vals );
224
225                                         if ( !a->a_comp_data ) return LDAP_NO_MEMORY;
226                                         a->a_comp_data->cd_tree = (ComponentSyntaxInfo**)
227                                                 ((char*)a->a_comp_data + sizeof(ComponentData));
228                                         a->a_comp_data->cd_tree[num_attr_vals - 1] =
229                                                 (ComponentSyntaxInfo*) NULL;
230                                         a->a_comp_data->cd_mem_op =
231                                                 nibble_mem_allocator( 1024*16, 1024 );
232                                 }
233                         }
234 #endif
235
236                         /* If ma_rule is not the same as the attribute's
237                          * normal rule, then we can't use the a_nvals.
238                          */
239                         if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
240                                 bv = a->a_nvals;
241
242                         } else {
243                                 bv = a->a_vals;
244                                 normalize_attribute = 1;
245                         }
246 #ifdef LDAP_COMP_MATCH
247                         i = 0;
248 #endif
249                         for ( ; !BER_BVISNULL( bv ); bv++ ) {
250                                 int ret;
251                                 int rc;
252                                 const char *text;
253         
254 #ifdef LDAP_COMP_MATCH
255                                 if ( mra->ma_cf &&
256                                         mra->ma_rule->smr_usage & SLAP_MR_COMPONENT )
257                                 {
258                                         /* Check if decoded component trees are already linked */
259                                         if ( num_attr_vals ) {
260                                                 a->a_comp_data->cd_tree[i] = attr_converter(
261                                                         a, a->a_desc->ad_type->sat_syntax, bv );
262                                         }
263                                         /* decoding error */
264                                         if ( !a->a_comp_data->cd_tree[i] ) {
265                                                 return LDAP_OPERATIONS_ERROR;
266                                         }
267                                         rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
268                                                 (struct berval*)a->a_comp_data->cd_tree[i++],
269                                                 (void*)mra, &text );
270                                 } else 
271 #endif
272                                 {
273                                         struct berval   nbv = BER_BVNULL;
274
275                                         if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
276                                                 /*
277                                 
278                                 Document: draft-ietf-ldapbis-protocol
279
280                                     4.5.1. Search Request 
281                                         ...
282                                     If the type field is present and the matchingRule is present, 
283                                     the matchValue is compared against entry attributes of the 
284                                     specified type. In this case, the matchingRule MUST be one 
285                                     suitable for use with the specified type (see [Syntaxes]), 
286                                     otherwise the filter item is Undefined.  
287
288
289                                 In this case, since the matchingRule requires the assertion
290                                 value to be normalized, we normalize the attribute value
291                                 according to the syntax of the matchingRule.
292
293                                 This should likely be done inside value_match(), by passing
294                                 the appropriate flags, but this is not done at present.
295                                 See ITS#3406.
296                                                  */
297                                                 if ( mra->ma_rule->smr_normalize(
298                                                                 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
299                                                                 mra->ma_rule->smr_syntax,
300                                                                 mra->ma_rule,
301                                                                 bv, &nbv, memctx ) != LDAP_SUCCESS )
302                                                 {
303                                                         /* FIXME: stop processing? */
304                                                         continue;
305                                                 }
306
307                                         } else {
308                                                 nbv = *bv;
309                                         }
310
311                                         rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
312                                                 &nbv, &mra->ma_value, &text );
313
314                                         if ( nbv.bv_val != bv->bv_val ) {
315                                                 memfree( nbv.bv_val, memctx );
316                                         }
317                                 }
318
319                                 if ( rc != LDAP_SUCCESS ) return rc;
320                                 if ( ret == 0 ) return LDAP_COMPARE_TRUE;
321                         }
322                 }
323
324         } else {
325                 /*
326                  * No attribute description: test all
327                  */
328                 for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
329                         struct berval   *bv, value;
330                         const char      *text = NULL;
331                         int             rc;
332                         int             normalize_attribute = 0;
333
334                         /* check if matching is appropriate */
335                         if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type ) ) {
336                                 continue;
337                         }
338
339                         /* normalize for equality */
340                         rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule,
341                                 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
342                                 &mra->ma_value, &value, &text, memctx );
343                         if ( rc != LDAP_SUCCESS ) continue;
344
345                         /* check search access */
346                         if ( !access_allowed( op, e,
347                                 a->a_desc, &value, ACL_SEARCH, NULL ) )
348                         {
349                                 memfree( value.bv_val, memctx );
350                                 continue;
351                         }
352 #ifdef LDAP_COMP_MATCH
353                         /* Component Matching */
354                         if ( mra->ma_cf &&
355                                 mra->ma_rule->smr_usage & SLAP_MR_COMPONENT )
356                         {
357                                 int ret;
358
359                                 rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
360                                         (struct berval*)a, (void*)mra, &text );
361                                 if ( rc != LDAP_SUCCESS ) break;
362         
363                                 if ( ret == 0 ) {
364                                         rc = LDAP_COMPARE_TRUE;
365                                         break;
366                                 }
367
368                         }
369 #endif
370
371                         /* check match */
372                         if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
373                                 bv = a->a_nvals;
374
375                         } else {
376                                 bv = a->a_vals;
377                                 normalize_attribute = 1;
378                         }
379
380                         for ( ; !BER_BVISNULL( bv ); bv++ ) {
381                                 int             ret;
382                                 struct berval   nbv = BER_BVNULL;
383
384                                 if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
385                                         /* see comment above */
386                                         if ( mra->ma_rule->smr_normalize(
387                                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
388                                                         mra->ma_rule->smr_syntax,
389                                                         mra->ma_rule,
390                                                         bv, &nbv, memctx ) != LDAP_SUCCESS )
391                                         {
392                                                 /* FIXME: stop processing? */
393                                                 continue;
394                                         }
395
396                                 } else {
397                                         nbv = *bv;
398                                 }
399
400                                 rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
401                                         &nbv, &value, &text );
402
403                                 if ( nbv.bv_val != bv->bv_val ) {
404                                         memfree( nbv.bv_val, memctx );
405                                 }
406
407                                 if ( rc != LDAP_SUCCESS ) break;
408         
409                                 if ( ret == 0 ) {
410                                         rc = LDAP_COMPARE_TRUE;
411                                         break;
412                                 }
413                         }
414                         memfree( value.bv_val, memctx );
415                         if ( rc != LDAP_SUCCESS ) return rc;
416                 }
417         }
418
419         /* check attrs in DN AVAs if required */
420         if ( mra->ma_dnattrs && !BER_BVISEMPTY( &e->e_nname ) ) {
421                 LDAPDN          dn = NULL;
422                 int             iRDN, iAVA;
423                 int             rc;
424
425                 /* parse and pretty the dn */
426                 rc = dnPrettyDN( NULL, &e->e_name, &dn, memctx );
427                 if ( rc != LDAP_SUCCESS ) {
428                         return LDAP_INVALID_SYNTAX;
429                 }
430
431                 /* for each AVA of each RDN ... */
432                 for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
433                         LDAPRDN         rdn = dn[ iRDN ];
434
435                         for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
436                                 LDAPAVA         *ava = rdn[ iAVA ];
437                                 struct berval   *bv = &ava->la_value, value;
438                                 AttributeDescription *ad =
439                                         (AttributeDescription *)ava->la_private;
440                                 int ret;
441                                 const char *text;
442
443                                 assert( ad );
444
445                                 if ( mra->ma_desc ) {
446                                         /* have a mra type? check for subtype */
447                                         if ( !is_ad_subtype( ad, mra->ma_desc ) ) {
448                                                 continue;
449                                         }
450                                         value = mra->ma_value;
451
452                                 } else {
453                                         const char      *text = NULL;
454
455                                         /* check if matching is appropriate */
456                                         if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type ) ) {
457                                                 continue;
458                                         }
459
460                                         /* normalize for equality */
461                                         rc = asserted_value_validate_normalize( ad,
462                                                 mra->ma_rule,
463                                                 SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
464                                                 &mra->ma_value, &value, &text, memctx );
465                                         if ( rc != LDAP_SUCCESS ) continue;
466
467                                         /* check search access */
468                                         if ( !access_allowed( op, e,
469                                                 ad, &value, ACL_SEARCH, NULL ) )
470                                         {
471                                                 memfree( value.bv_val, memctx );
472                                                 continue;
473                                         }
474                                 }
475
476                                 /* check match */
477                                 rc = value_match( &ret, ad, mra->ma_rule, 0,
478                                         bv, &value, &text );
479                                 if ( value.bv_val != mra->ma_value.bv_val ) {
480                                         memfree( value.bv_val, memctx );
481                                 }
482
483                                 if ( rc == LDAP_SUCCESS && ret == 0 ) rc = LDAP_COMPARE_TRUE;
484
485                                 if ( rc != LDAP_SUCCESS ) {
486                                         ldap_dnfree_x( dn, memctx );
487                                         return rc;
488                                 }
489                         }
490                 }
491                 ldap_dnfree_x( dn, memctx );
492         }
493
494         return LDAP_COMPARE_FALSE;
495 }
496
497 static int
498 test_ava_filter(
499         Operation       *op,
500         Entry           *e,
501         AttributeAssertion *ava,
502         int             type )
503 {
504         int rc;
505         Attribute       *a;
506 #ifdef LDAP_COMP_MATCH
507         int i, num_attr_vals;
508         AttributeAliasing *a_alias = NULL;
509 #endif
510
511         if ( !access_allowed( op, e,
512                 ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL ) )
513         {
514                 return LDAP_INSUFFICIENT_ACCESS;
515         }
516
517         if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates 
518                 && op && op->o_bd && op->o_bd->be_has_subordinates )
519         {
520                 int     hasSubordinates;
521                 struct berval hs;
522
523                 if( type != LDAP_FILTER_EQUALITY &&
524                         type != LDAP_FILTER_APPROX )
525                 {
526                         /* No other match is allowed */
527                         return LDAP_INAPPROPRIATE_MATCHING;
528                 }
529                 
530                 if ( op->o_bd->be_has_subordinates( op, e, &hasSubordinates ) !=
531                         LDAP_SUCCESS )
532                 {
533                         return LDAP_OTHER;
534                 }
535
536                 if ( hasSubordinates == LDAP_COMPARE_TRUE ) {
537                         hs = slap_true_bv;
538
539                 } else if ( hasSubordinates == LDAP_COMPARE_FALSE ) {
540                         hs = slap_false_bv;
541
542                 } else {
543                         return LDAP_OTHER;
544                 }
545
546                 if ( bvmatch( &ava->aa_value, &hs ) ) return LDAP_COMPARE_TRUE;
547                 return LDAP_COMPARE_FALSE;
548         }
549
550         if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
551                 MatchingRule *mr;
552                 int rc, match;
553                 const char *text;
554
555                 if( type != LDAP_FILTER_EQUALITY &&
556                         type != LDAP_FILTER_APPROX )
557                 {
558                         /* No other match is allowed */
559                         return LDAP_INAPPROPRIATE_MATCHING;
560                 }
561
562                 mr = slap_schema.si_ad_entryDN->ad_type->sat_equality;
563                 assert( mr );
564
565                 rc = value_match( &match, slap_schema.si_ad_entryDN, mr, 0,
566                         &e->e_nname, &ava->aa_value, &text );
567
568                 if( rc != LDAP_SUCCESS ) return rc;
569                 if( match == 0 ) return LDAP_COMPARE_TRUE;
570                 return LDAP_COMPARE_FALSE;
571         }
572
573         rc = LDAP_COMPARE_FALSE;
574
575 #ifdef LDAP_COMP_MATCH
576         if ( is_aliased_attribute && ava->aa_cf )
577         {
578                 a_alias = is_aliased_attribute ( ava->aa_desc );
579                 if ( a_alias )
580                         ava->aa_desc = a_alias->aa_aliased_ad;
581                 else
582                         ava->aa_cf = NULL;
583         }
584 #endif
585
586         for(a = attrs_find( e->e_attrs, ava->aa_desc );
587                 a != NULL;
588                 a = attrs_find( a->a_next, ava->aa_desc ) )
589         {
590                 MatchingRule *mr;
591                 struct berval *bv;
592
593                 if (( ava->aa_desc != a->a_desc ) && !access_allowed( op,
594                         e, a->a_desc, &ava->aa_value, ACL_SEARCH, NULL ))
595                 {
596                         rc = LDAP_INSUFFICIENT_ACCESS;
597                         continue;
598                 }
599
600                 switch ( type ) {
601                 case LDAP_FILTER_APPROX:
602                         mr = a->a_desc->ad_type->sat_approx;
603                         if( mr != NULL ) break;
604
605                         /* use EQUALITY matching rule if no APPROX rule */
606
607                 case LDAP_FILTER_EQUALITY:
608                         mr = a->a_desc->ad_type->sat_equality;
609                         break;
610
611                 case LDAP_FILTER_GE:
612                 case LDAP_FILTER_LE:
613                         mr = a->a_desc->ad_type->sat_ordering;
614                         break;
615
616                 default:
617                         mr = NULL;
618                 }
619
620                 if( mr == NULL ) {
621                         rc = LDAP_INAPPROPRIATE_MATCHING;
622                         continue;
623                 }
624
625 #ifdef LDAP_COMP_MATCH
626                 if ( nibble_mem_allocator && ava->aa_cf && !a->a_comp_data ) {
627                         /* Component Matching */
628                         for ( num_attr_vals = 0; a->a_vals[num_attr_vals].bv_val != NULL; num_attr_vals++ );
629                         if ( num_attr_vals <= 0 )/* no attribute value */
630                                 return LDAP_INAPPROPRIATE_MATCHING;
631                         num_attr_vals++;/* for NULL termination */
632
633                         /* following malloced will be freed by comp_tree_free () */
634                         a->a_comp_data = malloc( sizeof( ComponentData ) + sizeof( ComponentSyntaxInfo* )*num_attr_vals );
635
636                         if ( !a->a_comp_data ) {
637                                 return LDAP_NO_MEMORY;
638                         }
639
640                         a->a_comp_data->cd_tree = (ComponentSyntaxInfo**)((char*)a->a_comp_data + sizeof(ComponentData));
641                         i = num_attr_vals;
642                         for ( ; i ; i-- ) {
643                                 a->a_comp_data->cd_tree[ i-1 ] = (ComponentSyntaxInfo*)NULL;
644                         }
645
646                         a->a_comp_data->cd_mem_op = nibble_mem_allocator ( 1024*10*(num_attr_vals-1), 1024 );
647                         if ( a->a_comp_data->cd_mem_op == NULL ) {
648                                 free ( a->a_comp_data );
649                                 a->a_comp_data = NULL;
650                                 return LDAP_OPERATIONS_ERROR;
651                         }
652                 }
653
654                 i = 0;
655 #endif
656
657                 for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
658                         int ret, match;
659                         const char *text;
660
661 #ifdef LDAP_COMP_MATCH
662                         if( attr_converter && ava->aa_cf && a->a_comp_data ) {
663                                 /* Check if decoded component trees are already linked */
664                                 struct berval cf_bv = { 20, "componentFilterMatch" };
665                                 MatchingRule* cf_mr = mr_bvfind( &cf_bv );
666                                 MatchingRuleAssertion mra;
667                                 mra.ma_cf = ava->aa_cf;
668
669                                 if ( a->a_comp_data->cd_tree[i] == NULL )
670                                         a->a_comp_data->cd_tree[i] = attr_converter (a, a->a_desc->ad_type->sat_syntax, (a->a_vals + i));
671                                 /* decoding error */
672                                 if ( !a->a_comp_data->cd_tree[i] ) {
673                                         free_ComponentData ( a );
674                                         return LDAP_OPERATIONS_ERROR;
675                                 }
676
677                                 ret = value_match( &match, a->a_desc, cf_mr, 0,
678                                         (struct berval*)a->a_comp_data->cd_tree[i++], (void*)&mra, &text );
679                                 if ( ret == LDAP_INAPPROPRIATE_MATCHING ) {
680                                         /* cached component tree is broken, just remove it */
681                                         free_ComponentData ( a );
682                                         return ret;
683                                 }
684                                 if ( a_alias )
685                                         ava->aa_desc = a_alias->aa_aliasing_ad;
686                         }
687                         else 
688 #endif
689                         {
690
691                                 ret = value_match( &match, a->a_desc, mr, 0,
692                                         bv, &ava->aa_value, &text );
693                         }
694
695                         if( ret != LDAP_SUCCESS ) {
696                                 rc = ret;
697                                 break;
698                         }
699
700                         switch ( type ) {
701                         case LDAP_FILTER_EQUALITY:
702                         case LDAP_FILTER_APPROX:
703                                 if ( match == 0 ) return LDAP_COMPARE_TRUE;
704                                 break;
705
706                         case LDAP_FILTER_GE:
707                                 if ( match >= 0 ) return LDAP_COMPARE_TRUE;
708                                 break;
709
710                         case LDAP_FILTER_LE:
711                                 if ( match <= 0 ) return LDAP_COMPARE_TRUE;
712                                 break;
713                         }
714                 }
715         }
716
717 #ifdef LDAP_COMP_MATCH
718         if ( a_alias )
719                 ava->aa_desc = a_alias->aa_aliasing_ad;
720 #endif
721
722         return rc;
723 }
724
725
726 static int
727 test_presence_filter(
728         Operation       *op,
729         Entry           *e,
730         AttributeDescription *desc )
731 {
732         Attribute       *a;
733         int rc;
734
735         if ( !access_allowed( op, e, desc, NULL, ACL_SEARCH, NULL ) ) {
736                 return LDAP_INSUFFICIENT_ACCESS;
737         }
738
739         if ( desc == slap_schema.si_ad_hasSubordinates ) {
740                 /*
741                  * XXX: fairly optimistic: if the function is defined,
742                  * then PRESENCE must succeed, because hasSubordinate
743                  * is boolean-valued; I think we may live with this 
744                  * simplification by now.
745                  */
746                 if ( op && op->o_bd && op->o_bd->be_has_subordinates ) {
747                         return LDAP_COMPARE_TRUE;
748                 }
749
750                 return LDAP_COMPARE_FALSE;
751         }
752
753         if ( desc == slap_schema.si_ad_entryDN ||
754                 desc == slap_schema.si_ad_subschemaSubentry )
755         {
756                 /* entryDN and subschemaSubentry are always present */
757                 return LDAP_COMPARE_TRUE;
758         }
759
760         rc = LDAP_COMPARE_FALSE;
761
762         for(a = attrs_find( e->e_attrs, desc );
763                 a != NULL;
764                 a = attrs_find( a->a_next, desc ) )
765         {
766                 if (( desc != a->a_desc ) && !access_allowed( op,
767                         e, a->a_desc, NULL, ACL_SEARCH, NULL ))
768                 {
769                         rc = LDAP_INSUFFICIENT_ACCESS;
770                         continue;
771                 }
772
773                 rc = LDAP_COMPARE_TRUE;
774                 break;
775         }
776
777         return rc;
778 }
779
780
781 static int
782 test_filter_and(
783         Operation       *op,
784         Entry   *e,
785         Filter  *flist )
786 {
787         Filter  *f;
788         int rtn = LDAP_COMPARE_TRUE; /* True if empty */
789
790         Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 );
791
792         for ( f = flist; f != NULL; f = f->f_next ) {
793                 int rc = test_filter( op, e, f );
794
795                 if ( rc == LDAP_COMPARE_FALSE ) {
796                         /* filter is False */
797                         rtn = rc;
798                         break;
799                 }
800
801                 if ( rc != LDAP_COMPARE_TRUE ) {
802                         /* filter is Undefined unless later elements are False */
803                         rtn = rc;
804                 }
805         }
806
807         Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
808
809         return rtn;
810 }
811
812 static int
813 test_filter_or(
814         Operation       *op,
815         Entry   *e,
816         Filter  *flist )
817 {
818         Filter  *f;
819         int rtn = LDAP_COMPARE_FALSE; /* False if empty */
820
821         Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
822
823         for ( f = flist; f != NULL; f = f->f_next ) {
824                 int rc = test_filter( op, e, f );
825
826                 if ( rc == LDAP_COMPARE_TRUE ) {
827                         /* filter is True */
828                         rtn = rc;
829                         break;
830                 }
831
832                 if ( rc != LDAP_COMPARE_FALSE ) {
833                         /* filter is Undefined unless later elements are True */
834                         rtn = rc;
835                 }
836         }
837
838         Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
839         return rtn;
840 }
841
842
843 static int
844 test_substrings_filter(
845         Operation       *op,
846         Entry   *e,
847         Filter  *f )
848 {
849         Attribute       *a;
850         int rc;
851
852         Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 );
853
854         if ( !access_allowed( op, e,
855                 f->f_sub_desc, NULL, ACL_SEARCH, NULL ) )
856         {
857                 return LDAP_INSUFFICIENT_ACCESS;
858         }
859
860         rc = LDAP_COMPARE_FALSE;
861
862         for(a = attrs_find( e->e_attrs, f->f_sub_desc );
863                 a != NULL;
864                 a = attrs_find( a->a_next, f->f_sub_desc ) )
865         {
866                 MatchingRule *mr;
867                 struct berval *bv;
868
869                 if (( f->f_sub_desc != a->a_desc ) && !access_allowed( op,
870                         e, a->a_desc, NULL, ACL_SEARCH, NULL ))
871                 {
872                         rc = LDAP_INSUFFICIENT_ACCESS;
873                         continue;
874                 }
875
876                 mr = a->a_desc->ad_type->sat_substr;
877                 if( mr == NULL ) {
878                         rc = LDAP_INAPPROPRIATE_MATCHING;
879                         continue;
880                 }
881
882                 for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
883                         int ret, match;
884                         const char *text;
885
886                         ret = value_match( &match, a->a_desc, mr, 0,
887                                 bv, f->f_sub, &text );
888
889                         if( ret != LDAP_SUCCESS ) {
890                                 rc = ret;
891                                 break;
892                         }
893                         if ( match == 0 ) return LDAP_COMPARE_TRUE;
894                 }
895         }
896
897         Debug( LDAP_DEBUG_FILTER, "end test_substrings_filter %d\n",
898                 rc, 0, 0 );
899         return rc;
900 }