]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/filterentry.c
streamline group attr specification/diagnostics
[openldap] / servers / slapd / filterentry.c
index 005c6f7aa44ae4553e6e99961893000052118b98..336476a8fd39d9a8f624b706e95a91a1607aee71 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2005 The OpenLDAP Foundation.
+ * Copyright 1998-2007 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include <ac/socket.h>
 #include <ac/string.h>
 
-
 #include "slap.h"
 
+#ifdef LDAP_COMP_MATCH
+#include "component.h"
+#endif
+
 static int     test_filter_and( Operation *op, Entry *e, Filter *flist );
 static int     test_filter_or( Operation *op, Entry *e, Filter *flist );
 static int     test_substrings_filter( Operation *op, Entry *e, Filter *f);
@@ -63,6 +66,12 @@ test_filter(
        int     rc;
        Debug( LDAP_DEBUG_FILTER, "=> test_filter\n", 0, 0, 0 );
 
+       if ( f->f_choice & SLAPD_FILTER_UNDEFINED ) {
+               Debug( LDAP_DEBUG_FILTER, "    UNDEFINED\n", 0, 0, 0 );
+               rc = SLAPD_COMPARE_UNDEFINED;
+               goto out;
+       }
+
        switch ( f->f_choice ) {
        case SLAPD_FILTER_COMPUTED:
                Debug( LDAP_DEBUG_FILTER, "    COMPUTED %s (%d)\n",
@@ -141,7 +150,7 @@ test_filter(
                    f->f_choice, 0, 0 );
                rc = LDAP_PROTOCOL_ERROR;
        }
-
+out:
        Debug( LDAP_DEBUG_FILTER, "<= test_filter %d\n", rc, 0, 0 );
        return( rc );
 }
@@ -155,7 +164,7 @@ static int test_mra_filter(
        void            *memctx;
        BER_MEMFREE_FN  *memfree;
 #ifdef LDAP_COMP_MATCH
-       int i, num_attr_vals;
+       int i, num_attr_vals = 0;
 #endif
 
        if ( op == NULL ) {
@@ -183,7 +192,7 @@ static int test_mra_filter(
                        const char *text;
 
                        rc = value_match( &ret, slap_schema.si_ad_entryDN, mra->ma_rule,
-                               0, &e->e_nname, &mra->ma_value, &text );
+                               SLAP_MR_EXT, &e->e_nname, &mra->ma_value, &text );
        
        
                        if( rc != LDAP_SUCCESS ) return rc;
@@ -261,7 +270,8 @@ static int test_mra_filter(
                                        if ( !a->a_comp_data->cd_tree[i] ) {
                                                return LDAP_OPERATIONS_ERROR;
                                        }
-                                       rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
+                                       rc = value_match( &ret, a->a_desc, mra->ma_rule,
+                                               SLAP_MR_COMPONENT,
                                                (struct berval*)a->a_comp_data->cd_tree[i++],
                                                (void*)mra, &text );
                                } else 
@@ -272,14 +282,14 @@ static int test_mra_filter(
                                        if ( normalize_attribute && mra->ma_rule->smr_normalize ) {
                                                /*
                                
-                               Document: draft-ietf-ldapbis-protocol
+                               Document: RFC 4511
 
                                    4.5.1. Search Request 
                                        ...
                                    If the type field is present and the matchingRule is present, 
                                    the matchValue is compared against entry attributes of the 
                                    specified type. In this case, the matchingRule MUST be one 
-                                   suitable for use with the specified type (see [Syntaxes]), 
+                                   suitable for use with the specified type (see [RFC4517]), 
                                    otherwise the filter item is Undefined.  
 
 
@@ -305,8 +315,8 @@ static int test_mra_filter(
                                                nbv = *bv;
                                        }
 
-                                       rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
-                                               &nbv, &mra->ma_value, &text );
+                                       rc = value_match( &ret, a->a_desc, mra->ma_rule,
+                                               SLAP_MR_EXT, &nbv, &mra->ma_value, &text );
 
                                        if ( nbv.bv_val != bv->bv_val ) {
                                                memfree( nbv.bv_val, memctx );
@@ -353,7 +363,8 @@ static int test_mra_filter(
                        {
                                int ret;
 
-                               rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
+                               rc = value_match( &ret, a->a_desc, mra->ma_rule,
+                                       SLAP_MR_COMPONENT,
                                        (struct berval*)a, (void*)mra, &text );
                                if ( rc != LDAP_SUCCESS ) break;
        
@@ -394,8 +405,8 @@ static int test_mra_filter(
                                        nbv = *bv;
                                }
 
-                               rc = value_match( &ret, a->a_desc, mra->ma_rule, 0,
-                                       &nbv, &value, &text );
+                               rc = value_match( &ret, a->a_desc, mra->ma_rule,
+                                       SLAP_MR_EXT, &nbv, &value, &text );
 
                                if ( nbv.bv_val != bv->bv_val ) {
                                        memfree( nbv.bv_val, memctx );
@@ -431,13 +442,15 @@ static int test_mra_filter(
 
                        for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
                                LDAPAVA         *ava = rdn[ iAVA ];
-                               struct berval   *bv = &ava->la_value, value;
+                               struct berval   *bv = &ava->la_value,
+                                               value = BER_BVNULL,
+                                               nbv = BER_BVNULL;
                                AttributeDescription *ad =
                                        (AttributeDescription *)ava->la_private;
-                               int ret;
-                               const char *text;
+                               int             ret;
+                               const char      *text;
 
-                               assert( ad );
+                               assert( ad != NULL );
 
                                if ( mra->ma_desc ) {
                                        /* have a mra type? check for subtype */
@@ -470,13 +483,37 @@ static int test_mra_filter(
                                        }
                                }
 
+                               if ( mra->ma_rule->smr_normalize ) {
+                                       /* see comment above */
+                                       if ( mra->ma_rule->smr_normalize(
+                                                       SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
+                                                       mra->ma_rule->smr_syntax,
+                                                       mra->ma_rule,
+                                                       bv, &nbv, memctx ) != LDAP_SUCCESS )
+                                       {
+                                               /* FIXME: stop processing? */
+                                               rc = LDAP_SUCCESS;
+                                               ret = -1;
+                                               goto cleanup;
+                                       }
+
+                               } else {
+                                       nbv = *bv;
+                               }
+
                                /* check match */
-                               rc = value_match( &ret, ad, mra->ma_rule, 0,
-                                       bv, &value, &text );
-                               if ( value.bv_val != mra->ma_value.bv_val ) {
+                               rc = value_match( &ret, ad, mra->ma_rule, SLAP_MR_EXT,
+                                       &nbv, &value, &text );
+
+cleanup:;
+                               if ( !BER_BVISNULL( &value ) && value.bv_val != mra->ma_value.bv_val ) {
                                        memfree( value.bv_val, memctx );
                                }
 
+                               if ( !BER_BVISNULL( &nbv ) && nbv.bv_val != bv->bv_val ) {
+                                       memfree( nbv.bv_val, memctx );
+                               }
+
                                if ( rc == LDAP_SUCCESS && ret == 0 ) rc = LDAP_COMPARE_TRUE;
 
                                if ( rc != LDAP_SUCCESS ) {
@@ -500,6 +537,10 @@ test_ava_filter(
 {
        int rc;
        Attribute       *a;
+#ifdef LDAP_COMP_MATCH
+       int i, num_attr_vals = 0;
+       AttributeAliasing *a_alias = NULL;
+#endif
 
        if ( !access_allowed( op, e,
                ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL ) )
@@ -553,10 +594,10 @@ test_ava_filter(
                }
 
                mr = slap_schema.si_ad_entryDN->ad_type->sat_equality;
-               assert( mr );
+               assert( mr != NULL );
 
-               rc = value_match( &match, slap_schema.si_ad_entryDN, mr, 0,
-                       &e->e_nname, &ava->aa_value, &text );
+               rc = value_match( &match, slap_schema.si_ad_entryDN, mr,
+                       SLAP_MR_EXT, &e->e_nname, &ava->aa_value, &text );
 
                if( rc != LDAP_SUCCESS ) return rc;
                if( match == 0 ) return LDAP_COMPARE_TRUE;
@@ -565,10 +606,22 @@ test_ava_filter(
 
        rc = LDAP_COMPARE_FALSE;
 
+#ifdef LDAP_COMP_MATCH
+       if ( is_aliased_attribute && ava->aa_cf )
+       {
+               a_alias = is_aliased_attribute ( ava->aa_desc );
+               if ( a_alias )
+                       ava->aa_desc = a_alias->aa_aliased_ad;
+               else
+                       ava->aa_cf = NULL;
+       }
+#endif
+
        for(a = attrs_find( e->e_attrs, ava->aa_desc );
                a != NULL;
                a = attrs_find( a->a_next, ava->aa_desc ) )
        {
+               int use;
                MatchingRule *mr;
                struct berval *bv;
 
@@ -579,19 +632,24 @@ test_ava_filter(
                        continue;
                }
 
+               use = SLAP_MR_EQUALITY;
+
                switch ( type ) {
                case LDAP_FILTER_APPROX:
+                       use = SLAP_MR_EQUALITY_APPROX;
                        mr = a->a_desc->ad_type->sat_approx;
                        if( mr != NULL ) break;
 
-                       /* use EQUALITY matching rule if no APPROX rule */
+                       /* fallthru: use EQUALITY matching rule if no APPROX rule */
 
                case LDAP_FILTER_EQUALITY:
+                       /* use variable set above so fall thru use is not clobbered */
                        mr = a->a_desc->ad_type->sat_equality;
                        break;
 
                case LDAP_FILTER_GE:
                case LDAP_FILTER_LE:
+                       use = SLAP_MR_ORDERING;
                        mr = a->a_desc->ad_type->sat_ordering;
                        break;
 
@@ -604,12 +662,76 @@ test_ava_filter(
                        continue;
                }
 
+#ifdef LDAP_COMP_MATCH
+               if ( nibble_mem_allocator && ava->aa_cf && !a->a_comp_data ) {
+                       /* Component Matching */
+                       for ( num_attr_vals = 0; a->a_vals[num_attr_vals].bv_val != NULL; num_attr_vals++ );
+                       if ( num_attr_vals <= 0 )/* no attribute value */
+                               return LDAP_INAPPROPRIATE_MATCHING;
+                       num_attr_vals++;/* for NULL termination */
+
+                       /* following malloced will be freed by comp_tree_free () */
+                       a->a_comp_data = malloc( sizeof( ComponentData ) + sizeof( ComponentSyntaxInfo* )*num_attr_vals );
+
+                       if ( !a->a_comp_data ) {
+                               return LDAP_NO_MEMORY;
+                       }
+
+                       a->a_comp_data->cd_tree = (ComponentSyntaxInfo**)((char*)a->a_comp_data + sizeof(ComponentData));
+                       i = num_attr_vals;
+                       for ( ; i ; i-- ) {
+                               a->a_comp_data->cd_tree[ i-1 ] = (ComponentSyntaxInfo*)NULL;
+                       }
+
+                       a->a_comp_data->cd_mem_op = nibble_mem_allocator ( 1024*10*(num_attr_vals-1), 1024 );
+                       if ( a->a_comp_data->cd_mem_op == NULL ) {
+                               free ( a->a_comp_data );
+                               a->a_comp_data = NULL;
+                               return LDAP_OPERATIONS_ERROR;
+                       }
+               }
+
+               i = 0;
+#endif
+
                for ( bv = a->a_nvals; !BER_BVISNULL( bv ); bv++ ) {
                        int ret, match;
                        const char *text;
 
-                       ret = value_match( &match, a->a_desc, mr, 0,
-                               bv, &ava->aa_value, &text );
+#ifdef LDAP_COMP_MATCH
+                       if( attr_converter && ava->aa_cf && a->a_comp_data ) {
+                               /* Check if decoded component trees are already linked */
+                               struct berval cf_bv = { 20, "componentFilterMatch" };
+                               MatchingRule* cf_mr = mr_bvfind( &cf_bv );
+                               MatchingRuleAssertion mra;
+                               mra.ma_cf = ava->aa_cf;
+
+                               if ( a->a_comp_data->cd_tree[i] == NULL )
+                                       a->a_comp_data->cd_tree[i] = attr_converter (a, a->a_desc->ad_type->sat_syntax, (a->a_vals + i));
+                               /* decoding error */
+                               if ( !a->a_comp_data->cd_tree[i] ) {
+                                       free_ComponentData ( a );
+                                       return LDAP_OPERATIONS_ERROR;
+                               }
+
+                               ret = value_match( &match, a->a_desc, cf_mr,
+                                       SLAP_MR_COMPONENT,
+                                       (struct berval*)a->a_comp_data->cd_tree[i++],
+                                       (void*)&mra, &text );
+                               if ( ret == LDAP_INAPPROPRIATE_MATCHING ) {
+                                       /* cached component tree is broken, just remove it */
+                                       free_ComponentData ( a );
+                                       return ret;
+                               }
+                               if ( a_alias )
+                                       ava->aa_desc = a_alias->aa_aliasing_ad;
+
+                       } else 
+#endif
+                       {
+                               ret = value_match( &match, a->a_desc, mr, use,
+                                       bv, &ava->aa_value, &text );
+                       }
 
                        if( ret != LDAP_SUCCESS ) {
                                rc = ret;
@@ -633,6 +755,11 @@ test_ava_filter(
                }
        }
 
+#ifdef LDAP_COMP_MATCH
+       if ( a_alias )
+               ava->aa_desc = a_alias->aa_aliasing_ad;
+#endif
+
        return rc;
 }
 
@@ -797,7 +924,7 @@ test_substrings_filter(
                        int ret, match;
                        const char *text;
 
-                       ret = value_match( &match, a->a_desc, mr, 0,
+                       ret = value_match( &match, a->a_desc, mr, SLAP_MR_SUBSTR,
                                bv, f->f_sub, &text );
 
                        if( ret != LDAP_SUCCESS ) {