]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/component.c
minor naming cleanup; improvements to DN mapping layer; major docs update
[openldap] / servers / slapd / component.c
index 9b76edfa1b1db5dfb622f6d9059c06a9fd5b0020..2a88ae62d89540cdc181d4ed4f15985f9aa176aa 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2003-2004 The OpenLDAP Foundation.
+ * Copyright 2003-2005 The OpenLDAP Foundation.
  * Portions Copyright 2004 by IBM Corporation.
  * All rights reserved.
  *
 #include "component.h"
 
 /*
- * This three function pointers are initialized
+ * Following function pointers are initialized
  * when a component module is loaded
  */
 alloc_nibble_func* nibble_mem_allocator = NULL;
 free_nibble_func* nibble_mem_free = NULL;
-convert_attr_to_comp_func* attr_converter = NULL ;
+convert_attr_to_comp_func* attr_converter = NULL;
 convert_assert_to_comp_func* assert_converter = NULL ;
 free_component_func* component_destructor = NULL ;
-test_component_func* test_one_component = NULL;
-test_component_func* test_all_components = NULL;
-
+test_component_func* test_components = NULL;
+test_membership_func* is_aliased_attribute = NULL;
+component_encoder_func* component_encoder = NULL;
+get_component_info_func* get_component_description = NULL;
 #define OID_ALL_COMP_MATCH "1.2.36.79672281.1.13.6"
 #define OID_COMP_FILTER_MATCH "1.2.36.79672281.1.13.2"
 #define MAX_LDAP_STR_LEN 128
@@ -61,7 +62,7 @@ static void
 free_comp_filter( ComponentFilter* f );
 
 static int
