Commit 98485f52 authored by Sang Seok Lim's avatar Sang Seok Lim
Browse files

1) existing matching rules support in component filter

2) remove double buffering for decoded component values
3) caching decoded component assertion values
parent af9ce148
......@@ -1683,7 +1683,7 @@ int mode)
t->comp_desc->cd_free = (comp_free_func*)NULL;
t->comp_desc->cd_extract_i = (extract_component_from_id_func*)ExtractingComponentRelativeDistinguishedName;
t->comp_desc->cd_type = ASN_COMPOSITE;
t->comp_desc->cd_type_id = COMPOSITE_ASN1_TYPE;
t->comp_desc->cd_type_id = RelativeDistinguishedName ;
t->comp_desc->cd_all_match = (allcomponent_matching_func*)MatchingComponentRelativeDistinguishedName;
(*bytesDecoded) += totalElmtsLen1;
return LDAP_SUCCESS;
......@@ -1755,7 +1755,7 @@ int mode)
t->comp_desc->cd_free = (comp_free_func*)NULL;
t->comp_desc->cd_extract_i = (extract_component_from_id_func*)ExtractingComponentRelativeDistinguishedName;
t->comp_desc->cd_type = ASN_COMPOSITE;
t->comp_desc->cd_type_id = COMPOSITE_ASN1_TYPE;
t->comp_desc->cd_type_id = RelativeDistinguishedName ;
t->comp_desc->cd_all_match = (allcomponent_matching_func*)MatchingComponentRelativeDistinguishedName;
return LDAP_SUCCESS;
} /* GDecRelativeDistinguishedNameContent */
......@@ -1913,7 +1913,7 @@ int mode)
t->comp_desc->cd_free = (comp_free_func*)NULL;
t->comp_desc->cd_extract_i = (extract_component_from_id_func*)ExtractingComponentRDNSequence;
t->comp_desc->cd_type = ASN_COMPOSITE;
t->comp_desc->cd_type_id = COMPOSITE_ASN1_TYPE;
t->comp_desc->cd_type_id = RDNSequence;
t->comp_desc->cd_all_match = (allcomponent_matching_func*)MatchingComponentRDNSequence;
(*bytesDecoded) += totalElmtsLen1;
return LDAP_SUCCESS;
......@@ -1985,7 +1985,7 @@ int mode)
t->comp_desc->cd_free = (comp_free_func*)NULL;
t->comp_desc->cd_extract_i = (extract_component_from_id_func*)ExtractingComponentRDNSequence;
t->comp_desc->cd_type = ASN_COMPOSITE;
t->comp_desc->cd_type_id = COMPOSITE_ASN1_TYPE;
t->comp_desc->cd_type_id = RDNSequence;
t->comp_desc->cd_all_match = (allcomponent_matching_func*)MatchingComponentRDNSequence;
return LDAP_SUCCESS;
} /* GDecRDNSequenceContent */
......
......@@ -508,4 +508,23 @@ m_convert_attr_to_comp ( Attribute* a, struct berval* bv );
MatchingRule*
retrieve_matching_rule( char* mr_oid, AsnTypeId type );
#define INITIAL_DN_SIZE 128
#define INITIAL_ATTR_SIZE 256
#define INCREMENT_SIZE 32
int increment_bv_mem ( struct berval* in );
int intToAscii ( int value, char* buf );
typedef ComponentList irRDNSequence;
typedef ComponentList irRelativeDistinguishedName;
typedef ComponentOid irAttributeType;
typedef struct irAttributeTypeAndValue /* SEQUENCE */
{
Syntax* syntax;
ComponentDesc* comp_desc;
struct berval identifier;
char id_buf[MAX_IDENTIFIER_LEN];
irAttributeType type; /* AttributeType */
ComponentAnyDefinedBy value; /* ANY DEFINED BY type */
} irAttributeTypeAndValue;
#define RDN_MATCH_OID "1.2.36.79672281.1.13.3"
#define DN_MATCH_OID "2.5.13.1"
#endif
......@@ -2185,4 +2185,192 @@ int mode) {
return (*decoder)( mem_op, b, tag, elmtLen, (ComponentSyntaxInfo*)v,(int*)bytesDecoded, mode );
}
/*
* ASN.1 specification of a distinguished name
* DistinguishedName ::= RDNSequence
* RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
* RelativeDistinguishedName ::= SET SIZE(1..MAX) OF AttributeTypeandValue
* AttributeTypeandValue ::= SEQUENCE {
* type AttributeType
* value AttributeValue
* }
* When dnMatch/rdnMatch is used in a component assertion value
* the component in DistinguishedName/RelativeDistinguishedName
* need to be converted to the LDAP encodings in RFC2253
* in order to be matched against the assertion value
* If allComponentMatch is used, the assertion value may be
* decoded into the Internal Representation(Component Tree)
* by the corresponding GSER or BER decoder
* Following routine converts a component tree(DistinguishedName) into
* LDAP encodings in RFC2253
* Example)
* IR : ComponentRDNSequence
* GSER : { { type cn, value sang },{ type o, value ibm}, {type c, value us} }
* LDAP Encodings : cn=sang,o=ibm,c=us
*/
int
increment_bv_mem ( struct berval* in ) {
int new_size = in->bv_len + INCREMENT_SIZE;
in->bv_val = realloc( in->bv_val, new_size );
in->bv_len = new_size;
}
int
ConvertBER2Desc( char* in, int size, struct berval* out, int* pos ) {
int desc_size;
char* desc_ptr;
unsigned int firstArcNum;
unsigned int arcNum;
int i, rc, start_pos = *pos;
char buf[MAX_OID_LEN];
AttributeType *at;
struct berval bv_name;
/*convert BER oid to desc*/
for ( i = 0, arcNum = 0; (i < size) && (in[i] & 0x80 ); i++ )
arcNum = (arcNum << 7) + (in[i] & 0x7f);
arcNum = (arcNum << 7) + (in[i] & 0x7f);
i++;
firstArcNum = (unsigned short)(arcNum/40);
if ( firstArcNum > 2 )
firstArcNum = 2;
arcNum = arcNum - (firstArcNum * 40 );
rc = intToAscii ( arcNum, buf );
/*check if the buffer can store the first/second arc and two dots*/
if ( out->bv_len < *pos + 2 + 1 + rc )
increment_bv_mem ( out );
if ( firstArcNum == 1)
out->bv_val[*pos] = '1';
else
out->bv_val[*pos] = '2';
(*pos)++;
out->bv_val[*pos] = '.';
(*pos)++;
memcpy( out->bv_val + *pos, buf, rc );
*pos += rc;
out->bv_val[*pos] = '.';
(*pos)++;
for ( ; i < size ; ) {
for ( arcNum=0; (i < size) && (in[i] & 0x80) ; i++ )
arcNum = (arcNum << 7) + (in[i] & 0x7f);
arcNum = (arcNum << 7) + (in[i] & 0x7f);
i++;
rc = intToAscii ( arcNum, buf );
if ( out->bv_len < *pos + rc + 1 )
increment_bv_mem ( out );
memcpy( out->bv_val + *pos, buf, rc );
*pos += rc;
out->bv_val[*pos] = '.';
(*pos)++;
}
(*pos)--;/*remove the last '.'*/
/*
* lookup OID database to locate desc
* then overwrite OID with desc in *out
* If failed to look up desc, OID form is used
*/
bv_name.bv_val = out->bv_val + start_pos;
bv_name.bv_len = *pos - start_pos;
at = at_bvfind( &bv_name );
if ( !at )
return LDAP_SUCCESS;
desc_size = at->sat_cname.bv_len;
memcpy( out->bv_val + start_pos, at->sat_cname.bv_val, desc_size );
*pos = start_pos + desc_size;
return LDAP_SUCCESS;
}
int
ConvertComponentAttributeTypeAndValue2RFC2253 ( irAttributeTypeAndValue* in, struct berval* out, int *pos ) {
int rc;
int value_size = ((ComponentUTF8String*)in->value.value)->value.octetLen;
char* value_ptr = ((ComponentUTF8String*)in->value.value)->value.octs;
rc = ConvertBER2Desc( in->type.value.octs, in->type.value.octetLen, out, pos );
if ( rc != LDAP_SUCCESS ) return rc;
if ( out->bv_len < *pos + 1/*for '='*/ )
increment_bv_mem ( out );
/*Between type and value, put '='*/
out->bv_val[*pos] = '=';
(*pos)++;
/*Assume it is string*/
if ( out->bv_len < *pos + value_size )
increment_bv_mem ( out );
memcpy( out->bv_val + *pos, value_ptr, value_size );
out->bv_len += value_size;
*pos += value_size;
return LDAP_SUCCESS;
}
int
ConvertRelativeDistinguishedName2RFC2253 ( irRelativeDistinguishedName* in, struct berval *out , int* pos) {
irAttributeTypeAndValue* attr_typeNvalue;
int rc;
FOR_EACH_LIST_ELMT( attr_typeNvalue, &in->comp_list)
{
rc = ConvertComponentAttributeTypeAndValue2RFC2253( attr_typeNvalue, out, pos );
if ( rc != LDAP_SUCCESS ) return LDAP_INVALID_SYNTAX;
if ( out->bv_len < pos + 1/*for '+'*/ )
increment_bv_mem ( out );
/*between multivalued RDNs, put comma*/
out->bv_val[*pos++] = '+';
}
(*pos)--;/*remove the last '+'*/
return LDAP_SUCCESS;
}
int
ConvertRDN2RFC2253 ( irRelativeDistinguishedName* in, struct berval *out ) {
int rc, pos = 0;
out->bv_val = (char*)malloc( INITIAL_DN_SIZE );
out->bv_len = INITIAL_DN_SIZE;
rc = ConvertRelativeDistinguishedName2RFC2253 ( in, out , &pos);
if ( rc != LDAP_SUCCESS ) return rc;
out->bv_val[pos] = '\0';
out->bv_len = pos;
return LDAP_SUCCESS;
}
int
ConvertRDNSequence2RFC2253( irRDNSequence *in, struct berval* out ) {
irRelativeDistinguishedName* rdn_seq;
AsnList* seq = &in->comp_list;
int pos = 0, rc ;
out->bv_val = (char*)malloc( INITIAL_DN_SIZE );
out->bv_len = INITIAL_DN_SIZE;
FOR_EACH_LIST_ELMT( rdn_seq, seq )
{
rc = ConvertRelativeDistinguishedName2RFC2253( rdn_seq, out, &pos );
if ( rc != LDAP_SUCCESS ) return LDAP_INVALID_SYNTAX;
if ( out->bv_len < pos + 1/*for ','*/ )
increment_bv_mem ( out );
/*Between RDN, put comma*/
out->bv_val[pos++] = ',';
}
pos--;/*remove the last '+'*/
out->bv_val[pos] = '\0';
out->bv_len = pos;
return LDAP_SUCCESS;
}
#endif
......@@ -133,13 +133,11 @@ comp_convert_attr_to_comp LDAP_P (( Attribute* a, Syntax *syn, struct berval* bv
if ( size <= 0 ) return (void*)NULL;
}
ExpBufInit( 2048 );
buf = ExpBufAllocBufAndData();
ExpBufResetInWriteRvsMode( buf );
ExpBuftoGenBuf( buf, &b );
BufPutSegRvs( b, bv->bv_val, bv->bv_len );
BufResetInReadMode( b );
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?
......@@ -153,13 +151,15 @@ comp_convert_attr_to_comp LDAP_P (( Attribute* a, Syntax *syn, struct berval* bv
rc = od_entry->oe_gser_decoder( a->a_comp_data->cd_mem_op, b, component,&bytesDecoded,mode);
}
ExpBufFreeBuf( buf );
if ( rc == -1 ) {
ShutdownNibbleMemLocal ( a->a_comp_data->cd_mem_op );
a->a_comp_data->cd_mem_op = NULL;
return (void*)NULL;
}
else
else {
return component;
}
}
#include <nibble-alloc.h>
......@@ -176,21 +176,22 @@ comp_convert_assert_to_comp (
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;
ExpBufInit( 2048 );
buf = ExpBufAllocBufAndData();
ExpBufResetInWriteRvsMode( buf );
buf = ExpBufAllocBuf();
ExpBuftoGenBuf( buf, &genBuf );
BufPutSegRvs( genBuf, bv->bv_val, bv->bv_len );
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;
return (*decoder)( mem_op, genBuf, csi, len, mode );
rc = (*decoder)( mem_op, genBuf, csi, len, mode );
ExpBufFreeBuf ( buf );
return rc;
}
int intToAscii( int value, char* buf ) {
......@@ -222,10 +223,11 @@ int intToAscii( int value, char* buf ) {
}
int
comp_convert_asn_to_ldap LDAP_P(( ComponentSyntaxInfo* csi, struct berval* bv ))
comp_convert_asn_to_ldap ( MatchingRule* mr, ComponentSyntaxInfo* csi, struct berval* bv, int *allocated )
{
int value;
int value, rc;
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 )
......@@ -233,8 +235,12 @@ comp_convert_asn_to_ldap LDAP_P(( ComponentSyntaxInfo* csi, struct berval* bv ))
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;
......@@ -245,20 +251,25 @@ comp_convert_asn_to_ldap LDAP_P(( ComponentSyntaxInfo* csi, struct berval* bv ))
}
break ;
case BASICTYPE_NULL :
bv->bv_val = (char *) &((ComponentNull*)csi)->value;
bv->bv_len = sizeof(char);
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;
if ( bv->bv_len <= 0 )
return LDAP_INVALID_SYNTAX;
break;
case BASICTYPE_REAL :
bv->bv_val = (char *) &((ComponentReal*)csi)->value;
bv->bv_len = sizeof(double);
break;
return LDAP_INVALID_SYNTAX;
case BASICTYPE_ENUMERATED :
bv->bv_val = (char *) &((ComponentEnum*)csi)->value;
bv->bv_len = sizeof(int);
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 :
......@@ -280,25 +291,35 @@ comp_convert_asn_to_ldap LDAP_P(( ComponentSyntaxInfo* csi, struct berval* bv ))
case BASICTYPE_OCTETCONTAINING :
case BASICTYPE_BITCONTAINING :
case BASICTYPE_RELATIVE_OID :
bv->bv_val = ((ComponentOcts*)csi)->value.octs;
bv->bv_len = ((ComponentOcts*)csi)->value.octetLen;
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( csi, bv );
return comp_convert_asn_to_ldap( mr, csi, bv, allocated );
case COMPOSITE_ASN1_TYPE :
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 );
return rc;
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);
return rc;
case TelephoneNumber :
case FacsimileTelephoneNumber__telephoneNumber :
break;
case DirectoryString :
bv->bv_val = ((ComponentOcts*)csi)->value.octs;
bv->bv_len = ((ComponentOcts*)csi)->value.octetLen;
break;
return LDAP_INVALID_SYNTAX;
case ASN_COMP_CERTIFICATE :
case ASNTYPE_END :
break;
......@@ -526,7 +547,7 @@ comp_test_one_component (
ComponentSyntaxInfo *csi_attr,
ComponentAssertion *ca )
{
int len;
int len, rc;
ComponentSyntaxInfo *csi_assert = NULL;
char* oid = NULL;
MatchingRule* mr = ca->ca_ma_rule;
......@@ -553,29 +574,30 @@ comp_test_one_component (
} else {
/* LDAP existing matching rules */
struct berval attr_bv;
struct berval attr_bv = BER_BVNULL;
struct berval* assert_bv = &ca->ca_ma_value;
char attr_buf[MAX_LDAP_STR_LEN];
if ( csi_attr->csi_comp_desc->cd_type == ASN_BASIC ) {
/*Attribute component is converted to compatible LDAP encodings*/
attr_bv.bv_val = attr_buf;
if ( comp_convert_asn_to_ldap( csi_attr, &attr_bv ) != LDAP_SUCCESS )
return LDAP_INAPPROPRIATE_MATCHING;
/*Assertion value is validated by MR's syntax*/
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;
/*Assertion value is validated by MR's syntax*/
if ( !ca->ca_comp_data.cd_tree ) {
if ( get_primitive_GSER_value( assert_bv ) != LDAP_SUCCESS )
return LDAP_INVALID_SYNTAX;
assert_bv->bv_val[assert_bv->bv_len] = '\0';
if ( mr->smr_syntax->ssyn_validate( mr->smr_syntax, assert_bv ) != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
return csi_value_match( mr, &attr_bv, assert_bv );
} else if ( csi_attr->csi_comp_desc->cd_type == ASN_COMPOSITE ) {
return LDAP_INAPPROPRIATE_MATCHING;
ca->ca_comp_data.cd_tree = assert_bv;
}
else {
assert_bv = ca->ca_comp_data.cd_tree;
}
rc = csi_value_match( mr, &attr_bv, assert_bv );
if ( allocated ) free (attr_bv.bv_val);
return rc;
}
}
......@@ -612,7 +634,6 @@ int init_module(int argc, char *argv[]) {
*/
attr_converter = comp_convert_attr_to_comp;
assert_converter = comp_convert_assert_to_comp;
csi_converter = comp_convert_asn_to_ldap;
component_destructor = comp_free_component;
test_one_component = comp_test_one_component;
test_all_components = comp_test_all_components;
......
......@@ -36,7 +36,6 @@ 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 ;
convert_asn_to_ldap_func* csi_converter = NULL ;
free_component_func* component_destructor = NULL ;
test_component_func* test_one_component = NULL;
test_component_func* test_all_components = NULL;
......@@ -872,44 +871,6 @@ csi_value_match( MatchingRule *mr, struct berval* bv_attr,
return rc;
}
int
component_value_match( MatchingRule* mr,
ComponentSyntaxInfo* csi_attr, ComponentSyntaxInfo* csi_assert )
{
if ( mr->smr_usage & SLAP_MR_COMPONENT ){
if ( strcmp( mr->smr_mrule.mr_oid, OID_ALL_COMP_MATCH ) == 0 )
{
/* allComponentMatch */
return csi_attr->csi_comp_desc->cd_all_match( NULL,
csi_attr, csi_assert );
} else {
return csi_assert->csi_comp_desc->cd_all_match(
mr->smr_mrule.mr_oid, csi_attr, csi_assert );
}
} else {
if ( csi_attr->csi_comp_desc->cd_type == ASN_BASIC ) {
struct berval bv1, bv2;
char attr_buf[MAX_LDAP_STR_LEN],assert_buf[MAX_LDAP_STR_LEN];
bv1.bv_val = attr_buf;
bv2.bv_val = assert_buf;
if ( csi_converter &&
( csi_converter ( csi_attr, &bv1 ) == LDAP_SUCCESS ) &&
( csi_converter ( csi_assert, &bv2 ) == LDAP_SUCCESS ) )
{
return csi_value_match( mr, &bv1, &bv2 );
} else {
return LDAP_INAPPROPRIATE_MATCHING;
}
} else if ( csi_attr->csi_comp_desc->cd_type == ASN_COMPOSITE )
{
return LDAP_INAPPROPRIATE_MATCHING;
}
}
}
/*
* return codes : LDAP_COMPARE_TRUE, LDAP_COMPARE_FALSE
*/
......@@ -955,8 +916,15 @@ test_comp_filter_item(
return LDAP_PROTOCOL_ERROR;
/* Memory for storing component assertion values */
assert_nm = nibble_mem_allocator ( 256, 64 );
if ( !assert_nm ) return LDAP_PROTOCOL_ERROR;
if( !ca->ca_comp_data.cd_mem_op ) {
assert_nm = nibble_mem_allocator ( 256, 64 );
if ( !assert_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 ) {
/*
......
......@@ -32,6 +32,125 @@ userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
dAWtMjWq2ZJIa26bbvB4enGOF66KH5S823ZdKa0Kr2JcHAAYFpf+TQoGg5JO7TD3AECd7Qo9a+4Xr
EkBJ/Q=
dn: cn=beta,ou=Alumni Association,ou=People,dc=example,dc=com
objectClass: OpenLDAPperson
objectClass: extensibleObject
uid:: Y2hhcmxpZSA=
cn: beta
sn: Jee
userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
QQGEwJVUzAeFw0wNDEwMTIwMDAxNTBaFw0wNDExMTEwMDAxNTBaMA0xCzAJBgNVBAYTAlVTMIGfMA
0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQcTs4uD+gAoQ1XkYN4woLtZaEi7XVEVIJQ6Rsn2QP3MO
NBT9jvrhVcnUJQtvEEkfnsNANKeYntUTvih76jErFNTmg7zl0govFSkiuS+tfrZnn/Ebix3+tTMnA
KUQXkYi5Mr+x3U44yYo1EPLpZlcV1Caafc30EMRQ/Gv/PdrqYwIDAQABo2YwZDAdBgNVHQ4EFgQUA
zNnruNiI38IPf39ZJGFx8mDsxgwNQYDVR0jBC4wLIAUAzNnruNiI38IPf39ZJGFx8mDsxihEaQPMA
0xCzAJBgNVBAYTAlVTggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAf44laoKcTyS
uz3yQb/lfOBVDh6oMxysal0eEij+nypQJ1H+rsZ+ebUlKMiTYhrTk3n3H6moHaxICENIu4P5rD5Ue
dAWtMjWq2ZJIa26bbvB4enGOF66KH5S823ZdKa0Kr2JcHAAYFpf+TQoGg5JO7TD3AECd7Qo9a+4Xr
EkBJ/Q=
dn: cn=charlie,ou=Alumni Association,ou=People,dc=example,dc=com
objectClass: OpenLDAPperson
objectClass: extensibleObject
uid:: Y2hhcmxpZSA=
cn: charlie
sn: Jee
userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
QQGEwJVUzAeFw0wNDEwMTIwMDAxNTBaFw0wNDExMTEwMDAxNTBaMA0xCzAJBgNVBAYTAlVTMIGfMA
0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQcTs4uD+gAoQ1XkYN4woLtZaEi7XVEVIJQ6Rsn2QP3MO
NBT9jvrhVcnUJQtvEEkfnsNANKeYntUTvih76jErFNTmg7zl0govFSkiuS+tfrZnn/Ebix3+tTMnA
KUQXkYi5Mr+x3U44yYo1EPLpZlcV1Caafc30EMRQ/Gv/PdrqYwIDAQABo2YwZDAdBgNVHQ4EFgQUA
zNnruNiI38IPf39ZJGFx8mDsxgwNQYDVR0jBC4wLIAUAzNnruNiI38IPf39ZJGFx8mDsxihEaQPMA
0xCzAJBgNVBAYTAlVTggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAf44laoKcTyS
uz3yQb/lfOBVDh6oMxysal0eEij+nypQJ1H+rsZ+ebUlKMiTYhrTk3n3H6moHaxICENIu4P5rD5Ue
dAWtMjWq2ZJIa26bbvB4enGOF66KH5S823ZdKa0Kr2JcHAAYFpf+TQoGg5JO7TD3AECd7Qo9a+4Xr
EkBJ/Q=
dn: cn=beta,ou=Alumni Association,ou=People,dc=example,dc=com
objectClass: OpenLDAPperson
objectClass: extensibleObject
uid:: Y2hhcmxpZSA=
cn: beta
sn: Jee
userCertificate;binary:: MIIB9jCCAV+gAwIBAgIBADANBgkqhkiG9w0BAQQFADANMQswCQYDV
QQGEwJVUzAeFw0wNDEwMTIwMDAxNTBaFw0wNDExMTEwMDAxNTBaMA0xCzAJBgNVBAYTAlVTMIGfMA
0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQcTs4uD+gAoQ1XkYN4woLtZaEi7XVEVIJQ6Rsn2QP3MO