]> 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 75920a06e3b905dd9ed6c3a5fda5e7e4dd33234c..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 <ac/string.h>
 #include <ac/socket.h>
 
-#include "ldap_pvt.h"
 #include "lutil.h"
 #include <ldap.h>
 #include "slap.h"
 
 #ifdef LDAP_COMP_MATCH
 
-#include "asn.h"
+#include "component.h"
+
+/*
+ * 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_assert_to_comp_func* assert_converter = NULL ;
+free_component_func* component_destructor = 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
 
 static int
 peek_componentId_type( ComponentAssertionValue* cav );
@@ -42,10 +58,21 @@ static int
 parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
                                ComponentFilter** filt, const char** text );
 
+static void
+free_comp_filter( ComponentFilter* f );
+
 static int
-test_comp_filter_attr( Operation *op, Attribute        *a, struct berval *bv,
+test_comp_filter( Syntax *syn, ComponentSyntaxInfo *a, struct berval *bv,
                        ComponentFilter *f );
 
+int
+componentCertificateValidate(
+       Syntax *syntax,
+       struct berval *val )
+{
+       return LDAP_SUCCESS;
+}
+
 int
 componentFilterValidate(
        Syntax *syntax,
@@ -54,6 +81,14 @@ componentFilterValidate(
        return LDAP_SUCCESS;
 }
 
+int
+allComponentsValidate(
+       Syntax *syntax,
+       struct berval *val )
+{
+       return LDAP_SUCCESS;
+}
+
 int
 componentFilterMatch ( 
        int *matchp, 
@@ -63,40 +98,284 @@ componentFilterMatch (
        struct berval *value, 
        void *assertedValue )
 {
-       /* FIXME: to be implemented */
+       struct berval* bv;
+       Attribute *a = (Attribute*)value;
+       MatchingRuleAssertion * ma = (MatchingRuleAssertion*)assertedValue;
+       void* assert_nm;
+       int num_attr, rc, i;
+
+       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;
+
+       /* 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 );
+       }
+
+       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, 
+       slap_mask_t flags, 
+       Syntax *syntax, 
+       MatchingRule *mr,
+       struct berval *value, 
+       void *assertedValue )
+{
+       /* Only for Registeration */
        *matchp = 0;
        return LDAP_SUCCESS;
 }
 
+int
+allComponentsMatch( 
+       int *matchp, 
+       slap_mask_t flags, 
+       Syntax *syntax, 
+       MatchingRule *mr,
+       struct berval *value, 
+       void *assertedValue )
+{
+       /* Only for Registeration */
+       *matchp = 0;
+       return LDAP_SUCCESS;
+}
 
 static int
-slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav)
+slapd_ber2cav( struct berval* bv, ComponentAssertionValue* cav )
 {
        int len;
 
-       len = ldap_pvt_filter_value_unescape( bv->bv_val );
        cav->cav_ptr = cav->cav_buf = bv->bv_val;
-       cav->cav_end = bv->bv_val + len;
+       cav->cav_end = bv->bv_val + bv->bv_len;
+
+       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 )
+get_comp_filter( Operation* op, struct berval* bv, ComponentFilter** filt,
+                const char **text )
 {
        ComponentAssertionValue cav;
-       int len, rc;
+       int rc;
+
        Debug( LDAP_DEBUG_FILTER, "get_comp_filter\n", 0, 0, 0 );
-       slapd_ber2cav(bv, &cav);
+       if ( (rc = slapd_ber2cav(bv, &cav) ) != LDAP_SUCCESS ) {
+               return rc;
+       }
        rc = parse_comp_filter( op, &cav, filt, text );
        bv->bv_val = cav.cav_ptr;
+
        return rc;
 }
 
 static void
 eat_whsp( ComponentAssertionValue* cav )
 {
-       while ( ( cav->cav_ptr <= cav->cav_end ) && ( *cav->cav_ptr == ' ' ) )
-               cav->cav_ptr++;
+       for ( ; ( *cav->cav_ptr == ' ' ) && ( cav->cav_ptr < cav->cav_end ) ; ) {
+               cav->cav_ptr++;
+       }
 }
 
 static int