-test_comp_filter( Syntax *syn, Attribute       *a, struct berval *bv,
+test_comp_filter( Syntax *syn, ComponentSyntaxInfo *a, struct berval *bv,
                        ComponentFilter *f );
 
 int
@@ -97,29 +98,61 @@ componentFilterMatch (
        struct berval *value, 
        void *assertedValue )
 {
+       struct berval* bv;
        Attribute *a = (Attribute*)value;
        MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue;
+       void* assert_nm;
+       int num_attr, rc, i;
 
-       int rc;
-
-       if ( !(mr && mr->smr_usage & SLAP_MR_COMPONENT) || !ma->ma_cf )
+       if ( !mr || !ma->ma_cf )
+               return LDAP_INAPPROPRIATE_MATCHING;
+       /* Check if the component module is loaded */
+       if ( !attr_converter || !nibble_mem_allocator )
                return LDAP_INAPPROPRIATE_MATCHING;
-               
-       rc = test_comp_filter( syntax, a, a->a_vals, ma->ma_cf );
 
-       if ( rc == LDAP_COMPARE_TRUE ) {
-               *matchp = 0;
-               return LDAP_SUCCESS;
+       /* Check if decoded component trees are already linked */
+       num_attr = 0;
+       if ( !a->a_comp_data ) {
+               for ( ; a->a_vals[num_attr].bv_val != NULL; num_attr++ );
+               if ( num_attr <= 0 )/* no attribute value */
+                       return LDAP_INAPPROPRIATE_MATCHING;
+               num_attr++;
+               /* following malloced will be freed by comp_tree_free () */
+               a->a_comp_data = malloc( sizeof( ComponentData ) + sizeof( ComponentSyntaxInfo* )*num_attr );
+               if ( !a->a_comp_data )
+                       return LDAP_NO_MEMORY;
+               a->a_comp_data->cd_tree = (ComponentSyntaxInfo**)((char*)a->a_comp_data + sizeof(ComponentData));
+               a->a_comp_data->cd_tree[ num_attr - 1] = (ComponentSyntaxInfo*)NULL;
+               a->a_comp_data->cd_mem_op = nibble_mem_allocator ( 1024*16, 1024 );
        }
-       else if ( rc == LDAP_COMPARE_FALSE ) {
-               *matchp = 1;
-               return LDAP_SUCCESS;
-       }
-       else {
-               return LDAP_INAPPROPRIATE_MATCHING;
+
+       for ( bv = a->a_vals, i = 0 ; bv->bv_val != NULL; bv++, i++ ) {
+               /* decodes current attribute into components */
+               if ( num_attr != 0 ) {
+                       a->a_comp_data->cd_tree[i] = attr_converter (a, syntax, bv);
+               }
+               /* decoding error */
+               if ( !a->a_comp_data->cd_tree[i] )
+                       return LDAP_OPERATIONS_ERROR;
+
+               rc = test_comp_filter( syntax, a->a_comp_data->cd_tree[i], bv, ma->ma_cf );
+
+               if ( rc == LDAP_COMPARE_TRUE ) {
+                       *matchp = 0;
+                       return LDAP_SUCCESS;
+               }
+               else if ( rc == LDAP_COMPARE_FALSE ) {
+                       continue;
+               }
+               else {
+                       return LDAP_INAPPROPRIATE_MATCHING;
+               }
        }
+       *matchp = 1;
+       return LDAP_SUCCESS;
        
 }
+
 int
 directoryComponentsMatch( 
        int *matchp, 
@@ -149,7 +182,7 @@ allComponentsMatch(
 }
 
 static int
-slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav)
+slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav )
 {
        int len;
 
@@ -159,6 +192,167 @@ slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav)
        return LDAP_SUCCESS;
 }
 
+ComponentReference*
+dup_comp_ref ( Operation* op, ComponentReference* cr )
+{
+       int rc, count = 0;
+       ComponentReference* dup_cr;
+       ComponentId* ci_curr;
+       ComponentId** ci_temp;
+       ber_int_t type;
+
+       dup_cr = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
+
+       dup_cr->cr_len = cr->cr_len;
+       dup_cr->cr_string = cr->cr_string;
+
+       ci_temp = &dup_cr->cr_list;
+       ci_curr = cr->cr_list;
+
+       for ( ; ci_curr ; ci_curr = ci_curr->ci_next, ci_temp = &(*ci_temp)->ci_next ) {
+               *ci_temp = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
+               if ( !ci_temp ) return NULL;
+               **ci_temp = *ci_curr;
+       }
+
+       dup_cr->cr_curr = dup_cr->cr_list;
+
+       return dup_cr;
+}
+
+static int
+dup_comp_filter_list (
+       Operation *op,
+       struct berval *bv,
+       ComponentFilter* in_f,
+       ComponentFilter** out_f )
+{
+       ComponentFilter **new, *f;
+       int             rc;
+
+       new = out_f;
+       for ( f = in_f; f != NULL; f = f->cf_next ) {
+               rc = dup_comp_filter( op, bv, f, new );
+               if ( rc != LDAP_SUCCESS ) {
+                       return rc;
+               }
+               new = &(*new)->cf_next;
+       }
+       return LDAP_SUCCESS;
+}
+
+int
+get_len_of_next_assert_value ( struct berval* bv, char separator )
+{
+       int i = 0;
+       while (1) {
+               if ( (bv->bv_val[ i ] == separator) || ( i >= bv->bv_len) )
+                       break;
+               i++;
+       }
+       bv->bv_val += (i + 1);
+       bv->bv_len -= (i + 1);
+       return i;
+}
+
+int
+dup_comp_filter_item (
+       Operation *op,
+       struct berval* assert_bv,
+       ComponentAssertion* in_ca,
+       ComponentAssertion** out_ca )
+{
+       ComponentAssertion* ca;
+       int len;
+
+       if ( !in_ca->ca_comp_ref )
+               return SLAPD_DISCONNECT;
+
+       *out_ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
+       if ( !(*out_ca) )
+               return LDAP_NO_MEMORY;
+
+       (*out_ca)->ca_comp_data.cd_tree = NULL;
+       (*out_ca)->ca_comp_data.cd_mem_op = NULL;
+
+       (*out_ca)->ca_comp_ref = dup_comp_ref ( op, in_ca->ca_comp_ref );
+       (*out_ca)->ca_use_def = 0;
+       (*out_ca)->ca_ma_rule = in_ca->ca_ma_rule;
+
+       (*out_ca)->ca_ma_value.bv_val = assert_bv->bv_val;
+       len = get_len_of_next_assert_value ( assert_bv, '$' );
+       if ( len <= 0 )
+               return SLAPD_DISCONNECT;
+       (*out_ca)->ca_ma_value.bv_len = len;
+       
+       return LDAP_SUCCESS;
+}
+
+int
+dup_comp_filter (
+       Operation* op,
+       struct berval *bv,
+       ComponentFilter *in_f,
+       ComponentFilter **out_f )
+{
+       int     rc;
+       ComponentFilter dup_f = {0};
+
+       if ( !in_f ) return LDAP_PROTOCOL_ERROR;
+
+       switch ( in_f->cf_choice ) {
+       case LDAP_COMP_FILTER_AND:
+               rc = dup_comp_filter_list( op, bv, in_f->cf_and, &dup_f.cf_and);
+               dup_f.cf_choice = LDAP_COMP_FILTER_AND;
+               break;
+       case LDAP_COMP_FILTER_OR:
+               rc = dup_comp_filter_list( op, bv, in_f->cf_or, &dup_f.cf_or);
+               dup_f.cf_choice = LDAP_COMP_FILTER_OR;
+               break;
+       case LDAP_COMP_FILTER_NOT:
+               rc = dup_comp_filter( op, bv, in_f->cf_not, &dup_f.cf_not);
+               dup_f.cf_choice = LDAP_COMP_FILTER_NOT;
+               break;
+       case LDAP_COMP_FILTER_ITEM:
+               rc = dup_comp_filter_item( op, bv, in_f->cf_ca ,&dup_f.cf_ca );
+               dup_f.cf_choice = LDAP_COMP_FILTER_ITEM;
+               break;
+       default:
+               rc = LDAP_PROTOCOL_ERROR;
+       }
+
+       if ( rc == LDAP_SUCCESS ) {
+               *out_f = op->o_tmpalloc( sizeof(dup_f), op->o_tmpmemctx );
+               **out_f = dup_f;
+       }
+
+       return( rc );
+}
+
+
+int
+get_aliased_filter ( Operation* op, MatchingRuleAssertion* ma, AttributeAliasing* aa, const char** text )
+{
+       int rc;
+       struct berval assert_bv;
+       ComponentAssertion* ca;
+
+       Debug( LDAP_DEBUG_FILTER, "get_aliased_filter\n", 0, 0, 0 );
+
+       if ( !aa->aa_cf  ) return LDAP_PROTOCOL_ERROR;
+
+       assert_bv = ma->ma_value;
+       /* Attribute Description is replaced with aliased one */
+       ma->ma_desc = aa->aa_aliased_ad;
+       ma->ma_rule = aa->aa_mr;
+       /*
+        * Duplicate aa->aa_cf to ma->ma_cf by replacing the
+        * the component assertion value in assert_bv
+        * Multiple values may be separated with '$'
+        */
+       return dup_comp_filter ( op, &assert_bv, aa->aa_cf, &ma->ma_cf );
+}
+
 int
 get_comp_filter( Operation* op, struct berval* bv, ComponentFilter** filt,
                 const char **text )
@@ -292,11 +486,11 @@ get_componentId( Operation *op, ComponentAssertionValue* cav,
                if ( cav->cav_ptr[len] != '(' )
                        return LDAP_COMPREF_UNDEFINED;
                for( ;cav->cav_ptr[len] != ' ' && cav->cav_ptr[len] != '\0' &&
-                     cav->cav_ptr[len] != '.' && cav->cav_ptr[len] != '\"' &&
-                     cav->cav_ptr[len] != ')' ; len++ );
+                     cav->cav_ptr[len] != '\"' && cav->cav_ptr[len] != ')'
+                       ; len++ );
                _cid.ci_val.ci_select_value.bv_val = cav->cav_ptr + 1;
                _cid.ci_val.ci_select_value.bv_len = len - 1 ;
-               cav->cav_ptr += len;
+               cav->cav_ptr += len + 1;
                break;
        case LDAP_COMPREF_ALL :
                _cid.ci_val.ci_all = '*';
@@ -306,7 +500,10 @@ get_componentId( Operation *op, ComponentAssertionValue* cav,
                return LDAP_COMPREF_UNDEFINED;
        }
 
-       *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
+       if ( op )
+               *cid = op->o_tmpalloc( sizeof( ComponentId ), op->o_tmpmemctx );
+       else
+               *cid = malloc( sizeof( ComponentId ) );
        **cid = _cid;
        return LDAP_SUCCESS;
 }
