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