Back to index

openldap  2.4.31
filterentry.c
Go to the documentation of this file.
00001 /* filterentry.c - apply a filter to an entry */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
00017  * All rights reserved.
00018  *
00019  * Redistribution and use in source and binary forms are permitted
00020  * provided that this notice is preserved and that due credit is given
00021  * to the University of Michigan at Ann Arbor. The name of the University
00022  * may not be used to endorse or promote products derived from this
00023  * software without specific prior written permission. This software
00024  * is provided ``as is'' without express or implied warranty.
00025  */
00026 
00027 #include "portable.h"
00028 
00029 #include <stdio.h>
00030 
00031 #include <ac/socket.h>
00032 #include <ac/string.h>
00033 
00034 #include "slap.h"
00035 
00036 #ifdef LDAP_COMP_MATCH
00037 #include "component.h"
00038 #endif
00039 
00040 static int    test_filter_and( Operation *op, Entry *e, Filter *flist );
00041 static int    test_filter_or( Operation *op, Entry *e, Filter *flist );
00042 static int    test_substrings_filter( Operation *op, Entry *e, Filter *f);
00043 static int    test_ava_filter( Operation *op,
00044        Entry *e, AttributeAssertion *ava, int type );
00045 static int    test_mra_filter( Operation *op,
00046        Entry *e, MatchingRuleAssertion *mra );
00047 static int    test_presence_filter( Operation *op,
00048        Entry *e, AttributeDescription *desc );
00049 
00050 
00051 /*
00052  * test_filter - test a filter against a single entry.
00053  * returns:
00054  *            LDAP_COMPARE_TRUE           filter matched
00055  *            LDAP_COMPARE_FALSE          filter did not match
00056  *            SLAPD_COMPARE_UNDEFINED     filter is undefined
00057  *     or an ldap result code indicating error
00058  */
00059 
00060 int
00061 test_filter(
00062     Operation *op,
00063     Entry     *e,
00064     Filter    *f )
00065 {
00066        int    rc;
00067        Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
00068 
00069        if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
00070               Debug( LDAP_DEBUG_FILTER, "    UNDEFINED\n", 0, 0, 0 );
00071               rc = SLAPD_COMPARE_UNDEFINED;
00072               goto out;
00073        }
00074 
00075        switch ( f->f_choice ) {
00076        case SLAPD_FILTER_COMPUTED:
00077               Debug( LDAP_DEBUG_FILTER, "    COMPUTED %s (%d)\n",
00078                      f->f_result == LDAP_COMPARE_FALSE ? "false" :
00079                      f->f_result == LDAP_COMPARE_TRUE ? "true" :
00080                      f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" : "error",
00081                      f->f_result, 0 );
00082 
00083               rc = f->f_result;
00084               break;
00085 
00086        case LDAP_FILTER_EQUALITY:
00087               Debug( LDAP_DEBUG_FILTER, "    EQUALITY\n", 0, 0, 0 );
00088               rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_EQUALITY );
00089               break;
00090 
00091        case LDAP_FILTER_SUBSTRINGS:
00092               Debug( LDAP_DEBUG_FILTER, "    SUBSTRINGS\n", 0, 0, 0 );
00093               rc = test_substrings_filter( op, e, f );
00094               break;
00095 
00096        case LDAP_FILTER_GE:
00097               Debug( LDAP_DEBUG_FILTER, "    GE\n", 0, 0, 0 );
00098               rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_GE );
00099               break;
00100 
00101        case LDAP_FILTER_LE:
00102               Debug( LDAP_DEBUG_FILTER, "    LE\n", 0, 0, 0 );
00103               rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_LE );
00104               break;
00105 
00106        case LDAP_FILTER_PRESENT:
00107               Debug( LDAP_DEBUG_FILTER, "    PRESENT\n", 0, 0, 0 );
00108               rc = test_presence_filter( op, e, f->f_desc );
00109               break;
00110 
00111        case LDAP_FILTER_APPROX:
00112               Debug( LDAP_DEBUG_FILTER, "    APPROX\n", 0, 0, 0 );
00113               rc = test_ava_filter( op, e, f->f_ava, LDAP_FILTER_APPROX );
00114               break;
00115 
00116        case LDAP_FILTER_AND:
00117               Debug( LDAP_DEBUG_FILTER, "    AND\n", 0, 0, 0 );
00118               rc = test_filter_and( op, e, f->f_and );
00119               break;
00120 
00121        case LDAP_FILTER_OR:
00122               Debug( LDAP_DEBUG_FILTER, "    OR\n", 0, 0, 0 );
00123               rc = test_filter_or( op, e, f->f_or );
00124               break;
00125 
00126        case LDAP_FILTER_NOT:
00127               Debug( LDAP_DEBUG_FILTER, "    NOT\n", 0, 0, 0 );
00128               rc = test_filter( op, e, f->f_not );
00129 
00130               /* Flip true to false and false to true
00131                * but leave Undefined alone.
00132                */
00133               switch( rc ) {
00134               case LDAP_COMPARE_TRUE:
00135                      rc = LDAP_COMPARE_FALSE;
00136                      break;
00137               case LDAP_COMPARE_FALSE:
00138                      rc = LDAP_COMPARE_TRUE;
00139                      break;
00140               }
00141               break;
00142 
00143        case LDAP_FILTER_EXT:
00144               Debug( LDAP_DEBUG_FILTER, "    EXT\n", 0, 0, 0 );
00145               rc = test_mra_filter( op, e, f->f_mra );
00146               break;
00147 
00148        default:
00149               Debug( LDAP_DEBUG_ANY, "    unknown filter type %lu\n",
00150                   f->f_choice, 0, 0 );
00151               rc = LDAP_PROTOCOL_ERROR;
00152        }
00153 out:
00154        Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
00155        return( rc );
00156 }
00157 
00158 static int test_mra_filter(
00159        Operation *op,
00160        Entry *e,
00161        MatchingRuleAssertion *mra )
00162 {
00163        Attribute     *a;
00164        void          *memctx;
00165        BER_MEMFREE_FN       *memfree;
00166 #ifdef LDAP_COMP_MATCH
00167        int i, num_attr_vals = 0;
00168 #endif
00169 
00170        if ( op == NULL ) {
00171               memctx = NULL;
00172               memfree = slap_sl_mfuncs.bmf_free;
00173        } else {
00174               memctx = op->o_tmpmemctx;
00175               memfree = op->o_tmpfree;
00176        }
00177 
00178        if ( mra->ma_desc ) {
00179               /*
00180                * if ma_desc is available, then we're filtering for
00181                * one attribute, and SEARCH permissions can be checked
00182                * directly.
00183                */
00184               if ( !access_allowed( op, e,
00185                      mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
00186               {
00187                      return LDAP_INSUFFICIENT_ACCESS;
00188               }
00189 
00190               if ( mra->ma_desc == slap_schema.si_ad_entryDN ) {
00191                      int ret, rc;
00192                      const char *text;
00193 
00194                      rc = value_match( &ret, slap_schema.si_ad_entryDN, mra->ma_rule,
00195                             SLAP_MR_EXT, &e->e_nname, &mra->ma_value, &text );
00196        
00197        
00198                      if( rc != LDAP_SUCCESS ) return rc;
00199                      if ( ret == 0 ) return LDAP_COMPARE_TRUE;
00200                      return LDAP_COMPARE_FALSE;
00201               }
00202 
00203               for ( a = attrs_find( e->e_attrs, mra->ma_desc );
00204                      a != NULL;
00205                      a = attrs_find( a->a_next, mra->ma_desc ) )
00206               {
00207                      struct berval *bv;
00208                      int           normalize_attribute = 0;
00209 
00210 #ifdef LDAP_COMP_MATCH
00211                      /* Component Matching */
00212                      if ( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) {
00213                             num_attr_vals = 0;
00214                             if ( !a->a_comp_data ) {
00215                                    num_attr_vals = a->a_numvals;
00216                                    if ( num_attr_vals <= 0 ) {
00217                                           /* no attribute value */
00218                                           return LDAP_INAPPROPRIATE_MATCHING;
00219                                    }
00220                                    num_attr_vals++;
00221 
00222                                    /* following malloced will be freed by comp_tree_free () */
00223                                    a->a_comp_data = SLAP_MALLOC( sizeof( ComponentData ) +
00224                                           sizeof( ComponentSyntaxInfo* )*num_attr_vals );
00225 
00226                                    if ( !a->a_comp_data ) return LDAP_NO_MEMORY;
00227                                    a->a_comp_data->cd_tree = (ComponentSyntaxInfo**)
00228                                           ((char*)a->a_comp_data + sizeof(ComponentData));
00229                                    a->a_comp_data->cd_tree[num_attr_vals - 1] =
00230                                           (ComponentSyntaxInfo*) NULL;
00231                                    a->a_comp_data->cd_mem_op =
00232                                           nibble_mem_allocator( 1024*16, 1024 );
00233                             }
00234                      }
00235 #endif
00236 
00237                      /* If ma_rule is not the same as the attribute's
00238                       * normal rule, then we can't use the a_nvals.
00239                       */
00240                      if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
00241                             bv = a->a_nvals;
00242 
00243                      } else {
00244                             bv = a->a_vals;
00245                             normalize_attribute = 1;
00246                      }
00247 #ifdef LDAP_COMP_MATCH
00248                      i = 0;
00249 #endif
00250                      for ( ; !BER_BVISNULL( bv ); bv++ ) {
00251                             int ret;
00252                             int rc;
00253                             const char *text;
00254        
00255 #ifdef LDAP_COMP_MATCH
00256                             if ( mra->ma_cf &&
00257                                    mra->ma_rule->smr_usage & SLAP_MR_COMPONENT )
00258                             {
00259                                    /* Check if decoded component trees are already linked */
00260                                    if ( num_attr_vals ) {
00261                                           a->a_comp_data->cd_tree[i] = attr_converter(
00262                                                  a, a->a_desc->ad_type->sat_syntax, bv );
00263                                    }
00264                                    /* decoding error */
00265                                    if ( !a->a_comp_data->cd_tree[i] ) {
00266                                           return LDAP_OPERATIONS_ERROR;
00267                                    }
00268                                    rc = value_match( &ret, a->a_desc, mra->ma_rule,
00269                                           SLAP_MR_COMPONENT,
00270                                           (struct berval*)a->a_comp_data->cd_tree[i++],
00271                                           (void*)mra, &text );
00272                             } else 
00273 #endif
00274                             {
00275                                    struct berval nbv = BER_BVNULL;
00276 
00277                                    if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
00278                                           /*
00279                             
00280                             Document: RFC 4511
00281 
00282                                 4.5.1. Search Request 
00283                                     ...
00284                                 If the type field is present and the matchingRule is present, 
00285                                  the matchValue is compared against entry attributes of the 
00286                                  specified type. In this case, the matchingRule MUST be one 
00287                                 suitable for use with the specified type (see [RFC4517]), 
00288                                 otherwise the filter item is Undefined.  
00289 
00290 
00291                             In this case, since the matchingRule requires the assertion
00292                             value to be normalized, we normalize the attribute value
00293                             according to the syntax of the matchingRule.
00294 
00295                             This should likely be done inside value_match(), by passing
00296                             the appropriate flags, but this is not done at present.
00297                             See ITS#3406.
00298                                            */
00299                                           if ( mra->ma_rule->smr_normalize(
00300                                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
00301                                                         mra->ma_rule->smr_syntax,
00302                                                         mra->ma_rule,
00303                                                         bv, &nbv, memctx ) != LDAP_SUCCESS )
00304                                           {
00305                                                  /* FIXME: stop processing? */
00306                                                  continue;
00307                                           }
00308 
00309                                    } else {
00310                                           nbv = *bv;
00311                                    }
00312 
00313                                    rc = value_match( &ret, a->a_desc, mra->ma_rule,
00314                                           SLAP_MR_EXT, &nbv, &mra->ma_value, &text );
00315 
00316                                    if ( nbv.bv_val != bv->bv_val ) {
00317                                           memfree( nbv.bv_val, memctx );
00318                                    }
00319                             }
00320 
00321                             if ( rc != LDAP_SUCCESS ) return rc;
00322                             if ( ret == 0 ) return LDAP_COMPARE_TRUE;
00323                      }
00324               }
00325 
00326        } else {
00327               /*
00328                * No attribute description: test all
00329                */
00330               for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
00331                      struct berval *bv, value;
00332                      const char    *text = NULL;
00333                      int           rc;
00334                      int           normalize_attribute = 0;
00335 
00336                      /* check if matching is appropriate */
00337                      if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type ) ) {
00338                             continue;
00339                      }
00340 
00341                      /* normalize for equality */
00342                      rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule,
00343                             SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
00344                             &mra->ma_value, &value, &text, memctx );
00345                      if ( rc != LDAP_SUCCESS ) continue;
00346 
00347                      /* check search access */
00348                      if ( !access_allowed( op, e,
00349                             a->a_desc, &value, ACL_SEARCH, NULL ) )
00350                      {
00351                             memfree( value.bv_val, memctx );
00352                             continue;
00353                      }
00354 #ifdef LDAP_COMP_MATCH
00355                      /* Component Matching */
00356                      if ( mra->ma_cf &&
00357                             mra->ma_rule->smr_usage & SLAP_MR_COMPONENT )
00358                      {
00359                             int ret;
00360 
00361                             rc = value_match( &ret, a->a_desc, mra->ma_rule,
00362                                    SLAP_MR_COMPONENT,
00363                                    (struct berval*)a, (void*)mra, &text );
00364                             if ( rc != LDAP_SUCCESS ) break;
00365        
00366                             if ( ret == 0 ) {
00367                                    rc = LDAP_COMPARE_TRUE;
00368                                    break;
00369                             }
00370 
00371                      }
00372 #endif
00373 
00374                      /* check match */
00375                      if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) {
00376                             bv = a->a_nvals;
00377 
00378                      } else {
00379                             bv = a->a_vals;
00380                             normalize_attribute = 1;
00381                      }
00382 
00383                      for ( ; !BER_BVISNULL( bv ); bv++ ) {
00384                             int           ret;
00385                             struct berval nbv = BER_BVNULL;
00386 
00387                             if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
00388                                    /* see comment above */
00389                                    if ( mra->ma_rule->smr_normalize(
00390                                                  SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
00391                                                  mra->ma_rule->smr_syntax,
00392                                                  mra->ma_rule,
00393                                                  bv, &nbv, memctx ) != LDAP_SUCCESS )
00394                                    {
00395                                           /* FIXME: stop processing? */
00396                                           continue;
00397                                    }
00398 
00399                             } else {
00400                                    nbv = *bv;
00401                             }
00402 
00403                             rc = value_match( &ret, a->a_desc, mra->ma_rule,
00404                                    SLAP_MR_EXT, &nbv, &value, &text );
00405 
00406                             if ( nbv.bv_val != bv->bv_val ) {
00407                                    memfree( nbv.bv_val, memctx );
00408                             }
00409 
00410                             if ( rc != LDAP_SUCCESS ) break;
00411        
00412                             if ( ret == 0 ) {
00413                                    rc = LDAP_COMPARE_TRUE;
00414                                    break;
00415                             }
00416                      }
00417                      memfree( value.bv_val, memctx );
00418                      if ( rc != LDAP_SUCCESS ) return rc;
00419               }
00420        }
00421 
00422        /* check attrs in DN AVAs if required */
00423        if ( mra->ma_dnattrs && !BER_BVISEMPTY( &e->e_nname ) ) {
00424               LDAPDN        dn = NULL;
00425               int           iRDN, iAVA;
00426               int           rc;
00427 
00428               /* parse and pretty the dn */
00429               rc = dnPrettyDN( NULL, &e->e_name, &dn, memctx );
00430               if ( rc != LDAP_SUCCESS ) {
00431                      return LDAP_INVALID_SYNTAX;
00432               }
00433 
00434               /* for each AVA of each RDN ... */
00435               for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
00436                      LDAPRDN              rdn = dn[ iRDN ];
00437 
00438                      for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
00439                             LDAPAVA              *ava = rdn[ iAVA ];
00440                             struct berval *bv = &ava->la_value,
00441                                           value = BER_BVNULL,
00442                                           nbv = BER_BVNULL;
00443                             AttributeDescription *ad =
00444                                    (AttributeDescription *)ava->la_private;
00445                             int           ret;
00446                             const char    *text;
00447 
00448                             assert( ad != NULL );
00449 
00450                             if ( mra->ma_desc ) {
00451                                    /* have a mra type? check for subtype */
00452                                    if ( !is_ad_subtype( ad, mra->ma_desc ) ) {
00453                                           continue;
00454                                    }
00455                                    value = mra->ma_value;
00456 
00457                             } else {
00458                                    const char    *text = NULL;
00459 
00460                                    /* check if matching is appropriate */
00461                                    if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type ) ) {
00462                                           continue;
00463                                    }
00464 
00465                                    /* normalize for equality */
00466                                    rc = asserted_value_validate_normalize( ad,
00467                                           mra->ma_rule,
00468                                           SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
00469                                           &mra->ma_value, &value, &text, memctx );
00470                                    if ( rc != LDAP_SUCCESS ) continue;
00471 
00472                                    /* check search access */
00473                                    if ( !access_allowed( op, e,
00474                                           ad, &value, ACL_SEARCH, NULL ) )
00475                                    {
00476                                           memfree( value.bv_val, memctx );
00477                                           continue;
00478                                    }
00479                             }
00480 
00481                             if ( mra->ma_rule->smr_normalize ) {
00482                                    /* see comment above */
00483                                    if ( mra->ma_rule->smr_normalize(
00484                                                  SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
00485                                                  mra->ma_rule->smr_syntax,
00486                                                  mra->ma_rule,
00487                                                  bv, &nbv, memctx ) != LDAP_SUCCESS )
00488                                    {
00489                                           /* FIXME: stop processing? */
00490                                           rc = LDAP_SUCCESS;
00491                                           ret = -1;
00492                                           goto cleanup;
00493                                    }
00494 
00495                             } else {
00496                                    nbv = *bv;
00497                             }
00498 
00499                             /* check match */
00500                             rc = value_match( &ret, ad, mra->ma_rule, SLAP_MR_EXT,
00501                                    &nbv, &value, &text );
00502 
00503 cleanup:;
00504                             if ( !BER_BVISNULL( &value ) && value.bv_val != mra->ma_value.bv_val ) {
00505                                    memfree( value.bv_val, memctx );
00506                             }
00507 
00508                             if ( !BER_BVISNULL( &nbv ) && nbv.bv_val != bv->bv_val ) {
00509                                    memfree( nbv.bv_val, memctx );
00510                             }
00511 
00512                             if ( rc == LDAP_SUCCESS && ret == 0 ) rc = LDAP_COMPARE_TRUE;
00513 
00514                             if ( rc != LDAP_SUCCESS ) {
00515                                    ldap_dnfree_x( dn, memctx );
00516                                    return rc;
00517                             }
00518                      }
00519               }
00520               ldap_dnfree_x( dn, memctx );
00521        }
00522 
00523        return LDAP_COMPARE_FALSE;
00524 }
00525 
00526 static int
00527 test_ava_filter(
00528        Operation     *op,
00529        Entry         *e,
00530        AttributeAssertion *ava,
00531        int           type )
00532 {
00533        int rc;
00534        Attribute     *a;
00535 #ifdef LDAP_COMP_MATCH
00536        int i, num_attr_vals = 0;
00537        AttributeAliasing *a_alias = NULL;
00538 #endif
00539 
00540        if ( !access_allowed( op, e,
00541               ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL ) )
00542        {
00543               return LDAP_INSUFFICIENT_ACCESS;
00544        }
00545 
00546        if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates 
00547               && op && op->o_bd && op->o_bd->be_has_subordinates )
00548        {
00549               int    hasSubordinates = 0;
00550               struct berval hs;
00551 
00552               if( type != LDAP_FILTER_EQUALITY &&
00553                      type != LDAP_FILTER_APPROX )
00554               {
00555                      /* No other match is allowed */
00556                      return LDAP_INAPPROPRIATE_MATCHING;
00557               }
00558               
00559               if ( op->o_bd->be_has_subordinates( op, e, &hasSubordinates ) !=
00560                      LDAP_SUCCESS )
00561               {
00562                      return LDAP_OTHER;
00563               }
00564 
00565               if ( hasSubordinates == LDAP_COMPARE_TRUE ) {
00566                      hs = slap_true_bv;
00567 
00568               } else if ( hasSubordinates == LDAP_COMPARE_FALSE ) {
00569                      hs = slap_false_bv;
00570 
00571               } else {
00572                      return LDAP_OTHER;
00573               }
00574 
00575               if ( bvmatch( &ava->aa_value, &hs ) ) return LDAP_COMPARE_TRUE;
00576               return LDAP_COMPARE_FALSE;
00577        }
00578 
00579        if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
00580               MatchingRule *mr;
00581               int match;
00582               const char *text;
00583 
00584               if( type != LDAP_FILTER_EQUALITY &&
00585                      type != LDAP_FILTER_APPROX )
00586               {
00587                      /* No other match is allowed */
00588                      return LDAP_INAPPROPRIATE_MATCHING;
00589               }
00590 
00591               mr = slap_schema.si_ad_entryDN->ad_type->sat_equality;
00592               assert( mr != NULL );
00593 
00594               rc = value_match( &match, slap_schema.si_ad_entryDN, mr,
00595                      SLAP_MR_EXT, &e->e_nname, &ava->aa_value, &text );
00596 
00597               if( rc != LDAP_SUCCESS ) return rc;
00598               if( match == 0 ) return LDAP_COMPARE_TRUE;
00599               return LDAP_COMPARE_FALSE;
00600        }
00601 
00602        rc = LDAP_COMPARE_FALSE;
00603 
00604 #ifdef LDAP_COMP_MATCH
00605        if ( is_aliased_attribute && ava->aa_cf )
00606        {
00607               a_alias = is_aliased_attribute ( ava->aa_desc );
00608               if ( a_alias )
00609                      ava->aa_desc = a_alias->aa_aliased_ad;
00610               else
00611                      ava->aa_cf = NULL;
00612        }
00613 #endif
00614 
00615        for(a = attrs_find( e->e_attrs, ava->aa_desc );
00616               a != NULL;
00617               a = attrs_find( a->a_next, ava->aa_desc ) )
00618        {
00619               int use;
00620               MatchingRule *mr;
00621               struct berval *bv;
00622 
00623               if (( ava->aa_desc != a->a_desc ) && !access_allowed( op,
00624                      e, a->a_desc, &ava->aa_value, ACL_SEARCH, NULL ))
00625               {
00626                      rc = LDAP_INSUFFICIENT_ACCESS;
00627                      continue;
00628               }
00629 
00630               use = SLAP_MR_EQUALITY;
00631 
00632               switch ( type ) {
00633               case LDAP_FILTER_APPROX:
00634                      use = SLAP_MR_EQUALITY_APPROX;
00635                      mr = a->a_desc->ad_type->sat_approx;
00636                      if( mr != NULL ) break;
00637 
00638                      /* fallthru: use EQUALITY matching rule if no APPROX rule */
00639 
00640               case LDAP_FILTER_EQUALITY:
00641                      /* use variable set above so fall thru use is not clobbered */
00642                      mr = a->a_desc->ad_type->sat_equality;
00643                      break;
00644 
00645               case LDAP_FILTER_GE:
00646               case LDAP_FILTER_LE:
00647                      use = SLAP_MR_ORDERING;
00648                      mr = a->a_desc->ad_type->sat_ordering;
00649                      break;
00650 
00651               default:
00652                      mr = NULL;
00653               }
00654 
00655               if( mr == NULL ) {
00656                      rc = LDAP_INAPPROPRIATE_MATCHING;
00657                      continue;
00658               }
00659 
00660               /* We have no Sort optimization for Approx matches */
00661               if (( a->a_flags & SLAP_ATTR_SORTED_VALS ) && type != LDAP_FILTER_APPROX ) {
00662                      unsigned slot;
00663                      int ret;
00664 
00665                      /* For Ordering matches, we just need to do one comparison with
00666                       * either the first (least) or last (greatest) value.
00667                       */
00668                      if ( use == SLAP_MR_ORDERING ) {
00669                             const char *text;
00670                             int match, which;
00671                             which = (type == LDAP_FILTER_LE) ? 0 : a->a_numvals-1;
00672                             ret = value_match( &match, a->a_desc, mr, use,
00673                                    &a->a_nvals[which], &ava->aa_value, &text );
00674                             if ( ret != LDAP_SUCCESS ) return ret;
00675                             if (( type == LDAP_FILTER_LE && match <= 0 ) ||
00676                                    ( type == LDAP_FILTER_GE && match >= 0 ))
00677                                    return LDAP_COMPARE_TRUE;
00678                             continue;
00679                      }
00680                      /* Only Equality will get here */
00681                      ret = attr_valfind( a, use | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH |
00682                             SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH, 
00683                             &ava->aa_value, &slot, NULL );
00684                      if ( ret == LDAP_SUCCESS )
00685                             return LDAP_COMPARE_TRUE;
00686                      else if ( ret != LDAP_NO_SUCH_ATTRIBUTE )
00687                             return ret;
00688 #if 0
00689                      /* The following is useful if we want to know which values
00690                       * matched an ordering test. But here we don't care, we just
00691                       * want to know if any value did, and that is checked above.
00692                       */
00693                      if ( ret == LDAP_NO_SUCH_ATTRIBUTE ) {
00694                             /* If insertion point is not the end of the list, there was
00695                              * at least one value greater than the assertion.
00696                              */
00697                             if ( type == LDAP_FILTER_GE && slot < a->a_numvals )
00698                                    return LDAP_COMPARE_TRUE;
00699                             /* Likewise, if insertion point is not the head of the list,
00700                              * there was at least one value less than the assertion.
00701                              */
00702                             if ( type == LDAP_FILTER_LE && slot > 0 )
00703                                    return LDAP_COMPARE_TRUE;
00704                             return LDAP_COMPARE_FALSE;
00705                      }
00706 #endif
00707                      continue;
00708               }
00709 
00710 #ifdef LDAP_COMP_MATCH
00711               if ( nibble_mem_allocator && ava->aa_cf && !a->a_comp_data ) {
00712                      /* Component Matching */
00713                      for ( num_attr_vals = 0; a->a_vals[num_attr_vals].bv_val != NULL; num_attr_vals++ );
00714                      if ( num_attr_vals <= 0 )/* no attribute value */
00715                             return LDAP_INAPPROPRIATE_MATCHING;
00716                      num_attr_vals++;/* for NULL termination */
00717 
00718                      /* following malloced will be freed by comp_tree_free () */
00719                      a->a_comp_data = SLAP_MALLOC( sizeof( ComponentData ) + sizeof( ComponentSyntaxInfo* )*num_attr_vals );
00720 
00721                      if ( !a->a_comp_data ) {
00722                             return LDAP_NO_MEMORY;
00723                      }
00724 
00725                      a->a_comp_data->cd_tree = (ComponentSyntaxInfo**)((char*)a->a_comp_data + sizeof(ComponentData));
00726                      i = num_attr_vals;
00727                      for ( ; i ; i-- ) {
00728                             a->a_comp_data->cd_tree[ i-1 ] = (ComponentSyntaxInfo*)NULL;
00729                      }
00730 
00731                      a->a_comp_data->cd_mem_op = nibble_mem_allocator ( 1024*10*(num_attr_vals-1), 1024 );
00732                      if ( a->a_comp_data->cd_mem_op == NULL ) {
00733                             free ( a->a_comp_data );
00734                             a->a_comp_data = NULL;
00735                             return LDAP_OPERATIONS_ERROR;
00736                      }
00737               }
00738 
00739               i = 0;
00740 #endif
00741 
00742               for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
00743                      int ret, match;
00744                      const char *text;
00745 
00746 #ifdef LDAP_COMP_MATCH
00747                      if( attr_converter && ava->aa_cf && a->a_comp_data ) {
00748                             /* Check if decoded component trees are already linked */
00749                             struct berval cf_bv = { 20, "componentFilterMatch" };
00750                             MatchingRule* cf_mr = mr_bvfind( &cf_bv );
00751                             MatchingRuleAssertion mra;
00752                             mra.ma_cf = ava->aa_cf;
00753 
00754                             if ( a->a_comp_data->cd_tree[i] == NULL )
00755                                    a->a_comp_data->cd_tree[i] = attr_converter (a, a->a_desc->ad_type->sat_syntax, (a->a_vals + i));
00756                             /* decoding error */
00757                             if ( !a->a_comp_data->cd_tree[i] ) {
00758                                    free_ComponentData ( a );
00759                                    return LDAP_OPERATIONS_ERROR;
00760                             }
00761 
00762                             ret = value_match( &match, a->a_desc, cf_mr,
00763                                    SLAP_MR_COMPONENT,
00764                                    (struct berval*)a->a_comp_data->cd_tree[i++],
00765                                    (void*)&mra, &text );
00766                             if ( ret == LDAP_INAPPROPRIATE_MATCHING ) {
00767                                    /* cached component tree is broken, just remove it */
00768                                    free_ComponentData ( a );
00769                                    return ret;
00770                             }
00771                             if ( a_alias )
00772                                    ava->aa_desc = a_alias->aa_aliasing_ad;
00773 
00774                      } else 
00775 #endif
00776                      {
00777                             ret = ordered_value_match( &match, a->a_desc, mr, use,
00778                                    bv, &ava->aa_value, &text );
00779                      }
00780 
00781                      if( ret != LDAP_SUCCESS ) {
00782                             rc = ret;
00783                             break;
00784                      }
00785 
00786                      switch ( type ) {
00787                      case LDAP_FILTER_EQUALITY:
00788                      case LDAP_FILTER_APPROX:
00789                             if ( match == 0 ) return LDAP_COMPARE_TRUE;
00790                             break;
00791 
00792                      case LDAP_FILTER_GE:
00793                             if ( match >= 0 ) return LDAP_COMPARE_TRUE;
00794                             break;
00795 
00796                      case LDAP_FILTER_LE:
00797                             if ( match <= 0 ) return LDAP_COMPARE_TRUE;
00798                             break;
00799                      }
00800               }
00801        }
00802 
00803 #ifdef LDAP_COMP_MATCH
00804        if ( a_alias )
00805               ava->aa_desc = a_alias->aa_aliasing_ad;
00806 #endif
00807 
00808        return rc;
00809 }
00810 
00811 
00812 static int
00813 test_presence_filter(
00814        Operation     *op,
00815        Entry         *e,
00816        AttributeDescription *desc )
00817 {
00818        Attribute     *a;
00819        int rc;
00820 
00821        if ( !access_allowed( op, e, desc, NULL, ACL_SEARCH, NULL ) ) {
00822               return LDAP_INSUFFICIENT_ACCESS;
00823        }
00824 
00825        if ( desc == slap_schema.si_ad_hasSubordinates ) {
00826               /*
00827                * XXX: fairly optimistic: if the function is defined,
00828                * then PRESENCE must succeed, because hasSubordinate
00829                * is boolean-valued; I think we may live with this 
00830                * simplification by now.
00831                */
00832               if ( op && op->o_bd && op->o_bd->be_has_subordinates ) {
00833                      return LDAP_COMPARE_TRUE;
00834               }
00835 
00836               return LDAP_COMPARE_FALSE;
00837        }
00838 
00839        if ( desc == slap_schema.si_ad_entryDN ||
00840               desc == slap_schema.si_ad_subschemaSubentry )
00841        {
00842               /* entryDN and subschemaSubentry are always present */
00843               return LDAP_COMPARE_TRUE;
00844        }
00845 
00846        rc = LDAP_COMPARE_FALSE;
00847 
00848        for(a = attrs_find( e->e_attrs, desc );
00849               a != NULL;
00850               a = attrs_find( a->a_next, desc ) )
00851        {
00852               if (( desc != a->a_desc ) && !access_allowed( op,
00853                      e, a->a_desc, NULL, ACL_SEARCH, NULL ))
00854               {
00855                      rc = LDAP_INSUFFICIENT_ACCESS;
00856                      continue;
00857               }
00858 
00859               rc = LDAP_COMPARE_TRUE;
00860               break;
00861        }
00862 
00863        return rc;
00864 }
00865 
00866 
00867 static int
00868 test_filter_and(
00869        Operation     *op,
00870        Entry  *e,
00871        Filter *flist )
00872 {
00873        Filter *f;
00874        int rtn = LDAP_COMPARE_TRUE; /* True if empty */
00875 
00876        Debug( LDAP_DEBUG_FILTER, "=> test_filter_and\n", 0, 0, 0 );
00877 
00878        for ( f = flist; f != NULL; f = f->f_next ) {
00879               int rc = test_filter( op, e, f );
00880 
00881               if ( rc == LDAP_COMPARE_FALSE ) {
00882                      /* filter is False */
00883                      rtn = rc;
00884                      break;
00885               }
00886 
00887               if ( rc != LDAP_COMPARE_TRUE ) {
00888                      /* filter is Undefined unless later elements are False */
00889                      rtn = rc;
00890               }
00891        }
00892 
00893        Debug( LDAP_DEBUG_FILTER, "<= test_filter_and %d\n", rtn, 0, 0 );
00894 
00895        return rtn;
00896 }
00897 
00898 static int
00899 test_filter_or(
00900        Operation     *op,
00901        Entry  *e,
00902        Filter *flist )
00903 {
00904        Filter *f;
00905        int rtn = LDAP_COMPARE_FALSE; /* False if empty */
00906 
00907        Debug( LDAP_DEBUG_FILTER, "=> test_filter_or\n", 0, 0, 0 );
00908 
00909        for ( f = flist; f != NULL; f = f->f_next ) {
00910               int rc = test_filter( op, e, f );
00911 
00912               if ( rc == LDAP_COMPARE_TRUE ) {
00913                      /* filter is True */
00914                      rtn = rc;
00915                      break;
00916               }
00917 
00918               if ( rc != LDAP_COMPARE_FALSE ) {
00919                      /* filter is Undefined unless later elements are True */
00920                      rtn = rc;
00921               }
00922        }
00923 
00924        Debug( LDAP_DEBUG_FILTER, "<= test_filter_or %d\n", rtn, 0, 0 );
00925        return rtn;
00926 }
00927 
00928 
00929 static int
00930 test_substrings_filter(
00931        Operation     *op,
00932        Entry  *e,
00933        Filter *f )
00934 {
00935        Attribute     *a;
00936        int rc;
00937 
00938        Debug( LDAP_DEBUG_FILTER, "begin test_substrings_filter\n", 0, 0, 0 );
00939 
00940        if ( !access_allowed( op, e,
00941               f->f_sub_desc, NULL, ACL_SEARCH, NULL ) )
00942        {
00943               return LDAP_INSUFFICIENT_ACCESS;
00944        }
00945 
00946        rc = LDAP_COMPARE_FALSE;
00947 
00948        for(a = attrs_find( e->e_attrs, f->f_sub_desc );
00949               a != NULL;
00950               a = attrs_find( a->a_next, f->f_sub_desc ) )
00951        {
00952               MatchingRule *mr;
00953               struct berval *bv;
00954 
00955               if (( f->f_sub_desc != a->a_desc ) && !access_allowed( op,
00956                      e, a->a_desc, NULL, ACL_SEARCH, NULL ))
00957               {
00958                      rc = LDAP_INSUFFICIENT_ACCESS;
00959                      continue;
00960               }
00961 
00962               mr = a->a_desc->ad_type->sat_substr;
00963               if( mr == NULL ) {
00964                      rc = LDAP_INAPPROPRIATE_MATCHING;
00965                      continue;
00966               }
00967 
00968               for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
00969                      int ret, match;
00970                      const char *text;
00971 
00972                      ret = value_match( &match, a->a_desc, mr, SLAP_MR_SUBSTR,
00973                             bv, f->f_sub, &text );
00974 
00975                      if( ret != LDAP_SUCCESS ) {
00976                             rc = ret;
00977                             break;
00978                      }
00979                      if ( match == 0 ) return LDAP_COMPARE_TRUE;
00980               }
00981        }
00982 
00983        Debug( LDAP_DEBUG_FILTER, "end test_substrings_filter %d\n",
00984               rc, 0, 0 );
00985        return rc;
00986 }