@@ -321,8 +518,6 @@ peek_componentId_type( ComponentAssertionValue* cav )
                return LDAP_COMPREF_SELECT;
        else if ( cav->cav_ptr[0] == '*' )
                return LDAP_COMPREF_ALL;
-       else if ( strncmp(cav->cav_ptr,"all",3) == 0 )
-               return LDAP_COMPREF_ALL;
        else if ( cav->cav_ptr[0] == '0' )
                return LDAP_COMPREF_COUNT;
        else if ( cav->cav_ptr[0] > '0' && cav->cav_ptr[0] <= '9' )
@@ -349,22 +544,29 @@ comp_next_id( ComponentAssertionValue* cav )
        else return LDAP_COMPREF_UNDEFINED;
 }
 
+
+
 static int
 get_component_reference( Operation *op, ComponentAssertionValue* cav,
                        ComponentReference** cr, const char** text )
 {
-       int rc,count=0;
+       int rc, count = 0;
        ber_int_t type;
        ComponentReference* ca_comp_ref;
        ComponentId** cr_list;
+       char* start, *end;
 
        eat_whsp( cav );
 
+       start = cav->cav_ptr;
        if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS )
                return rc;
+       if ( op )
+               ca_comp_ref = op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
+       else
+               ca_comp_ref = malloc( sizeof( ComponentReference ) );
 
