summaryrefslogtreecommitdiffstats
path: root/contrib/slapd-modules/comp_match/init.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:35:32 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 16:35:32 +0000
commit5ea77a75dd2d2158401331879f3c8f47940a732c (patch)
treed89dc06e9f4850a900f161e25f84e922c4f86cc8 /contrib/slapd-modules/comp_match/init.c
parentInitial commit. (diff)
downloadopenldap-5ea77a75dd2d2158401331879f3c8f47940a732c.tar.xz
openldap-5ea77a75dd2d2158401331879f3c8f47940a732c.zip
Adding upstream version 2.5.13+dfsg.upstream/2.5.13+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'contrib/slapd-modules/comp_match/init.c')
-rw-r--r--contrib/slapd-modules/comp_match/init.c839
1 files changed, 839 insertions, 0 deletions
diff --git a/contrib/slapd-modules/comp_match/init.c b/contrib/slapd-modules/comp_match/init.c
new file mode 100644
index 0000000..c3ab83c
--- /dev/null
+++ b/contrib/slapd-modules/comp_match/init.c
@@ -0,0 +1,839 @@
+/* Copyright 2004 IBM Corporation
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ */
+/* ACKNOWLEDGEMENTS
+ * This work originally developed by Sang Seok Lim
+ * 2004/06/18 03:20:00 slim@OpenLDAP.org
+ */
+
+#include "portable.h"
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ldap_pvt.h>
+#include "lutil.h"
+#include <ldap.h>
+#include "slap.h"
+#include "component.h"
+
+#include "componentlib.h"
+#include "asn.h"
+#include <asn-gser.h>
+
+#include <string.h>
+
+#ifndef SLAPD_COMP_MATCH
+#define SLAPD_COMP_MATCH SLAPD_MOD_DYNAMIC
+#endif
+
+/*
+ * Attribute and MatchingRule aliasing table
+ */
+AttributeAliasing aa_table [ MAX_ALIASING_ENTRY ];
+MatchingRuleAliasing mra_table [ MAX_ALIASING_ENTRY ];
+
+OD_entry* gOD_table = NULL;
+AsnTypetoMatchingRuleTable* gATMR_table = NULL;
+
+int
+load_derived_matching_rule ( char* cfg_path ){
+}
+
+AttributeAliasing*
+comp_is_aliased_attribute( void *in )
+{
+ AttributeAliasing* curr_aa;
+ int i;
+ AttributeDescription *ad = (AttributeDescription*)in;
+
+ for ( i = 0; aa_table[i].aa_aliasing_ad && i < MAX_ALIASING_ENTRY; i++ ) {
+ if ( strncmp(aa_table[i].aa_aliasing_ad->ad_cname.bv_val , ad->ad_cname.bv_val, ad->ad_cname.bv_len) == 0 )
+ return &aa_table[i];
+ }
+ return NULL;
+}
+
+static int
+add_aa_entry( int index, char* aliasing_at_name, char* aliased_at_name, char* mr_name, char* component_filter )
+{
+ char text[1][128];
+ int rc;
+ struct berval type;
+
+ /* get and store aliasing AttributeDescription */
+ type.bv_val = aliasing_at_name;
+ type.bv_len = strlen ( aliasing_at_name );
+ rc = slap_bv2ad ( &type, &aa_table[index].aa_aliasing_ad,(const char**)text );
+ if ( rc != LDAP_SUCCESS ) return rc;
+
+ /* get and store aliased AttributeDescription */
+ type.bv_val = aliased_at_name;
+ type.bv_len = strlen ( aliased_at_name );
+ rc = slap_bv2ad ( &type, &aa_table[index].aa_aliased_ad,(const char**)text );
+ if ( rc != LDAP_SUCCESS ) return rc;
+
+ /* get and store componentFilterMatch */
+ type.bv_val = mr_name;
+ type.bv_len = strlen ( mr_name);
+ aa_table[index].aa_mr = mr_bvfind ( &type );
+
+ /* get and store a component filter */
+ type.bv_val = component_filter;
+ type.bv_len = strlen ( component_filter );
+ rc = get_comp_filter( NULL, &type, &aa_table[index].aa_cf,(const char**)text);
+
+ aa_table[index].aa_cf_str = component_filter;
+
+ return rc;
+}
+
+/*
+ * Initialize attribute aliasing table when this module is loaded
+ * add_aa_entry ( index for the global table,
+ * name of the aliasing attribute,
+ * component filter with filling value parts "xxx"
+ * )
+ * "xxx" will be replaced with effective values later.
+ * See RFC3687 to understand the content of a component filter.
+ */
+char* pre_processed_comp_filter[] = {
+/*1*/"item:{ component \"toBeSigned.issuer.rdnSequence\", rule distinguishedNameMatch, value xxx }",
+/*2*/"item:{ component \"toBeSigned.serialNumber\", rule integerMatch, value xxx }",
+/*3*/"and:{ item:{ component \"toBeSigned.serialNumber\", rule integerMatch, value xxx }, item:{ component \"toBeSigned.issuer.rdnSequence\", rule distinguishedNameMatch, value xxx } }"
+};
+
+static int
+init_attribute_aliasing_table ()
+{
+ int rc;
+ int index = 0 ;
+
+ rc = add_aa_entry ( index, "x509CertificateIssuer", "userCertificate","componentFilterMatch", pre_processed_comp_filter[index] );
+ if ( rc != LDAP_SUCCESS ) return LDAP_PARAM_ERROR;
+ index++;
+
+ rc = add_aa_entry ( index, "x509CertificateSerial","userCertificate", "componentFilterMatch", pre_processed_comp_filter[index] );
+ if ( rc != LDAP_SUCCESS ) return LDAP_PARAM_ERROR;
+ index++;
+
+ rc = add_aa_entry ( index, "x509CertificateSerialAndIssuer", "userCertificate", "componentFilterMatch", pre_processed_comp_filter[index] );
+ if ( rc != LDAP_SUCCESS ) return LDAP_PARAM_ERROR;
+ index++;
+
+ return LDAP_SUCCESS;
+}
+
+void
+init_component_description_table () {
+ AsnTypeId id;
+ struct berval mr;
+ AsnTypetoSyntax* asn_to_syn;
+ Syntax* syn;
+
+ for ( id = BASICTYPE_BOOLEAN; id != ASNTYPE_END ; id++ ) {
+ asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_subtypes = NULL;
+ asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_syntax = NULL;
+
+ /* Equality Matching Rule */
+ if ( asntype_to_compMR_mapping_tbl[id].atc_equality ) {
+ mr.bv_val = asntype_to_compMR_mapping_tbl[id].atc_equality;
+ mr.bv_len = strlen(asntype_to_compMR_mapping_tbl[id].atc_equality);
+ asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_equality = mr_bvfind( &mr );
+ }
+ /* Approx Matching Rule */
+ if ( asntype_to_compMR_mapping_tbl[id].atc_approx ) {
+ mr.bv_val = asntype_to_compMR_mapping_tbl[id].atc_approx;
+ mr.bv_len = strlen(asntype_to_compMR_mapping_tbl[id].atc_approx);
+ asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_approx = mr_bvfind( &mr );
+ }
+
+ /* Ordering Matching Rule */
+ if ( asntype_to_compMR_mapping_tbl[id].atc_ordering ) {
+ mr.bv_val = asntype_to_compMR_mapping_tbl[id].atc_ordering;
+ mr.bv_len = strlen(asntype_to_compMR_mapping_tbl[id].atc_ordering);
+ asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_ordering= mr_bvfind( &mr );
+ }
+
+ /* Substr Matching Rule */
+ if ( asntype_to_compMR_mapping_tbl[id].atc_substr ) {
+ mr.bv_val = asntype_to_compMR_mapping_tbl[id].atc_substr;
+ mr.bv_len = strlen(asntype_to_compMR_mapping_tbl[id].atc_substr);
+ asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_substr = mr_bvfind( &mr );
+ }
+ /* Syntax */
+
+ asn_to_syn = &asn_to_syntax_mapping_tbl[ id ];
+ if ( asn_to_syn->ats_syn_oid )
+ syn = syn_find ( asn_to_syn->ats_syn_oid );
+ else
+ syn = NULL;
+ asntype_to_compType_mapping_tbl[id].ac_comp_type.ct_syntax = syn;
+
+ /* Initialize Component Descriptions of primitive ASN.1 types */
+ asntype_to_compdesc_mapping_tbl[id].atcd_cd.cd_comp_type = (AttributeType*)&asntype_to_compType_mapping_tbl[id].ac_comp_type;
+ }
+}
+
+MatchingRule*
+retrieve_matching_rule( char* mr_oid, AsnTypeId type ) {
+ char* tmp;
+ struct berval mr_name = BER_BVNULL;
+ AsnTypetoMatchingRuleTable* atmr;
+
+ for ( atmr = gATMR_table ; atmr ; atmr = atmr->atmr_table_next ) {
+ if ( strcmp( atmr->atmr_oid, mr_oid ) == 0 ) {
+ tmp = atmr->atmr_table[type].atmr_mr_name;
+ if ( tmp ) {
+ mr_name.bv_val = tmp;
+ mr_name.bv_len = strlen( tmp );
+ return mr_bvfind ( &mr_name );
+ }
+ }
+ }
+ return (MatchingRule*)NULL;
+}
+
+void*
+comp_convert_attr_to_comp LDAP_P (( Attribute* a, Syntax *syn, struct berval* bv ))
+{
+ char* peek_head;
+ int mode, bytesDecoded, size, rc;
+ void* component;
+ char* oid = a->a_desc->ad_type->sat_atype.at_oid ;
+ GenBuf* b = NULL;
+ ExpBuf* buf = NULL;
+ OidDecoderMapping* odm;
+
+ /* look for the decoder registered for the given attribute */
+ odm = RetrieveOidDecoderMappingbyOid( oid, strlen(oid) );
+
+ if ( !odm || (!odm->BER_Decode && !odm->GSER_Decode) )
+ return (void*)NULL;
+
+ buf = ExpBufAllocBuf();
+ ExpBuftoGenBuf( buf, &b );
+ ExpBufInstallDataInBuf ( buf, bv->bv_val, bv->bv_len );
+ BufResetInReadMode( b );
+
+ mode = DEC_ALLOC_MODE_2;
+ /*
+ * How can we decide which decoder will be called, GSER or BER?
+ * Currently BER decoder is called for a certificate.
+ * The flag of Attribute will say something about it in the future
+ */
+ if ( syn && slap_syntax_is_ber ( syn ) ) {
+#if 0
+ rc =BDecComponentTop(odm->BER_Decode, a->a_comp_data->cd_mem_op, b, 0,0, &component,&bytesDecoded,mode ) ;
+#endif
+ rc = odm->BER_Decode ( a->a_comp_data->cd_mem_op, b, (ComponentSyntaxInfo*)&component, &bytesDecoded, mode );
+ }
+ else {
+ rc = odm->GSER_Decode( a->a_comp_data->cd_mem_op, b, (ComponentSyntaxInfo**)component, &bytesDecoded, mode);
+ }
+
+ ExpBufFreeBuf( buf );
+ GenBufFreeBuf( b );
+ if ( rc == -1 ) {
+#if 0
+ ShutdownNibbleMemLocal ( a->a_comp_data->cd_mem_op );
+ free ( a->a_comp_data );
+ a->a_comp_data = NULL;
+#endif
+ return (void*)NULL;
+ }
+ else {
+ return component;
+ }
+}
+
+#include <nibble-alloc.h>
+void
+comp_free_component ( void* mem_op ) {
+ ShutdownNibbleMemLocal( (NibbleMem*)mem_op );
+ return;
+}
+
+void
+comp_convert_assert_to_comp (
+ void* mem_op,
+ ComponentSyntaxInfo *csi_attr,
+ struct berval* bv,
+ ComponentSyntaxInfo** csi, int* len, int mode )
+{
+ int rc;
+ GenBuf* genBuf;
+ ExpBuf* buf;
+ gser_decoder_func *decoder = csi_attr->csi_comp_desc->cd_gser_decoder;
+
+ buf = ExpBufAllocBuf();
+ ExpBuftoGenBuf( buf, &genBuf );
+ ExpBufInstallDataInBuf ( buf, bv->bv_val, bv->bv_len );
+ BufResetInReadMode( genBuf );
+
+ if ( csi_attr->csi_comp_desc->cd_type_id == BASICTYPE_ANY )
+ decoder = ((ComponentAny*)csi_attr)->cai->GSER_Decode;
+
+ rc = (*decoder)( mem_op, genBuf, csi, len, mode );
+ ExpBufFreeBuf ( buf );
+ GenBufFreeBuf( genBuf );
+}
+
+int intToAscii( int value, char* buf ) {
+ int minus=0,i,temp;
+ int total_num_digits;
+
+ if ( value == 0 ){
+ buf[0] = '0';
+ return 1;
+ }
+
+ if ( value < 0 ){
+ minus = 1;
+ value = value*(-1);
+ buf[0] = '-';
+ }
+
+ /* How many digits */
+ for ( temp = value, total_num_digits=0 ; temp ; total_num_digits++ )
+ temp = temp/10;
+
+ total_num_digits += minus;
+
+ for ( i = minus ; value ; i++ ) {
+ buf[ total_num_digits - i - 1 ]= (char)(value%10 + '0');
+ value = value/10;
+ }
+ return i;
+}
+
+int
+comp_convert_asn_to_ldap ( MatchingRule* mr, ComponentSyntaxInfo* csi, struct berval* bv, int *allocated )
+{
+ int rc;
+ struct berval prettied;
+ Syntax* syn;
+
+ AsnTypetoSyntax* asn_to_syn =
+ &asn_to_syntax_mapping_tbl[csi->csi_comp_desc->cd_type_id];
+ if ( asn_to_syn->ats_syn_oid )
+ csi->csi_syntax = syn_find ( asn_to_syn->ats_syn_oid );
+ else
+ csi->csi_syntax = NULL;
+
+
+ switch ( csi->csi_comp_desc->cd_type_id ) {
+ case BASICTYPE_BOOLEAN :
+ bv->bv_val = (char*)malloc( 5 );
+ *allocated = 1;
+ bv->bv_len = 5;
+ if ( ((ComponentBool*)csi)->value > 0 ) {
+ strcpy ( bv->bv_val , "TRUE" );
+ bv->bv_len = 4;
+ }
+ else {
+ strcpy ( bv->bv_val , "FALSE" );
+ bv->bv_len = 5;
+ }
+ break ;
+ case BASICTYPE_NULL :
+ bv->bv_len = 0;
+ break;
+ case BASICTYPE_INTEGER :
+ bv->bv_val = (char*)malloc( INITIAL_ATTR_SIZE );
+ *allocated = 1;
+ bv->bv_len = INITIAL_ATTR_SIZE;
+ bv->bv_len = intToAscii(((ComponentInt*)csi)->value, bv->bv_val );
+ if ( bv->bv_len <= 0 )
+ return LDAP_INVALID_SYNTAX;
+ break;
+ case BASICTYPE_REAL :
+ return LDAP_INVALID_SYNTAX;
+ case BASICTYPE_ENUMERATED :
+ bv->bv_val = (char*)malloc( INITIAL_ATTR_SIZE );
+ *allocated = 1;
+ bv->bv_len = INITIAL_ATTR_SIZE;
+ bv->bv_len = intToAscii(((ComponentEnum*)csi)->value, bv->bv_val );
+ if ( bv->bv_len <= 0 )
+ return LDAP_INVALID_SYNTAX;
+ break;
+ case BASICTYPE_OID :
+ case BASICTYPE_OCTETSTRING :
+ case BASICTYPE_BITSTRING :
+ case BASICTYPE_NUMERIC_STR :
+ case BASICTYPE_PRINTABLE_STR :
+ case BASICTYPE_UNIVERSAL_STR :
+ case BASICTYPE_IA5_STR :
+ case BASICTYPE_BMP_STR :
+ case BASICTYPE_UTF8_STR :
+ case BASICTYPE_UTCTIME :
+ case BASICTYPE_GENERALIZEDTIME :
+ case BASICTYPE_GRAPHIC_STR :
+ case BASICTYPE_VISIBLE_STR :
+ case BASICTYPE_GENERAL_STR :
+ case BASICTYPE_OBJECTDESCRIPTOR :
+ case BASICTYPE_VIDEOTEX_STR :
+ case BASICTYPE_T61_STR :
+ case BASICTYPE_OCTETCONTAINING :
+ case BASICTYPE_BITCONTAINING :
+ case BASICTYPE_RELATIVE_OID :
+ bv->bv_val = ((ComponentOcts*)csi)->value.octs;
+ bv->bv_len = ((ComponentOcts*)csi)->value.octetLen;
+ break;
+ case BASICTYPE_ANY :
+ csi = ((ComponentAny*)csi)->value;
+ if ( csi->csi_comp_desc->cd_type != ASN_BASIC ||
+ csi->csi_comp_desc->cd_type_id == BASICTYPE_ANY )
+ return LDAP_INVALID_SYNTAX;
+ return comp_convert_asn_to_ldap( mr, csi, bv, allocated );
+ case COMPOSITE_ASN1_TYPE :
+ break;
+ case RDNSequence :
+ /*dnMatch*/
+ if( strncmp( mr->smr_mrule.mr_oid, DN_MATCH_OID, strlen(DN_MATCH_OID) ) != 0 )
+ return LDAP_INVALID_SYNTAX;
+ *allocated = 1;
+ rc = ConvertRDNSequence2RFC2253( (irRDNSequence*)csi, bv );
+ if ( rc != LDAP_SUCCESS ) return rc;
+ break;
+ case RelativeDistinguishedName :
+ /*rdnMatch*/
+ if( strncmp( mr->smr_mrule.mr_oid, RDN_MATCH_OID, strlen(RDN_MATCH_OID) ) != 0 )
+ return LDAP_INVALID_SYNTAX;
+ *allocated = 1;
+ rc = ConvertRDN2RFC2253((irRelativeDistinguishedName*)csi,bv);
+ if ( rc != LDAP_SUCCESS ) return rc;
+ break;
+ case TelephoneNumber :
+ case FacsimileTelephoneNumber__telephoneNumber :
+ break;
+ case DirectoryString :
+ return LDAP_INVALID_SYNTAX;
+ case ASN_COMP_CERTIFICATE :
+ case ASNTYPE_END :
+ break;
+ default :
+ /*Only ASN Basic Type can be converted into LDAP string*/
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ if ( csi->csi_syntax ) {
+ if ( csi->csi_syntax->ssyn_validate ) {
+ rc = csi->csi_syntax->ssyn_validate(csi->csi_syntax, bv);
+ if ( rc != LDAP_SUCCESS )
+ return LDAP_INVALID_SYNTAX;
+ }
+ if ( csi->csi_syntax->ssyn_pretty ) {
+ rc = csi->csi_syntax->ssyn_pretty(csi->csi_syntax, bv, &prettied , NULL );
+ if ( rc != LDAP_SUCCESS )
+ return LDAP_INVALID_SYNTAX;
+#if 0
+ free ( bv->bv_val );/*potential memory leak?*/
+#endif
+ bv->bv_val = prettied.bv_val;
+ bv->bv_len = prettied.bv_len;
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+/*
+ * If <all> type component referenced is used
+ * more than one component will be tested
+ */
+#define IS_TERMINAL_COMPREF(cr) (cr->cr_curr->ci_next == NULL)
+int
+comp_test_all_components (
+ void* attr_mem_op,
+ void* assert_mem_op,
+ ComponentSyntaxInfo *csi_attr,
+ ComponentAssertion* ca )
+{
+ int rc;
+ ComponentSyntaxInfo *csi_temp = NULL, *csi_assert = NULL, *comp_elmt = NULL;
+ ComponentReference *cr = ca->ca_comp_ref;
+ struct berval *ca_val = &ca->ca_ma_value;
+
+ switch ( cr->cr_curr->ci_type ) {
+ case LDAP_COMPREF_ALL:
+ if ( IS_TERMINAL_COMPREF(cr) ) {
+ FOR_EACH_LIST_ELMT( comp_elmt, &((ComponentList*)csi_attr)->comp_list )
+ {
+ rc = comp_test_one_component( attr_mem_op, assert_mem_op, comp_elmt, ca );
+ if ( rc == LDAP_COMPARE_TRUE ) {
+ break;
+ }
+ }
+ } else {
+ ComponentId *start_compid = ca->ca_comp_ref->cr_curr->ci_next;
+ FOR_EACH_LIST_ELMT( comp_elmt, &((ComponentList*)csi_attr)->comp_list )
+ {
+ cr->cr_curr = start_compid;
+ rc = comp_test_components ( attr_mem_op, assert_mem_op, comp_elmt, ca );
+ if ( rc != LDAP_COMPARE_FALSE ) {
+ break;
+ }
+#if 0
+ if ( rc == LDAP_COMPARE_TRUE ) {
+ break;
+ }
+#endif
+ }
+ }
+ break;
+ case LDAP_COMPREF_CONTENT:
+ case LDAP_COMPREF_SELECT:
+ case LDAP_COMPREF_DEFINED:
+ case LDAP_COMPREF_UNDEFINED:
+ case LDAP_COMPREF_IDENTIFIER:
+ case LDAP_COMPREF_FROM_BEGINNING:
+ case LDAP_COMPREF_FROM_END:
+ case LDAP_COMPREF_COUNT:
+ rc = LDAP_OPERATIONS_ERROR;
+ break;
+ default:
+ rc = LDAP_OPERATIONS_ERROR;
+ }
+ return rc;
+}
+
+void
+eat_bv_whsp ( struct berval* in )
+{
+ char* end = in->bv_val + in->bv_len;
+ for ( ; ( *in->bv_val == ' ' ) && ( in->bv_val < end ) ; ) {
+ in->bv_val++;
+ }
+}
+
+/*
+ * Perform matching one referenced component against assertion
+ * If the matching rule in a component filter is allComponentsMatch
+ * or its derivatives the extracted component's ASN.1 specification
+ * is applied to the assertion value as its syntax
+ * Otherwise, the matching rule's syntax is applied to the assertion value
+ * By RFC 3687
+ */
+int
+comp_test_one_component (
+ void* attr_mem_op,
+ void* assert_mem_op,
+ ComponentSyntaxInfo *csi_attr,
+ ComponentAssertion *ca )
+{
+ int len, rc;
+ ComponentSyntaxInfo *csi_assert = NULL;
+ char* oid = NULL;
+ MatchingRule* mr = ca->ca_ma_rule;
+
+ if ( mr->smr_usage & SLAP_MR_COMPONENT ) {
+ /* If allComponentsMatch or its derivatives */
+ if ( !ca->ca_comp_data.cd_tree ) {
+ comp_convert_assert_to_comp( assert_mem_op, csi_attr, &ca->ca_ma_value, &csi_assert, &len, DEC_ALLOC_MODE_0 );
+ ca->ca_comp_data.cd_tree = (void*)csi_assert;
+ } else {
+ csi_assert = ca->ca_comp_data.cd_tree;
+ }
+
+ if ( !csi_assert )
+ return LDAP_PROTOCOL_ERROR;
+
+ if ( strcmp( mr->smr_mrule.mr_oid, OID_ALL_COMP_MATCH ) != 0 )
+ {
+ /* allComponentMatch's derivatives */
+ oid = mr->smr_mrule.mr_oid;
+ }
+ return csi_attr->csi_comp_desc->cd_all_match(
+ oid, csi_attr, csi_assert );
+
+ } else {
+ /* LDAP existing matching rules */
+ struct berval attr_bv = BER_BVNULL;
+ struct berval n_attr_bv = BER_BVNULL;
+ struct berval* assert_bv = &ca->ca_ma_value;
+ int allocated = 0;
+ /*Attribute is converted to compatible LDAP encodings*/
+ if ( comp_convert_asn_to_ldap( mr, csi_attr, &attr_bv, &allocated ) != LDAP_SUCCESS )
+ return LDAP_INAPPROPRIATE_MATCHING;
+ /* extracted component value is not normalized */
+ if ( ca->ca_ma_rule->smr_normalize ) {
+ rc = ca->ca_ma_rule->smr_normalize (
+ SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
+ NULL, ca->ca_ma_rule,
+ &attr_bv, &n_attr_bv, NULL );
+ if ( rc != LDAP_SUCCESS )
+ return rc;
+ if ( allocated && attr_bv.bv_val )
+ free (attr_bv.bv_val);
+ } else {
+ n_attr_bv = attr_bv;
+ }
+#if 0
+ /*Assertion value is validated by MR's syntax*/
+ if ( !ca->ca_comp_data.cd_tree ) {
+ ca->ca_comp_data.cd_tree = assert_bv;
+ }
+ else {
+ assert_bv = ca->ca_comp_data.cd_tree;
+ }
+#endif
+ if ( !n_attr_bv.bv_val )
+ return LDAP_COMPARE_FALSE;
+ rc = csi_value_match( mr, &n_attr_bv, assert_bv );
+ if ( n_attr_bv.bv_val )
+ free ( n_attr_bv.bv_val );
+ return rc;
+ }
+}
+
+int
+comp_test_components( void* attr_nm, void* assert_nm, ComponentSyntaxInfo* csi_attr, ComponentAssertion* ca) {
+ char* peek_head;
+ int mode, bytesDecoded = 0, rc;
+ GenBuf* b;
+ ExpBuf* buf;
+ OidDecoderMapping* odm;
+ struct berval bv;
+ char oid[MAX_OID_LEN];
+ void* contained_comp, *anytype_comp;
+ ComponentReference* cr = ca->ca_comp_ref;
+
+ if ( !cr )
+ return comp_test_one_component ( attr_nm, assert_nm, csi_attr, ca );
+ /* Extracting the component referenced by ca->ca_comp_ref */
+ csi_attr = (ComponentSyntaxInfo*)csi_attr->csi_comp_desc->cd_extract_i( attr_nm, cr, csi_attr );
+ if ( !csi_attr ) return LDAP_INVALID_SYNTAX;
+ /* perform matching, considering the type of a Component Reference(CR)*/
+ switch( cr->cr_curr->ci_type ) {
+ case LDAP_COMPREF_IDENTIFIER:
+ case LDAP_COMPREF_FROM_BEGINNING:
+ case LDAP_COMPREF_FROM_END:
+ case LDAP_COMPREF_COUNT:
+ /*
+ * Exactly one component is referenced
+ * Fast Path for matching for this case
+ */
+ rc = comp_test_one_component ( attr_nm, assert_nm, csi_attr, ca );
+ break;
+ case LDAP_COMPREF_ALL:
+ /*
+ * If <all> type CR is used
+ * more than one component will be tested
+ */
+ rc = comp_test_all_components ( attr_nm, assert_nm, csi_attr, ca );
+ break;
+
+ case LDAP_COMPREF_CONTENT:
+ /*
+ * <content> type CR is used
+ * check if it is followed by <select> type CR.
+ * 1) If so, look up the corresponding decoder in the mapping
+ * table(OID to decoder) by <select>
+ * and then decode the OCTET/BIT STRING with the decoder
+ * Finally, extract the target component with the remaining CR.
+ * 2) If not, just return the current component, It SHOULD not be
+ * extracted further, because the component MUST be BIT/OCTET
+ * string.
+ */
+
+ cr->cr_curr = cr->cr_curr->ci_next;
+ if ( !cr->cr_curr ) {
+ /* case 2) in above description */
+ rc = comp_test_one_component ( attr_nm, assert_nm, csi_attr, ca );
+ break;
+ }
+
+ if ( cr->cr_curr->ci_type == LDAP_COMPREF_SELECT ) {
+ /* Look up OID mapping table */
+ odm = RetrieveOidDecoderMappingbyBV( &cr->cr_curr->ci_val.ci_select_value );
+
+ if ( !odm || !odm->BER_Decode )
+ return LDAP_PROTOCOL_ERROR;
+
+ /* current component MUST be either BIT or OCTET STRING */
+ if ( csi_attr->csi_comp_desc->cd_type_id != BASICTYPE_BITSTRING ) {
+ bv.bv_val = ((ComponentBits*)csi_attr)->value.bits;
+ bv.bv_len = ((ComponentBits*)csi_attr)->value.bitLen;
+ }
+ else if ( csi_attr->csi_comp_desc->cd_type_id != BASICTYPE_BITSTRING ) {
+ bv.bv_val = ((ComponentOcts*)csi_attr)->value.octs;
+ bv.bv_len = ((ComponentOcts*)csi_attr)->value.octetLen;
+ }
+ else
+ return LDAP_PROTOCOL_ERROR;
+
+ buf = ExpBufAllocBuf();
+ ExpBuftoGenBuf( buf, &b );
+ ExpBufInstallDataInBuf ( buf, bv.bv_val, bv.bv_len );
+ BufResetInReadMode( b );
+ mode = DEC_ALLOC_MODE_2;
+
+ /* Try to decode with BER/DER decoder */
+ rc = odm->BER_Decode ( attr_nm, b, (ComponentSyntaxInfo*)&contained_comp, &bytesDecoded, mode );
+
+ ExpBufFreeBuf( buf );
+ GenBufFreeBuf( b );
+
+ if ( rc != LDAP_SUCCESS ) return LDAP_PROTOCOL_ERROR;
+
+ /* xxx.content.(x.xy.xyz).rfc822Name */
+ /* In the aboe Ex. move CR to the right to (x.xy.xyz)*/
+ cr->cr_curr = cr->cr_curr->ci_next;
+ if (!cr->cr_curr )
+ rc = comp_test_one_component ( attr_nm, assert_nm, csi_attr, ca );
+ else
+ rc = comp_test_components( attr_nm, assert_nm, contained_comp, ca );
+ }
+ else {
+ /* Invalid Component reference */
+ rc = LDAP_PROTOCOL_ERROR;
+ }
+ break;
+ case LDAP_COMPREF_SELECT:
+ if (csi_attr->csi_comp_desc->cd_type_id != BASICTYPE_ANY )
+ return LDAP_INVALID_SYNTAX;
+ rc = CheckSelectTypeCorrect( attr_nm, ((ComponentAny*)csi_attr)->cai, &cr->cr_curr->ci_val.ci_select_value );
+ if ( rc < 0 ) return LDAP_INVALID_SYNTAX;
+
+ /* point to the real component, not any type component */
+ csi_attr = ((ComponentAny*)csi_attr)->value;
+ cr->cr_curr = cr->cr_curr->ci_next;
+ if ( cr->cr_curr )
+ rc = comp_test_components( attr_nm, assert_nm, csi_attr, ca);
+ else
+ rc = comp_test_one_component( attr_nm, assert_nm, csi_attr, ca);
+ break;
+ default:
+ rc = LDAP_INVALID_SYNTAX;
+ }
+ return rc;
+}
+
+
+void*
+comp_nibble_memory_allocator ( int init_mem, int inc_mem ) {
+ void* nm;
+ nm = (void*)InitNibbleMemLocal( (unsigned long)init_mem, (unsigned long)inc_mem );
+ if ( !nm ) return NULL;
+ else return (void*)nm;
+}
+
+void
+comp_nibble_memory_free ( void* nm ) {
+ ShutdownNibbleMemLocal( nm );
+}
+
+void*
+comp_get_component_description ( int id ) {
+ if ( asntype_to_compdesc_mapping_tbl[id].atcd_typeId == id )
+ return &asntype_to_compdesc_mapping_tbl[id].atcd_cd;
+ else
+ return NULL;
+}
+
+int
+comp_component_encoder ( void* mem_op, ComponentSyntaxInfo* csi , struct berval* nval ) {
+ int size, rc;
+ GenBuf* b;
+ ExpBuf* buf;
+ struct berval bv;
+
+ buf = ExpBufAllocBufAndData();
+ ExpBufResetInWriteRvsMode(buf);
+ ExpBuftoGenBuf( buf, &b );
+
+ if ( !csi->csi_comp_desc->cd_gser_encoder && !csi->csi_comp_desc->cd_ldap_encoder )
+ return (-1);
+
+ /*
+ * if an LDAP specific encoder is provided :
+ * dn and rdn have their LDAP specific encoder
+ */
+ if ( csi->csi_comp_desc->cd_ldap_encoder ) {
+ rc = csi->csi_comp_desc->cd_ldap_encoder( csi, &bv );
+ if ( rc != LDAP_SUCCESS )
+ return rc;
+ if ( mem_op )
+ nval->bv_val = CompAlloc( mem_op, bv.bv_len );
+ else
+ nval->bv_val = malloc( size );
+ memcpy( nval->bv_val, bv.bv_val, bv.bv_len );
+ nval->bv_len = bv.bv_len;
+ /*
+ * This free will be eliminated by making ldap_encoder
+ * use nibble memory in it
+ */
+ free ( bv.bv_val );
+ GenBufFreeBuf( b );
+ BufFreeBuf( buf );
+ return LDAP_SUCCESS;
+ }
+
+ rc = csi->csi_comp_desc->cd_gser_encoder( b, csi );
+ if ( rc < 0 ) {
+ GenBufFreeBuf( b );
+ BufFreeBuf( buf );
+ return rc;
+ }
+
+ size = ExpBufDataSize( buf );
+ if ( size > 0 ) {
+ if ( mem_op )
+ nval->bv_val = CompAlloc ( mem_op, size );
+ else
+ nval->bv_val = malloc( size );
+ nval->bv_len = size;
+ BufResetInReadMode(b);
+ BufCopy( nval->bv_val, b, size );
+ }
+ ExpBufFreeBuf( buf );
+ GenBufFreeBuf( b );
+
+ return LDAP_SUCCESS;
+}
+
+#if SLAPD_COMP_MATCH == SLAPD_MOD_DYNAMIC
+
+#include "certificate.h"
+
+extern convert_attr_to_comp_func* attr_converter;
+extern convert_assert_to_comp_func* assert_converter;
+extern convert_asn_to_ldap_func* csi_converter;
+extern free_component_func* component_destructor;
+extern test_component_func* test_components;
+extern alloc_nibble_func* nibble_mem_allocator;
+extern free_nibble_func* nibble_mem_free;
+extern test_membership_func* is_aliased_attribute;
+extern get_component_info_func* get_component_description;
+extern component_encoder_func* component_encoder;
+
+
+int init_module(int argc, char *argv[]) {
+ /*
+ * Initialize function pointers in slapd
+ */
+ attr_converter = (convert_attr_to_comp_func*)comp_convert_attr_to_comp;
+ assert_converter = (convert_assert_to_comp_func*)comp_convert_assert_to_comp;
+ component_destructor = (free_component_func*)comp_free_component;
+ test_components = (test_component_func*)comp_test_components;
+ nibble_mem_allocator = (free_nibble_func*)comp_nibble_memory_allocator;
+ nibble_mem_free = (free_nibble_func*)comp_nibble_memory_free;
+ is_aliased_attribute = (test_membership_func*)comp_is_aliased_attribute;
+ get_component_description = (get_component_info_func*)comp_get_component_description;
+ component_encoder = (component_encoder_func*)comp_component_encoder;
+
+ /* file path needs to be */
+ load_derived_matching_rule ("derived_mr.cfg");
+
+ /* the initialization for example X.509 certificate */
+ init_module_AuthenticationFramework();
+ init_module_AuthorityKeyIdentifierDefinition();
+ init_module_CertificateRevokationList();
+ init_attribute_aliasing_table ();
+ init_component_description_table ();
+ return 0;
+}
+
+#endif /* SLAPD_PASSWD */