@@ -145,8 +424,6 @@ get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
        ComponentFilter **new;
        int             err;
        ber_tag_t       tag;
-       ber_len_t       len;
-       char            *last;
 
        Debug( LDAP_DEBUG_FILTER, "get_comp_filter_list\n", 0, 0, 0 );
        new = f;
@@ -160,7 +437,6 @@ get_comp_filter_list( Operation *op, ComponentAssertionValue *cav,
        }
        *new = NULL;
 
-
        return( LDAP_SUCCESS );
 }
 
@@ -203,21 +479,31 @@ get_componentId( Operation *op, ComponentAssertionValue* cav,
                cav->cav_ptr++;
                break;
        case LDAP_COMPREF_CONTENT :
-               /* FIXEME: yet to be implemented */
+               _cid.ci_val.ci_content = 1;
+               cav->cav_ptr += strlen("content");
                break;
        case LDAP_COMPREF_SELECT :
-               /* FIXEME: yet to be implemented */
+               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] != ')'
+                       ; 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 + 1;
                break;
        case LDAP_COMPREF_ALL :
                _cid.ci_val.ci_all = '*';
                cav->cav_ptr++;
-       Debug( LDAP_DEBUG_FILTER, "get_compId : ALL\n", 0, 0, 0 );
                break;
        default :
                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;
 }
@@ -239,7 +525,9 @@ peek_componentId_type( ComponentAssertionValue* cav )
        else if ( (cav->cav_end - cav->cav_ptr) >= 7 &&
                strncmp(cav->cav_ptr,"content",7) == 0 )
                return LDAP_COMPREF_CONTENT;
-       else if ( cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z' )
+       else if ( (cav->cav_ptr[0] >= 'a' && cav->cav_ptr[0] <= 'z') ||
+                       (cav->cav_ptr[0] >= 'A' && cav->cav_ptr[0] <= 'Z') )
+                
                return LDAP_COMPREF_IDENTIFIER;
        else
                return LDAP_COMPREF_UNDEFINED;
@@ -256,21 +544,32 @@ 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 );
-       ca_comp_ref =
-               op->o_tmpalloc( sizeof( ComponentReference ), op->o_tmpmemctx );
+
+       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 ) );
+
+       if ( !ca_comp_ref ) return LDAP_NO_MEMORY;
 
        cr_list = &ca_comp_ref->cr_list;
-       strip_cav_str( cav, "\"");
+
        for ( type = peek_componentId_type( cav ) ; type != LDAP_COMPREF_UNDEFINED
                ; type = comp_next_id( cav ), count++ ) {
                rc = get_componentId( op, cav, cr_list, text );
@@ -278,39 +577,117 @@ get_component_reference( Operation *op, ComponentAssertionValue* cav,
                        if ( count == 0 ) ca_comp_ref->cr_curr = ca_comp_ref->cr_list;
                        cr_list = &(*cr_list)->ci_next;
                }
+               else if ( rc == LDAP_COMPREF_UNDEFINED )
+                       return rc;
        }
        ca_comp_ref->cr_len = count;
-       strip_cav_str( cav, "\"");
+       end = cav->cav_ptr;
+       if ( ( rc = strip_cav_str( cav,"\"") ) != LDAP_SUCCESS ) {
+               if ( op )
+                       op->o_tmpfree( ca_comp_ref , op->o_tmpmemctx );
+               else
+                       free( ca_comp_ref );
+               return rc;
+       }
 
        if ( rc == LDAP_SUCCESS ) {     
                *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 )
 {
-       int rc;
-       if ( peek_cav_str( cav, "useDefaultValues" ) == LDAP_SUCCESS ) {
-               strip_cav_str( cav, "useDefaultValues" );
-               if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
-                       strip_cav_str( cav, "TRUE" );
-                       *ca_use_def = 1;
-               }
-               else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
-                       strip_cav_str( cav, "FALSE" );
-                       *ca_use_def = 0;
-               }
-               else
-                       return LDAP_INVALID_SYNTAX;
-       }
-       else /* If not defined, default value is TRUE */
+       strip_cav_str( cav, "useDefaultValues" );
+       if ( peek_cav_str( cav, "TRUE" ) == LDAP_SUCCESS ) {
+               strip_cav_str( cav, "TRUE" );
                *ca_use_def = 1;
+       } else if ( peek_cav_str( cav, "FALSE" ) == LDAP_SUCCESS ) {
+               strip_cav_str( cav, "FALSE" );
+               *ca_use_def = 0;
+       } else {
+               return LDAP_INVALID_SYNTAX;
+       }
+
        return LDAP_SUCCESS;
 }
 