-       ca_comp_ref =
-               op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
+       if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
 
        cr_list = &ca_comp_ref->cr_list;
 
@@ -379,9 +581,12 @@ get_component_reference( Operation *op, ComponentAssertionValue* cav,
                        return rc;
        }
        ca_comp_ref->cr_len = count;
-
+       end = cav->cav_ptr;
        if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
-               op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
+               if ( op )
+                       op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
+               else
+                       free( ca_comp_ref );
                return rc;
        }
 
@@ -389,11 +594,85 @@ get_component_reference( Operation *op, ComponentAssertionValue* cav,
                *cr = ca_comp_ref;
                **cr = *ca_comp_ref;    
        }
-       else op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
+       else if ( op )
+                op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
+       else
+                free( ca_comp_ref ) ;
 
+       (*cr)->cr_string.bv_val = start;
+       (*cr)->cr_string.bv_len = end - start + 1;
+       
        return rc;
 }
 
+int
+insert_component_reference( ComponentReference *cr, ComponentReference** cr_list) {
+       if ( !cr )
+               return LDAP_PARAM_ERROR;
+       if ( !(*cr_list) ) {
+               *cr_list = cr;
+               cr->cr_next = NULL;
+       } else {
+               cr->cr_next = *cr_list;
+               *cr_list = cr;
+       }
+       return LDAP_SUCCESS;
+}
+
+/*
+ * If there is '.' in the name of a given attribute
+ * the first '.'- following characters are considered
+ * as a component reference of the attribute
+ * EX) userCertificate.toBeSigned.serialNumber
+ * attribute : userCertificate
+ * component reference : toBeSigned.serialNumber
+ */
+int
+is_component_reference( char* attr ) {
+       int i;
+       for ( i=0; attr[i] != '\0' ; i++ ) {
+               if ( attr[i] == '.' )
+                       return (1);
+       }
+       return (0);
+}
+
+int
+extract_component_reference( char* attr, ComponentReference** cr ) {
+        int i, rc;
+        char* cr_ptr;
+        int cr_len;
+        ComponentAssertionValue cav;
+       char text[1][128];
+
+        for ( i=0; attr[i] != '\0' ; i++ ) {
+                if ( attr[i] == '.' ) break;
+        }
+
+        if (attr[i] != '.' )
+                return LDAP_PARAM_ERROR;
+        else
+                attr[i] = '\0';
+        cr_ptr = attr + i + 1 ;
+        cr_len = strlen ( cr_ptr );
+        if ( cr_len <= 0 )
+                return LDAP_PARAM_ERROR;
+
+       /* enclosed between double quotes*/
+       cav.cav_ptr = cav.cav_buf = ch_malloc (cr_len+2);
+       memcpy( cav.cav_buf+1, cr_ptr, cr_len );
+       cav.cav_buf[0] = '"';
+       cav.cav_buf[cr_len+1] = '"';
+        cav.cav_end = cr_ptr + cr_len + 2;
+
+        rc = get_component_reference ( NULL, &cav, cr, (const char**)text );
+       if ( rc != LDAP_SUCCESS )
+               return rc;
+       (*cr)->cr_string.bv_val = cav.cav_buf;
+       (*cr)->cr_string.bv_len = cr_len + 2;
+
+       return LDAP_SUCCESS;
+}
 static int
 get_ca_use_default( Operation *op, ComponentAssertionValue* cav,
                int* ca_use_def, const char**  text )
