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