@@ -319,7 +696,6 @@ get_matching_rule( Operation *op, ComponentAssertionValue* cav,
                MatchingRule** mr, const char**  text )
 {
        int count = 0;
-       char temp;
        struct berval rule_text = { 0L, NULL };
 
        eat_whsp( cav );
@@ -348,10 +724,10 @@ get_matching_rule( Operation *op, ComponentAssertionValue* cav,
        return LDAP_SUCCESS;
 }
 
-static void
+static int
 get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
 {
-       int count;
+       int count, sequent_dquote, unclosed_brace, succeed;
 
        eat_whsp( cav );
        /*
@@ -366,39 +742,83 @@ get_GSER_value( ComponentAssertionValue* cav, struct berval* bv )
         *      INTEGER, BOOLEAN, NULL,ENUMERATE, etc
         */
 
+       succeed = 0;
        if ( cav->cav_ptr[0] == '"' ) {
-               for( count = 0 ; ; count++ ) {
-                       if ( cav->cav_ptr[count] == '\0' ||
-                       ( cav->cav_ptr[count] == '"' && cav->cav_ptr[count-1] != '"') )
+               for( count = 1, sequent_dquote = 0 ; ; count++ ) {
+                       /* In order to find escaped double quote */
+                       if ( cav->cav_ptr[count] == '"' ) sequent_dquote++;
+                       else sequent_dquote = 0;
+
+                       if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
                                break;
+                       }
+                               
+                       if ( ( cav->cav_ptr[count] == '"' && cav->cav_ptr[count-1] != '"') ||
+                       ( sequent_dquote > 2 && (sequent_dquote%2) == 1 ) ) {
+                               succeed = 1;
+                               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 = 0 ; ; count++ ) {
-                       if ( cav->cav_ptr[count] == '\0' ||
-                       (cav->cav_ptr[count] == '\'' && cav->cav_ptr[count] == 'B')||
-                       (cav->cav_ptr[count] == '\'' && cav->cav_ptr[count] == 'H') )
+               for( count = 1 ; ; count++ ) {
+                       if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end ) {
+                               break;
+                       }
+                       if ((cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'B')||
+                       (cav->cav_ptr[count-1] == '\'' && cav->cav_ptr[count] == 'H') ) {
+                               succeed = 1;
                                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] == '{' ) {
-               for( count = 0 ; ; count++ ) {
-                       if ( cav->cav_ptr[count] == '\0' ||
-                       (cav->cav_ptr[count] == '}' && cav->cav_ptr[count] == ' ') )
+               for( count = 1, unclosed_brace = 1 ; ; count++ ) {
+                       if ( cav->cav_ptr[count] == '{' ) unclosed_brace++;
+                       if ( cav->cav_ptr[count] == '}' ) unclosed_brace--;
+
+                       if ( cav->cav_ptr[count] == '\0' || (cav->cav_ptr+count) > cav->cav_end )
                                break;
+                       if ( unclosed_brace == 0 ) {
+                               succeed = 1;
+                               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 {
-               for( count = 0 ; ; count++ ) {
-                       if ( cav->cav_ptr[count] == ' ')
+               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_ptr[count] == '{' || (cav->cav_ptr+count) > cav->cav_end ) {
                                break;
+                       }
                }
+               bv->bv_val = cav->cav_ptr;
+               bv->bv_len = count;
        }
 
-       bv->bv_val = cav->cav_ptr;
-       bv->bv_len = count;
-       cav->cav_ptr += count;
+       cav->cav_ptr += bv->bv_len;
+
+       return LDAP_SUCCESS;
 }
 
 static int
@@ -406,13 +826,12 @@ get_matching_value( Operation *op, ComponentAssertion* ca,
                        ComponentAssertionValue* cav, struct berval* bv,
                        const char**  text )
 {
-       int count;
-       ber_tag_t tag;
-
        if ( !(ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT)) ) {
-               get_GSER_value( cav, bv );
-       }
-       else {
+               if ( get_GSER_value( cav, bv ) != LDAP_SUCCESS ) {
+                       return LDAP_FILTER_ERROR;
+               }
+
+       } else {
                /* embeded componentFilterMatch Description */
                bv->bv_val = cav->cav_ptr;
                bv->bv_len = cav_cur_len( cav );
@@ -488,55 +907,109 @@ 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 \n", 0, 0, 0 );
+       if ( op )
+               _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
+       else
+               _ca = malloc( sizeof( ComponentAssertion ) );
 
-       Debug( LDAP_DEBUG_FILTER, "get_item: %s\n", 0, 0, 0 );
-       _ca = op->o_tmpalloc( sizeof( ComponentAssertion ), op->o_tmpmemctx );
+       if ( !_ca ) return LDAP_NO_MEMORY;
+
+       _ca->ca_comp_data.cd_tree = NULL;
+       _ca->ca_comp_data.cd_mem_op = NULL;
 
        rc = peek_cav_str( cav, "component" );
        if ( rc == LDAP_SUCCESS ) {
                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;
        }
 
-       strip_cav_str( cav,",");
        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;
        }
+       else _ca->ca_use_def = 1;
 
        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;
        }
        
-       strip_cav_str( cav,",");
-       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 );
+       if ( ( rc = strip_cav_str( cav,",") ) != LDAP_SUCCESS )
                return rc;
+       if ( !(strip_cav_str( cav, "value" ) == LDAP_SUCCESS &&
+               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 ( _ca->ca_ma_rule->smr_usage & (SLAP_MR_COMPONENT) ) {
+       if ( strcmp(_ca->ca_ma_rule->smr_mrule.mr_oid, OID_COMP_FILTER_MATCH ) == 0) {
                struct berval bv;
                bv.bv_val = cav->cav_ptr;
                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;
@@ -562,7 +1035,6 @@ parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
         */
 
        ber_tag_t       tag;
-       ber_len_t       len;
        int             err;
        ComponentFilter f;
        /* TAG : item, and, or, not in RFC 2254 */
@@ -650,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;
        }
 
@@ -670,8 +1144,8 @@ parse_comp_filter( Operation* op, ComponentAssertionValue* cav,
 
 static int
 test_comp_filter_and(
-       Operation *op,
-       Attribute *a,
+       Syntax *syn,
+       ComponentSyntaxInfo *a,
        struct berval  *bv,
        ComponentFilter *flist )
 {
@@ -679,7 +1153,7 @@ test_comp_filter_and(
        int rtn = LDAP_COMPARE_TRUE;
 
        for ( f = flist ; f != NULL; f = f->cf_next ) {
-               int rc = test_comp_filter_attr( op, a, bv, f );
+               int rc = test_comp_filter( syn, a, bv, f );
                if ( rc == LDAP_COMPARE_FALSE ) {
                        rtn = rc;
                        break;
@@ -695,8 +1169,8 @@ test_comp_filter_and(
 
 static int
 test_comp_filter_or(
-       Operation *op,
-       Attribute *a,
+       Syntax *syn,
+       ComponentSyntaxInfo *a,
        struct berval     *bv,
        ComponentFilter *flist )
 {
@@ -704,7 +1178,7 @@ test_comp_filter_or(
        int rtn = LDAP_COMPARE_TRUE;
 
        for ( f = flist ; f != NULL; f = f->cf_next ) {
-               int rc = test_comp_filter_attr( op, a, bv, f );
+               int rc = test_comp_filter( syn, a, bv, f );
                if ( rc == LDAP_COMPARE_TRUE ) {
                        rtn = rc;
                        break;
@@ -718,136 +1192,99 @@ test_comp_filter_or(
        return rtn;
 }
 
-/*
- * Convert attribute value to C internal data structure
- * This function has an associated ASN.1 type
- * bv must contain the value for the type( type name is T1 )
- * This function is linked to ssyn_attr2comp
- */
+int
+csi_value_match( MatchingRule *mr, struct berval* bv_attr,
+               struct berval* bv_assert )
+{
+       int rc;
+       int match;
+
+       assert( mr != NULL );
+       assert( !(mr->smr_usage & SLAP_MR_COMPONENT) );
+
+       if( !mr->smr_match ) {
+               return LDAP_INAPPROPRIATE_MATCHING;
+       }
+
+       rc = (mr->smr_match)( &match, 0, NULL /*ad->ad_type->sat_syntax*/,
+                               mr, bv_attr, bv_assert );
+       if ( rc == LDAP_SUCCESS )
+               return match? LDAP_COMPARE_FALSE:LDAP_COMPARE_TRUE;
+       else
+               return rc;
+}
 
 /*
  * return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
  */
 static int
 test_comp_filter_item(
-       Operation       *op,
-       Attribute       *a,
+       Syntax *syn,
+       ComponentSyntaxInfo *csi_attr,
        struct berval   *bv,
        ComponentAssertion *ca )
 {
-       int rc = LDAP_COMPARE_TRUE;
-       int len;
-       ComponentSyntaxInfo* csi_attr, *csi_assert;
+       int rc, len;
+       void *attr_nm, *assert_nm;
 
-       if ( (ca->ca_ma_rule->smr_usage & SLAP_MR_COMPONENT) && ca->ca_cf ) {
+       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_attr( op, a, bv, ca->ca_cf );
+               rc = test_comp_filter( syn, csi_attr, bv, ca->ca_cf );
                return rc;
        }
 
-       assert( !(ca->ca_ma_rule->smr_usage & SLAP_MR_COMPONENT) );
-       /* FIXME : Return ALWAYS true */
-       return LDAP_COMPARE_TRUE;
-}
+       /* Memory for storing will-be-extracted attribute values */
+       attr_nm = nibble_mem_allocator ( 1024*4 , 1024 );
+       if ( !attr_nm ) return LDAP_PROTOCOL_ERROR;
 
-/*
- * If matched, LDAP_COMPARE_TRUE is returned
- */
-int
-test_comp_filter_entry(
-    Operation  *op,
-    Entry      *e,
-    MatchingRuleAssertion *mra )
-{
-       Attribute *a;
-       void    *memctx;
-
-       mra->cf->cf_ca->ca_mra = mra;
-
-       Debug( LDAP_DEBUG_FILTER, "test_comp_filter_entry\n", 0, 0, 0 );
-       if ( mra->ma_desc ) {
-               /*
-                * ma_desc is available, so filtering for one attribute
-                * SEARCH permissionc can be checked directly
-                */
-               if ( !access_allowed( op, e, mra->ma_desc,
-                       &mra->ma_value, ACL_SEARCH, NULL ) )
-               {
-                       return LDAP_INSUFFICIENT_ACCESS;
+       /* Memory for storing component assertion values */
+       if( !ca->ca_comp_data.cd_mem_op ) {
+               assert_nm = nibble_mem_allocator ( 256, 64 );
+               if ( !assert_nm ) {
+                       nibble_mem_free ( attr_nm );
+                       return LDAP_PROTOCOL_ERROR;
                }
-               /* Find attributes that componentFilter Match can be applied to */
-               for( a=attrs_find( e->e_attrs, mra->ma_desc );
-                       a != NULL ;
-                       a = attrs_find( a->a_next, mra->ma_desc ) )
-               {
-                       struct berval *bv = a->a_vals;
-
-                       for ( ; bv->bv_val != NULL ; bv++ ) {
-                               int ret, rc;
-                               const char *text;
-                               rc = test_comp_filter_attr( op, a, bv, mra->cf );
-                               if ( rc == LDAP_COMPARE_TRUE ) return rc;
-                       }
-               }
-
-       } else {
-               /*
-                * No attribute description : test all
-                */
-                for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
-                        struct berval   *bv, value;
-                        const char      *text = NULL;
-                        int             rc;
-                                                                                  
-                        /* check if matching is appropriate */
-                        if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type
-)) {
-                                continue;
-                        }
-                                                                                  
-                        /* check search access */
-                        if ( !access_allowed( op, e,
-                                a->a_desc, &value, ACL_SEARCH, NULL ) ) {
-                                continue;
-                        }
-                                                                                  
-                       bv = a->a_vals;
-
-                       for ( ; bv->bv_val != NULL ; bv++ ) {
-                               int ret, rc;
-                               const char *text;
-                               rc = test_comp_filter_attr( op, a, bv, mra->cf );
-                               if ( rc == LDAP_COMPARE_TRUE ) break;
-                       }
-                        if ( rc != LDAP_SUCCESS ) return rc;
-                }
+               ca->ca_comp_data.cd_mem_op = assert_nm;
        }
+       else {
+               assert_nm = ca->ca_comp_data.cd_mem_op;
+       }
+
+       /* 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 );
 
-       return LDAP_COMPARE_FALSE;
+       /* free memory used for storing extracted attribute value */
+       nibble_mem_free ( attr_nm );
+       return rc;
 }
 
 static int
-test_comp_filter_attr(
-    Operation  *op,
-    Attribute  *a,
+test_comp_filter(
+    Syntax *syn,
+    ComponentSyntaxInfo *a,
     struct berval *bv,
     ComponentFilter *f )
 {
        int     rc;
 
-       Debug( LDAP_DEBUG_FILTER, "test_comp_filter_attr\n", 0, 0, 0 );
+       if ( !f ) return LDAP_PROTOCOL_ERROR;
+
+       Debug( LDAP_DEBUG_FILTER, "test_comp_filter\n", 0, 0, 0 );
        switch ( f->cf_choice ) {
        case SLAPD_FILTER_COMPUTED:
                rc = f->cf_result;
                break;
        case LDAP_COMP_FILTER_AND:
-               rc = test_comp_filter_and( op, a, bv, f->cf_and );
+               rc = test_comp_filter_and( syn, a, bv, f->cf_and );
                break;
        case LDAP_COMP_FILTER_OR:
-               rc = test_comp_filter_or( op, a, bv, f->cf_or );
+               rc = test_comp_filter_or( syn, a, bv, f->cf_or );
                break;
        case LDAP_COMP_FILTER_NOT:
-               rc = test_comp_filter_attr( op, a, bv, f->cf_not );
+               rc = test_comp_filter( syn, a, bv, f->cf_not );
 
                switch ( rc ) {
                case LDAP_COMPARE_TRUE:
@@ -859,7 +1296,7 @@ test_comp_filter_attr(
                }
                break;
        case LDAP_COMP_FILTER_ITEM:
-               rc = test_comp_filter_item( op, a, bv, f->cf_ca );
+               rc = test_comp_filter_item( syn, a, bv, f->cf_ca );
                break;
        default:
                rc = LDAP_PROTOCOL_ERROR;
@@ -867,4 +1304,45 @@ test_comp_filter_attr(
 
        return( rc );
 }
+
+static void
+free_comp_filter_list( ComponentFilter* f )
+{
+       ComponentFilter* tmp;
+       for ( tmp = f; tmp; tmp = tmp->cf_next )
+       {
+               free_comp_filter( tmp );
+       }
+}
+
+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 );
+               break;
+
+       default:
+               break;
+       }
+}
+
+void
+component_free( ComponentFilter *f ) {
+       free_comp_filter( f );
+}
+
 #endif