@@ -480,6 +759,12 @@ get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
                                break;
                        }
                }
+               
+               if ( !succeed || cav->cav_ptr[count] != '"' )
+                       return LDAP_FILTER_ERROR;
+
+               bv->bv_val = cav->cav_ptr + 1;
+               bv->bv_len = count - 1; /* exclude '"' */
        }
        else if ( cav->cav_ptr[0] == '\'' ) {
                for( count = 1 ; ; count++ ) {
@@ -492,6 +777,12 @@ get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
                                break;
                        }
                }
+
+                if ( !succeed || !(cav->cav_ptr[count] == 'H' || cav->cav_ptr[count] == 'B') )
+                        return LDAP_FILTER_ERROR;
+
+               bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
+               bv->bv_len = count - 2;/* exclude "'H" or "'B" */
                                
        }
        else if ( cav->cav_ptr[0] == '{' ) {
@@ -506,22 +797,27 @@ get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
                                break;
                        }
                }
+
+                if ( !succeed || cav->cav_ptr[count] != '}' )
+                        return LDAP_FILTER_ERROR;
+
+               bv->bv_val = cav->cav_ptr + 1;/*the next to '"' */
+               bv->bv_len = count - 1;/* exclude  "'B" */
        }
        else {
                succeed = 1;
                /*Find  following white space where the value is ended*/
                for( count = 1 ; ; count++ ) {
-                       if ( cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == ' ' || (cav->cav_ptr+count) > cav->cav_end ) {
+                       if ( cav->cav_ptr[count] == '\0' || cav->cav_ptr[count] == ' ' || cav->cav_ptr[count] == '}' || cav->cav_ptr[count] == '{' || (cav->cav_ptr+count) > cav->cav_end ) {
                                break;
                        }
                }
+               bv->bv_val = cav->cav_ptr;
+               bv->bv_len = count;
        }
 
-       if ( !succeed ) return LDAP_FILTER_ERROR;
+       cav->cav_ptr += bv->bv_len;
 
-       bv->bv_val = cav->cav_ptr;
-       bv->bv_len = count ;
-       cav->cav_ptr += count;
        return LDAP_SUCCESS;
 }
 
