#include "portable.h"
#include <stdio.h>
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include <ac/ctype.h>
#include <ac/errno.h>
#include <ac/string.h>
#include <ac/socket.h>
#include "slap.h"
#include "../../libraries/liblber/lber-int.h"
#include "ldap_utf8.h"
#include "lutil.h"
#include "lutil_hash.h"
#define HASH_BYTES LUTIL_HASH_BYTES
#define HASH_CONTEXT lutil_HASH_CTX
#define HASH_Init(c) lutil_HASHInit(c)
#define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len)
#define HASH_Final(d,c) lutil_HASHFinal(d,c)
#define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4"
#define directoryStringApproxMatch approxMatch
#define directoryStringApproxIndexer approxIndexer
#define directoryStringApproxFilter approxFilter
#define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5"
#define IA5StringApproxMatch approxMatch
#define IA5StringApproxIndexer approxIndexer
#define IA5StringApproxFilter approxFilter
#define csnMatch octetStringMatch
#define csnOrderingMatch octetStringOrderingMatch
#define csnIndexer generalizedTimeIndexer
#define csnFilter generalizedTimeFilter
#define authzMatch octetStringMatch
#if 0
#define attributeCertificateSyntaxOID "1.2.826.0.1.3344810.7.5"
#define attributeCertificateExactAssertionSyntaxOID "1.2.826.0.1.3344810.7.6"
#define attributeCertificateAssertionSyntaxOID "1.2.826.0.1.3344810.7.7"
#else
#define X509_PMI_SyntaxOID "1.3.6.1.4.1.4203.666.11.10.2"
#define attributeCertificateSyntaxOID X509_PMI_SyntaxOID ".1"
#define attributeCertificateExactAssertionSyntaxOID X509_PMI_SyntaxOID ".2"
#define attributeCertificateAssertionSyntaxOID X509_PMI_SyntaxOID ".3"
#endif
unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
unsigned int index_substr_any_step = SLAP_INDEX_SUBSTR_ANY_STEP_DEFAULT;
unsigned int index_intlen = SLAP_INDEX_INTLEN_DEFAULT;
unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
SLAP_INDEX_INTLEN_DEFAULT );
ldap_pvt_thread_mutex_t ad_index_mutex;
ldap_pvt_thread_mutex_t ad_undef_mutex;
ldap_pvt_thread_mutex_t oc_undef_mutex;
static int
generalizedTimeValidate(
Syntax *syntax,
struct berval *in );
#ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
static int
utcTimeValidate(
Syntax *syntax,
struct berval *in );
#endif
static int
inValidate(
Syntax *syntax,
struct berval *in )
{
return LDAP_INVALID_SYNTAX;
}
static int
blobValidate(
Syntax *syntax,
struct berval *in )
{
return LDAP_SUCCESS;
}
#define berValidate blobValidate
static int
sequenceValidate(
Syntax *syntax,
struct berval *in )
{
if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX;
if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
return LDAP_SUCCESS;
}
enum {
SLAP_X509_V1 = 0,
SLAP_X509_V2 = 1,
SLAP_X509_V3 = 2
};
enum {
SLAP_TAG_UTCTIME = 0x17U,
SLAP_TAG_GENERALIZEDTIME = 0x18U
};
#define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED)
enum {
SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0,
SLAP_X509_OPT_C_ISSUERUNIQUEID = LBER_CLASS_CONTEXT + 1,
SLAP_X509_OPT_C_SUBJECTUNIQUEID = LBER_CLASS_CONTEXT + 2,
SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3
};
enum {
SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0
};
enum {
SLAP_X509_GN_OTHERNAME = SLAP_X509_OPTION + 0,
SLAP_X509_GN_RFC822NAME = SLAP_X509_OPTION + 1,
SLAP_X509_GN_DNSNAME = SLAP_X509_OPTION + 2,
SLAP_X509_GN_X400ADDRESS = SLAP_X509_OPTION + 3,
SLAP_X509_GN_DIRECTORYNAME = SLAP_X509_OPTION + 4,
SLAP_X509_GN_EDIPARTYNAME = SLAP_X509_OPTION + 5,
SLAP_X509_GN_URI = SLAP_X509_OPTION + 6,
SLAP_X509_GN_IPADDRESS = SLAP_X509_OPTION + 7,
SLAP_X509_GN_REGISTEREDID = SLAP_X509_OPTION + 8
};
enum {
SLAP_X509AC_V1 = 0,
SLAP_X509AC_V2 = 1
};
enum {
SLAP_X509AC_ISSUER = SLAP_X509_OPTION + 0
};
static int
certificateValidate( Syntax *syntax, struct berval *in )
{
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
ber_tag_t tag;
ber_len_t len;
ber_int_t version = SLAP_X509_V1;
ber_init2( ber, in, LBER_USE_DER );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
tag = ber_peek_tag( ber, &len );
if ( tag == SLAP_X509_OPT_C_VERSION ) {
tag = ber_skip_tag( ber, &len );
tag = ber_get_int( ber, &version );
if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
}
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag == SLAP_X509_OPT_C_ISSUERUNIQUEID ) {
if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
}
if ( tag == SLAP_X509_OPT_C_SUBJECTUNIQUEID ) {
if ( version < SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
}
if ( tag == SLAP_X509_OPT_C_EXTENSIONS ) {
if ( version < SLAP_X509_V3 ) return LDAP_INVALID_SYNTAX;
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
}
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
return LDAP_SUCCESS;
}
static int
checkTime( struct berval *in, struct berval *out );
static int
certificateListValidate( Syntax *syntax, struct berval *in )
{
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
ber_tag_t tag;
ber_len_t len, wrapper_len;
char *wrapper_start;
int wrapper_ok = 0;
ber_int_t version = SLAP_X509_V1;
struct berval bvdn, bvtu;
ber_init2( ber, in, LBER_USE_DER );
tag = ber_skip_tag( ber, &wrapper_len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
wrapper_start = ber->ber_ptr;
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
tag = ber_peek_tag( ber, &len );
if ( tag == LBER_INTEGER ) {
tag = ber_get_int( ber, &version );
assert( tag == LBER_INTEGER );
if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
}
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_peek_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
len = ber_ptrlen( ber );
bvdn.bv_val = in->bv_val + len;
bvdn.bv_len = in->bv_len - len;
tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
bvtu.bv_val = (char *)ber->ber_ptr;
bvtu.bv_len = len;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag == SLAP_TAG_UTCTIME || tag == SLAP_TAG_GENERALIZEDTIME ) {
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
}
if ( tag == LBER_SEQUENCE ) {
ber_len_t seqlen;
ber_tag_t stag;
stag = ber_peek_tag( ber, &seqlen );
if ( stag == LBER_SEQUENCE || !len ) {
if ( len )
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
}
}
if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) {
ber_len_t seqlen;
if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
tag = ber_peek_tag( ber, &seqlen );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
}
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
if ( ber->ber_ptr == wrapper_start + wrapper_len ) wrapper_ok = 1;
tag = ber_skip_tag( ber, &len );
if ( len || tag != LBER_DEFAULT ) {
struct berval issuer_dn = BER_BVNULL, thisUpdate;
char tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
int rc;
if ( ! wrapper_ok ) {
return LDAP_INVALID_SYNTAX;
}
rc = dnX509normalize( &bvdn, &issuer_dn );
if ( rc != LDAP_SUCCESS ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
thisUpdate.bv_val = tubuf;
thisUpdate.bv_len = sizeof(tubuf);
if ( checkTime( &bvtu, &thisUpdate ) ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
Debug( LDAP_DEBUG_ANY,
"certificateListValidate issuer=\"%s\", thisUpdate=%s: extra cruft past end of certificateList\n",
issuer_dn.bv_val, thisUpdate.bv_val, 0 );
done:;
if ( ! BER_BVISNULL( &issuer_dn ) ) {
ber_memfree( issuer_dn.bv_val );
}
return rc;
}
return LDAP_SUCCESS;
}
static int
attributeCertificateValidate( Syntax *syntax, struct berval *in )
{
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
ber_tag_t tag;
ber_len_t len;
ber_int_t version;
int cont = 0;
ber_init2( ber, in, LBER_USE_DER );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
tag = ber_peek_tag( ber, &len );
if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
tag = ber_get_int( ber, &version );
if ( version != SLAP_X509AC_V2 ) return LDAP_INVALID_SYNTAX;
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != SLAP_X509AC_ISSUER ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_peek_tag( ber, &len );
if ( tag == LBER_BITSTRING ) {
tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
tag = ber_peek_tag( ber, &len );
}
if ( tag == LBER_SEQUENCE ) {
tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
cont++;
tag = ber_peek_tag( ber, &len );
}
if ( tag == LBER_SEQUENCE ) {
tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
cont++;
tag = ber_peek_tag( ber, &len );
}
if ( tag == LBER_BITSTRING ) {
tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
cont++;
tag = ber_peek_tag( ber, &len );
}
if ( len != 0 || tag != LBER_DEFAULT || cont < 2 ) return LDAP_INVALID_SYNTAX;
return LDAP_SUCCESS;
}
int
octetStringMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
struct berval *asserted = (struct berval *) assertedValue;
ber_slen_t d = (ber_slen_t) value->bv_len - (ber_slen_t) asserted->bv_len;
*matchp = d ? (sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1)
: memcmp( value->bv_val, asserted->bv_val, value->bv_len );
return LDAP_SUCCESS;
}
int
octetStringOrderingMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
struct berval *asserted = (struct berval *) assertedValue;
ber_len_t v_len = value->bv_len;
ber_len_t av_len = asserted->bv_len;
int match = memcmp( value->bv_val, asserted->bv_val,
(v_len < av_len ? v_len : av_len) );
if( match == 0 )
match = sizeof(v_len) == sizeof(int)
? (int) v_len - (int) av_len
: v_len < av_len ? -1 : v_len > av_len;
if ( flags & SLAP_MR_EXT )
match = (match >= 0);
*matchp = match;
return LDAP_SUCCESS;
}
static void
hashPreset(
HASH_CONTEXT *HASHcontext,
struct berval *prefix,
char pre,
Syntax *syntax,
MatchingRule *mr)
{
HASH_Init(HASHcontext);
if(prefix && prefix->bv_len > 0) {
HASH_Update(HASHcontext,
(unsigned char *)prefix->bv_val, prefix->bv_len);
}
if(pre) HASH_Update(HASHcontext, (unsigned char*)&pre, sizeof(pre));
HASH_Update(HASHcontext, (unsigned char*)syntax->ssyn_oid, syntax->ssyn_oidlen);
HASH_Update(HASHcontext, (unsigned char*)mr->smr_oid, mr->smr_oidlen);
return;
}
static void
hashIter(
HASH_CONTEXT *HASHcontext,
unsigned char *HASHdigest,
unsigned char *value,
int len)
{
HASH_CONTEXT ctx = *HASHcontext;
HASH_Update( &ctx, value, len );
HASH_Final( HASHdigest, &ctx );
}
int octetStringIndexer(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
BerVarray values,
BerVarray *keysp,
void *ctx )
{
int i;
size_t slen, mlen;
BerVarray keys;
HASH_CONTEXT HASHcontext;
unsigned char HASHdigest[HASH_BYTES];
struct berval digest;
digest.bv_val = (char *)HASHdigest;
digest.bv_len = sizeof(HASHdigest);
for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
}
assert( i > 0 );
keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
slen = syntax->ssyn_oidlen;
mlen = mr->smr_oidlen;
hashPreset( &HASHcontext, prefix, 0, syntax, mr);
for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
hashIter( &HASHcontext, HASHdigest,
(unsigned char *)values[i].bv_val, values[i].bv_len );
ber_dupbv_x( &keys[i], &digest, ctx );
}
BER_BVZERO( &keys[i] );
*keysp = keys;
return LDAP_SUCCESS;
}
int octetStringFilter(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
void * assertedValue,
BerVarray *keysp,
void *ctx )
{
size_t slen, mlen;
BerVarray keys;
HASH_CONTEXT HASHcontext;
unsigned char HASHdigest[HASH_BYTES];
struct berval *value = (struct berval *) assertedValue;
struct berval digest;
digest.bv_val = (char *)HASHdigest;
digest.bv_len = sizeof(HASHdigest);
slen = syntax->ssyn_oidlen;
mlen = mr->smr_oidlen;
keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
hashPreset( &HASHcontext, prefix, 0, syntax, mr );
hashIter( &HASHcontext, HASHdigest,
(unsigned char *)value->bv_val, value->bv_len );
ber_dupbv_x( keys, &digest, ctx );
BER_BVZERO( &keys[1] );
*keysp = keys;
return LDAP_SUCCESS;
}
static int
octetStringSubstringsMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
int match = 0;
SubstringsAssertion *sub = assertedValue;
struct berval left = *value;
int i;
ber_len_t inlen = 0;
if ( !BER_BVISNULL( &sub->sa_initial ) ) {
inlen += sub->sa_initial.bv_len;
}
if ( sub->sa_any ) {
for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
inlen += sub->sa_any[i].bv_len;
}
}
if ( !BER_BVISNULL( &sub->sa_final ) ) {
inlen += sub->sa_final.bv_len;
}
if ( !BER_BVISNULL( &sub->sa_initial ) ) {
if ( inlen > left.bv_len ) {
match = 1;
goto done;
}
match = memcmp( sub->sa_initial.bv_val, left.bv_val,
sub->sa_initial.bv_len );
if ( match != 0 ) {
goto done;
}
left.bv_val += sub->sa_initial.bv_len;
left.bv_len -= sub->sa_initial.bv_len;
inlen -= sub->sa_initial.bv_len;
}
if ( !BER_BVISNULL( &sub->sa_final ) ) {
if ( inlen > left.bv_len ) {
match = 1;
goto done;
}
match = memcmp( sub->sa_final.bv_val,
&left.bv_val[left.bv_len - sub->sa_final.bv_len],
sub->sa_final.bv_len );
if ( match != 0 ) {
goto done;
}
left.bv_len -= sub->sa_final.bv_len;
inlen -= sub->sa_final.bv_len;
}
if ( sub->sa_any ) {
for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
ber_len_t idx;
char *p;
retry:
if ( inlen > left.bv_len ) {
match = 1;
goto done;
}
if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
continue;
}
p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
if( p == NULL ) {
match = 1;
goto done;
}
idx = p - left.bv_val;
if ( idx >= left.bv_len ) {
return LDAP_OTHER;
}
left.bv_val = p;
left.bv_len -= idx;
if ( sub->sa_any[i].bv_len > left.bv_len ) {
match = 1;
goto done;
}
match = memcmp( left.bv_val,
sub->sa_any[i].bv_val,
sub->sa_any[i].bv_len );
if ( match != 0 ) {
left.bv_val++;
left.bv_len--;
goto retry;
}
left.bv_val += sub->sa_any[i].bv_len;
left.bv_len -= sub->sa_any[i].bv_len;
inlen -= sub->sa_any[i].bv_len;
}
}
done:
*matchp = match;
return LDAP_SUCCESS;
}
static int
octetStringSubstringsIndexer(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
BerVarray values,
BerVarray *keysp,
void *ctx )
{
ber_len_t i, nkeys;
size_t slen, mlen;
BerVarray keys;
HASH_CONTEXT HCany, HCini, HCfin;
unsigned char HASHdigest[HASH_BYTES];
struct berval digest;
digest.bv_val = (char *)HASHdigest;
digest.bv_len = sizeof(HASHdigest);
nkeys = 0;
for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
if( values[i].bv_len >= index_substr_if_maxlen ) {
nkeys += index_substr_if_maxlen -
(index_substr_if_minlen - 1);
} else if( values[i].bv_len >= index_substr_if_minlen ) {
nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
}
}
if( flags & SLAP_INDEX_SUBSTR_ANY ) {
if( values[i].bv_len >= index_substr_any_len ) {
nkeys += values[i].bv_len - (index_substr_any_len - 1);
}
}
if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
if( values[i].bv_len >= index_substr_if_maxlen ) {
nkeys += index_substr_if_maxlen -
(index_substr_if_minlen - 1);
} else if( values[i].bv_len >= index_substr_if_minlen ) {
nkeys += values[i].bv_len - (index_substr_if_minlen - 1);
}
}
}
if( nkeys == 0 ) {
*keysp = NULL;
return LDAP_SUCCESS;
}
keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
slen = syntax->ssyn_oidlen;
mlen = mr->smr_oidlen;
if ( flags & SLAP_INDEX_SUBSTR_ANY )
hashPreset( &HCany, prefix, SLAP_INDEX_SUBSTR_PREFIX, syntax, mr );
if( flags & SLAP_INDEX_SUBSTR_INITIAL )
hashPreset( &HCini, prefix, SLAP_INDEX_SUBSTR_INITIAL_PREFIX, syntax, mr );
if( flags & SLAP_INDEX_SUBSTR_FINAL )
hashPreset( &HCfin, prefix, SLAP_INDEX_SUBSTR_FINAL_PREFIX, syntax, mr );
nkeys = 0;
for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
ber_len_t j,max;
if( ( flags & SLAP_INDEX_SUBSTR_ANY ) &&
( values[i].bv_len >= index_substr_any_len ) )
{
max = values[i].bv_len - (index_substr_any_len - 1);
for( j=0; j<max; j++ ) {
hashIter( &HCany, HASHdigest,
(unsigned char *)&values[i].bv_val[j],
index_substr_any_len );
ber_dupbv_x( &keys[nkeys++], &digest, ctx );
}
}
if( values[i].bv_len < index_substr_if_minlen ) continue;
max = index_substr_if_maxlen < values[i].bv_len
? index_substr_if_maxlen : values[i].bv_len;
for( j=index_substr_if_minlen; j<=max; j++ ) {
if( flags & SLAP_INDEX_SUBSTR_INITIAL ) {
hashIter( &HCini, HASHdigest,
(unsigned char *)values[i].bv_val, j );
ber_dupbv_x( &keys[nkeys++], &digest, ctx );
}
if( flags & SLAP_INDEX_SUBSTR_FINAL ) {
hashIter( &HCfin, HASHdigest,
(unsigned char *)&values[i].bv_val[values[i].bv_len-j], j );
ber_dupbv_x( &keys[nkeys++], &digest, ctx );
}
}
}
if( nkeys > 0 ) {
BER_BVZERO( &keys[nkeys] );
*keysp = keys;
} else {
ch_free( keys );
*keysp = NULL;
}
return LDAP_SUCCESS;
}
static int
octetStringSubstringsFilter (
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
void * assertedValue,
BerVarray *keysp,
void *ctx)
{
SubstringsAssertion *sa;
char pre;
ber_len_t nkeys = 0;
size_t slen, mlen, klen;
BerVarray keys;
HASH_CONTEXT HASHcontext;
unsigned char HASHdigest[HASH_BYTES];
struct berval *value;
struct berval digest;
sa = (SubstringsAssertion *) assertedValue;
if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
!BER_BVISNULL( &sa->sa_initial ) &&
sa->sa_initial.bv_len >= index_substr_if_minlen )
{
nkeys++;
if ( sa->sa_initial.bv_len > index_substr_if_maxlen &&
( flags & SLAP_INDEX_SUBSTR_ANY ))
{
nkeys += 1 + (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step;
}
}
if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
ber_len_t i;
for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
if( sa->sa_any[i].bv_len >= index_substr_any_len ) {
nkeys += sa->sa_any[i].bv_len -
( index_substr_any_len - 1 );
}
}
}
if( flags & SLAP_INDEX_SUBSTR_FINAL &&
!BER_BVISNULL( &sa->sa_final ) &&
sa->sa_final.bv_len >= index_substr_if_minlen )
{
nkeys++;
if ( sa->sa_final.bv_len > index_substr_if_maxlen &&
( flags & SLAP_INDEX_SUBSTR_ANY ))
{
nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step;
}
}
if( nkeys == 0 ) {
*keysp = NULL;
return LDAP_SUCCESS;
}
digest.bv_val = (char *)HASHdigest;
digest.bv_len = sizeof(HASHdigest);
slen = syntax->ssyn_oidlen;
mlen = mr->smr_oidlen;
keys = slap_sl_malloc( sizeof( struct berval ) * (nkeys+1), ctx );
nkeys = 0;
if( flags & SLAP_INDEX_SUBSTR_INITIAL &&
!BER_BVISNULL( &sa->sa_initial ) &&
sa->sa_initial.bv_len >= index_substr_if_minlen )
{
pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX;
value = &sa->sa_initial;
klen = index_substr_if_maxlen < value->bv_len
? index_substr_if_maxlen : value->bv_len;
hashPreset( &HASHcontext, prefix, pre, syntax, mr );
hashIter( &HASHcontext, HASHdigest,
(unsigned char *)value->bv_val, klen );
ber_dupbv_x( &keys[nkeys++], &digest, ctx );
if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
{
ber_len_t j;
pre = SLAP_INDEX_SUBSTR_PREFIX;
hashPreset( &HASHcontext, prefix, pre, syntax, mr);
for ( j=index_substr_if_maxlen-1; j <= value->bv_len - index_substr_any_len; j+=index_substr_any_step )
{
hashIter( &HASHcontext, HASHdigest,
(unsigned char *)&value->bv_val[j], index_substr_any_len );
ber_dupbv_x( &keys[nkeys++], &digest, ctx );
}
}
}
if( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) {
ber_len_t i, j;
pre = SLAP_INDEX_SUBSTR_PREFIX;
klen = index_substr_any_len;
for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) {
if( sa->sa_any[i].bv_len < index_substr_any_len ) {
continue;
}
value = &sa->sa_any[i];
hashPreset( &HASHcontext, prefix, pre, syntax, mr);
for(j=0;
j <= value->bv_len - index_substr_any_len;
j += index_substr_any_step )
{
hashIter( &HASHcontext, HASHdigest,
(unsigned char *)&value->bv_val[j], klen );
ber_dupbv_x( &keys[nkeys++], &digest, ctx );
}
}
}
if( flags & SLAP_INDEX_SUBSTR_FINAL &&
!BER_BVISNULL( &sa->sa_final ) &&
sa->sa_final.bv_len >= index_substr_if_minlen )
{
pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX;
value = &sa->sa_final;
klen = index_substr_if_maxlen < value->bv_len
? index_substr_if_maxlen : value->bv_len;
hashPreset( &HASHcontext, prefix, pre, syntax, mr );
hashIter( &HASHcontext, HASHdigest,
(unsigned char *)&value->bv_val[value->bv_len-klen], klen );
ber_dupbv_x( &keys[nkeys++], &digest, ctx );
if (value->bv_len > index_substr_if_maxlen && (flags & SLAP_INDEX_SUBSTR_ANY))
{
ber_len_t j;
pre = SLAP_INDEX_SUBSTR_PREFIX;
hashPreset( &HASHcontext, prefix, pre, syntax, mr);
for ( j=0; j <= value->bv_len - index_substr_if_maxlen; j+=index_substr_any_step )
{
hashIter( &HASHcontext, HASHdigest,
(unsigned char *)&value->bv_val[j], index_substr_any_len );
ber_dupbv_x( &keys[nkeys++], &digest, ctx );
}
}
}
if( nkeys > 0 ) {
BER_BVZERO( &keys[nkeys] );
*keysp = keys;
} else {
ch_free( keys );
*keysp = NULL;
}
return LDAP_SUCCESS;
}
static int
bitStringValidate(
Syntax *syntax,
struct berval *in )
{
ber_len_t i;
if( in->bv_len < 3 ) {
return LDAP_INVALID_SYNTAX;
}
if( in->bv_val[0] != '\'' ||
in->bv_val[in->bv_len - 2] != '\'' ||
in->bv_val[in->bv_len - 1] != 'B' )
{
return LDAP_INVALID_SYNTAX;
}
for( i = in->bv_len - 3; i > 0; i-- ) {
if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
return LDAP_INVALID_SYNTAX;
}
}
return LDAP_SUCCESS;
}
static int
nameUIDValidate(
Syntax *syntax,
struct berval *in )
{
int rc;
struct berval dn, uid;
if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS;
ber_dupbv( &dn, in );
if( !dn.bv_val ) return LDAP_OTHER;
uid.bv_val = strrchr( dn.bv_val, '#' );
if ( !BER_BVISNULL( &uid ) ) {
uid.bv_val++;
uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val );
rc = bitStringValidate( NULL, &uid );
if ( rc == LDAP_SUCCESS ) {
dn.bv_len -= uid.bv_len + 1;
uid.bv_val[-1] = '\0';
}
}
rc = dnValidate( NULL, &dn );
ber_memfree( dn.bv_val );
return rc;
}
int
nameUIDPretty(
Syntax *syntax,
struct berval *val,
struct berval *out,
void *ctx )
{
assert( val != NULL );
assert( out != NULL );
Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 );
if( BER_BVISEMPTY( val ) ) {
ber_dupbv_x( out, val, ctx );
} else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
return LDAP_INVALID_SYNTAX;
} else {
int rc;
struct berval dnval = *val;
struct berval uidval = BER_BVNULL;
uidval.bv_val = strrchr( val->bv_val, '#' );
if ( !BER_BVISNULL( &uidval ) ) {
uidval.bv_val++;
uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val );
rc = bitStringValidate( NULL, &uidval );
if ( rc == LDAP_SUCCESS ) {
ber_dupbv_x( &dnval, val, ctx );
uidval.bv_val--;
dnval.bv_len -= ++uidval.bv_len;
dnval.bv_val[dnval.bv_len] = '\0';
} else {
BER_BVZERO( &uidval );
}
}
rc = dnPretty( syntax, &dnval, out, ctx );
if ( dnval.bv_val != val->bv_val ) {
slap_sl_free( dnval.bv_val, ctx );
}
if( rc != LDAP_SUCCESS ) {
return rc;
}
if( !BER_BVISNULL( &uidval ) ) {
char *tmp;
tmp = slap_sl_realloc( out->bv_val, out->bv_len
+ uidval.bv_len + 1,
ctx );
if( tmp == NULL ) {
ber_memfree_x( out->bv_val, ctx );
return LDAP_OTHER;
}
out->bv_val = tmp;
memcpy( out->bv_val + out->bv_len, uidval.bv_val, uidval.bv_len );
out->bv_len += uidval.bv_len;
out->bv_val[out->bv_len] = '\0';
}
}
Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 );
return LDAP_SUCCESS;
}
static int
uniqueMemberNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
struct berval out;
int rc;
assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
ber_dupbv_x( &out, val, ctx );
if ( BER_BVISEMPTY( &out ) ) {
*normalized = out;
} else {
struct berval uid = BER_BVNULL;
uid.bv_val = strrchr( out.bv_val, '#' );
if ( !BER_BVISNULL( &uid ) ) {
uid.bv_val++;
uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val );
rc = bitStringValidate( NULL, &uid );
if ( rc == LDAP_SUCCESS ) {
uid.bv_val[-1] = '\0';
out.bv_len -= uid.bv_len + 1;
} else {
BER_BVZERO( &uid );
}
}
rc = dnNormalize( 0, NULL, NULL, &out, normalized, ctx );
if( rc != LDAP_SUCCESS ) {
slap_sl_free( out.bv_val, ctx );
return LDAP_INVALID_SYNTAX;
}
if( !BER_BVISNULL( &uid ) ) {
char *tmp;
tmp = ch_realloc( normalized->bv_val,
normalized->bv_len + uid.bv_len
+ STRLENOF("#") + 1 );
if ( tmp == NULL ) {
ber_memfree_x( normalized->bv_val, ctx );
return LDAP_OTHER;
}
normalized->bv_val = tmp;
normalized->bv_val[normalized->bv_len++] = '#';
AC_MEMCPY( &normalized->bv_val[normalized->bv_len],
uid.bv_val, uid.bv_len );
normalized->bv_len += uid.bv_len;
normalized->bv_val[normalized->bv_len] = '\0';
}
slap_sl_free( out.bv_val, ctx );
}
return LDAP_SUCCESS;
}
static int
uniqueMemberMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
int match;
struct berval *asserted = (struct berval *) assertedValue;
struct berval assertedDN = *asserted;
struct berval assertedUID = BER_BVNULL;
struct berval valueDN = *value;
struct berval valueUID = BER_BVNULL;
int approx = ((flags & SLAP_MR_EQUALITY_APPROX) == SLAP_MR_EQUALITY_APPROX);
if ( !BER_BVISEMPTY( asserted ) ) {
assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
if ( !BER_BVISNULL( &assertedUID ) ) {
assertedUID.bv_val++;
assertedUID.bv_len = assertedDN.bv_len
- ( assertedUID.bv_val - assertedDN.bv_val );
if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
assertedDN.bv_len -= assertedUID.bv_len + 1;
} else {
BER_BVZERO( &assertedUID );
}
}
}
if ( !BER_BVISEMPTY( value ) ) {
valueUID.bv_val = strrchr( valueDN.bv_val, '#' );
if ( !BER_BVISNULL( &valueUID ) ) {
valueUID.bv_val++;
valueUID.bv_len = valueDN.bv_len
- ( valueUID.bv_val - valueDN.bv_val );
if ( bitStringValidate( NULL, &valueUID ) == LDAP_SUCCESS ) {
valueDN.bv_len -= valueUID.bv_len + 1;
} else {
BER_BVZERO( &valueUID );
}
}
}
if( valueUID.bv_len && assertedUID.bv_len ) {
ber_slen_t d;
d = (ber_slen_t) valueUID.bv_len - (ber_slen_t) assertedUID.bv_len;
if ( d ) {
*matchp = sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1;
return LDAP_SUCCESS;
}
match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len );
if( match ) {
*matchp = match;
return LDAP_SUCCESS;
}
} else if ( !approx && valueUID.bv_len ) {
match = -1;
*matchp = match;
return LDAP_SUCCESS;
} else if ( !approx && assertedUID.bv_len ) {
match = 1;
*matchp = match;
return LDAP_SUCCESS;
}
return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN );
}
static int
uniqueMemberIndexer(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
BerVarray values,
BerVarray *keysp,
void *ctx )
{
BerVarray dnvalues;
int rc;
int i;
for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
}
assert( i > 0 );
dnvalues = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
for( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
struct berval assertedDN = values[i];
struct berval assertedUID = BER_BVNULL;
if ( !BER_BVISEMPTY( &assertedDN ) ) {
assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
if ( !BER_BVISNULL( &assertedUID ) ) {
assertedUID.bv_val++;
assertedUID.bv_len = assertedDN.bv_len
- ( assertedUID.bv_val - assertedDN.bv_val );
if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
assertedDN.bv_len -= assertedUID.bv_len + 1;
} else {
BER_BVZERO( &assertedUID );
}
}
}
dnvalues[i] = assertedDN;
}
BER_BVZERO( &dnvalues[i] );
rc = octetStringIndexer( use, flags, syntax, mr, prefix,
dnvalues, keysp, ctx );
slap_sl_free( dnvalues, ctx );
return rc;
}
static int
uniqueMemberFilter(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
void * assertedValue,
BerVarray *keysp,
void *ctx )
{
struct berval *asserted = (struct berval *) assertedValue;
struct berval assertedDN = *asserted;
struct berval assertedUID = BER_BVNULL;
if ( !BER_BVISEMPTY( asserted ) ) {
assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' );
if ( !BER_BVISNULL( &assertedUID ) ) {
assertedUID.bv_val++;
assertedUID.bv_len = assertedDN.bv_len
- ( assertedUID.bv_val - assertedDN.bv_val );
if ( bitStringValidate( NULL, &assertedUID ) == LDAP_SUCCESS ) {
assertedDN.bv_len -= assertedUID.bv_len + 1;
} else {
BER_BVZERO( &assertedUID );
}
}
}
return octetStringFilter( use, flags, syntax, mr, prefix,
&assertedDN, keysp, ctx );
}
static int
booleanValidate(
Syntax *syntax,
struct berval *in )
{
if( in->bv_len == 4 ) {
if( bvmatch( in, &slap_true_bv ) ) {
return LDAP_SUCCESS;
}
} else if( in->bv_len == 5 ) {
if( bvmatch( in, &slap_false_bv ) ) {
return LDAP_SUCCESS;
}
}
return LDAP_INVALID_SYNTAX;
}
static int
booleanMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
struct berval *asserted = (struct berval *) assertedValue;
*matchp = (int) asserted->bv_len - (int) value->bv_len;
return LDAP_SUCCESS;
}
static int
UTF8StringValidate(
Syntax *syntax,
struct berval *in )
{
ber_len_t count;
int len;
unsigned char *u = (unsigned char *)in->bv_val;
if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
return LDAP_INVALID_SYNTAX;
}
for( count = in->bv_len; count > 0; count -= len, u += len ) {
len = LDAP_UTF8_CHARLEN2( u, len );
switch( len ) {
case 6:
if( (u[5] & 0xC0) != 0x80 ) {
return LDAP_INVALID_SYNTAX;
}
case 5:
if( (u[4] & 0xC0) != 0x80 ) {
return LDAP_INVALID_SYNTAX;
}
case 4:
if( (u[3] & 0xC0) != 0x80 ) {
return LDAP_INVALID_SYNTAX;
}
case 3:
if( (u[2] & 0xC0 )!= 0x80 ) {
return LDAP_INVALID_SYNTAX;
}
case 2:
if( (u[1] & 0xC0) != 0x80 ) {
return LDAP_INVALID_SYNTAX;
}
case 1:
break;
default:
return LDAP_INVALID_SYNTAX;
}
if( LDAP_UTF8_OFFSET( (char *)u ) != len ) return LDAP_INVALID_SYNTAX;
}
if( count != 0 ) {
return LDAP_INVALID_SYNTAX;
}
return LDAP_SUCCESS;
}
static int
UTF8StringNormalize(
slap_mask_t use,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
struct berval tmp, nvalue;
int flags, wasspace;
ber_len_t i;
assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
if( BER_BVISNULL( val ) ) {
BER_BVZERO( normalized );
return LDAP_SUCCESS;
}
flags = SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseExactMatch )
? LDAP_UTF8_NOCASEFOLD : LDAP_UTF8_CASEFOLD;
flags |= ( ( use & SLAP_MR_EQUALITY_APPROX ) == SLAP_MR_EQUALITY_APPROX )
? LDAP_UTF8_APPROX : 0;
val = UTF8bvnormalize( val, &tmp, flags, ctx );
if( val == NULL ) {
return LDAP_INVALID_SYNTAX;
}
nvalue.bv_len = 0;
nvalue.bv_val = tmp.bv_val;
wasspace = !((( use & SLAP_MR_SUBSTR_ANY ) == SLAP_MR_SUBSTR_ANY ) ||
(( use & SLAP_MR_SUBSTR_FINAL ) == SLAP_MR_SUBSTR_FINAL ));
for( i = 0; i < tmp.bv_len; i++) {
if ( ASCII_SPACE( tmp.bv_val[i] )) {
if( wasspace++ == 0 ) {
nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
}
} else {
wasspace = 0;
nvalue.bv_val[nvalue.bv_len++] = tmp.bv_val[i];
}
}
if( !BER_BVISEMPTY( &nvalue ) ) {
if( wasspace && (
(( use & SLAP_MR_SUBSTR_INITIAL ) != SLAP_MR_SUBSTR_INITIAL ) &&
( use & SLAP_MR_SUBSTR_ANY ) != SLAP_MR_SUBSTR_ANY ))
{
--nvalue.bv_len;
}
nvalue.bv_val[nvalue.bv_len] = '\0';
} else if ( tmp.bv_len ) {
nvalue.bv_val[0] = ' ';
nvalue.bv_val[1] = '\0';
nvalue.bv_len = 1;
}
*normalized = nvalue;
return LDAP_SUCCESS;
}
static int
directoryStringSubstringsMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
int match = 0;
SubstringsAssertion *sub = assertedValue;
struct berval left = *value;
ber_len_t i;
int priorspace=0;
if ( !BER_BVISNULL( &sub->sa_initial ) ) {
if ( sub->sa_initial.bv_len > left.bv_len ) {
match = 1;
goto done;
}
match = memcmp( sub->sa_initial.bv_val, left.bv_val,
sub->sa_initial.bv_len );
if ( match != 0 ) {
goto done;
}
left.bv_val += sub->sa_initial.bv_len;
left.bv_len -= sub->sa_initial.bv_len;
priorspace = ASCII_SPACE(
sub->sa_initial.bv_val[sub->sa_initial.bv_len] );
}
if ( sub->sa_any ) {
for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) {
ber_len_t idx;
char *p;
if( priorspace && !BER_BVISEMPTY( &sub->sa_any[i] )
&& ASCII_SPACE( sub->sa_any[i].bv_val[0] ))
{
left.bv_val--;
left.bv_len++;
}
priorspace=0;
retry:
if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) {
continue;
}
if ( sub->sa_any[i].bv_len > left.bv_len ) {
match = 1;
goto done;
}
p = memchr( left.bv_val, *sub->sa_any[i].bv_val, left.bv_len );
if( p == NULL ) {
match = 1;
goto done;
}
idx = p - left.bv_val;
if ( idx >= left.bv_len ) {
return LDAP_OTHER;
}
left.bv_val = p;
left.bv_len -= idx;
if ( sub->sa_any[i].bv_len > left.bv_len ) {
match = 1;
goto done;
}
match = memcmp( left.bv_val,
sub->sa_any[i].bv_val,
sub->sa_any[i].bv_len );
if ( match != 0 ) {
left.bv_val++;
left.bv_len--;
goto retry;
}
left.bv_val += sub->sa_any[i].bv_len;
left.bv_len -= sub->sa_any[i].bv_len;
priorspace = ASCII_SPACE(
sub->sa_any[i].bv_val[sub->sa_any[i].bv_len] );
}
}
if ( !BER_BVISNULL( &sub->sa_final ) ) {
if( priorspace && !BER_BVISEMPTY( &sub->sa_final )
&& ASCII_SPACE( sub->sa_final.bv_val[0] ))
{
left.bv_val--;
left.bv_len++;
}
if ( sub->sa_final.bv_len > left.bv_len ) {
match = 1;
goto done;
}
match = memcmp( sub->sa_final.bv_val,
&left.bv_val[left.bv_len - sub->sa_final.bv_len],
sub->sa_final.bv_len );
if ( match != 0 ) {
goto done;
}
}
done:
*matchp = match;
return LDAP_SUCCESS;
}
#if defined(SLAPD_APPROX_INITIALS)
# define SLAPD_APPROX_DELIMITER "._ "
# define SLAPD_APPROX_WORDLEN 2
#else
# define SLAPD_APPROX_DELIMITER " "
# define SLAPD_APPROX_WORDLEN 1
#endif
static int
approxMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
struct berval *nval, *assertv;
char *val, **values, **words, *c;
int i, count, len, nextchunk=0, nextavail=0;
nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL );
if( nval == NULL ) {
*matchp = 1;
return LDAP_SUCCESS;
}
assertv = UTF8bvnormalize( ((struct berval *)assertedValue),
NULL, LDAP_UTF8_APPROX, NULL );
if( assertv == NULL ) {
ber_bvfree( nval );
*matchp = 1;
return LDAP_SUCCESS;
}
for ( c = nval->bv_val, count = 1; *c; c++ ) {
c = strpbrk( c, SLAPD_APPROX_DELIMITER );
if ( c == NULL ) break;
*c = '\0';
count++;
}
words = (char **)ch_malloc( count * sizeof(char *) );
values = (char **)ch_malloc( count * sizeof(char *) );
for ( c = nval->bv_val, i = 0; i < count; i++, c += strlen(c) + 1 ) {
words[i] = c;
values[i] = phonetic(c);
}
len = 0;
while ( (ber_len_t) nextchunk < assertv->bv_len ) {
len = strcspn( assertv->bv_val + nextchunk, SLAPD_APPROX_DELIMITER);
if( len == 0 ) {
nextchunk++;
continue;
}
#if defined(SLAPD_APPROX_INITIALS)
else if( len == 1 ) {
for( i=nextavail; i<count; i++ )
if( !strncasecmp( assertv->bv_val + nextchunk, words[i], 1 )) {
nextavail=i+1;
break;
}
}
#endif
else {
assertv->bv_val[nextchunk+len] = '\0';
val = phonetic( assertv->bv_val + nextchunk );
for( i=nextavail; i<count; i++ ){
if( !strcmp( val, values[i] ) ){
nextavail = i+1;
break;
}
}
ch_free( val );
}
if( i >= count ) {
nextavail=-1;
break;
}
nextchunk += len+1;
}
if( nextavail > 0 ) {
*matchp = 0;
}
else {
*matchp = 1;
}
ber_bvfree( assertv );
for( i=0; i<count; i++ ) {
ch_free( values[i] );
}
ch_free( values );
ch_free( words );
ber_bvfree( nval );
return LDAP_SUCCESS;
}
static int
approxIndexer(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
BerVarray values,
BerVarray *keysp,
void *ctx )
{
char *c;
int i,j, len, wordcount, keycount=0;
struct berval *newkeys;
BerVarray keys=NULL;
for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) {
struct berval val = BER_BVNULL;
UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL );
assert( !BER_BVISNULL( &val ) );
for( wordcount = 0, c = val.bv_val; *c; c++) {
len = strcspn(c, SLAPD_APPROX_DELIMITER);
if( len >= SLAPD_APPROX_WORDLEN ) wordcount++;
c+= len;
if (*c == '\0') break;
*c = '\0';
}
newkeys = (struct berval *)ch_malloc( (keycount + wordcount + 1)
* sizeof(struct berval) );
AC_MEMCPY( newkeys, keys, keycount * sizeof(struct berval) );
if( keys ) ch_free( keys );
keys = newkeys;
for( c = val.bv_val, i = 0; i < wordcount; c += len + 1 ) {
len = strlen( c );
if( len < SLAPD_APPROX_WORDLEN ) continue;
ber_str2bv( phonetic( c ), 0, 0, &keys[keycount] );
keycount++;
i++;
}
ber_memfree( val.bv_val );
}
BER_BVZERO( &keys[keycount] );
*keysp = keys;
return LDAP_SUCCESS;
}
static int
approxFilter(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
void * assertedValue,
BerVarray *keysp,
void *ctx )
{
char *c;
int i, count, len;
struct berval *val;
BerVarray keys;
val = UTF8bvnormalize( ((struct berval *)assertedValue),
NULL, LDAP_UTF8_APPROX, NULL );
if( val == NULL || BER_BVISNULL( val ) ) {
keys = (struct berval *)ch_malloc( sizeof(struct berval) );
BER_BVZERO( &keys[0] );
*keysp = keys;
ber_bvfree( val );
return LDAP_SUCCESS;
}
for( count = 0,c = val->bv_val; *c; c++) {
len = strcspn(c, SLAPD_APPROX_DELIMITER);
if( len >= SLAPD_APPROX_WORDLEN ) count++;
c+= len;
if (*c == '\0') break;
*c = '\0';
}
keys = (struct berval *)ch_malloc( (count + 1) * sizeof(struct berval) );
for( c = val->bv_val, i = 0; i < count; c += len + 1 ) {
len = strlen(c);
if( len < SLAPD_APPROX_WORDLEN ) continue;
ber_str2bv( phonetic( c ), 0, 0, &keys[i] );
i++;
}
ber_bvfree( val );
BER_BVZERO( &keys[count] );
*keysp = keys;
return LDAP_SUCCESS;
}
static int
telephoneNumberNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
char *p, *q;
assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
assert( !BER_BVISEMPTY( val ) );
q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
for( p = val->bv_val; *p; p++ ) {
if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) {
*q++ = *p;
}
}
*q = '\0';
normalized->bv_len = q - normalized->bv_val;
if( BER_BVISEMPTY( normalized ) ) {
slap_sl_free( normalized->bv_val, ctx );
BER_BVZERO( normalized );
return LDAP_INVALID_SYNTAX;
}
return LDAP_SUCCESS;
}
static int
postalAddressValidate(
Syntax *syntax,
struct berval *in )
{
struct berval bv = *in;
ber_len_t c;
for ( c = 0; c < in->bv_len; c++ ) {
if ( in->bv_val[c] == '\\' ) {
c++;
if ( strncasecmp( &in->bv_val[c], "24", STRLENOF( "24" ) ) != 0
&& strncasecmp( &in->bv_val[c], "5C", STRLENOF( "5C" ) ) != 0 )
{
return LDAP_INVALID_SYNTAX;
}
continue;
}
if ( in->bv_val[c] == '$' ) {
bv.bv_len = &in->bv_val[c] - bv.bv_val;
if ( UTF8StringValidate( NULL, &bv ) != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
bv.bv_val = &in->bv_val[c] + 1;
}
}
bv.bv_len = &in->bv_val[c] - bv.bv_val;
return UTF8StringValidate( NULL, &bv );
}
static int
postalAddressNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
BerVarray lines = NULL, nlines = NULL;
ber_len_t l, c;
int rc = LDAP_SUCCESS;
MatchingRule *xmr = NULL;
char *p;
if ( SLAP_MR_ASSOCIATED( mr, slap_schema.si_mr_caseIgnoreListMatch ) ) {
xmr = slap_schema.si_mr_caseIgnoreMatch;
} else {
xmr = slap_schema.si_mr_caseExactMatch;
}
for ( l = 0, c = 0; c < val->bv_len; c++ ) {
if ( val->bv_val[c] == '$' ) {
l++;
}
}
lines = slap_sl_calloc( sizeof( struct berval ), 2 * ( l + 2 ), ctx );
nlines = &lines[l + 2];
lines[0].bv_val = val->bv_val;
for ( l = 0, c = 0; c < val->bv_len; c++ ) {
if ( val->bv_val[c] == '$' ) {
lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
l++;
lines[l].bv_val = &val->bv_val[c + 1];
}
}
lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
normalized->bv_len = c = l;
for ( l = 0; l <= c; l++ ) {
if ( !lines[l].bv_len ) {
nlines[l].bv_len = 0;
nlines[l].bv_val = NULL;
continue;
}
rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
if ( rc != LDAP_SUCCESS ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
normalized->bv_len += nlines[l].bv_len;
}
normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
p = normalized->bv_val;
for ( l = 0; l <= c ; l++ ) {
p = lutil_strbvcopy( p, &nlines[l] );
*p++ = '$';
}
*--p = '\0';
assert( p == &normalized->bv_val[normalized->bv_len] );
done:;
if ( nlines != NULL ) {
for ( l = 0; !BER_BVISNULL( &nlines[ l ] ); l++ ) {
slap_sl_free( nlines[l].bv_val, ctx );
}
slap_sl_free( lines, ctx );
}
return rc;
}
int
numericoidValidate(
Syntax *syntax,
struct berval *in )
{
struct berval val = *in;
if( BER_BVISEMPTY( &val ) ) {
return LDAP_INVALID_SYNTAX;
}
while( OID_LEADCHAR( val.bv_val[0] ) ) {
if ( val.bv_len == 1 ) {
return LDAP_SUCCESS;
}
if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) {
break;
}
val.bv_val++;
val.bv_len--;
while ( OID_LEADCHAR( val.bv_val[0] )) {
val.bv_val++;
val.bv_len--;
if ( val.bv_len == 0 ) {
return LDAP_SUCCESS;
}
}
if( !OID_SEPARATOR( val.bv_val[0] )) {
break;
}
val.bv_val++;
val.bv_len--;
}
return LDAP_INVALID_SYNTAX;
}
static int
integerValidate(
Syntax *syntax,
struct berval *in )
{
ber_len_t i;
struct berval val = *in;
if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX;
if ( val.bv_val[0] == '-' ) {
val.bv_len--;
val.bv_val++;
if( BER_BVISEMPTY( &val ) ) {
return LDAP_INVALID_SYNTAX;
}
if( val.bv_val[0] == '0' ) {
return LDAP_INVALID_SYNTAX;
}
} else if ( val.bv_val[0] == '0' ) {
if( val.bv_len > 1 ) {
return LDAP_INVALID_SYNTAX;
}
return LDAP_SUCCESS;
}
for( i=0; i < val.bv_len; i++ ) {
if( !ASCII_DIGIT(val.bv_val[i]) ) {
return LDAP_INVALID_SYNTAX;
}
}
return LDAP_SUCCESS;
}
static int
integerMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
struct berval *asserted = (struct berval *) assertedValue;
int vsign = 1, asign = 1;
struct berval v, a;
int match;
v = *value;
if( v.bv_val[0] == '-' ) {
vsign = -1;
v.bv_val++;
v.bv_len--;
}
if( BER_BVISEMPTY( &v ) ) vsign = 0;
a = *asserted;
if( a.bv_val[0] == '-' ) {
asign = -1;
a.bv_val++;
a.bv_len--;
}
if( BER_BVISEMPTY( &a ) ) vsign = 0;
match = vsign - asign;
if( match == 0 ) {
match = ( v.bv_len != a.bv_len
? ( v.bv_len < a.bv_len ? -1 : 1 )
: memcmp( v.bv_val, a.bv_val, v.bv_len ));
if( vsign < 0 ) match = -match;
}
if ( (flags & SLAP_MR_EXT) && (mr->smr_usage & SLAP_MR_ORDERING) )
match = (match >= 0);
*matchp = match;
return LDAP_SUCCESS;
}
#define INDEX_INTLEN_CHOP 7
#define INDEX_INTLEN_CHOPBYTES 3
static int
integerVal2Key(
struct berval *in,
struct berval *key,
struct berval *tmp,
void *ctx )
{
ber_slen_t k = index_intlen_strlen;
ber_len_t chop = 0;
unsigned signmask = ~0x7fU;
unsigned char lenbuf[sizeof(k) + 2], *lenp, neg = 0xff;
struct berval val = *in, itmp = *tmp;
if ( val.bv_val[0] != '-' ) {
neg = 0;
--k;
}
if ( val.bv_len > (ber_len_t) k ) {
chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP;
val.bv_len -= chop * INDEX_INTLEN_CHOP;
chop *= INDEX_INTLEN_CHOPBYTES;
}
if ( lutil_str2bin( &val, &itmp, ctx )) {
return LDAP_INVALID_SYNTAX;
}
if ( itmp.bv_val[0] == neg ) {
itmp.bv_val++;
itmp.bv_len--;
}
k = (ber_slen_t) index_intlen - (ber_slen_t) (itmp.bv_len + chop);
if ( k > 0 ) {
assert( chop == 0 );
memset( key->bv_val, neg, k );
} else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
lenp = lenbuf + sizeof(lenbuf);
chop = - (ber_len_t) k;
do {
*--lenp = ((unsigned char) chop & 0xff) ^ neg;
signmask >>= 1;
} while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
k = (lenbuf + sizeof(lenbuf)) - lenp;
if ( k > (ber_slen_t) index_intlen )
k = index_intlen;
memcpy( key->bv_val, lenp, k );
itmp.bv_len = index_intlen - k;
}
memcpy( key->bv_val + k, itmp.bv_val, itmp.bv_len );
key->bv_val[0] ^= (unsigned char) signmask & 0xff;
return 0;
}
static int
integerIndexer(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
BerVarray values,
BerVarray *keysp,
void *ctx )
{
char ibuf[64];
struct berval itmp;
BerVarray keys;
ber_len_t vlen;
int i, rc;
unsigned maxstrlen = index_intlen_strlen + INDEX_INTLEN_CHOP-1;
vlen = 0;
for( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
if ( vlen < values[i].bv_len )
vlen = values[i].bv_len;
}
if ( vlen > maxstrlen )
vlen = maxstrlen;
assert( i > 0 );
keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) {
keys[i].bv_len = index_intlen;
keys[i].bv_val = slap_sl_malloc( index_intlen, ctx );
}
keys[i].bv_len = 0;
keys[i].bv_val = NULL;
if ( vlen > sizeof(ibuf) ) {
itmp.bv_val = slap_sl_malloc( vlen, ctx );
} else {
itmp.bv_val = ibuf;
}
itmp.bv_len = sizeof(ibuf);
for ( i=0; !BER_BVISNULL( &values[i] ); i++ ) {
if ( itmp.bv_val != ibuf ) {
itmp.bv_len = values[i].bv_len;
if ( itmp.bv_len <= sizeof(ibuf) )
itmp.bv_len = sizeof(ibuf);
else if ( itmp.bv_len > maxstrlen )
itmp.bv_len = maxstrlen;
}
rc = integerVal2Key( &values[i], &keys[i], &itmp, ctx );
if ( rc )
goto func_leave;
}
*keysp = keys;
func_leave:
if ( itmp.bv_val != ibuf ) {
slap_sl_free( itmp.bv_val, ctx );
}
return rc;
}
static int
integerFilter(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
void * assertedValue,
BerVarray *keysp,
void *ctx )
{
char ibuf[64];
struct berval iv;
BerVarray keys;
struct berval *value;
int rc;
value = (struct berval *) assertedValue;
keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
keys[0].bv_len = index_intlen;
keys[0].bv_val = slap_sl_malloc( index_intlen, ctx );
keys[1].bv_len = 0;
keys[1].bv_val = NULL;
iv.bv_len = value->bv_len < index_intlen_strlen + INDEX_INTLEN_CHOP-1
? value->bv_len : index_intlen_strlen + INDEX_INTLEN_CHOP-1;
if ( iv.bv_len > (int) sizeof(ibuf) ) {
iv.bv_val = slap_sl_malloc( iv.bv_len, ctx );
} else {
iv.bv_val = ibuf;
iv.bv_len = sizeof(ibuf);
}
rc = integerVal2Key( value, keys, &iv, ctx );
if ( rc == 0 )
*keysp = keys;
if ( iv.bv_val != ibuf ) {
slap_sl_free( iv.bv_val, ctx );
}
return rc;
}
static int
countryStringValidate(
Syntax *syntax,
struct berval *val )
{
if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX;
if( !SLAP_PRINTABLE(val->bv_val[0]) ) {
return LDAP_INVALID_SYNTAX;
}
if( !SLAP_PRINTABLE(val->bv_val[1]) ) {
return LDAP_INVALID_SYNTAX;
}
return LDAP_SUCCESS;
}
static int
printableStringValidate(
Syntax *syntax,
struct berval *val )
{
ber_len_t i;
if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
for(i=0; i < val->bv_len; i++) {
if( !SLAP_PRINTABLE(val->bv_val[i]) ) {
return LDAP_INVALID_SYNTAX;
}
}
return LDAP_SUCCESS;
}
static int
printablesStringValidate(
Syntax *syntax,
struct berval *val )
{
ber_len_t i, len;
if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX;
for(i=0,len=0; i < val->bv_len; i++) {
int c = val->bv_val[i];
if( c == '$' ) {
if( len == 0 ) {
return LDAP_INVALID_SYNTAX;
}
len = 0;
} else if ( SLAP_PRINTABLE(c) ) {
len++;
} else {
return LDAP_INVALID_SYNTAX;
}
}
if( len == 0 ) {
return LDAP_INVALID_SYNTAX;
}
return LDAP_SUCCESS;
}
static int
IA5StringValidate(
Syntax *syntax,
struct berval *val )
{
ber_len_t i;
for(i=0; i < val->bv_len; i++) {
if( !LDAP_ASCII(val->bv_val[i]) ) {
return LDAP_INVALID_SYNTAX;
}
}
return LDAP_SUCCESS;
}
static int
IA5StringNormalize(
slap_mask_t use,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
char *p, *q;
int casefold = !SLAP_MR_ASSOCIATED( mr,
slap_schema.si_mr_caseExactIA5Match );
assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 );
p = val->bv_val;
while ( ASCII_SPACE( *p ) ) p++;
normalized->bv_len = val->bv_len - ( p - val->bv_val );
normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
AC_MEMCPY( normalized->bv_val, p, normalized->bv_len );
normalized->bv_val[normalized->bv_len] = '\0';
p = q = normalized->bv_val;
while ( *p ) {
if ( ASCII_SPACE( *p ) ) {
*q++ = *p++;
while ( ASCII_SPACE( *p ) ) {
p++;
}
} else if ( casefold ) {
*q++ = TOLOWER(*p); p++;
} else {
*q++ = *p++;
}
}
assert( normalized->bv_val <= p );
assert( q <= p );
if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q;
*q = '\0';
normalized->bv_len = q - normalized->bv_val;
return LDAP_SUCCESS;
}
static int
UUIDValidate(
Syntax *syntax,
struct berval *in )
{
int i;
if( in->bv_len != 36 ) {
return LDAP_INVALID_SYNTAX;
}
for( i=0; i<36; i++ ) {
switch(i) {
case 8:
case 13:
case 18:
case 23:
if( in->bv_val[i] != '-' ) {
return LDAP_INVALID_SYNTAX;
}
break;
default:
if( !ASCII_HEX( in->bv_val[i]) ) {
return LDAP_INVALID_SYNTAX;
}
}
}
return LDAP_SUCCESS;
}
static int
UUIDPretty(
Syntax *syntax,
struct berval *in,
struct berval *out,
void *ctx )
{
int i;
int rc=LDAP_INVALID_SYNTAX;
assert( in != NULL );
assert( out != NULL );
if( in->bv_len != 36 ) return LDAP_INVALID_SYNTAX;
out->bv_len = 36;
out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
for( i=0; i<36; i++ ) {
switch(i) {
case 8:
case 13:
case 18:
case 23:
if( in->bv_val[i] != '-' ) {
goto handle_error;
}
out->bv_val[i] = '-';
break;
default:
if( !ASCII_HEX( in->bv_val[i]) ) {
goto handle_error;
}
out->bv_val[i] = TOLOWER( in->bv_val[i] );
}
}
rc = LDAP_SUCCESS;
out->bv_val[ out->bv_len ] = '\0';
if( 0 ) {
handle_error:
slap_sl_free( out->bv_val, ctx );
out->bv_val = NULL;
}
return rc;
}
int
UUIDNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
unsigned char octet = '\0';
int i;
int j;
if ( SLAP_MR_IS_DENORMALIZE( usage ) ) {
assert( val->bv_len == 16 );
normalized->bv_val = slap_sl_malloc( LDAP_LUTIL_UUIDSTR_BUFSIZE, ctx );
normalized->bv_len = lutil_uuidstr_from_normalized( val->bv_val,
val->bv_len, normalized->bv_val, LDAP_LUTIL_UUIDSTR_BUFSIZE );
assert( normalized->bv_len == STRLENOF( "BADBADBA-DBAD-0123-4567-BADBADBADBAD" ) );
return LDAP_SUCCESS;
}
normalized->bv_len = 16;
normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
for( i=0, j=0; i<36; i++ ) {
unsigned char nibble;
if( val->bv_val[i] == '-' ) {
continue;
} else if( ASCII_DIGIT( val->bv_val[i] ) ) {
nibble = val->bv_val[i] - '0';
} else if( ASCII_HEXLOWER( val->bv_val[i] ) ) {
nibble = val->bv_val[i] - ('a'-10);
} else if( ASCII_HEXUPPER( val->bv_val[i] ) ) {
nibble = val->bv_val[i] - ('A'-10);
} else {
slap_sl_free( normalized->bv_val, ctx );
BER_BVZERO( normalized );
return LDAP_INVALID_SYNTAX;
}
if( j & 1 ) {
octet |= nibble;
normalized->bv_val[j>>1] = octet;
} else {
octet = nibble << 4;
}
j++;
}
normalized->bv_val[normalized->bv_len] = 0;
return LDAP_SUCCESS;
}
int
numericStringValidate(
Syntax *syntax,
struct berval *in )
{
ber_len_t i;
if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX;
for(i=0; i < in->bv_len; i++) {
if( !SLAP_NUMERIC(in->bv_val[i]) ) {
return LDAP_INVALID_SYNTAX;
}
}
return LDAP_SUCCESS;
}
static int
numericStringNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
char *p, *q;
assert( !BER_BVISEMPTY( val ) );
normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx );
p = val->bv_val;
q = normalized->bv_val;
while ( *p ) {
if ( ASCII_SPACE( *p ) ) {
p++;
} else {
*q++ = *p++;
}
}
assert( (q - normalized->bv_val) <= (p - val->bv_val) );
*q = '\0';
normalized->bv_len = q - normalized->bv_val;
if( BER_BVISEMPTY( normalized ) ) {
normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx );
normalized->bv_val[0] = ' ';
normalized->bv_val[1] = '\0';
normalized->bv_len = 1;
}
return LDAP_SUCCESS;
}
#if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG)
# define SLAP_STRTOL(n,e,b) strtoll(n,e,b)
# define SLAP_LONG long long
#else
# define SLAP_STRTOL(n,e,b) strtol(n,e,b)
# define SLAP_LONG long
#endif
static int
integerBitAndMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
SLAP_LONG lValue, lAssertedValue;
errno = 0;
lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
if( errno == ERANGE )
{
return LDAP_CONSTRAINT_VIOLATION;
}
lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val,
NULL, 10);
if( errno == ERANGE )
{
return LDAP_CONSTRAINT_VIOLATION;
}
*matchp = ((lValue & lAssertedValue) == lAssertedValue) ? 0 : 1;
return LDAP_SUCCESS;
}
static int
integerBitOrMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
SLAP_LONG lValue, lAssertedValue;
errno = 0;
lValue = SLAP_STRTOL(value->bv_val, NULL, 10);
if( errno == ERANGE )
{
return LDAP_CONSTRAINT_VIOLATION;
}
lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val,
NULL, 10);
if( errno == ERANGE )
{
return LDAP_CONSTRAINT_VIOLATION;
}
*matchp = ((lValue & lAssertedValue) != 0) ? 0 : -1;
return LDAP_SUCCESS;
}
static int
checkNum( struct berval *in, struct berval *out )
{
ber_len_t neg = 0, extra = 0;
char first = '\0';
out->bv_val = in->bv_val;
out->bv_len = 0;
if ( out->bv_val[0] == '-' ) {
neg++;
out->bv_len++;
}
if ( strncasecmp( out->bv_val, "0x", STRLENOF("0x") ) == 0 ) {
first = out->bv_val[2];
extra = 2;
out->bv_len += STRLENOF("0x");
for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
}
} else if ( out->bv_val[0] == '\'' ) {
first = out->bv_val[1];
extra = 3;
out->bv_len += STRLENOF("'");
for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
if ( !ASCII_HEX( out->bv_val[out->bv_len] ) ) break;
}
if ( strncmp( &out->bv_val[out->bv_len], "'H", STRLENOF("'H") ) != 0 ) {
return -1;
}
out->bv_len += STRLENOF("'H");
} else {
first = out->bv_val[0];
for ( ; out->bv_len < in->bv_len; out->bv_len++ ) {
if ( !ASCII_DIGIT( out->bv_val[out->bv_len] ) ) break;
}
}
if ( !( out->bv_len > neg ) ) {
return -1;
}
if ( ( out->bv_len > extra + 1 + neg ) && ( first == '0' ) ) {
return -1;
}
return 0;
}
static int
serialNumberAndIssuerCheck(
struct berval *in,
struct berval *sn,
struct berval *is,
void *ctx )
{
ber_len_t n;
if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
is->bv_val = ber_bvchr( in, '$' );
if( BER_BVISNULL( is ) ) return LDAP_INVALID_SYNTAX;
sn->bv_val = in->bv_val;
sn->bv_len = is->bv_val - in->bv_val;
is->bv_val++;
is->bv_len = in->bv_len - (sn->bv_len + 1);
for( n=0; n < (sn->bv_len-1); n++ ) {
if( sn->bv_val[n] != '0' ) break;
}
sn->bv_val += n;
sn->bv_len -= n;
for( n=0; n < sn->bv_len; n++ ) {
if( !ASCII_DIGIT(sn->bv_val[n]) ) return LDAP_INVALID_SYNTAX;
}
} else {
enum {
HAVE_NONE = 0x0,
HAVE_ISSUER = 0x1,
HAVE_SN = 0x2,
HAVE_ALL = ( HAVE_ISSUER | HAVE_SN )
} have = HAVE_NONE;
int numdquotes = 0;
struct berval x = *in;
struct berval ni;
x.bv_val++;
x.bv_len -= 2;
do {
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
x.bv_val += STRLENOF("issuer");
x.bv_len -= STRLENOF("issuer");
if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) == 0 ) {
x.bv_val += STRLENOF("rdnSequence:");
x.bv_len -= STRLENOF("rdnSequence:");
}
if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
is->bv_val = x.bv_val;
is->bv_len = 0;
for ( ; is->bv_len < x.bv_len; ) {
if ( is->bv_val[is->bv_len] != '"' ) {
is->bv_len++;
continue;
}
if ( is->bv_val[is->bv_len+1] == '"' ) {
is->bv_len += 2;
continue;
}
break;
}
x.bv_val += is->bv_len + 1;
x.bv_len -= is->bv_len + 1;
have |= HAVE_ISSUER;
} else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 )
{
if ( have & HAVE_SN ) return LDAP_INVALID_SYNTAX;
x.bv_val += STRLENOF("serialNumber");
x.bv_len -= STRLENOF("serialNumber");
if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( checkNum( &x, sn ) ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val += sn->bv_len;
x.bv_len -= sn->bv_len;
have |= HAVE_SN;
} else {
return LDAP_INVALID_SYNTAX;
}
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( have == HAVE_ALL ) {
break;
}
if ( x.bv_val[0] != ',' ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val++;
x.bv_len--;
} while ( 1 );
if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
if ( numdquotes == 0 ) {
ber_dupbv_x( &ni, is, ctx );
} else {
ber_len_t src, dst;
ni.bv_len = is->bv_len - numdquotes;
ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
if ( is->bv_val[src] == '"' ) {
src++;
}
ni.bv_val[dst] = is->bv_val[src];
}
ni.bv_val[dst] = '\0';
}
*is = ni;
}
return 0;
}
static int
serialNumberAndIssuerValidate(
Syntax *syntax,
struct berval *in )
{
int rc;
struct berval sn, i;
Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerValidate: <%s>\n",
in->bv_val, 0, 0 );
rc = serialNumberAndIssuerCheck( in, &sn, &i, NULL );
if ( rc ) {
goto done;
}
rc = dnValidate( NULL, &i );
if ( rc ) {
rc = LDAP_INVALID_SYNTAX;
}
if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, NULL );
}
Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerValidate: <%s> err=%d\n",
in->bv_val, rc, 0 );
done:;
return rc;
}
static int
serialNumberAndIssuerPretty(
Syntax *syntax,
struct berval *in,
struct berval *out,
void *ctx )
{
int rc;
struct berval sn, i, ni = BER_BVNULL;
char *p;
assert( in != NULL );
assert( out != NULL );
BER_BVZERO( out );
Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n",
in->bv_val, 0, 0 );
rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
if ( rc ) {
goto done;
}
rc = dnPretty( syntax, &i, &ni, ctx );
if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, ctx );
}
if ( rc ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
out->bv_len = STRLENOF("{ serialNumber , issuer rdnSequence:\"\" }")
+ sn.bv_len + ni.bv_len;
out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
if ( out->bv_val == NULL ) {
out->bv_len = 0;
rc = LDAP_OTHER;
goto done;
}
p = out->bv_val;
p = lutil_strcopy( p, "{ serialNumber " );
p = lutil_strbvcopy( p, &sn );
p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, "\" }" );
assert( p == &out->bv_val[out->bv_len] );
done:;
Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s> => <%s>\n",
in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
slap_sl_free( ni.bv_val, ctx );
return LDAP_SUCCESS;
}
static int
slap_bin2hex(
struct berval *in,
struct berval *out,
void *ctx )
{
unsigned char *ptr, zero = '\0';
char *sptr;
int first;
ber_len_t i, len, nlen;
assert( in != NULL );
assert( !BER_BVISNULL( in ) );
assert( out != NULL );
assert( !BER_BVISNULL( out ) );
ptr = (unsigned char *)in->bv_val;
len = in->bv_len;
if ( len > 1 ) {
if ( ptr[0] & 0x80 ) {
if ( ( ptr[0] == 0xff ) && ( ptr[1] & 0x80 ) ) {
return -1;
}
} else if ( ptr[0] == 0 ) {
if ( !( ptr[1] & 0x80 ) ) {
return -1;
}
len--;
ptr++;
}
} else if ( len == 0 ) {
len = 1;
ptr = &zero;
}
first = !( ptr[0] & 0xf0U );
nlen = len * 2 - first + STRLENOF("''H");
if ( nlen >= out->bv_len ) {
out->bv_val = slap_sl_malloc( nlen + 1, ctx );
}
sptr = out->bv_val;
*sptr++ = '\'';
i = 0;
if ( first ) {
sprintf( sptr, "%01X", ( ptr[0] & 0x0fU ) );
sptr++;
i = 1;
}
for ( ; i < len; i++ ) {
sprintf( sptr, "%02X", ptr[i] );
sptr += 2;
}
*sptr++ = '\'';
*sptr++ = 'H';
*sptr = '\0';
assert( sptr == &out->bv_val[nlen] );
out->bv_len = nlen;
return 0;
}
#define SLAP_SN_BUFLEN (64)
static int
serialNumberAndIssuerNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *in,
struct berval *out,
void *ctx )
{
struct berval sn, sn2, sn3, i, ni;
char sbuf2[SLAP_SN_BUFLEN];
char sbuf3[SLAP_SN_BUFLEN];
char *p;
int rc;
assert( in != NULL );
assert( out != NULL );
Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n",
in->bv_val, 0, 0 );
rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx );
if ( rc ) {
return rc;
}
rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, ctx );
}
if ( rc ) {
return LDAP_INVALID_SYNTAX;
}
sn2.bv_val = sbuf2;
if ( sn.bv_len > sizeof( sbuf2 ) ) {
sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
}
sn2.bv_len = sn.bv_len;
sn3.bv_val = sbuf3;
sn3.bv_len = sizeof(sbuf3);
if ( lutil_str2bin( &sn, &sn2, ctx ) || slap_bin2hex( &sn2, &sn3, ctx ) ) {
rc = LDAP_INVALID_SYNTAX;
goto func_leave;
}
out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
+ sn3.bv_len + ni.bv_len;
out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
if ( out->bv_val == NULL ) {
out->bv_len = 0;
rc = LDAP_OTHER;
goto func_leave;
}
p = out->bv_val;
p = lutil_strcopy( p, "{ serialNumber " );
p = lutil_strbvcopy( p, &sn3 );
p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, "\" }" );
assert( p == &out->bv_val[out->bv_len] );
func_leave:
Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s> => <%s>\n",
in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
if ( sn2.bv_val != sbuf2 ) {
slap_sl_free( sn2.bv_val, ctx );
}
if ( sn3.bv_val != sbuf3 ) {
slap_sl_free( sn3.bv_val, ctx );
}
slap_sl_free( ni.bv_val, ctx );
return rc;
}
static int
certificateExactNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
ber_tag_t tag;
ber_len_t len;
ber_int_t i;
char serialbuf2[SLAP_SN_BUFLEN];
struct berval sn, sn2 = BER_BVNULL;
struct berval issuer_dn = BER_BVNULL, bvdn;
char *p;
int rc = LDAP_INVALID_SYNTAX;
assert( val != NULL );
Debug( LDAP_DEBUG_TRACE, ">>> certificateExactNormalize: <%p, %lu>\n",
val->bv_val, val->bv_len, 0 );
if ( BER_BVISEMPTY( val ) ) goto done;
if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
return serialNumberAndIssuerNormalize( 0, NULL, NULL, val, normalized, ctx );
}
assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
ber_init2( ber, val, LBER_USE_DER );
tag = ber_skip_tag( ber, &len );
tag = ber_skip_tag( ber, &len );
tag = ber_peek_tag( ber, &len );
if ( tag == SLAP_X509_OPT_C_VERSION ) {
tag = ber_skip_tag( ber, &len );
tag = ber_get_int( ber, &i );
}
tag = ber_skip_tag( ber, &len );
sn.bv_len = len;
sn.bv_val = (char *)ber->ber_ptr;
sn2.bv_val = serialbuf2;
sn2.bv_len = sizeof(serialbuf2);
if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
tag = ber_peek_tag( ber, &len );
len = ber_ptrlen( ber );
bvdn.bv_val = val->bv_val + len;
bvdn.bv_len = val->bv_len - len;
rc = dnX509normalize( &bvdn, &issuer_dn );
if ( rc != LDAP_SUCCESS ) goto done;
normalized->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
+ sn2.bv_len + issuer_dn.bv_len;
normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
p = normalized->bv_val;
p = lutil_strcopy( p, "{ serialNumber " );
p = lutil_strbvcopy( p, &sn2 );
p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
p = lutil_strbvcopy( p, &issuer_dn );
p = lutil_strcopy( p, "\" }" );
rc = LDAP_SUCCESS;
done:
Debug( LDAP_DEBUG_TRACE, "<<< certificateExactNormalize: <%p, %lu> => <%s>\n",
val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
if ( sn2.bv_val != serialbuf2 ) ber_memfree_x( sn2.bv_val, ctx );
return rc;
}
static int
checkTime( struct berval *in, struct berval *out )
{
int rc;
ber_len_t i;
char buf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
struct berval bv;
assert( in != NULL );
assert( !BER_BVISNULL( in ) );
assert( !BER_BVISEMPTY( in ) );
if ( in->bv_len < STRLENOF( "YYmmddHHMMSSZ" ) ) {
return -1;
}
if ( out != NULL ) {
assert( !BER_BVISNULL( out ) );
assert( out->bv_len >= sizeof( buf ) );
bv.bv_val = out->bv_val;
} else {
bv.bv_val = buf;
}
for ( i = 0; i < STRLENOF( "YYYYmmddHHMMSS" ); i++ ) {
if ( !ASCII_DIGIT( in->bv_val[i] ) ) break;
}
if ( in->bv_val[i] != 'Z' ) {
return -1;
}
i++;
if ( i != in->bv_len ) {
return -1;
}
if ( i == STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
lutil_strncopy( bv.bv_val, in->bv_val, i );
bv.bv_len = i;
} else if ( i == STRLENOF( "YYmmddHHMMSSZ" ) ) {
char *p = bv.bv_val;
if ( in->bv_val[0] < '7' ) {
p = lutil_strcopy( p, "20" );
} else {
p = lutil_strcopy( p, "19" );
}
lutil_strncopy( p, in->bv_val, i );
bv.bv_len = 2 + i;
} else {
return -1;
}
rc = generalizedTimeValidate( NULL, &bv );
if ( rc == LDAP_SUCCESS && out != NULL ) {
if ( out->bv_len > bv.bv_len ) {
out->bv_val[ bv.bv_len ] = '\0';
}
out->bv_len = bv.bv_len;
}
return rc != LDAP_SUCCESS;
}
static int
issuerAndThisUpdateCheck(
struct berval *in,
struct berval *is,
struct berval *tu,
void *ctx )
{
int numdquotes = 0;
struct berval x = *in;
struct berval ni = BER_BVNULL;
enum {
HAVE_NONE = 0x0,
HAVE_ISSUER = 0x1,
HAVE_THISUPDATE = 0x2,
HAVE_ALL = ( HAVE_ISSUER | HAVE_THISUPDATE )
} have = HAVE_NONE;
if ( in->bv_len < STRLENOF( "{issuer \"\",thisUpdate \"YYMMDDhhmmssZ\"}" ) ) return LDAP_INVALID_SYNTAX;
if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val++;
x.bv_len -= STRLENOF("{}");
do {
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
if ( have & HAVE_ISSUER ) return LDAP_INVALID_SYNTAX;
x.bv_val += STRLENOF("issuer");
x.bv_len -= STRLENOF("issuer");
if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:") ) != 0 ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val += STRLENOF("rdnSequence:");
x.bv_len -= STRLENOF("rdnSequence:");
if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
is->bv_val = x.bv_val;
is->bv_len = 0;
for ( ; is->bv_len < x.bv_len; ) {
if ( is->bv_val[is->bv_len] != '"' ) {
is->bv_len++;
continue;
}
if ( is->bv_val[is->bv_len+1] == '"' ) {
is->bv_len += 2;
continue;
}
break;
}
x.bv_val += is->bv_len + 1;
x.bv_len -= is->bv_len + 1;
have |= HAVE_ISSUER;
} else if ( strncasecmp( x.bv_val, "thisUpdate", STRLENOF("thisUpdate") ) == 0 )
{
if ( have & HAVE_THISUPDATE ) return LDAP_INVALID_SYNTAX;
x.bv_val += STRLENOF("thisUpdate");
x.bv_len -= STRLENOF("thisUpdate");
if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
tu->bv_val = x.bv_val;
tu->bv_len = 0;
for ( ; tu->bv_len < x.bv_len; tu->bv_len++ ) {
if ( tu->bv_val[tu->bv_len] == '"' ) {
break;
}
}
x.bv_val += tu->bv_len + 1;
x.bv_len -= tu->bv_len + 1;
have |= HAVE_THISUPDATE;
} else {
return LDAP_INVALID_SYNTAX;
}
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( have == HAVE_ALL ) {
break;
}
if ( x.bv_val[0] != ',' ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val++;
x.bv_len--;
} while ( 1 );
if ( x.bv_len ) return LDAP_INVALID_SYNTAX;
if ( numdquotes == 0 ) {
ber_dupbv_x( &ni, is, ctx );
} else {
ber_len_t src, dst;
ni.bv_len = is->bv_len - numdquotes;
ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
if ( is->bv_val[src] == '"' ) {
src++;
}
ni.bv_val[dst] = is->bv_val[src];
}
ni.bv_val[dst] = '\0';
}
*is = ni;
return 0;
}
static int
issuerAndThisUpdateValidate(
Syntax *syntax,
struct berval *in )
{
int rc;
struct berval i, tu;
Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateValidate: <%s>\n",
in->bv_val, 0, 0 );
rc = issuerAndThisUpdateCheck( in, &i, &tu, NULL );
if ( rc ) {
goto done;
}
rc = dnValidate( NULL, &i );
if ( rc ) {
rc = LDAP_INVALID_SYNTAX;
} else if ( checkTime( &tu, NULL ) ) {
rc = LDAP_INVALID_SYNTAX;
}
if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, NULL );
}
Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateValidate: <%s> err=%d\n",
in->bv_val, rc, 0 );
done:;
return rc;
}
static int
issuerAndThisUpdatePretty(
Syntax *syntax,
struct berval *in,
struct berval *out,
void *ctx )
{
int rc;
struct berval i, tu, ni = BER_BVNULL;
char *p;
assert( in != NULL );
assert( out != NULL );
BER_BVZERO( out );
Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdatePretty: <%s>\n",
in->bv_val, 0, 0 );
rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
if ( rc ) {
goto done;
}
rc = dnPretty( syntax, &i, &ni, ctx );
if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, ctx );
}
if ( rc || checkTime( &tu, NULL ) ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
out->bv_len = STRLENOF("{ issuer rdnSequence:\"\", thisUpdate \"\" }")
+ ni.bv_len + tu.bv_len;
out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
if ( out->bv_val == NULL ) {
out->bv_len = 0;
rc = LDAP_OTHER;
goto done;
}
p = out->bv_val;
p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, "\", thisUpdate \"" );
p = lutil_strbvcopy( p, &tu );
p = lutil_strcopy( p, "\" }" );
assert( p == &out->bv_val[out->bv_len] );
done:;
Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdatePretty: <%s> => <%s>\n",
in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
slap_sl_free( ni.bv_val, ctx );
return rc;
}
static int
issuerAndThisUpdateNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *in,
struct berval *out,
void *ctx )
{
struct berval i, ni, tu, tu2;
char sbuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
char *p;
int rc;
assert( in != NULL );
assert( out != NULL );
Debug( LDAP_DEBUG_TRACE, ">>> issuerAndThisUpdateNormalize: <%s>\n",
in->bv_val, 0, 0 );
rc = issuerAndThisUpdateCheck( in, &i, &tu, ctx );
if ( rc ) {
return rc;
}
rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, ctx );
}
tu2.bv_val = sbuf;
tu2.bv_len = sizeof( sbuf );
if ( rc || checkTime( &tu, &tu2 ) ) {
return LDAP_INVALID_SYNTAX;
}
out->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
+ ni.bv_len + tu2.bv_len;
out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
if ( out->bv_val == NULL ) {
out->bv_len = 0;
rc = LDAP_OTHER;
goto func_leave;
}
p = out->bv_val;
p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, "\", thisUpdate \"" );
p = lutil_strbvcopy( p, &tu2 );
p = lutil_strcopy( p, "\" }" );
assert( p == &out->bv_val[out->bv_len] );
func_leave:
Debug( LDAP_DEBUG_TRACE, "<<< issuerAndThisUpdateNormalize: <%s> => <%s>\n",
in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
slap_sl_free( ni.bv_val, ctx );
return rc;
}
static int
certificateListExactNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
ber_tag_t tag;
ber_len_t len;
ber_int_t version;
struct berval issuer_dn = BER_BVNULL, bvdn,
thisUpdate, bvtu;
char *p, tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
int rc = LDAP_INVALID_SYNTAX;
assert( val != NULL );
Debug( LDAP_DEBUG_TRACE, ">>> certificateListExactNormalize: <%p, %lu>\n",
val->bv_val, val->bv_len, 0 );
if ( BER_BVISEMPTY( val ) ) goto done;
if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
return issuerAndThisUpdateNormalize( 0, NULL, NULL, val, normalized, ctx );
}
assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
ber_init2( ber, val, LBER_USE_DER );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
tag = ber_peek_tag( ber, &len );
if ( tag == LBER_INTEGER ) {
tag = ber_get_int( ber, &version );
assert( tag == LBER_INTEGER );
if ( version != SLAP_X509_V2 ) return LDAP_INVALID_SYNTAX;
}
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
tag = ber_peek_tag( ber, &len );
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
len = ber_ptrlen( ber );
bvdn.bv_val = val->bv_val + len;
bvdn.bv_len = val->bv_len - len;
tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
bvtu.bv_val = (char *)ber->ber_ptr;
bvtu.bv_len = len;
rc = dnX509normalize( &bvdn, &issuer_dn );
if ( rc != LDAP_SUCCESS ) goto done;
thisUpdate.bv_val = tubuf;
thisUpdate.bv_len = sizeof(tubuf);
if ( checkTime( &bvtu, &thisUpdate ) ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
normalized->bv_len = STRLENOF( "{ issuer rdnSequence:\"\", thisUpdate \"\" }" )
+ issuer_dn.bv_len + thisUpdate.bv_len;
normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
p = normalized->bv_val;
p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
p = lutil_strbvcopy( p, &issuer_dn );
p = lutil_strcopy( p, "\", thisUpdate \"" );
p = lutil_strbvcopy( p, &thisUpdate );
p = lutil_strcopy( p, "\" }" );
rc = LDAP_SUCCESS;
done:
Debug( LDAP_DEBUG_TRACE, "<<< certificateListExactNormalize: <%p, %lu> => <%s>\n",
val->bv_val, val->bv_len, rc == LDAP_SUCCESS ? normalized->bv_val : "(err)" );
if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
return rc;
}
static int
serialNumberAndIssuerSerialCheck(
struct berval *in,
struct berval *sn,
struct berval *is,
struct berval *i_sn,
void *ctx )
{
enum {
HAVE_NONE = 0x0,
HAVE_SN = 0x1,
HAVE_ISSUER = 0x2,
HAVE_ALL = ( HAVE_SN | HAVE_ISSUER )
} have = HAVE_NONE, have2 = HAVE_NONE;
int numdquotes = 0;
struct berval x = *in;
struct berval ni;
if ( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
if ( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len -= 2;
do {
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer") ) == 0 ) {
if ( have & HAVE_ISSUER ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val += STRLENOF("issuer");
x.bv_len -= STRLENOF("issuer");
if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( x.bv_val[0] != '{' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( strncasecmp( x.bv_val, "baseCertificateID ", STRLENOF("baseCertificateID ") ) != 0 ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val += STRLENOF("baseCertificateID ");
x.bv_len -= STRLENOF("baseCertificateID ");
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( x.bv_val[0] != '{' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
do {
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( strncasecmp( x.bv_val, "issuer ", STRLENOF("issuer ") ) == 0 ) {
if ( have2 & HAVE_ISSUER ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val += STRLENOF("issuer ");
x.bv_len -= STRLENOF("issuer ");
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( x.bv_val[0] != '{' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( strncasecmp( x.bv_val, "directoryName:rdnSequence:", STRLENOF("directoryName:rdnSequence:") ) != 0 ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val += STRLENOF("directoryName:rdnSequence:");
x.bv_len -= STRLENOF("directoryName:rdnSequence:");
if ( x.bv_val[0] != '"' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
is->bv_val = x.bv_val;
is->bv_len = 0;
for ( ; is->bv_len < x.bv_len; ) {
if ( is->bv_val[is->bv_len] != '"' ) {
is->bv_len++;
continue;
}
if ( is->bv_val[is->bv_len + 1] == '"' ) {
is->bv_len += 2;
continue;
}
break;
}
x.bv_val += is->bv_len + 1;
x.bv_len -= is->bv_len + 1;
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( x.bv_val[0] != '}' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
have2 |= HAVE_ISSUER;
} else if ( strncasecmp( x.bv_val, "serial ", STRLENOF("serial ") ) == 0 ) {
if ( have2 & HAVE_SN ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val += STRLENOF("serial ");
x.bv_len -= STRLENOF("serial ");
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) {
;
}
if ( checkNum( &x, i_sn ) ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val += i_sn->bv_len;
x.bv_len -= i_sn->bv_len;
have2 |= HAVE_SN;
} else {
return LDAP_INVALID_SYNTAX;
}
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( have2 == HAVE_ALL ) {
break;
}
if ( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
} while ( 1 );
if ( x.bv_val[0] != '}' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( x.bv_val[0] != '}' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
have |= HAVE_ISSUER;
} else if ( strncasecmp( x.bv_val, "serialNumber", STRLENOF("serialNumber") ) == 0 ) {
if ( have & HAVE_SN ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val += STRLENOF("serialNumber");
x.bv_len -= STRLENOF("serialNumber");
if ( x.bv_val[0] != ' ' ) return LDAP_INVALID_SYNTAX;
x.bv_val++;
x.bv_len--;
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( checkNum( &x, sn ) ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val += sn->bv_len;
x.bv_len -= sn->bv_len;
have |= HAVE_SN;
} else {
return LDAP_INVALID_SYNTAX;
}
for ( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len-- ) {
;
}
if ( have == HAVE_ALL ) {
break;
}
if ( x.bv_val[0] != ',' ) {
return LDAP_INVALID_SYNTAX;
}
x.bv_val++ ;
x.bv_len--;
} while ( 1 );
if( x.bv_len ) return LDAP_INVALID_SYNTAX;
if ( numdquotes == 0 ) {
ber_dupbv_x( &ni, is, ctx );
} else {
ber_len_t src, dst;
ni.bv_len = is->bv_len - numdquotes;
ni.bv_val = ber_memalloc_x( ni.bv_len + 1, ctx );
for ( src = 0, dst = 0; src < is->bv_len; src++, dst++ ) {
if ( is->bv_val[src] == '"' ) {
src++;
}
ni.bv_val[dst] = is->bv_val[src];
}
ni.bv_val[dst] = '\0';
}
*is = ni;
return 0;
}
static int
serialNumberAndIssuerSerialValidate(
Syntax *syntax,
struct berval *in )
{
int rc;
struct berval sn, i, i_sn;
Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialValidate: <%s>\n",
in->bv_val, 0, 0 );
rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, NULL );
if ( rc ) {
goto done;
}
rc = dnValidate( NULL, &i );
if ( rc ) {
rc = LDAP_INVALID_SYNTAX;
}
if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, NULL );
}
done:;
Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialValidate: <%s> err=%d\n",
in->bv_val, rc, 0 );
return rc;
}
static int
serialNumberAndIssuerSerialPretty(
Syntax *syntax,
struct berval *in,
struct berval *out,
void *ctx )
{
struct berval sn, i, i_sn, ni = BER_BVNULL;
char *p;
int rc;
assert( in != NULL );
assert( out != NULL );
Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialPretty: <%s>\n",
in->bv_val, 0, 0 );
rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
if ( rc ) {
goto done;
}
rc = dnPretty( syntax, &i, &ni, ctx );
if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, ctx );
}
if ( rc ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
+ sn.bv_len + ni.bv_len + i_sn.bv_len;
out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
if ( out->bv_val == NULL ) {
out->bv_len = 0;
rc = LDAP_OTHER;
goto done;
}
p = out->bv_val;
p = lutil_strcopy( p, "{ serialNumber " );
p = lutil_strbvcopy( p, &sn );
p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, "\" }, serial " );
p = lutil_strbvcopy( p, &i_sn );
p = lutil_strcopy( p, " } } }" );
assert( p == &out->bv_val[out->bv_len] );
done:;
Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialPretty: <%s> => <%s>\n",
in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
slap_sl_free( ni.bv_val, ctx );
return rc;
}
static int
serialNumberAndIssuerSerialNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *in,
struct berval *out,
void *ctx )
{
struct berval i, ni = BER_BVNULL,
sn, sn2 = BER_BVNULL, sn3 = BER_BVNULL,
i_sn, i_sn2 = BER_BVNULL, i_sn3 = BER_BVNULL;
char sbuf2[SLAP_SN_BUFLEN], i_sbuf2[SLAP_SN_BUFLEN],
sbuf3[SLAP_SN_BUFLEN], i_sbuf3[SLAP_SN_BUFLEN];
char *p;
int rc;
assert( in != NULL );
assert( out != NULL );
Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerSerialNormalize: <%s>\n",
in->bv_val, 0, 0 );
rc = serialNumberAndIssuerSerialCheck( in, &sn, &i, &i_sn, ctx );
if ( rc ) {
goto func_leave;
}
rc = dnNormalize( usage, syntax, mr, &i, &ni, ctx );
if ( in->bv_val[0] == '{' && in->bv_val[in->bv_len-1] == '}' ) {
slap_sl_free( i.bv_val, ctx );
}
if ( rc ) {
rc = LDAP_INVALID_SYNTAX;
goto func_leave;
}
sn2.bv_val = sbuf2;
sn2.bv_len = sn.bv_len;
if ( sn.bv_len > sizeof( sbuf2 ) ) {
sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
}
if ( lutil_str2bin( &sn, &sn2, ctx ) ) {
rc = LDAP_INVALID_SYNTAX;
goto func_leave;
}
i_sn2.bv_val = i_sbuf2;
i_sn2.bv_len = i_sn.bv_len;
if ( i_sn.bv_len > sizeof( i_sbuf2 ) ) {
i_sn2.bv_val = slap_sl_malloc( i_sn.bv_len, ctx );
}
if ( lutil_str2bin( &i_sn, &i_sn2, ctx ) ) {
rc = LDAP_INVALID_SYNTAX;
goto func_leave;
}
sn3.bv_val = sbuf3;
sn3.bv_len = sizeof(sbuf3);
if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
rc = LDAP_INVALID_SYNTAX;
goto func_leave;
}
i_sn3.bv_val = i_sbuf3;
i_sn3.bv_len = sizeof(i_sbuf3);
if ( slap_bin2hex( &i_sn2, &i_sn3, ctx ) ) {
rc = LDAP_INVALID_SYNTAX;
goto func_leave;
}
out->bv_len = STRLENOF("{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }")
+ sn3.bv_len + ni.bv_len + i_sn3.bv_len;
out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
if ( out->bv_val == NULL ) {
out->bv_len = 0;
rc = LDAP_OTHER;
goto func_leave;
}
p = out->bv_val;
p = lutil_strcopy( p, "{ serialNumber " );
p = lutil_strbvcopy( p, &sn3 );
p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, "\" }, serial " );
p = lutil_strbvcopy( p, &i_sn3 );
p = lutil_strcopy( p, " } } }" );
assert( p == &out->bv_val[out->bv_len] );
func_leave:
Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerSerialNormalize: <%s> => <%s>\n",
in->bv_val, rc == LDAP_SUCCESS ? out->bv_val : "(err)", 0 );
if ( sn2.bv_val != sbuf2 ) {
slap_sl_free( sn2.bv_val, ctx );
}
if ( i_sn2.bv_val != i_sbuf2 ) {
slap_sl_free( i_sn2.bv_val, ctx );
}
if ( sn3.bv_val != sbuf3 ) {
slap_sl_free( sn3.bv_val, ctx );
}
if ( i_sn3.bv_val != i_sbuf3 ) {
slap_sl_free( i_sn3.bv_val, ctx );
}
slap_sl_free( ni.bv_val, ctx );
return rc;
}
static int
attributeCertificateExactNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
ber_tag_t tag;
ber_len_t len;
char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
struct berval sn, i_sn, sn2 = BER_BVNULL, i_sn2 = BER_BVNULL;
struct berval issuer_dn = BER_BVNULL, bvdn;
char *p;
int rc = LDAP_INVALID_SYNTAX;
if ( BER_BVISEMPTY( val ) ) {
return rc;
}
if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
return serialNumberAndIssuerSerialNormalize( 0, NULL, NULL, val, normalized, ctx );
}
assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
ber_init2( ber, val, LBER_USE_DER );
tag = ber_skip_tag( ber, &len );
tag = ber_skip_tag( ber, &len );
tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
tag = ber_skip_tag( ber, &len );
tag = ber_skip_tag( ber, &len );
tag = ber_skip_tag( ber, &len );
if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
return LDAP_INVALID_SYNTAX;
}
tag = ber_peek_tag( ber, &len );
len = ber_ptrlen( ber );
bvdn.bv_val = val->bv_val + len;
bvdn.bv_len = val->bv_len - len;
rc = dnX509normalize( &bvdn, &issuer_dn );
if ( rc != LDAP_SUCCESS ) goto done;
tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_INTEGER ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
i_sn.bv_val = (char *)ber->ber_ptr;
i_sn.bv_len = len;
i_sn2.bv_val = issuer_serialbuf;
i_sn2.bv_len = sizeof(issuer_serialbuf);
if ( slap_bin2hex( &i_sn, &i_sn2, ctx ) ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
if ( tag != LBER_INTEGER ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
sn.bv_val = (char *)ber->ber_ptr;
sn.bv_len = len;
sn2.bv_val = serialbuf;
sn2.bv_len = sizeof(serialbuf);
if ( slap_bin2hex( &sn, &sn2, ctx ) ) {
rc = LDAP_INVALID_SYNTAX;
goto done;
}
ber_skip_data( ber, len );
normalized->bv_len = STRLENOF( "{ serialNumber , issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"\" }, serial } } }" )
+ sn2.bv_len + issuer_dn.bv_len + i_sn2.bv_len;
normalized->bv_val = ch_malloc( normalized->bv_len + 1 );
p = normalized->bv_val;
p = lutil_strcopy( p, "{ serialNumber " );
p = lutil_strbvcopy( p, &sn2 );
p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
p = lutil_strbvcopy( p, &issuer_dn );
p = lutil_strcopy( p, "\" }, serial " );
p = lutil_strbvcopy( p, &i_sn2 );
p = lutil_strcopy( p, " } } }" );
Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
normalized->bv_val, NULL, NULL );
rc = LDAP_SUCCESS;
done:
if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val );
if ( i_sn2.bv_val != issuer_serialbuf ) ber_memfree_x( i_sn2.bv_val, ctx );
if ( sn2.bv_val != serialbuf ) ber_memfree_x( sn2.bv_val, ctx );
return rc;
}
static int
hexValidate(
Syntax *syntax,
struct berval *in )
{
ber_len_t i;
assert( in != NULL );
assert( !BER_BVISNULL( in ) );
for ( i = 0; i < in->bv_len; i++ ) {
if ( !ASCII_HEX( in->bv_val[ i ] ) ) {
return LDAP_INVALID_SYNTAX;
}
}
return LDAP_SUCCESS;
}
static int
hexNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
ber_len_t i;
assert( val != NULL );
assert( normalized != NULL );
ber_dupbv_x( normalized, val, ctx );
for ( i = 0; i < normalized->bv_len; i++ ) {
if ( !ASCII_HEX( normalized->bv_val[ i ] ) ) {
ber_memfree_x( normalized->bv_val, ctx );
BER_BVZERO( normalized );
return LDAP_INVALID_SYNTAX;
}
normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
}
return LDAP_SUCCESS;
}
static int
sidValidate (
Syntax *syntax,
struct berval *in )
{
assert( in != NULL );
assert( !BER_BVISNULL( in ) );
if ( in->bv_len != 3 ) {
return LDAP_INVALID_SYNTAX;
}
return hexValidate( NULL, in );
}
static int
sidNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
if ( val->bv_len != 3 ) {
return LDAP_INVALID_SYNTAX;
}
return hexNormalize( 0, NULL, NULL, val, normalized, ctx );
}
static int
sidPretty(
Syntax *syntax,
struct berval *val,
struct berval *out,
void *ctx )
{
return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
}
static int
csnSidNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
struct berval bv;
char *ptr,
buf[ 4 ];
if ( BER_BVISEMPTY( val ) ) {
return LDAP_INVALID_SYNTAX;
}
if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
return sidNormalize( 0, NULL, NULL, val, normalized, ctx );
}
assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 );
ptr = ber_bvchr( val, '#' );
if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
bv.bv_val = ptr + 1;
bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
ptr = ber_bvchr( &bv, '#' );
if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
bv.bv_val = ptr + 1;
bv.bv_len = val->bv_len - ( ptr + 1 - val->bv_val );
ptr = ber_bvchr( &bv, '#' );
if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
bv.bv_len = ptr - bv.bv_val;
if ( bv.bv_len == 2 ) {
buf[ 0 ] = '0';
buf[ 1 ] = bv.bv_val[ 0 ];
buf[ 2 ] = bv.bv_val[ 1 ];
buf[ 3 ] = '\0';
bv.bv_val = buf;
bv.bv_len = 3;
}
return sidNormalize( 0, NULL, NULL, &bv, normalized, ctx );
}
static int
csnValidate(
Syntax *syntax,
struct berval *in )
{
struct berval bv;
char *ptr;
int rc;
assert( in != NULL );
assert( !BER_BVISNULL( in ) );
if ( BER_BVISEMPTY( in ) ) {
return LDAP_INVALID_SYNTAX;
}
bv = *in;
ptr = ber_bvchr( &bv, '#' );
if ( ptr == NULL || ptr == &bv.bv_val[bv.bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
bv.bv_len = ptr - bv.bv_val;
if ( bv.bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) &&
bv.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) )
{
return LDAP_INVALID_SYNTAX;
}
rc = generalizedTimeValidate( NULL, &bv );
if ( rc != LDAP_SUCCESS ) {
return rc;
}
bv.bv_val = ptr + 1;
bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
ptr = ber_bvchr( &bv, '#' );
if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
bv.bv_len = ptr - bv.bv_val;
if ( bv.bv_len != 6 ) {
return LDAP_INVALID_SYNTAX;
}
rc = hexValidate( NULL, &bv );
if ( rc != LDAP_SUCCESS ) {
return rc;
}
bv.bv_val = ptr + 1;
bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
ptr = ber_bvchr( &bv, '#' );
if ( ptr == NULL || ptr == &in->bv_val[in->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
bv.bv_len = ptr - bv.bv_val;
if ( bv.bv_len == 2 ) {
rc = hexValidate( NULL, &bv );
} else {
rc = sidValidate( NULL, &bv );
}
if ( rc != LDAP_SUCCESS ) {
return rc;
}
bv.bv_val = ptr + 1;
bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
if ( bv.bv_len != 6 ) {
return LDAP_INVALID_SYNTAX;
}
return hexValidate( NULL, &bv );
}
static int
csnNormalize21(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
struct berval gt, cnt, sid, mod;
struct berval bv;
char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
char *ptr;
ber_len_t i;
assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
assert( !BER_BVISEMPTY( val ) );
gt = *val;
ptr = ber_bvchr( >, '#' );
if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
gt.bv_len = ptr - gt.bv_val;
if ( gt.bv_len != STRLENOF( "YYYYmmddHH:MM:SSZ" ) ) {
return LDAP_INVALID_SYNTAX;
}
if ( gt.bv_val[ 10 ] != ':' || gt.bv_val[ 13 ] != ':' ) {
return LDAP_INVALID_SYNTAX;
}
cnt.bv_val = ptr + 1;
cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
ptr = ber_bvchr( &cnt, '#' );
if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
cnt.bv_len = ptr - cnt.bv_val;
if ( cnt.bv_len != STRLENOF( "0x0000" ) ) {
return LDAP_INVALID_SYNTAX;
}
if ( strncmp( cnt.bv_val, "0x", STRLENOF( "0x" ) ) != 0 ) {
return LDAP_INVALID_SYNTAX;
}
cnt.bv_val += STRLENOF( "0x" );
cnt.bv_len -= STRLENOF( "0x" );
sid.bv_val = ptr + 1;
sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
ptr = ber_bvchr( &sid, '#' );
if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
sid.bv_len = ptr - sid.bv_val;
if ( sid.bv_len != STRLENOF( "0" ) ) {
return LDAP_INVALID_SYNTAX;
}
mod.bv_val = ptr + 1;
mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
if ( mod.bv_len != STRLENOF( "0000" ) ) {
return LDAP_INVALID_SYNTAX;
}
bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
bv.bv_val = buf;
ptr = bv.bv_val;
ptr = lutil_strncopy( ptr, gt.bv_val, STRLENOF( "YYYYmmddHH" ) );
ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:" ) ],
STRLENOF( "MM" ) );
ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
STRLENOF( "SS" ) );
ptr = lutil_strcopy( ptr, ".000000Z#00" );
ptr = lutil_strbvcopy( ptr, &cnt );
*ptr++ = '#';
*ptr++ = '0';
*ptr++ = '0';
*ptr++ = sid.bv_val[ 0 ];
*ptr++ = '#';
*ptr++ = '0';
*ptr++ = '0';
for ( i = 0; i < mod.bv_len; i++ ) {
*ptr++ = TOLOWER( mod.bv_val[ i ] );
}
*ptr = '\0';
assert( ptr == &bv.bv_val[bv.bv_len] );
if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
ber_dupbv_x( normalized, &bv, ctx );
return LDAP_SUCCESS;
}
static int
csnNormalize23(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
struct berval gt, cnt, sid, mod;
struct berval bv;
char buf[ STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) + 1 ];
char *ptr;
ber_len_t i;
assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
assert( !BER_BVISEMPTY( val ) );
gt = *val;
ptr = ber_bvchr( >, '#' );
if ( ptr == NULL || ptr == >.bv_val[gt.bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
gt.bv_len = ptr - gt.bv_val;
if ( gt.bv_len != STRLENOF( "YYYYmmddHHMMSSZ" ) ) {
return LDAP_INVALID_SYNTAX;
}
cnt.bv_val = ptr + 1;
cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
ptr = ber_bvchr( &cnt, '#' );
if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
cnt.bv_len = ptr - cnt.bv_val;
if ( cnt.bv_len != STRLENOF( "000000" ) ) {
return LDAP_INVALID_SYNTAX;
}
sid.bv_val = ptr + 1;
sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
ptr = ber_bvchr( &sid, '#' );
if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
sid.bv_len = ptr - sid.bv_val;
if ( sid.bv_len != STRLENOF( "00" ) ) {
return LDAP_INVALID_SYNTAX;
}
mod.bv_val = ptr + 1;
mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
if ( mod.bv_len != STRLENOF( "000000" ) ) {
return LDAP_INVALID_SYNTAX;
}
bv.bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" );
bv.bv_val = buf;
ptr = bv.bv_val;
ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
ptr = lutil_strcopy( ptr, ".000000Z#" );
ptr = lutil_strbvcopy( ptr, &cnt );
*ptr++ = '#';
*ptr++ = '0';
for ( i = 0; i < sid.bv_len; i++ ) {
*ptr++ = TOLOWER( sid.bv_val[ i ] );
}
*ptr++ = '#';
for ( i = 0; i < mod.bv_len; i++ ) {
*ptr++ = TOLOWER( mod.bv_val[ i ] );
}
*ptr = '\0';
assert( ptr == &bv.bv_val[bv.bv_len] );
if ( csnValidate( syntax, &bv ) != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
ber_dupbv_x( normalized, &bv, ctx );
return LDAP_SUCCESS;
}
static int
csnNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
struct berval cnt, sid, mod;
char *ptr;
ber_len_t i;
assert( val != NULL );
assert( normalized != NULL );
assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 );
if ( BER_BVISEMPTY( val ) ) {
return LDAP_INVALID_SYNTAX;
}
if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) {
return csnNormalize23( usage, syntax, mr, val, normalized, ctx );
}
if ( val->bv_len == STRLENOF( "YYYYmmddHH:MM:SSZ#0xSSSS#I#ssss" ) ) {
return csnNormalize21( usage, syntax, mr, val, normalized, ctx );
}
if ( val->bv_len != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ) {
return LDAP_INVALID_SYNTAX;
}
ptr = ber_bvchr( val, '#' );
if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
if ( ptr - val->bv_val != STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ) {
return LDAP_INVALID_SYNTAX;
}
cnt.bv_val = ptr + 1;
cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val );
ptr = ber_bvchr( &cnt, '#' );
if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
if ( ptr - cnt.bv_val != STRLENOF( "000000" ) ) {
return LDAP_INVALID_SYNTAX;
}
sid.bv_val = ptr + 1;
sid.bv_len = val->bv_len - ( sid.bv_val - val->bv_val );
ptr = ber_bvchr( &sid, '#' );
if ( ptr == NULL || ptr == &val->bv_val[val->bv_len] ) {
return LDAP_INVALID_SYNTAX;
}
sid.bv_len = ptr - sid.bv_val;
if ( sid.bv_len != STRLENOF( "000" ) ) {
return LDAP_INVALID_SYNTAX;
}
mod.bv_val = ptr + 1;
mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val );
if ( mod.bv_len != STRLENOF( "000000" ) ) {
return LDAP_INVALID_SYNTAX;
}
ber_dupbv_x( normalized, val, ctx );
for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" );
i < normalized->bv_len; i++ )
{
normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] );
}
return LDAP_SUCCESS;
}
static int
csnPretty(
Syntax *syntax,
struct berval *val,
struct berval *out,
void *ctx )
{
return csnNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx );
}
#ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
#define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
enum { start = 0 };
#endif
static int
check_time_syntax (struct berval *val,
int start,
int *parts,
struct berval *fraction)
{
static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
static const int mdays[2][12] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
char *p, *e;
int part, c, c1, c2, tzoffset, leapyear = 0;
p = val->bv_val;
e = p + val->bv_len;
#ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
parts[0] = 20;
#endif
for (part = start; part < 7 && p < e; part++) {
c1 = *p;
if (!ASCII_DIGIT(c1)) {
break;
}
p++;
if (p == e) {
return LDAP_INVALID_SYNTAX;
}
c = *p++;
if (!ASCII_DIGIT(c)) {
return LDAP_INVALID_SYNTAX;
}
c += c1 * 10 - '0' * 11;
if ((part | 1) == 3) {
--c;
if (c < 0) {
return LDAP_INVALID_SYNTAX;
}
}
if (c >= ceiling[part]) {
if (! (c == 60 && part == 6 && start == 0))
return LDAP_INVALID_SYNTAX;
}
parts[part] = c;
}
if (part < 5 + start) {
return LDAP_INVALID_SYNTAX;
}
for (; part < 9; part++) {
parts[part] = 0;
}
if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
leapyear = 1;
}
if (parts[3] >= mdays[leapyear][parts[2]]) {
return LDAP_INVALID_SYNTAX;
}
if (start == 0) {
fraction->bv_val = p;
fraction->bv_len = 0;
if (p < e && (*p == '.' || *p == ',')) {
char *end_num;
while (++p < e && ASCII_DIGIT(*p)) {
;
}
if (p - fraction->bv_val == 1) {
return LDAP_INVALID_SYNTAX;
}
for (end_num = p; end_num[-1] == '0'; --end_num) {
;
}
c = end_num - fraction->bv_val;
if (c != 1) fraction->bv_len = c;
}
}
if (p == e) {
return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
}
tzoffset = *p++;
switch (tzoffset) {
default:
return LDAP_INVALID_SYNTAX;
case 'Z':
break;
case '+':
case '-':
for (part = 7; part < 9 && p < e; part++) {
c1 = *p;
if (!ASCII_DIGIT(c1)) {
break;
}
p++;
if (p == e) {
return LDAP_INVALID_SYNTAX;
}
c2 = *p++;
if (!ASCII_DIGIT(c2)) {
return LDAP_INVALID_SYNTAX;
}
parts[part] = c1 * 10 + c2 - '0' * 11;
if (parts[part] >= ceiling[part]) {
return LDAP_INVALID_SYNTAX;
}
}
if (part < 8 + start) {
return LDAP_INVALID_SYNTAX;
}
if (tzoffset == '-') {
parts[4] += parts[7];
parts[5] += parts[8];
for (part = 6; --part >= 0; ) {
if (part != 3) {
c = ceiling[part];
} else {
c = mdays[leapyear][parts[2]];
}
if (parts[part] >= c) {
if (part == 0) {
return LDAP_INVALID_SYNTAX;
}
parts[part] -= c;
parts[part - 1]++;
continue;
} else if (part != 5) {
break;
}
}
} else {
parts[4] -= parts[7];
parts[5] -= parts[8];
for (part = 6; --part >= 0; ) {
if (parts[part] < 0) {
if (part == 0) {
return LDAP_INVALID_SYNTAX;
}
if (part != 3) {
c = ceiling[part];
} else {
c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
}
parts[part] += c;
parts[part - 1]--;
continue;
} else if (part != 5) {
break;
}
}
}
}
return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
}
#ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
#if 0
static int
xutcTimeNormalize(
Syntax *syntax,
struct berval *val,
struct berval *normalized )
{
int parts[9], rc;
rc = check_time_syntax(val, 1, parts, NULL);
if (rc != LDAP_SUCCESS) {
return rc;
}
normalized->bv_val = ch_malloc( 14 );
if ( normalized->bv_val == NULL ) {
return LBER_ERROR_MEMORY;
}
sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02dZ",
parts[1], parts[2] + 1, parts[3] + 1,
parts[4], parts[5], parts[6] );
normalized->bv_len = 13;
return LDAP_SUCCESS;
}
#endif
static int
utcTimeValidate(
Syntax *syntax,
struct berval *in )
{
int parts[9];
return check_time_syntax(in, 1, parts, NULL);
}
#endif
static int
generalizedTimeValidate(
Syntax *syntax,
struct berval *in )
{
int parts[9];
struct berval fraction;
return check_time_syntax(in, 0, parts, &fraction);
}
static int
generalizedTimeNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
int parts[9], rc;
unsigned int len;
struct berval fraction;
rc = check_time_syntax(val, 0, parts, &fraction);
if (rc != LDAP_SUCCESS) {
return rc;
}
len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
normalized->bv_val = slap_sl_malloc( len + 1, ctx );
if ( BER_BVISNULL( normalized ) ) {
return LBER_ERROR_MEMORY;
}
sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
parts[0], parts[1], parts[2] + 1, parts[3] + 1,
parts[4], parts[5], parts[6] );
if ( !BER_BVISEMPTY( &fraction ) ) {
memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
fraction.bv_val, fraction.bv_len );
normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
}
strcpy( normalized->bv_val + len-1, "Z" );
normalized->bv_len = len;
return LDAP_SUCCESS;
}
static int
generalizedTimeOrderingMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
struct berval *asserted = (struct berval *) assertedValue;
ber_len_t v_len = value->bv_len;
ber_len_t av_len = asserted->bv_len;
int match = memcmp( value->bv_val, asserted->bv_val,
(v_len < av_len ? v_len : av_len) - 1 );
if ( match == 0 ) match = v_len - av_len;
if ( flags & SLAP_MR_EXT )
match = (match >= 0);
*matchp = match;
return LDAP_SUCCESS;
}
int generalizedTimeIndexer(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
BerVarray values,
BerVarray *keysp,
void *ctx )
{
int i, j;
BerVarray keys;
char tmp[5];
BerValue bvtmp;
struct lutil_tm tm;
struct lutil_timet tt;
bvtmp.bv_len = sizeof(tmp);
bvtmp.bv_val = tmp;
for( i=0; values[i].bv_val != NULL; i++ ) {
}
assert( i > 0 );
keys = slap_sl_malloc( sizeof( struct berval ) * (i+1), ctx );
for( i=0, j=0; values[i].bv_val != NULL; i++ ) {
assert(values[i].bv_val != NULL && values[i].bv_len >= 10);
if ( lutil_parsetime( values[i].bv_val, &tm ) == 0 ) {
lutil_tm2time( &tm, &tt );
tmp[0] = tt.tt_gsec & 0xff;
tmp[4] = tt.tt_sec & 0xff;
tt.tt_sec >>= 8;
tmp[3] = tt.tt_sec & 0xff;
tt.tt_sec >>= 8;
tmp[2] = tt.tt_sec & 0xff;
tt.tt_sec >>= 8;
tmp[1] = tt.tt_sec & 0xff;
ber_dupbv_x(&keys[j++], &bvtmp, ctx );
}
}
keys[j].bv_val = NULL;
keys[j].bv_len = 0;
*keysp = keys;
return LDAP_SUCCESS;
}
int generalizedTimeFilter(
slap_mask_t use,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *prefix,
void * assertedValue,
BerVarray *keysp,
void *ctx )
{
BerVarray keys;
char tmp[5];
BerValue bvtmp;
BerValue *value = (BerValue *) assertedValue;
struct lutil_tm tm;
struct lutil_timet tt;
bvtmp.bv_len = sizeof(tmp);
bvtmp.bv_val = tmp;
if ( value->bv_val && value->bv_len >= 10 &&
lutil_parsetime( value->bv_val, &tm ) == 0 ) {
lutil_tm2time( &tm, &tt );
tmp[0] = tt.tt_gsec & 0xff;
tmp[4] = tt.tt_sec & 0xff;
tt.tt_sec >>= 8;
tmp[3] = tt.tt_sec & 0xff;
tt.tt_sec >>= 8;
tmp[2] = tt.tt_sec & 0xff;
tt.tt_sec >>= 8;
tmp[1] = tt.tt_sec & 0xff;
keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx );
ber_dupbv_x(keys, &bvtmp, ctx );
keys[1].bv_val = NULL;
keys[1].bv_len = 0;
} else {
keys = NULL;
}
*keysp = keys;
return LDAP_SUCCESS;
}
static int
deliveryMethodValidate(
Syntax *syntax,
struct berval *val )
{
#undef LENOF
#define LENOF(s) (sizeof(s)-1)
struct berval tmp = *val;
again:
if( tmp.bv_len < 3 ) return LDAP_INVALID_SYNTAX;
switch( tmp.bv_val[0] ) {
case 'a':
case 'A':
if(( tmp.bv_len >= LENOF("any") ) &&
( strncasecmp(tmp.bv_val, "any", LENOF("any")) == 0 ))
{
tmp.bv_len -= LENOF("any");
tmp.bv_val += LENOF("any");
break;
}
return LDAP_INVALID_SYNTAX;
case 'm':
case 'M':
if(( tmp.bv_len >= LENOF("mhs") ) &&
( strncasecmp(tmp.bv_val, "mhs", LENOF("mhs")) == 0 ))
{
tmp.bv_len -= LENOF("mhs");
tmp.bv_val += LENOF("mhs");
break;
}
return LDAP_INVALID_SYNTAX;
case 'p':
case 'P':
if(( tmp.bv_len >= LENOF("physical") ) &&
( strncasecmp(tmp.bv_val, "physical", LENOF("physical")) == 0 ))
{
tmp.bv_len -= LENOF("physical");
tmp.bv_val += LENOF("physical");
break;
}
return LDAP_INVALID_SYNTAX;
case 't':
case 'T':
if(( tmp.bv_len >= LENOF("telex") ) &&
( strncasecmp(tmp.bv_val, "telex", LENOF("telex")) == 0 ))
{
tmp.bv_len -= LENOF("telex");
tmp.bv_val += LENOF("telex");
break;
}
if(( tmp.bv_len >= LENOF("teletex") ) &&
( strncasecmp(tmp.bv_val, "teletex", LENOF("teletex")) == 0 ))
{
tmp.bv_len -= LENOF("teletex");
tmp.bv_val += LENOF("teletex");
break;
}
if(( tmp.bv_len >= LENOF("telephone") ) &&
( strncasecmp(tmp.bv_val, "telephone", LENOF("telephone")) == 0 ))
{
tmp.bv_len -= LENOF("telephone");
tmp.bv_val += LENOF("telephone");
break;
}
return LDAP_INVALID_SYNTAX;
case 'g':
case 'G':
if(( tmp.bv_len >= LENOF("g3fax") ) && (
( strncasecmp(tmp.bv_val, "g3fax", LENOF("g3fax")) == 0 ) ||
( strncasecmp(tmp.bv_val, "g4fax", LENOF("g4fax")) == 0 )))
{
tmp.bv_len -= LENOF("g3fax");
tmp.bv_val += LENOF("g3fax");
break;
}
return LDAP_INVALID_SYNTAX;
case 'i':
case 'I':
if(( tmp.bv_len >= LENOF("ia5") ) &&
( strncasecmp(tmp.bv_val, "ia5", LENOF("ia5")) == 0 ))
{
tmp.bv_len -= LENOF("ia5");
tmp.bv_val += LENOF("ia5");
break;
}
return LDAP_INVALID_SYNTAX;
case 'v':
case 'V':
if(( tmp.bv_len >= LENOF("videotex") ) &&
( strncasecmp(tmp.bv_val, "videotex", LENOF("videotex")) == 0 ))
{
tmp.bv_len -= LENOF("videotex");
tmp.bv_val += LENOF("videotex");
break;
}
return LDAP_INVALID_SYNTAX;
default:
return LDAP_INVALID_SYNTAX;
}
if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS;
while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
tmp.bv_len++;
tmp.bv_val--;
}
if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) {
tmp.bv_len++;
tmp.bv_val--;
} else {
return LDAP_INVALID_SYNTAX;
}
while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) {
tmp.bv_len++;
tmp.bv_val--;
}
goto again;
}
static int
nisNetgroupTripleValidate(
Syntax *syntax,
struct berval *val )
{
char *p, *e;
int commas = 0;
if ( BER_BVISEMPTY( val ) ) {
return LDAP_INVALID_SYNTAX;
}
p = (char *)val->bv_val;
e = p + val->bv_len;
if ( *p != '(' ) {
return LDAP_INVALID_SYNTAX;
}
for ( p++; ( p < e ) && ( *p != ')' ); p++ ) {
if ( *p == ',' ) {
commas++;
if ( commas > 2 ) {
return LDAP_INVALID_SYNTAX;
}
} else if ( !AD_CHAR( *p ) ) {
return LDAP_INVALID_SYNTAX;
}
}
if ( ( commas != 2 ) || ( *p != ')' ) ) {
return LDAP_INVALID_SYNTAX;
}
p++;
if (p != e) {
return LDAP_INVALID_SYNTAX;
}
return LDAP_SUCCESS;
}
static int
bootParameterValidate(
Syntax *syntax,
struct berval *val )
{
char *p, *e;
if ( BER_BVISEMPTY( val ) ) {
return LDAP_INVALID_SYNTAX;
}
p = (char *)val->bv_val;
e = p + val->bv_len;
for (; ( p < e ) && ( *p != '=' ); p++ ) {
if ( !AD_CHAR( *p ) ) {
return LDAP_INVALID_SYNTAX;
}
}
if ( *p != '=' ) {
return LDAP_INVALID_SYNTAX;
}
for ( p++; ( p < e ) && ( *p != ':' ); p++ ) {
if ( !AD_CHAR( *p ) ) {
return LDAP_INVALID_SYNTAX;
}
}
if ( *p != ':' ) {
return LDAP_INVALID_SYNTAX;
}
for ( p++; p < e; p++ ) {
if ( !SLAP_PRINTABLE( *p ) ) {
return LDAP_INVALID_SYNTAX;
}
}
return LDAP_SUCCESS;
}
static int
firstComponentNormalize(
slap_mask_t usage,
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval *normalized,
void *ctx )
{
int rc;
struct berval comp;
ber_len_t len;
if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX( usage )) {
ber_dupbv_x( normalized, val, ctx );
return LDAP_SUCCESS;
}
if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX;
if( ! ( val->bv_val[0] == '('
&& val->bv_val[val->bv_len - 1] == ')' )
&& ! ( val->bv_val[0] == '{'
&& val->bv_val[val->bv_len - 1] == '}' ) )
{
return LDAP_INVALID_SYNTAX;
}
for( len=1;
len < val->bv_len && ASCII_SPACE(val->bv_val[len]);
len++ )
{
}
comp.bv_val = &val->bv_val[len];
len = val->bv_len - len - STRLENOF( "}");
for( comp.bv_len = 0;
!ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len;
comp.bv_len++ )
{
}
if( mr == slap_schema.si_mr_objectIdentifierFirstComponentMatch ) {
rc = numericoidValidate( NULL, &comp );
} else if( mr == slap_schema.si_mr_integerFirstComponentMatch ) {
rc = integerValidate( NULL, &comp );
} else {
rc = LDAP_INVALID_SYNTAX;
}
if( rc == LDAP_SUCCESS ) {
ber_dupbv_x( normalized, &comp, ctx );
}
return rc;
}
static char *country_gen_syn[] = {
"1.3.6.1.4.1.1466.115.121.1.15",
"1.3.6.1.4.1.1466.115.121.1.26",
"1.3.6.1.4.1.1466.115.121.1.44",
NULL
};
#define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' "
#define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' "
static slap_syntax_defs_rec syntax_defs[] = {
{"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' "
X_BINARY X_NOT_H_R ")",
SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.2 DESC 'Access Point' " X_NOT_H_R ")",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' "
X_NOT_H_R ")",
SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' "
X_NOT_H_R ")",
SLAP_SYNTAX_BER, NULL, berValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
0, NULL, bitStringValidate, NULL },
{"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
0, NULL, booleanValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
X_BINARY X_NOT_H_R ")",
SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
NULL, certificateValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' "
X_BINARY X_NOT_H_R ")",
SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
NULL, certificateListValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' "
X_BINARY X_NOT_H_R ")",
SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
NULL, sequenceValidate, NULL},
{"( " attributeCertificateSyntaxOID " DESC 'X.509 AttributeCertificate' "
X_BINARY X_NOT_H_R ")",
SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER,
NULL, attributeCertificateValidate, NULL},
#if 0
{"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
0, "1.3.6.1.4.1.1466.115.121.1.44",
countryStringValidate, NULL},
#endif
{"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
SLAP_SYNTAX_DN, NULL, dnValidate, dnPretty},
{"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
0, NULL, rdnValidate, rdnPretty},
#ifdef LDAP_COMP_MATCH
{"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )",
0, NULL, allComponentsValidate, NULL},
{"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ",
0, NULL, componentFilterValidate, NULL},
#endif
{"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )",
0, NULL, deliveryMethodValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )",
0, NULL, UTF8StringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )",
0, NULL, printablesStringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
0, NULL, generalizedTimeValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
0, NULL, IA5StringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
0, NULL, integerValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")",
SLAP_SYNTAX_BLOB, NULL, blobValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.29 DESC 'Master And Shadow Access Points' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
SLAP_SYNTAX_DN, NULL, nameUIDValidate, nameUIDPretty },
{"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
0, NULL, numericStringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )",
0, NULL, numericoidValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )",
0, NULL, IA5StringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )",
0, NULL, blobValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )",
0, NULL, postalAddressValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )",
0, NULL, printableStringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )",
0, country_gen_syn, countryStringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.45 DESC 'SubtreeSpecification' )",
#define subtreeSpecificationValidate UTF8StringValidate
0, NULL, subtreeSpecificationValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.49 DESC 'Supported Algorithm' "
X_BINARY X_NOT_H_R ")",
SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )",
0, NULL, printableStringValidate, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
0, NULL, printablesStringValidate, NULL},
#ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
{"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
0, NULL, utcTimeValidate, NULL},
#endif
{"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )",
0, NULL, nisNetgroupTripleValidate, NULL},
{"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
0, NULL, bootParameterValidate, NULL},
{"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )",
SLAP_SYNTAX_HIDE, NULL,
serialNumberAndIssuerValidate,
serialNumberAndIssuerPretty},
{"( 1.3.6.1.1.15.2 DESC 'Certificate Assertion' )",
SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( 1.3.6.1.1.15.3 DESC 'Certificate Pair Exact Assertion' )",
SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( 1.3.6.1.1.15.4 DESC 'Certificate Pair Assertion' )",
SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( 1.3.6.1.1.15.5 DESC 'Certificate List Exact Assertion' )",
SLAP_SYNTAX_HIDE, NULL,
issuerAndThisUpdateValidate,
issuerAndThisUpdatePretty},
{"( 1.3.6.1.1.15.6 DESC 'Certificate List Assertion' )",
SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( 1.3.6.1.1.15.7 DESC 'Algorithm Identifier' )",
SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
{"( " attributeCertificateExactAssertionSyntaxOID " DESC 'AttributeCertificate Exact Assertion' )",
SLAP_SYNTAX_HIDE, NULL,
serialNumberAndIssuerSerialValidate,
serialNumberAndIssuerSerialPretty},
{"( " attributeCertificateAssertionSyntaxOID " DESC 'AttributeCertificate Assertion' )",
SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
#ifdef SLAPD_AUTHPASSWD
{"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
#endif
{"( 1.3.6.1.1.16.1 DESC 'UUID' )",
0, NULL, UUIDValidate, UUIDPretty},
{"( 1.3.6.1.4.1.4203.666.11.2.1 DESC 'CSN' )",
SLAP_SYNTAX_HIDE, NULL, csnValidate, csnPretty },
{"( 1.3.6.1.4.1.4203.666.11.2.4 DESC 'CSN SID' )",
SLAP_SYNTAX_HIDE, NULL, sidValidate, sidPretty },
{"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
SLAP_SYNTAX_HIDE, NULL, inValidate, NULL},
{"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
SLAP_SYNTAX_HIDE, NULL, authzValidate, authzPretty},
{NULL, 0, NULL, NULL, NULL}
};
char *csnSIDMatchSyntaxes[] = {
"1.3.6.1.4.1.4203.666.11.2.1" ,
NULL
};
char *certificateExactMatchSyntaxes[] = {
"1.3.6.1.4.1.1466.115.121.1.8" ,
NULL
};
char *certificateListExactMatchSyntaxes[] = {
"1.3.6.1.4.1.1466.115.121.1.9" ,
NULL
};
char *attributeCertificateExactMatchSyntaxes[] = {
attributeCertificateSyntaxOID ,
NULL
};
#ifdef LDAP_COMP_MATCH
char *componentFilterMatchSyntaxes[] = {
"1.3.6.1.4.1.1466.115.121.1.8" ,
"1.3.6.1.4.1.1466.115.121.1.9" ,
attributeCertificateSyntaxOID ,
NULL
};
#endif
char *directoryStringSyntaxes[] = {
"1.3.6.1.4.1.1466.115.121.1.44" ,
NULL
};
char *integerFirstComponentMatchSyntaxes[] = {
"1.3.6.1.4.1.1466.115.121.1.27" ,
"1.3.6.1.4.1.1466.115.121.1.17" ,
NULL
};
char *objectIdentifierFirstComponentMatchSyntaxes[] = {
"1.3.6.1.4.1.1466.115.121.1.38" ,
"1.3.6.1.4.1.1466.115.121.1.3" ,
"1.3.6.1.4.1.1466.115.121.1.16" ,
"1.3.6.1.4.1.1466.115.121.1.54" ,
"1.3.6.1.4.1.1466.115.121.1.30" ,
"1.3.6.1.4.1.1466.115.121.1.31" ,
"1.3.6.1.4.1.1466.115.121.1.35" ,
"1.3.6.1.4.1.1466.115.121.1.37" ,
NULL
};
static slap_mrule_defs_rec mrule_defs[] = {
{"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
NULL, NULL, directoryStringApproxMatch,
directoryStringApproxIndexer, directoryStringApproxFilter,
NULL},
{"( " IA5StringApproxMatchOID " NAME 'IA5StringApproxMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL,
NULL, NULL, IA5StringApproxMatch,
IA5StringApproxIndexer, IA5StringApproxFilter,
NULL},
{"( 2.5.13.0 NAME 'objectIdentifierMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, NULL, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.1 NAME 'distinguishedNameMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, dnNormalize, dnMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 1.3.6.1.4.1.4203.666.4.9 NAME 'dnSubtreeMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
NULL, dnNormalize, dnRelativeMatch,
NULL, NULL,
NULL },
{"( 1.3.6.1.4.1.4203.666.4.8 NAME 'dnOneLevelMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
NULL, dnNormalize, dnRelativeMatch,
NULL, NULL,
NULL },
{"( 1.3.6.1.4.1.4203.666.4.10 NAME 'dnSubordinateMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
NULL, dnNormalize, dnRelativeMatch,
NULL, NULL,
NULL },
{"( 1.3.6.1.4.1.4203.666.4.11 NAME 'dnSuperiorMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )",
SLAP_MR_HIDE | SLAP_MR_EXT, NULL,
NULL, dnNormalize, dnRelativeMatch,
NULL, NULL,
NULL },
{"( 1.2.36.79672281.1.13.3 NAME 'rdnMatch' "
"SYNTAX 1.2.36.79672281.1.5.0 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, rdnNormalize, rdnMatch,
octetStringIndexer, octetStringFilter,
NULL },
#ifdef LDAP_COMP_MATCH
{"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
"SYNTAX 1.2.36.79672281.1.5.2 )",
SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
NULL, NULL , componentFilterMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
"SYNTAX 1.2.36.79672281.1.5.3 )",
SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
NULL, NULL , allComponentsMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
"SYNTAX 1.2.36.79672281.1.5.3 )",
SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
NULL, NULL , directoryComponentsMatch,
octetStringIndexer, octetStringFilter,
NULL },
#endif
{"( 2.5.13.2 NAME 'caseIgnoreMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
NULL, UTF8StringNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
directoryStringApproxMatchOID },
{"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
NULL, UTF8StringNormalize, octetStringOrderingMatch,
NULL, NULL,
"caseIgnoreMatch" },
{"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
SLAP_MR_SUBSTR, directoryStringSyntaxes,
NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
octetStringSubstringsIndexer, octetStringSubstringsFilter,
"caseIgnoreMatch" },
{"( 2.5.13.5 NAME 'caseExactMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, directoryStringSyntaxes,
NULL, UTF8StringNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
directoryStringApproxMatchOID },
{"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
NULL, UTF8StringNormalize, octetStringOrderingMatch,
NULL, NULL,
"caseExactMatch" },
{"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
SLAP_MR_SUBSTR, directoryStringSyntaxes,
NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
octetStringSubstringsIndexer, octetStringSubstringsFilter,
"caseExactMatch" },
{"( 2.5.13.8 NAME 'numericStringMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, numericStringNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
NULL, numericStringNormalize, octetStringOrderingMatch,
NULL, NULL,
"numericStringMatch" },
{"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
SLAP_MR_SUBSTR, NULL,
NULL, numericStringNormalize, octetStringSubstringsMatch,
octetStringSubstringsIndexer, octetStringSubstringsFilter,
"numericStringMatch" },
{"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, postalAddressNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
SLAP_MR_SUBSTR, NULL,
NULL, NULL, NULL, NULL, NULL,
"caseIgnoreListMatch" },
{"( 2.5.13.13 NAME 'booleanMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, NULL, booleanMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.14 NAME 'integerMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
NULL, NULL, integerMatch,
integerIndexer, integerFilter,
NULL },
{"( 2.5.13.15 NAME 'integerOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
NULL, NULL, integerMatch,
NULL, NULL,
"integerMatch" },
{"( 2.5.13.16 NAME 'bitStringMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, NULL, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.17 NAME 'octetStringMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, NULL, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
NULL, NULL, octetStringOrderingMatch,
NULL, NULL,
"octetStringMatch" },
{"( 2.5.13.19 NAME 'octetStringSubstringsMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
SLAP_MR_SUBSTR, NULL,
NULL, NULL, octetStringSubstringsMatch,
octetStringSubstringsIndexer, octetStringSubstringsFilter,
"octetStringMatch" },
{"( 2.5.13.20 NAME 'telephoneNumberMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL,
telephoneNumberNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
SLAP_MR_SUBSTR, NULL,
NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
octetStringSubstringsIndexer, octetStringSubstringsFilter,
"telephoneNumberMatch" },
{"( 2.5.13.22 NAME 'presentationAddressMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.43 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, NULL, NULL, NULL, NULL, NULL },
{"( 2.5.13.23 NAME 'uniqueMemberMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, uniqueMemberNormalize, uniqueMemberMatch,
uniqueMemberIndexer, uniqueMemberFilter,
NULL },
{"( 2.5.13.24 NAME 'protocolInformationMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, NULL, NULL, NULL, NULL, NULL },
{"( 2.5.13.27 NAME 'generalizedTimeMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
NULL, generalizedTimeNormalize, octetStringMatch,
generalizedTimeIndexer, generalizedTimeFilter,
NULL },
{"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
NULL, NULL,
"generalizedTimeMatch" },
{"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT,
integerFirstComponentMatchSyntaxes,
NULL, firstComponentNormalize, integerMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT,
objectIdentifierFirstComponentMatchSyntaxes,
NULL, firstComponentNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.34 NAME 'certificateExactMatch' "
"SYNTAX 1.3.6.1.1.15.1 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
NULL, certificateExactNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.35 NAME 'certificateMatch' "
"SYNTAX 1.3.6.1.1.15.2 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL },
{"( 2.5.13.38 NAME 'certificateListExactMatch' "
"SYNTAX 1.3.6.1.1.15.5 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
NULL, certificateListExactNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.39 NAME 'certificateListMatch' "
"SYNTAX 1.3.6.1.1.15.6 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL },
{"( 2.5.13.45 NAME 'attributeCertificateExactMatch' "
"SYNTAX " attributeCertificateExactAssertionSyntaxOID " )",
SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, attributeCertificateExactMatchSyntaxes,
NULL, attributeCertificateExactNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.46 NAME 'attributeCertificateMatch' "
"SYNTAX " attributeCertificateAssertionSyntaxOID " )",
SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_HIDE, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL },
{"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, IA5StringNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
IA5StringApproxMatchOID },
{"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, IA5StringNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
IA5StringApproxMatchOID },
{"( 1.3.6.1.4.1.1466.109.114.3 NAME 'caseIgnoreIA5SubstringsMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
SLAP_MR_SUBSTR, NULL,
NULL, IA5StringNormalize, directoryStringSubstringsMatch,
octetStringSubstringsIndexer, octetStringSubstringsFilter,
"caseIgnoreIA5Match" },
{"( 1.3.6.1.4.1.4203.1.2.1 NAME 'caseExactIA5SubstringsMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
SLAP_MR_SUBSTR, NULL,
NULL, IA5StringNormalize, directoryStringSubstringsMatch,
octetStringSubstringsIndexer, octetStringSubstringsFilter,
"caseExactIA5Match" },
#ifdef SLAPD_AUTHPASSWD
{"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
NULL, NULL, authPasswordMatch,
NULL, NULL,
NULL},
#endif
{"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
SLAP_MR_EXT, NULL,
NULL, NULL, integerBitAndMatch,
NULL, NULL,
"integerMatch" },
{"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
SLAP_MR_EXT, NULL,
NULL, NULL, integerBitOrMatch,
NULL, NULL,
"integerMatch" },
{"( 1.3.6.1.1.16.2 NAME 'UUIDMatch' "
"SYNTAX 1.3.6.1.1.16.1 )",
SLAP_MR_EQUALITY | SLAP_MR_MUTATION_NORMALIZER, NULL,
NULL, UUIDNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL},
{"( 1.3.6.1.1.16.3 NAME 'UUIDOrderingMatch' "
"SYNTAX 1.3.6.1.1.16.1 )",
SLAP_MR_ORDERING | SLAP_MR_MUTATION_NORMALIZER, NULL,
NULL, UUIDNormalize, octetStringOrderingMatch,
octetStringIndexer, octetStringFilter,
"UUIDMatch"},
{"( 1.3.6.1.4.1.4203.666.11.2.2 NAME 'CSNMatch' "
"SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_ORDERED_INDEX, NULL,
NULL, csnNormalize, csnMatch,
csnIndexer, csnFilter,
NULL},
{"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
NULL, csnNormalize, csnOrderingMatch,
NULL, NULL,
"CSNMatch" },
{"( 1.3.6.1.4.1.4203.666.11.2.5 NAME 'CSNSIDMatch' "
"SYNTAX 1.3.6.1.4.1.4203.666.11.2.4 )",
SLAP_MR_HIDE | SLAP_MR_EQUALITY | SLAP_MR_EXT, csnSIDMatchSyntaxes,
NULL, csnSidNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
"SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
NULL, authzNormalize, authzMatch,
NULL, NULL,
NULL},
{NULL, SLAP_MR_NONE, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL }
};
int
slap_schema_init( void )
{
int res;
int i;
assert( schema_init_done == 0 );
for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) {
res = register_syntax( &syntax_defs[i] );
if ( res ) {
fprintf( stderr, "slap_schema_init: Error registering syntax %s\n",
syntax_defs[i].sd_desc );
return LDAP_OTHER;
}
}
for ( i=0; mrule_defs[i].mrd_desc != NULL; i++ ) {
if( mrule_defs[i].mrd_usage == SLAP_MR_NONE &&
mrule_defs[i].mrd_compat_syntaxes == NULL )
{
fprintf( stderr,
"slap_schema_init: Ignoring unusable matching rule %s\n",
mrule_defs[i].mrd_desc );
continue;
}
res = register_matching_rule( &mrule_defs[i] );
if ( res ) {
fprintf( stderr,
"slap_schema_init: Error registering matching rule %s\n",
mrule_defs[i].mrd_desc );
return LDAP_OTHER;
}
}
res = slap_schema_load();
schema_init_done = 1;
return res;
}
void
schema_destroy( void )
{
oidm_destroy();
oc_destroy();
at_destroy();
mr_destroy();
mru_destroy();
syn_destroy();
if( schema_init_done ) {
ldap_pvt_thread_mutex_destroy( &ad_index_mutex );
ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );
}
}