@@ -611,9 +907,17 @@ get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
 {
        int rc;
        ComponentAssertion* _ca;
+       struct berval t_bv;
+       struct berval value;
+       MatchingRule* mr;
 
-       Debug( LDAP_DEBUG_FILTER, "get_item: %s\n", 0, 0, 0 );
-       _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
+       Debug( LDAP_DEBUG_FILTER, "get_item \n", 0, 0, 0 );
+       if ( op )
+               _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
+       else
+               _ca = malloc( sizeof( ComponentAssertion ) );
+
+       if ( !_ca ) return LDAP_NO_MEMORY;
 
        _ca->ca_comp_data.cd_tree = NULL;
        _ca->ca_comp_data.cd_mem_op = NULL;
@@ -623,22 +927,27 @@ get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
                strip_cav_str( cav, "component" );
                rc = get_component_reference( op, cav, &_ca->ca_comp_ref, text );
                if ( rc != LDAP_SUCCESS ) {
-                       rc = LDAP_INVALID_SYNTAX;
-                       op->o_tmpfree( _ca, op->o_tmpmemctx );
-                       return rc;
+                       if ( op )
+                               op->o_tmpfree( _ca, op->o_tmpmemctx );
+                       else
+                               free( _ca );
+                       return LDAP_INVALID_SYNTAX;
                }
+               if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
+                       return rc;
+       } else {
+               _ca->ca_comp_ref = NULL;
        }
 
-       if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
-               return rc;
-
        rc = peek_cav_str( cav, "useDefaultValues");
        if ( rc == LDAP_SUCCESS ) {
                rc = get_ca_use_default( op, cav, &_ca->ca_use_def, text );
                if ( rc != LDAP_SUCCESS ) {
-                       rc = LDAP_INVALID_SYNTAX;
-                       op->o_tmpfree( _ca, op->o_tmpmemctx );
-                       return rc;
+                       if ( op )
+                               op->o_tmpfree( _ca, op->o_tmpmemctx );
+                       else
+                               free( _ca );
+                       return LDAP_INVALID_SYNTAX;
                }
                if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
                        return rc;
@@ -647,20 +956,49 @@ get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
 
        if ( !( strip_cav_str( cav, "rule" ) == LDAP_SUCCESS &&
                get_matching_rule( op, cav , &_ca->ca_ma_rule, text ) == LDAP_SUCCESS )) {
-               rc = LDAP_INAPPROPRIATE_MATCHING;
-               op->o_tmpfree( _ca, op->o_tmpmemctx );
-               return rc;
+               if ( op )
+                       op->o_tmpfree( _ca, op->o_tmpmemctx );
+               else
+                       free( _ca );
+               return LDAP_INAPPROPRIATE_MATCHING;
        }
        
        if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
                return rc;
        if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
-               get_matching_value( op, _ca, cav, &_ca->ca_ma_value,text ) == LDAP_SUCCESS )) {
-               rc = LDAP_INVALID_SYNTAX;
-               op->o_tmpfree( _ca, op->o_tmpmemctx );
-               return rc;
+               get_matching_value( op, _ca, cav,&value ,text ) == LDAP_SUCCESS )) {
+               if ( op )
+                       op->o_tmpfree( _ca, op->o_tmpmemctx );
+               else
+                       free( _ca );
+               return LDAP_INVALID_SYNTAX;
+       }
+
+       /*
+        * Normalize the value of this component assertion when the matching
+        * rule is one of existing matching rules
+        */
+       mr = _ca->ca_ma_rule;
+       if ( op && !(mr->smr_usage & (SLAP_MR_COMPONENT)) && mr->smr_normalize ) {
+
+               value.bv_val[value.bv_len] = '\0';
+               rc = mr->smr_normalize (
+                       SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
+                       NULL, mr,
+                       &value, &_ca->ca_ma_value, op->o_tmpmemctx );
+               if ( rc != LDAP_SUCCESS )
+                       return rc;
+       }
+       else
+               _ca->ca_ma_value = value;
+       /*
+        * Validate the value of this component assertion
+        */
+       if ( op && mr->smr_syntax->ssyn_validate( mr->smr_syntax, &_ca->ca_ma_value) != LDAP_SUCCESS ) {
+               return LDAP_INVALID_SYNTAX;
        }
 
+
        /* componentFilterMatch contains componentFilterMatch in it */
        if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
                struct berval bv;
@@ -668,7 +1006,10 @@ get_item( Operation *op, ComponentAssertionValue* cav, ComponentAssertion** ca,
                bv.bv_len = cav_cur_len( cav );
                rc = get_comp_filter( op, &bv,(ComponentFilter**)&_ca->ca_cf, text );
                if ( rc != LDAP_SUCCESS ) {
-                       op->o_tmpfree( _ca, op->o_tmpmemctx );
+                       if ( op )
+                               op->o_tmpfree( _ca, op->o_tmpmemctx );
+                       else
+                               free( _ca );
                        return rc;
                }
                cav->cav_ptr = bv.bv_val;
@@ -781,18 +1122,20 @@ parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
                break;
        }
 
-       if ( tag != LDAP_COMP_FILTER_NOT )
-               strip_cav_str( cav, "}");
-
        if ( err != LDAP_SUCCESS && err != SLAPD_DISCONNECT ) {
-               *text = NULL;
-               f.cf_choice = SLAPD_FILTER_COMPUTED;
-               f.cf_result = SLAPD_COMPARE_UNDEFINED;
-               err = LDAP_SUCCESS;
+               *text = "Component Filter Syntax Error";
+               return err;
        }
 
+       if ( tag != LDAP_COMP_FILTER_NOT )
+               strip_cav_str( cav, "}");
+
        if ( err == LDAP_SUCCESS ) {
-               *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
+               if ( op ) {
+                       *filt = op->o_tmpalloc( sizeof(f), op->o_tmpmemctx );
+               } else {
+                       *filt = malloc( sizeof(f) );
+               }
                **filt = f;
        }
 
@@ -802,7 +1145,7 @@ parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
 static int
 test_comp_filter_and(
        Syntax *syn,
-       Attribute *a,
+       ComponentSyntaxInfo *a,
        struct berval  *bv,
        ComponentFilter *flist )
 {
@@ -827,7 +1170,7 @@ test_comp_filter_and(
 static int
 test_comp_filter_or(
        Syntax *syn,
-       Attribute *a,
+       ComponentSyntaxInfo *a,
        struct berval     *bv,
        ComponentFilter *flist )
 {
@@ -877,74 +1220,42 @@ csi_value_match( MatchingRule *mr, struct berval* bv_attr,
 static int
 test_comp_filter_item(
        Syntax *syn,
-       Attribute       *a,
+       ComponentSyntaxInfo *csi_attr,
        struct berval   *bv,
        ComponentAssertion *ca )
 {
        int rc, len;
-       ComponentSyntaxInfo* csi_attr, *csi_assert=NULL;
        void *attr_nm, *assert_nm;
 
        if ( strcmp(ca->ca_ma_rule->smr_mrule.mr_oid,
                OID_COMP_FILTER_MATCH ) == 0 && ca->ca_cf ) {
                /* componentFilterMatch inside of componentFilterMatch */
-               rc = test_comp_filter( syn, a, bv, ca->ca_cf );
+               rc = test_comp_filter( syn, csi_attr, bv, ca->ca_cf );
                return rc;
        }
 
-       /* load attribute containg components */
-       if ( !a->a_comp_data && attr_converter && nibble_mem_allocator ) {
-               a->a_comp_data = malloc( sizeof( ComponentData ) );
-               /* Memory chunk pre-allocation for decoders */
-               a->a_comp_data->cd_mem_op = (void*) nibble_mem_allocator ( 1024, 128 );
-               a->a_comp_data->cd_tree = attr_converter (a, syn, bv);
-       }
-
-       if ( a->a_comp_data->cd_tree == NULL ) {
-               free ( a->a_comp_data );
-               return LDAP_PROTOCOL_ERROR;
-       }
-
        /* Memory for storing will-be-extracted attribute values */
-       attr_nm = nibble_mem_allocator ( 256, 64 );
-       if ( !attr_nm )return LDAP_PROTOCOL_ERROR;
-       /* component reference initialization */
-       ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
-       /* load component containg the referenced component */
-       csi_attr = (((ComponentSyntaxInfo*)a->a_comp_data->cd_tree)->csi_comp_desc->cd_extract_i)( attr_nm, ca->ca_comp_ref, a->a_comp_data->cd_tree );
-       if ( !csi_attr )
-               return LDAP_PROTOCOL_ERROR;
+       attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
+       if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
 
        /* Memory for storing component assertion values */
        if( !ca->ca_comp_data.cd_mem_op ) {
                assert_nm = nibble_mem_allocator ( 256, 64 );
-               if ( !assert_nm )
+               if ( !assert_nm ) {
+                       nibble_mem_free ( attr_nm );
                        return LDAP_PROTOCOL_ERROR;
+               }
                ca->ca_comp_data.cd_mem_op = assert_nm;
        }
        else {
                assert_nm = ca->ca_comp_data.cd_mem_op;
        }
-       /* perform matching */
-       if ( ca->ca_comp_ref->cr_curr->ci_type == LDAP_COMPREF_ALL ) {
-               /*
-                * If <all> type component referenced is used
-                * more than one component will be tested
-                */
-               if ( test_all_components )
-                       rc = test_all_components ( assert_nm, csi_attr, ca );
-               else
-                       rc = LDAP_PROTOCOL_ERROR;
-       } else {
-               /*
-                * Exactly one component is referenced
-                * Fast Path for matching for this case
-                */
-               if ( test_one_component )
-                       rc = test_one_component ( assert_nm, csi_attr, ca );
-               else
-                       rc = LDAP_PROTOCOL_ERROR;
-       }
+
+       /* component reference initialization */
+       if ( ca->ca_comp_ref )
+               ca->ca_comp_ref->cr_curr = ca->ca_comp_ref->cr_list;
+       rc = test_components( attr_nm, assert_nm, csi_attr, ca );
+
        /* free memory used for storing extracted attribute value */
        nibble_mem_free ( attr_nm );
        return rc;
@@ -953,7 +1264,7 @@ test_comp_filter_item(
 static int
 test_comp_filter(
     Syntax *syn,
-    Attribute  *a,
+    ComponentSyntaxInfo *a,
     struct berval *bv,
     ComponentFilter *f )
 {
@@ -998,7 +1309,7 @@ static void
 free_comp_filter_list( ComponentFilter* f )
 {
        ComponentFilter* tmp;
-       for ( tmp = f ; tmp; tmp = tmp->cf_next );
+       for ( tmp = f; tmp; tmp = tmp->cf_next )
        {
                free_comp_filter( tmp );
        }
@@ -1007,13 +1318,18 @@ free_comp_filter_list( ComponentFilter* f )
 static void
 free_comp_filter( ComponentFilter* f )
 {
+       if ( !f ) {
+               Debug( LDAP_DEBUG_FILTER, "free_comp_filter:Invalid filter so failed to release memory\n", 0, 0, 0 );
+               return;
+       }
        switch ( f->cf_choice ) {
        case LDAP_COMP_FILTER_AND:
        case LDAP_COMP_FILTER_OR:
+               free_comp_filter_list( f->cf_any );
+               break;
        case LDAP_COMP_FILTER_NOT:
                free_comp_filter( f->cf_any );
                break;
-
        case LDAP_COMP_FILTER_ITEM:
                if ( nibble_mem_free && f->cf_ca->ca_comp_data.cd_mem_op )
                        nibble_mem_free( f->cf_ca->ca_comp_data.cd_mem_op );