X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fschema_init.c;h=c5fd69a2bda218dc705d08fac0956b928a9681cd;hb=37d65aed6e108ba43e158121086df6ce0076bd85;hp=e8c97c30e9b708c2b32f7ac1040521680105f3cb;hpb=02a85a1c935fb4668f029329e84bab304ebc7e1c;p=openldap diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c index e8c97c30e9..c5fd69a2bd 100644 --- a/servers/slapd/schema_init.c +++ b/servers/slapd/schema_init.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1998-2004 The OpenLDAP Foundation. + * Copyright 1998-2008 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -17,7 +17,9 @@ #include "portable.h" #include +#ifdef HAVE_LIMITS_H #include +#endif #include #include @@ -25,21 +27,10 @@ #include #include "slap.h" +#include "../../libraries/liblber/lber-int.h" /* get ber_ptrlen() */ #include "ldap_utf8.h" -#ifdef HAVE_TLS -#include -#include -#include -#include -#include -#include -#include -#include -#include -#endif - #include "lutil.h" #include "lutil_hash.h" #define HASH_BYTES LUTIL_HASH_BYTES @@ -48,8 +39,6 @@ #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len) #define HASH_Final(d,c) lutil_HASHFinal(d,c) -#define OpenLDAPaciMatch NULL - /* approx matching rules */ #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4" #define directoryStringApproxMatch approxMatch @@ -61,17 +50,30 @@ #define IA5StringApproxFilter approxFilter /* Change Sequence Number (CSN) - much of this will change */ -#define csnValidate blobValidate #define csnMatch octetStringMatch #define csnOrderingMatch octetStringOrderingMatch #define csnIndexer generalizedTimeIndexer #define csnFilter generalizedTimeFilter +#define authzMatch octetStringMatch + 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_undef_mutex; +ldap_pvt_thread_mutex_t oc_undef_mutex; + +static int +generalizedTimeValidate( + Syntax *syntax, + struct berval *in ); + static int inValidate( Syntax *syntax, @@ -103,23 +105,167 @@ sequenceValidate( return LDAP_SUCCESS; } +/* X.509 related stuff */ + +enum { + SLAP_X509_V1 = 0, + SLAP_X509_V2 = 1, + SLAP_X509_V3 = 2 +}; + +#define SLAP_X509_OPTION (LBER_CLASS_CONTEXT|LBER_CONSTRUCTED) + +enum { + SLAP_X509_OPT_C_VERSION = SLAP_X509_OPTION + 0, + SLAP_X509_OPT_C_ISSUERUNIQUEID = SLAP_X509_OPTION + 1, + SLAP_X509_OPT_C_SUBJECTUNIQUEID = SLAP_X509_OPTION + 2, + SLAP_X509_OPT_C_EXTENSIONS = SLAP_X509_OPTION + 3 +}; + +enum { + SLAP_X509_OPT_CL_CRLEXTENSIONS = SLAP_X509_OPTION + 0 +}; -#ifdef HAVE_TLS +/* X.509 certificate validation */ static int certificateValidate( Syntax *syntax, struct berval *in ) { - X509 *xcert=NULL; - unsigned char *p = (unsigned char *)in->bv_val; - - xcert = d2i_X509(NULL, &p, in->bv_len); - if ( !xcert ) return LDAP_INVALID_SYNTAX; - X509_free(xcert); + 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 ); /* Signed wrapper */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + tag = ber_skip_tag( ber, &len ); /* Sequence */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + tag = ber_peek_tag( ber, &len ); + /* Optional version */ + 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; + } + /* NOTE: don't try to parse Serial, because it might be longer + * than sizeof(ber_int_t); deferred to certificateExactNormalize() */ + tag = ber_skip_tag( ber, &len ); /* Serial */ + if ( tag != LBER_INTEGER ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); /* Issuer DN */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); /* Validity */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); /* Subject DN */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); /* Subject PublicKeyInfo */ + 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 ) { /* 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 ) { /* 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 ) { /* 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 ); + } + /* signatureAlgorithm */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); + /* Signature */ + if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); + /* Must be at end now */ + if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX; return LDAP_SUCCESS; } -#else -#define certificateValidate sequenceValidate -#endif -static int +/* X.509 certificate list validation */ +static int certificateListValidate( 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 ); /* Signed wrapper */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + tag = ber_skip_tag( ber, &len ); /* Sequence */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + tag = ber_peek_tag( ber, &len ); + /* Optional version */ + 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 ); /* Signature Algorithm */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); /* Issuer DN */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); /* thisUpdate */ + /* Time is a CHOICE { UTCTime, GeneralizedTime } */ + if ( tag != 0x17U && tag != 0x18U ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + /* Optional nextUpdate */ + tag = ber_skip_tag( ber, &len ); + if ( tag == 0x17U || tag == 0x18U ) { + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); + } + /* revokedCertificates - Sequence of Sequence, Optional */ + if ( tag == LBER_SEQUENCE ) { + ber_len_t seqlen; + if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) { + /* Should NOT be empty */ + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); + } + } + /* Optional Extensions */ + if ( tag == SLAP_X509_OPT_CL_CRLEXTENSIONS ) { /* ? */ + 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_skip_tag( ber, &len ); + } + /* signatureAlgorithm */ + if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); + /* Signature */ + if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX; + ber_skip_data( ber, len ); + tag = ber_skip_tag( ber, &len ); + /* Must be at end now */ + if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX; + return LDAP_SUCCESS; +} + +int octetStringMatch( int *matchp, slap_mask_t flags, @@ -139,7 +285,7 @@ octetStringMatch( return LDAP_SUCCESS; } -static int +int octetStringOrderingMatch( int *matchp, slap_mask_t flags, @@ -161,15 +307,13 @@ octetStringOrderingMatch( return LDAP_SUCCESS; } -hashDigestify( +static void +hashPreset( HASH_CONTEXT *HASHcontext, - unsigned char *HASHdigest, struct berval *prefix, char pre, Syntax *syntax, - MatchingRule *mr, - unsigned char *value, - int value_len) + MatchingRule *mr) { HASH_Init(HASHcontext); if(prefix && prefix->bv_len > 0) { @@ -179,11 +323,21 @@ hashDigestify( 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); - HASH_Update(HASHcontext, value, value_len); - HASH_Final(HASHdigest, HASHcontext); 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 ); +} + /* Index generation function */ int octetStringIndexer( slap_mask_t use, @@ -204,7 +358,7 @@ int octetStringIndexer( digest.bv_val = (char *)HASHdigest; digest.bv_len = sizeof(HASHdigest); - for( i=0; values[i].bv_val != NULL; i++ ) { + for( i=0; !BER_BVISNULL( &values[i] ); i++ ) { /* just count them */ } @@ -216,14 +370,14 @@ int octetStringIndexer( slen = syntax->ssyn_oidlen; mlen = mr->smr_oidlen; - for( i=0; values[i].bv_val != NULL; i++ ) { - hashDigestify( &HASHcontext, HASHdigest, prefix, 0, - syntax, mr, (unsigned char *)values[i].bv_val, values[i].bv_len ); + 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 ); } - keys[i].bv_val = NULL; - keys[i].bv_len = 0; + BER_BVZERO( &keys[i] ); *keysp = keys; @@ -255,12 +409,12 @@ int octetStringFilter( keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); - hashDigestify( &HASHcontext, HASHdigest, prefix, 0, - syntax, mr, (unsigned char *)value->bv_val, value->bv_len ); + hashPreset( &HASHcontext, prefix, 0, syntax, mr ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)value->bv_val, value->bv_len ); ber_dupbv_x( keys, &digest, ctx ); - keys[1].bv_val = NULL; - keys[1].bv_len = 0; + BER_BVZERO( &keys[1] ); *keysp = keys; @@ -283,20 +437,20 @@ octetStringSubstringsMatch( ber_len_t inlen = 0; /* Add up asserted input length */ - if( sub->sa_initial.bv_val ) { + if ( !BER_BVISNULL( &sub->sa_initial ) ) { inlen += sub->sa_initial.bv_len; } - if( sub->sa_any ) { - for(i=0; sub->sa_any[i].bv_val != NULL; i++) { + if ( sub->sa_any ) { + for ( i = 0; !BER_BVISNULL( &sub->sa_any[i] ); i++ ) { inlen += sub->sa_any[i].bv_len; } } - if( sub->sa_final.bv_val ) { + if ( !BER_BVISNULL( &sub->sa_final ) ) { inlen += sub->sa_final.bv_len; } - if( sub->sa_initial.bv_val ) { - if( inlen > left.bv_len ) { + if ( !BER_BVISNULL( &sub->sa_initial ) ) { + if ( inlen > left.bv_len ) { match = 1; goto done; } @@ -304,7 +458,7 @@ octetStringSubstringsMatch( match = memcmp( sub->sa_initial.bv_val, left.bv_val, sub->sa_initial.bv_len ); - if( match != 0 ) { + if ( match != 0 ) { goto done; } @@ -313,8 +467,8 @@ octetStringSubstringsMatch( inlen -= sub->sa_initial.bv_len; } - if( sub->sa_final.bv_val ) { - if( inlen > left.bv_len ) { + if ( !BER_BVISNULL( &sub->sa_final ) ) { + if ( inlen > left.bv_len ) { match = 1; goto done; } @@ -323,7 +477,7 @@ octetStringSubstringsMatch( &left.bv_val[left.bv_len - sub->sa_final.bv_len], sub->sa_final.bv_len ); - if( match != 0 ) { + if ( match != 0 ) { goto done; } @@ -331,19 +485,19 @@ octetStringSubstringsMatch( inlen -= sub->sa_final.bv_len; } - if( sub->sa_any ) { - for(i=0; sub->sa_any[i].bv_val; i++) { + 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 ) { + if ( inlen > left.bv_len ) { /* not enough length */ match = 1; goto done; } - if( sub->sa_any[i].bv_len == 0 ) { + if ( BER_BVISEMPTY( &sub->sa_any[i] ) ) { continue; } @@ -356,7 +510,7 @@ retry: idx = p - left.bv_val; - if( idx >= left.bv_len ) { + if ( idx >= left.bv_len ) { /* this shouldn't happen */ return LDAP_OTHER; } @@ -364,7 +518,7 @@ retry: left.bv_val = p; left.bv_len -= idx; - if( sub->sa_any[i].bv_len > left.bv_len ) { + if ( sub->sa_any[i].bv_len > left.bv_len ) { /* not enough left */ match = 1; goto done; @@ -374,7 +528,7 @@ retry: sub->sa_any[i].bv_val, sub->sa_any[i].bv_len ); - if( match != 0 ) { + if ( match != 0 ) { left.bv_val++; left.bv_len--; goto retry; @@ -403,19 +557,19 @@ octetStringSubstringsIndexer( BerVarray *keysp, void *ctx ) { - ber_len_t i, j, len, nkeys; + ber_len_t i, nkeys; size_t slen, mlen; BerVarray keys; - HASH_CONTEXT HASHcontext; + 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; + nkeys = 0; - for( i=0; values[i].bv_val != NULL; i++ ) { + for ( i = 0; !BER_BVISNULL( &values[i] ); i++ ) { /* count number of indices to generate */ if( flags & SLAP_INDEX_SUBSTR_INITIAL ) { if( values[i].bv_len >= index_substr_if_maxlen ) { @@ -453,19 +607,26 @@ octetStringSubstringsIndexer( slen = syntax->ssyn_oidlen; mlen = mr->smr_oidlen; - nkeys=0; - for( i=0; values[i].bv_val != NULL; i++ ) { + 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 ) ) { - char pre = SLAP_INDEX_SUBSTR_PREFIX; max = values[i].bv_len - (index_substr_any_len - 1); for( j=0; j 0 ) { - keys[nkeys].bv_val = NULL; + BER_BVZERO( &keys[nkeys] ); *keysp = keys; } else { ch_free( keys ); @@ -520,7 +678,7 @@ octetStringSubstringsFilter ( { SubstringsAssertion *sa; char pre; - ber_len_t len, max, nkeys = 0; + ber_len_t nkeys = 0; size_t slen, mlen, klen; BerVarray keys; HASH_CONTEXT HASHcontext; @@ -531,20 +689,20 @@ octetStringSubstringsFilter ( sa = (SubstringsAssertion *) assertedValue; if( flags & SLAP_INDEX_SUBSTR_INITIAL && - sa->sa_initial.bv_val != NULL && + !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 += (sa->sa_initial.bv_len - index_substr_if_maxlen) / index_substr_any_step; + 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 ) { + if ( flags & SLAP_INDEX_SUBSTR_ANY && sa->sa_any != NULL ) { ber_len_t i; - for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) { + for( i=0; !BER_BVISNULL( &sa->sa_any[i] ); i++ ) { if( sa->sa_any[i].bv_len >= index_substr_any_len ) { /* don't bother accounting with stepping */ nkeys += sa->sa_any[i].bv_len - @@ -554,14 +712,14 @@ octetStringSubstringsFilter ( } if( flags & SLAP_INDEX_SUBSTR_FINAL && - sa->sa_final.bv_val != NULL && + !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 += (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step; + nkeys += 1 + (sa->sa_final.bv_len - index_substr_if_maxlen) / index_substr_any_step; } } @@ -580,7 +738,7 @@ octetStringSubstringsFilter ( nkeys = 0; if( flags & SLAP_INDEX_SUBSTR_INITIAL && - sa->sa_initial.bv_val != NULL && + !BER_BVISNULL( &sa->sa_initial ) && sa->sa_initial.bv_len >= index_substr_if_minlen ) { pre = SLAP_INDEX_SUBSTR_INITIAL_PREFIX; @@ -589,8 +747,9 @@ octetStringSubstringsFilter ( klen = index_substr_if_maxlen < value->bv_len ? index_substr_if_maxlen : value->bv_len; - hashDigestify( &HASHcontext, HASHdigest, prefix, pre, - syntax, mr, (unsigned char *)value->bv_val, klen ); + hashPreset( &HASHcontext, prefix, pre, syntax, mr ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)value->bv_val, klen ); ber_dupbv_x( &keys[nkeys++], &digest, ctx ); /* If initial is too long and we have subany indexed, use it @@ -600,10 +759,11 @@ octetStringSubstringsFilter ( { 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 ) { - hashDigestify( &HASHcontext, HASHdigest, prefix, pre, - syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)&value->bv_val[j], index_substr_any_len ); ber_dupbv_x( &keys[nkeys++], &digest, ctx ); } } @@ -614,26 +774,27 @@ octetStringSubstringsFilter ( pre = SLAP_INDEX_SUBSTR_PREFIX; klen = index_substr_any_len; - for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) { + 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 ) { - hashDigestify( &HASHcontext, HASHdigest, prefix, pre, - syntax, mr, (unsigned char *)&value->bv_val[j], klen ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)&value->bv_val[j], klen ); ber_dupbv_x( &keys[nkeys++], &digest, ctx ); } } } if( flags & SLAP_INDEX_SUBSTR_FINAL && - sa->sa_final.bv_val != NULL && + !BER_BVISNULL( &sa->sa_final ) && sa->sa_final.bv_len >= index_substr_if_minlen ) { pre = SLAP_INDEX_SUBSTR_FINAL_PREFIX; @@ -642,8 +803,9 @@ octetStringSubstringsFilter ( klen = index_substr_if_maxlen < value->bv_len ? index_substr_if_maxlen : value->bv_len; - hashDigestify( &HASHcontext, HASHdigest, prefix, pre, - syntax, mr, (unsigned char *)&value->bv_val[value->bv_len-klen], klen ); + 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 final is too long and we have subany indexed, use it @@ -653,17 +815,18 @@ octetStringSubstringsFilter ( { 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 ) { - hashDigestify( &HASHcontext, HASHdigest, prefix, pre, - syntax, mr, (unsigned char *)&value->bv_val[j], index_substr_any_len ); + hashIter( &HASHcontext, HASHdigest, + (unsigned char *)&value->bv_val[j], index_substr_any_len ); ber_dupbv_x( &keys[nkeys++], &digest, ctx ); } } } if( nkeys > 0 ) { - keys[nkeys].bv_val = NULL; + BER_BVZERO( &keys[nkeys] ); *keysp = keys; } else { ch_free( keys ); @@ -687,21 +850,24 @@ bitStringValidate( return LDAP_INVALID_SYNTAX; } - /* - * RFC 2252 section 6.3 Bit String - * bitstring = "'" *binary-digit "'B" - * binary-digit = "0" / "1" - * example: '0101111101'B + /* RFC 4517 Section 3.3.2 Bit String: + * BitString = SQUOTE *binary-digit SQUOTE "B" + * binary-digit = "0" / "1" + * + * where SQUOTE [RFC4512] is + * SQUOTE = %x27 ; single quote ("'") + * + * Example: '0101111101'B */ if( in->bv_val[0] != '\'' || - in->bv_val[in->bv_len-2] != '\'' || - in->bv_val[in->bv_len-1] != 'B' ) + 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-- ) { + for( i = in->bv_len - 3; i > 0; i-- ) { if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) { return LDAP_INVALID_SYNTAX; } @@ -711,39 +877,7 @@ bitStringValidate( } /* - * Syntax is [RFC2252]: - * - -6.3. Bit String - - ( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' ) - - Values in this syntax are encoded according to the following BNF: - - bitstring = "'" *binary-digit "'B" - - binary-digit = "0" / "1" - - ... - -6.21. Name And Optional UID - - ( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' ) - - Values in this syntax are encoded according to the following BNF: - - NameAndOptionalUID = DistinguishedName [ "#" bitstring ] - - Although the '#' character may occur in a string representation of a - distinguished name, no additional special quoting is done. This - syntax has been added subsequent to RFC 1778. - - Example: - - 1.3.6.1.4.1.1466.0=#04024869,O=Test,C=GB#'0101'B - - * - * draft-ietf-ldapbis-syntaxes-xx.txt says: + * Syntaxes from RFC 4517 * 3.3.2. Bit String @@ -801,7 +935,7 @@ bitStringValidate( [X.520]. * - * draft-ietf-ldapbis-models-xx.txt [MODELS] says: + * RFC 4512 says: * 1.4. Common ABNF Productions @@ -819,11 +953,11 @@ bitStringValidate( * * 1.3.6.1.4.1.1466.0=#04024869,o=test,c=gb#'101'B * - * Since draft-ietf-ldapbis-dn-xx.txt clarifies that SHARP, - * i.e. "#", doesn't have to be escaped except when at the - * beginning of a value, the definition of Name and Optional - * UID appears to be flawed, because there is no clear means - * to determine whether the UID part is present or not. + * RFC 4514 clarifies that SHARP, i.e. "#", doesn't have to + * be escaped except when at the beginning of a value, the + * definition of Name and Optional UID appears to be flawed, + * because there is no clear means to determine whether the + * UID part is present or not. * * Example: * @@ -858,14 +992,14 @@ nameUIDValidate( int rc; struct berval dn, uid; - if( in->bv_len == 0 ) return LDAP_SUCCESS; + if( BER_BVISEMPTY( in ) ) return LDAP_SUCCESS; ber_dupbv( &dn, in ); if( !dn.bv_val ) return LDAP_OTHER; /* if there's a "#", try bitStringValidate()... */ uid.bv_val = strrchr( dn.bv_val, '#' ); - if ( uid.bv_val ) { + if ( !BER_BVISNULL( &uid ) ) { uid.bv_val++; uid.bv_len = dn.bv_len - ( uid.bv_val - dn.bv_val ); @@ -891,13 +1025,13 @@ nameUIDPretty( struct berval *out, void *ctx ) { - assert( val ); - assert( out ); + assert( val != NULL ); + assert( out != NULL ); Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 ); - if( val->bv_len == 0 ) { + if( BER_BVISEMPTY( val ) ) { ber_dupbv_x( out, val, ctx ); } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { @@ -909,7 +1043,7 @@ nameUIDPretty( struct berval uidval = BER_BVNULL; uidval.bv_val = strrchr( val->bv_val, '#' ); - if ( uidval.bv_val ) { + if ( !BER_BVISNULL( &uidval ) ) { uidval.bv_val++; uidval.bv_len = val->bv_len - ( uidval.bv_val - val->bv_val ); @@ -921,7 +1055,7 @@ nameUIDPretty( dnval.bv_val[dnval.bv_len] = '\0'; } else { - uidval.bv_val = NULL; + BER_BVZERO( &uidval ); } } @@ -933,7 +1067,7 @@ nameUIDPretty( return rc; } - if( uidval.bv_val ) { + if( !BER_BVISNULL( &uidval ) ) { int i, c, got1; char *tmp; @@ -985,7 +1119,7 @@ uniqueMemberNormalize( struct berval out; int rc; - assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage )); + assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); ber_dupbv_x( &out, val, ctx ); if ( BER_BVISEMPTY( &out ) ) { @@ -995,7 +1129,7 @@ uniqueMemberNormalize( struct berval uid = BER_BVNULL; uid.bv_val = strrchr( out.bv_val, '#' ); - if ( uid.bv_val ) { + if ( !BER_BVISNULL( &uid ) ) { uid.bv_val++; uid.bv_len = out.bv_len - ( uid.bv_val - out.bv_val ); @@ -1004,7 +1138,7 @@ uniqueMemberNormalize( uid.bv_val[-1] = '\0'; out.bv_len -= uid.bv_len + 1; } else { - uid.bv_val = NULL; + BER_BVZERO( &uid ); } } @@ -1015,7 +1149,7 @@ uniqueMemberNormalize( return LDAP_INVALID_SYNTAX; } - if( uid.bv_val ) { + if( !BER_BVISNULL( &uid ) ) { char *tmp; tmp = ch_realloc( normalized->bv_val, @@ -1059,8 +1193,9 @@ uniqueMemberMatch( struct berval *asserted = (struct berval *) assertedValue; struct berval assertedDN = *asserted; struct berval assertedUID = BER_BVNULL; - struct berval valueDN = 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, '#' ); @@ -1079,7 +1214,6 @@ uniqueMemberMatch( } if ( !BER_BVISEMPTY( value ) ) { - valueDN = *value; valueUID.bv_val = strrchr( valueDN.bv_val, '#' ); if ( !BER_BVISNULL( &valueUID ) ) { @@ -1108,11 +1242,109 @@ uniqueMemberMatch( *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++ ) { + /* just count them */ + } + 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 ); +} + + /* * Handling boolean syntax and matching is quite rigid. * A more flexible approach would be to allow a variety @@ -1171,7 +1403,7 @@ Summary: TelephoneNumber subset subset i + ignore all spaces and "-" - See draft-ietf-ldapbis-strpro for details (once published). + See RFC 4518 for details. Directory String - @@ -1219,12 +1451,11 @@ PrintableString In ASN.1, Printable string is just a string of printable characters and can be empty. In X.500, semantics much like NumericString (see serialNumber for a like example) excepting uses insignificant space - handling instead of ignore all spaces. + handling instead of ignore all spaces. They must be non-empty. IA5String Basically same as PrintableString. There are no examples in X.500, - but same logic applies. So we require them to be non-empty as - well. + but same logic applies. Empty strings are allowed. -------------------------------------------------------------------*/ @@ -1237,12 +1468,12 @@ UTF8StringValidate( int len; unsigned char *u = (unsigned char *)in->bv_val; - if( in->bv_len == 0 && syntax == slap_schema.si_syn_directoryString ) { + if( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) { /* directory strings cannot be empty */ return LDAP_INVALID_SYNTAX; } - for( count = in->bv_len; count > 0; count-=len, u+=len ) { + for( count = in->bv_len; count > 0; count -= len, u += len ) { /* get the length indicated by the first byte */ len = LDAP_UTF8_CHARLEN2( u, len ); @@ -1300,14 +1531,13 @@ UTF8StringNormalize( int flags; int i, wasspace; - assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use )); + assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 ); - if( val->bv_val == NULL ) { + if( BER_BVISNULL( val ) ) { /* assume we're dealing with a syntax (e.g., UTF8String) * which allows empty strings */ - normalized->bv_len = 0; - normalized->bv_val = NULL; + BER_BVZERO( normalized ); return LDAP_SUCCESS; } @@ -1325,8 +1555,11 @@ UTF8StringNormalize( nvalue.bv_len = 0; nvalue.bv_val = tmp.bv_val; - wasspace=1; /* trim leading spaces */ - for( i=0; isa_initial ) ) { + if ( sub->sa_initial.bv_len > left.bv_len ) { + /* not enough left */ + 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] )) + { + /* allow next space to match */ + 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 ) { + /* not enough left */ + 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 ) { + /* this shouldn't happen */ + return LDAP_OTHER; + } + + left.bv_val = p; + left.bv_len -= idx; + + if ( sub->sa_any[i].bv_len > left.bv_len ) { + /* not enough left */ + 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] )) + { + /* allow next space to match */ + left.bv_val--; + left.bv_len++; + } + + if ( sub->sa_final.bv_len > left.bv_len ) { + /* not enough left */ + 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 @@ -1489,11 +1856,11 @@ approxIndexer( struct berval *newkeys; BerVarray keys=NULL; - for( j=0; values[j].bv_val != NULL; j++ ) { + for( j = 0; !BER_BVISNULL( &values[j] ); j++ ) { struct berval val = BER_BVNULL; /* Yes, this is necessary */ UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL ); - assert( val.bv_val != NULL ); + assert( !BER_BVISNULL( &val ) ); /* Isolate how many words there are. There will be a key for each */ for( wordcount = 0, c = val.bv_val; *c; c++) { @@ -1522,7 +1889,7 @@ approxIndexer( ber_memfree( val.bv_val ); } - keys[keycount].bv_val = NULL; + BER_BVZERO( &keys[keycount] ); *keysp = keys; return LDAP_SUCCESS; @@ -1547,9 +1914,9 @@ approxFilter( /* Yes, this is necessary */ val = UTF8bvnormalize( ((struct berval *)assertedValue), NULL, LDAP_UTF8_APPROX, NULL ); - if( val == NULL || val->bv_val == NULL ) { + if( val == NULL || BER_BVISNULL( val ) ) { keys = (struct berval *)ch_malloc( sizeof(struct berval) ); - keys[0].bv_val = NULL; + BER_BVZERO( &keys[0] ); *keysp = keys; ber_bvfree( val ); return LDAP_SUCCESS; @@ -1577,7 +1944,7 @@ approxFilter( ber_bvfree( val ); - keys[count].bv_val = NULL; + BER_BVZERO( &keys[count] ); *keysp = keys; return LDAP_SUCCESS; @@ -1595,10 +1962,10 @@ telephoneNumberNormalize( { char *p, *q; - assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage )); + assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); /* validator should have refused an empty string */ - assert( val->bv_len ); + assert( !BER_BVISEMPTY( val ) ); q = normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx ); @@ -1611,23 +1978,23 @@ telephoneNumberNormalize( normalized->bv_len = q - normalized->bv_val; - if( normalized->bv_len == 0 ) { + if( BER_BVISEMPTY( normalized ) ) { slap_sl_free( normalized->bv_val, ctx ); - normalized->bv_val = NULL; + BER_BVZERO( normalized ); return LDAP_INVALID_SYNTAX; } return LDAP_SUCCESS; } -static int +int numericoidValidate( Syntax *syntax, struct berval *in ) { struct berval val = *in; - if( val.bv_len == 0 ) { + if( BER_BVISEMPTY( &val ) ) { /* disallow empty strings */ return LDAP_INVALID_SYNTAX; } @@ -1637,7 +2004,7 @@ numericoidValidate( return LDAP_SUCCESS; } - if ( val.bv_val[0] == '0' ) { + if ( val.bv_val[0] == '0' && !OID_SEPARATOR( val.bv_val[1] )) { break; } @@ -1672,13 +2039,13 @@ integerValidate( ber_len_t i; struct berval val = *in; - if( val.bv_len == 0 ) return LDAP_INVALID_SYNTAX; + if ( BER_BVISEMPTY( &val ) ) return LDAP_INVALID_SYNTAX; if ( val.bv_val[0] == '-' ) { val.bv_len--; val.bv_val++; - if( val.bv_len == 0 ) { /* bare "-" */ + if( BER_BVISEMPTY( &val ) ) { /* bare "-" */ return LDAP_INVALID_SYNTAX; } @@ -1724,7 +2091,7 @@ integerMatch( v.bv_len--; } - if( v.bv_len == 0 ) vsign = 0; + if( BER_BVISEMPTY( &v ) ) vsign = 0; a = *asserted; if( a.bv_val[0] == '-' ) { @@ -1733,7 +2100,7 @@ integerMatch( a.bv_len--; } - if( a.bv_len == 0 ) vsign = 0; + if( BER_BVISEMPTY( &a ) ) vsign = 0; match = vsign - asign; if( match == 0 ) { @@ -1746,15 +2113,194 @@ integerMatch( *matchp = match; return LDAP_SUCCESS; } - + +/* 10**Chop < 256**Chopbytes and Chop > Chopbytes<<1 (for sign bit and itmp) */ +#define INDEX_INTLEN_CHOP 7 +#define INDEX_INTLEN_CHOPBYTES 3 + static int -countryStringValidate( - Syntax *syntax, - struct berval *val ) +integerVal2Key( + struct berval *in, + struct berval *key, + struct berval *tmp, + void *ctx ) { - if( val->bv_len != 2 ) return LDAP_INVALID_SYNTAX; + /* index format: + * only if too large: one's complement , + * two's complement value (sign-extended or chopped as needed), + * however the top bits of first byte + * above is the inverse sign. The next bit is the sign as delimiter. + */ + 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( !SLAP_PRINTABLE(val->bv_val[0]) ) { + /* Chop least significant digits, increase length instead */ + if ( val.bv_len > (ber_len_t) k ) { + chop = (val.bv_len-k+2)/INDEX_INTLEN_CHOP; /* 2 fewer digits */ + val.bv_len -= chop * INDEX_INTLEN_CHOP; /* #digits chopped */ + chop *= INDEX_INTLEN_CHOPBYTES; /* #bytes added */ + } + + if ( lutil_str2bin( &val, &itmp, ctx )) { + return LDAP_INVALID_SYNTAX; + } + + /* Omit leading sign byte */ + 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 ); /* sign-extend */ + } 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) ); + /* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff) + * are 1, and the top n+2 bits of lenp[] are the sign bit. */ + 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; /* invert sign */ + return 0; +} + +/* Index generation function */ +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; + + /* count the values and find max needed length */ + 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; + + /* we should have at least one value at this point */ + 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 leave; + } + *keysp = keys; +leave: + if ( itmp.bv_val != ibuf ) { + slap_sl_free( itmp.bv_val, ctx ); + } + return rc; +} + +/* Index generation function */ +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 ); + + 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]) ) { @@ -1771,7 +2317,7 @@ printableStringValidate( { ber_len_t i; - if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX; + if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX; for(i=0; i < val->bv_len; i++) { if( !SLAP_PRINTABLE(val->bv_val[i]) ) { @@ -1789,7 +2335,7 @@ printablesStringValidate( { ber_len_t i, len; - if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX; + if( BER_BVISEMPTY( val ) ) return LDAP_INVALID_SYNTAX; for(i=0,len=0; i < val->bv_len; i++) { int c = val->bv_val[i]; @@ -1821,8 +2367,6 @@ IA5StringValidate( { ber_len_t i; - if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX; - for(i=0; i < val->bv_len; i++) { if( !LDAP_ASCII(val->bv_val[i]) ) { return LDAP_INVALID_SYNTAX; @@ -1842,18 +2386,21 @@ IA5StringNormalize( void *ctx ) { char *p, *q; - int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match); - - assert( val->bv_len ); + int casefold = !SLAP_MR_ASSOCIATED( mr, + slap_schema.si_mr_caseExactIA5Match ); - assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use )); + assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use ) != 0 ); p = val->bv_val; /* Ignore initial whitespace */ while ( ASCII_SPACE( *p ) ) p++; - normalized->bv_val = ber_strdup_x( p, ctx ); + 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 ) { @@ -1882,18 +2429,12 @@ IA5StringNormalize( * position. One is enough because the above loop collapsed * all whitespace to a single space. */ - if ( ASCII_SPACE( q[-1] ) ) --q; + if ( q > normalized->bv_val && ASCII_SPACE( q[-1] ) ) --q; /* null terminate */ *q = '\0'; normalized->bv_len = q - normalized->bv_val; - if( normalized->bv_len == 0 ) { - 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; } @@ -1929,6 +2470,56 @@ UUIDValidate( } 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, @@ -1940,6 +2531,19 @@ UUIDNormalize( unsigned char octet = '\0'; int i; int j; + + if ( SLAP_MR_IS_DENORMALIZE( usage ) ) { + /* NOTE: must be a normalized UUID */ + 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 ); @@ -1977,14 +2581,14 @@ UUIDNormalize( -static int +int numericStringValidate( Syntax *syntax, struct berval *in ) { ber_len_t i; - if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX; + if( BER_BVISEMPTY( in ) ) return LDAP_INVALID_SYNTAX; for(i=0; i < in->bv_len; i++) { if( !SLAP_NUMERIC(in->bv_val[i]) ) { @@ -2007,7 +2611,7 @@ numericStringNormalize( /* removal all spaces */ char *p, *q; - assert( val->bv_len ); + assert( !BER_BVISEMPTY( val ) ); normalized->bv_val = slap_sl_malloc( val->bv_len + 1, ctx ); @@ -2023,7 +2627,7 @@ numericStringNormalize( } } - /* we should have copied no more then is in val */ + /* we should have copied no more than is in val */ assert( (q - normalized->bv_val) <= (p - val->bv_val) ); /* null terminate */ @@ -2031,7 +2635,7 @@ numericStringNormalize( normalized->bv_len = q - normalized->bv_val; - if( normalized->bv_len == 0 ) { + if( BER_BVISEMPTY( normalized ) ) { normalized->bv_val = slap_sl_realloc( normalized->bv_val, 2, ctx ); normalized->bv_val[0] = ' '; normalized->bv_val[1] = '\0'; @@ -2045,260 +2649,997 @@ numericStringNormalize( * Integer conversion macros that will use the largest available * type. */ -#if defined(HAVE_STRTOLL) && defined(LLONG_MAX) \ - && defined(LLONG_MIN) && defined(HAVE_LONG_LONG) +#if defined(HAVE_STRTOLL) && defined(HAVE_LONG_LONG) # define SLAP_STRTOL(n,e,b) strtoll(n,e,b) -# define SLAP_LONG_MAX LLONG_MAX -# define SLAP_LONG_MIN LLONG_MIN # define SLAP_LONG long long #else # define SLAP_STRTOL(n,e,b) strtol(n,e,b) -# define SLAP_LONG_MAX LONG_MAX -# define SLAP_LONG_MIN LONG_MIN # define SLAP_LONG long #endif /* HAVE_STRTOLL ... */ static int -integerBitAndMatch( - int *matchp, - slap_mask_t flags, +integerBitAndMatch( + int *matchp, + slap_mask_t flags, + Syntax *syntax, + MatchingRule *mr, + struct berval *value, + void *assertedValue ) +{ + SLAP_LONG lValue, lAssertedValue; + + errno = 0; + /* safe to assume integers are NUL terminated? */ + 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; + /* safe to assume integers are NUL terminated? */ + 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 +serialNumberAndIssuerCheck( + struct berval *in, + struct berval *sn, + struct berval *is, + void *ctx +) +{ + int is_hex = 0, n; + + if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX; + + if( in->bv_val[0] != '{' && in->bv_val[in->bv_len-1] != '}' ) { + /* Parse old format */ + 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); + + /* eat leading zeros */ + 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 { + /* Parse GSER format */ + int havesn=0,haveissuer=0; + struct berval x = *in; + struct berval ni; + x.bv_val++; + x.bv_len-=2; + + /* eat leading spaces */ + for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { + /* empty */; + } + + if ( x.bv_len < STRLENOF("serialNumber 0,issuer \"\"")) { + return LDAP_INVALID_SYNTAX; + } + + /* should be at issuer or serialNumber NamedValue */ + if( strncasecmp( x.bv_val, "issuer", STRLENOF("issuer")) == 0 ) { + /* parse issuer */ + 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--; + + /* eat leading spaces */ + for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { + /* empty */; + } + + /* For backward compatibility, this part is optional */ + if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) { + 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] == '"' ) { + /* double dquote */ + is->bv_len+=2; + continue; + } + break; + } + x.bv_val += is->bv_len+1; + x.bv_len -= is->bv_len+1; + + if ( x.bv_len < STRLENOF(",serialNumber 0")) { + return LDAP_INVALID_SYNTAX; + } + + haveissuer++; + + } else if( strncasecmp( x.bv_val, "serialNumber", + STRLENOF("serialNumber")) == 0 ) + { + /* parse serialNumber */ + int neg=0; + 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--; + + /* eat leading spaces */ + for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { + /* empty */; + } + + sn->bv_val = x.bv_val; + sn->bv_len = 0; + + if( sn->bv_val[0] == '-' ) { + neg++; + sn->bv_len++; + } + + if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' || + sn->bv_val[1] == 'X' )) { + is_hex = 1; + for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { + if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; + } + } else if ( sn->bv_val[0] == '\'' ) { + for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { + if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; + } + if ( sn->bv_val[sn->bv_len] == '\'' && + sn->bv_val[sn->bv_len+1] == 'H' ) + is_hex = 1; + else + return LDAP_INVALID_SYNTAX; + sn->bv_len += 2; + } else { + for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { + if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break; + } + } + + if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX; + if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) { + return LDAP_INVALID_SYNTAX; + } + + x.bv_val += sn->bv_len; x.bv_len -= sn->bv_len; + + if ( x.bv_len < STRLENOF( ",issuer \"\"" )) { + return LDAP_INVALID_SYNTAX; + } + + havesn++; + + } else return LDAP_INVALID_SYNTAX; + + if( x.bv_val[0] != ',' ) return LDAP_INVALID_SYNTAX; + x.bv_val++; x.bv_len--; + + /* eat spaces */ + for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { + /* empty */; + } + + /* should be at remaining NamedValue */ + if( !haveissuer && (strncasecmp( x.bv_val, "issuer", + STRLENOF("issuer" )) == 0 )) + { + /* parse issuer */ + 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--; + + /* eat leading spaces */ + for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { + /* empty */; + } + + /* For backward compatibility, this part is optional */ + if( !strncasecmp( x.bv_val, "rdnSequence:", STRLENOF("rdnSequence:"))) { + 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] == '"' ) { + /* double dquote */ + is->bv_len+=2; + continue; + } + break; + } + x.bv_val += is->bv_len+1; + x.bv_len -= is->bv_len+1; + + } else if( !havesn && (strncasecmp( x.bv_val, "serialNumber", + STRLENOF("serialNumber")) == 0 )) + { + /* parse serialNumber */ + int neg=0; + 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--; + + /* eat leading spaces */ + for( ; (x.bv_val[0] == ' ') && x.bv_len ; x.bv_val++, x.bv_len--) { + /* empty */; + } + + sn->bv_val = x.bv_val; + sn->bv_len = 0; + + if( sn->bv_val[0] == '-' ) { + neg++; + sn->bv_len++; + } + + if ( sn->bv_val[0] == '0' && ( sn->bv_val[1] == 'x' || + sn->bv_val[1] == 'X' )) { + is_hex = 1; + for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { + if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; + } + } else if ( sn->bv_val[0] == '\'' ) { + for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { + if ( !ASCII_HEX( sn->bv_val[sn->bv_len] )) break; + } + if ( sn->bv_val[sn->bv_len] == '\'' && + sn->bv_val[sn->bv_len+1] == 'H' ) + is_hex = 1; + else + return LDAP_INVALID_SYNTAX; + sn->bv_len += 2; + } else { + for( ; sn->bv_len < x.bv_len; sn->bv_len++ ) { + if ( !ASCII_DIGIT( sn->bv_val[sn->bv_len] )) break; + } + } + + if (!( sn->bv_len > neg )) return LDAP_INVALID_SYNTAX; + if (( sn->bv_len > 1+neg ) && ( sn->bv_val[neg] == '0' )) { + return LDAP_INVALID_SYNTAX; + } + + x.bv_val += sn->bv_len; + x.bv_len -= sn->bv_len; + + } else return LDAP_INVALID_SYNTAX; + + /* eat trailing spaces */ + for( ; (x.bv_val[0] == ' ') && x.bv_len; x.bv_val++, x.bv_len--) { + /* empty */; + } + + /* should have no characters left... */ + if( x.bv_len ) return LDAP_INVALID_SYNTAX; + + ber_dupbv_x( &ni, is, ctx ); + *is = ni; + + /* need to handle double dquotes here */ + } + 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 ) + return rc; + + /* validate DN -- doesn't handle double dquote */ + 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: OKAY\n", + 0, 0, 0 ); + return rc; +} + +int +serialNumberAndIssuerPretty( + Syntax *syntax, + struct berval *in, + struct berval *out, + void *ctx ) +{ + int n, rc; + struct berval sn, i, ni; + + assert( in != NULL ); + assert( out != NULL ); + + Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n", + in->bv_val, 0, 0 ); + + rc = serialNumberAndIssuerCheck( in, &sn, &i, ctx ); + if ( rc ) + return rc; + + 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 ) return LDAP_INVALID_SYNTAX; + + /* make room from sn + "$" */ + 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; + slap_sl_free( ni.bv_val, ctx ); + return LDAP_OTHER; + } + + n = 0; + AC_MEMCPY( &out->bv_val[n], "{ serialNumber ", + STRLENOF("{ serialNumber ")); + n = STRLENOF("{ serialNumber "); + + AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len ); + n += sn.bv_len; + + AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF(", issuer rdnSequence:\"")); + n += STRLENOF(", issuer rdnSequence:\""); + + AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len ); + n += ni.bv_len; + + AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF("\" }")); + n += STRLENOF("\" }"); + + out->bv_val[n] = '\0'; + + assert( n == out->bv_len ); + + Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n", + out->bv_val, 0, 0 ); + + slap_sl_free( ni.bv_val, ctx ); + + return LDAP_SUCCESS; +} + +/* + * This routine is called by certificateExactNormalize when + * certificateExactNormalize receives a search string instead of + * a certificate. This routine checks if the search value is valid + * and then returns the normalized value + */ +static int +serialNumberAndIssuerNormalize( + slap_mask_t usage, + Syntax *syntax, + MatchingRule *mr, + struct berval *in, + struct berval *out, + void *ctx ) +{ + struct berval sn, sn2, i, ni; + char sbuf[64], *stmp = sbuf; + int rc; + ber_len_t n; + + 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; + + /* Convert sn to canonical hex */ + if ( sn.bv_len > sizeof( sbuf )) { + stmp = slap_sl_malloc( sn.bv_len, ctx ); + } + sn2.bv_val = stmp; + sn2.bv_len = sn.bv_len; + if ( lutil_str2bin( &sn, &sn2, ctx )) { + rc = LDAP_INVALID_SYNTAX; + goto leave; + } + + /* make room for sn + "$" */ + out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" ) + + ( sn2.bv_len * 2 + 3 ) + ni.bv_len; + out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx ); + + if( out->bv_val == NULL ) { + out->bv_len = 0; + slap_sl_free( ni.bv_val, ctx ); + rc = LDAP_OTHER; + goto leave; + } + + n = 0; + AC_MEMCPY( &out->bv_val[n], "{ serialNumber ", + STRLENOF( "{ serialNumber " )); + n = STRLENOF( "{ serialNumber " ); + + AC_MEMCPY( &out->bv_val[n], sn.bv_val, sn.bv_len ); + { + int j; + unsigned char *v = (unsigned char *)sn2.bv_val; + out->bv_val[n++] = '\''; + for ( j = 0; j < sn2.bv_len; j++ ) { + snprintf( &out->bv_val[n], out->bv_len - n + 1, + "%02X", v[j] ); + n += 2; + } + out->bv_val[n++] = '\''; + out->bv_val[n++] = 'H'; + } + + AC_MEMCPY( &out->bv_val[n], ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" )); + n += STRLENOF( ", issuer rdnSequence:\"" ); + + AC_MEMCPY( &out->bv_val[n], ni.bv_val, ni.bv_len ); + n += ni.bv_len; + + AC_MEMCPY( &out->bv_val[n], "\" }", STRLENOF( "\" }" )); + n += STRLENOF( "\" }" ); + + out->bv_val[n] = '\0'; + + assert( n == out->bv_len ); + + Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n", + out->bv_val, 0, 0 ); + +leave: + if ( stmp != sbuf ) + slap_sl_free( stmp, 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 serialbuf[64], *serial = serialbuf; + ber_len_t seriallen; + struct berval issuer_dn = BER_BVNULL, bvdn; + unsigned char *p; + int rc = LDAP_INVALID_SYNTAX; + + 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 ); /* Signed Sequence */ + tag = ber_skip_tag( ber, &len ); /* Sequence */ + tag = ber_peek_tag( ber, &len ); /* Optional version? */ + if ( tag == SLAP_X509_OPT_C_VERSION ) { + tag = ber_skip_tag( ber, &len ); + tag = ber_get_int( ber, &i ); /* version */ + } + + /* NOTE: move the test here from certificateValidate, + * so that we can validate certs with serial longer + * than sizeof(ber_int_t) */ + tag = ber_peek_tag( ber, &len ); /* serial */ + + /* Use hex format. '123456789abcdef'H + */ + { + unsigned char *ptr; + char *sptr; + + tag = ber_skip_tag( ber, &len ); + ptr = (unsigned char *)ber->ber_ptr; + ber_skip_data( ber, len ); + + /* Check for minimal encodings */ + if ( len > 1 ) { + if ( ptr[0] & 0x80 ) { + if (( ptr[0] == 0xff ) && ( ptr[1] & 0x80 )) + return LDAP_INVALID_SYNTAX; + } else if ( ptr[0] == 0 ) { + if (!( ptr[1] & 0x80 )) + return LDAP_INVALID_SYNTAX; + } + } + + seriallen = len * 2 + 4; /* quotes, H, NUL */ + if ( seriallen > sizeof( serialbuf )) + serial = slap_sl_malloc( seriallen, ctx ); + sptr = serial; + *sptr++ = '\''; + for ( i = 0; ibv_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:\"\" }" ) + + seriallen + issuer_dn.bv_len; + normalized->bv_val = ch_malloc(normalized->bv_len+1); + + p = (unsigned char *)normalized->bv_val; + + AC_MEMCPY(p, "{ serialNumber ", STRLENOF( "{ serialNumber " )); + p += STRLENOF( "{ serialNumber " ); + + AC_MEMCPY(p, serial, seriallen); + p += seriallen; + + AC_MEMCPY(p, ", issuer rdnSequence:\"", STRLENOF( ", issuer rdnSequence:\"" )); + p += STRLENOF( ", issuer rdnSequence:\"" ); + + AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len); + p += issuer_dn.bv_len; + + AC_MEMCPY(p, "\" }", STRLENOF( "\" }" )); + p += STRLENOF( "\" }" ); + + *p = '\0'; + + Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n", + normalized->bv_val, NULL, NULL ); + + rc = LDAP_SUCCESS; + +done: + if ( issuer_dn.bv_val ) ber_memfree( issuer_dn.bv_val ); + if ( serial != serialbuf ) ber_memfree_x( serial, ctx ); + + return rc; +} + +static int +hexValidate( + Syntax *syntax, + struct berval *in ) +{ + int 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; +} + +/* Normalize a SID as used inside a CSN: + * three-digit numeric string */ +static int +hexNormalize( + slap_mask_t usage, Syntax *syntax, MatchingRule *mr, - struct berval *value, - void *assertedValue ) + struct berval *val, + struct berval *normalized, + void *ctx ) { - SLAP_LONG lValue, lAssertedValue; + int i; - /* safe to assume integers are NUL terminated? */ - lValue = SLAP_STRTOL(value->bv_val, NULL, 10); - if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && - errno == ERANGE ) - { - return LDAP_CONSTRAINT_VIOLATION; - } + assert( val != NULL ); + assert( normalized != NULL ); - lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, - NULL, 10); - if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) && - errno == ERANGE ) - { - return LDAP_CONSTRAINT_VIOLATION; + 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 ] ); } - *matchp = (lValue & lAssertedValue) ? 0 : 1; return LDAP_SUCCESS; } static int -integerBitOrMatch( - int *matchp, - slap_mask_t flags, +sidValidate ( Syntax *syntax, - MatchingRule *mr, - struct berval *value, - void *assertedValue ) + struct berval *in ) { - SLAP_LONG lValue, lAssertedValue; + assert( in != NULL ); + assert( !BER_BVISNULL( in ) ); - /* safe to assume integers are NUL terminated? */ - lValue = SLAP_STRTOL(value->bv_val, NULL, 10); - if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) && - errno == ERANGE ) - { - return LDAP_CONSTRAINT_VIOLATION; + if ( in->bv_len != 3 ) { + return LDAP_INVALID_SYNTAX; } - lAssertedValue = SLAP_STRTOL( ((struct berval *)assertedValue)->bv_val, - NULL, 10); - if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) && - errno == ERANGE ) - { - return LDAP_CONSTRAINT_VIOLATION; + return hexValidate( NULL, in ); +} + +/* Normalize a SID as used inside a CSN: + * three-digit numeric string */ +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; } - *matchp = (lValue | lAssertedValue) ? 0 : -1; - return LDAP_SUCCESS; + return hexNormalize( 0, NULL, NULL, val, normalized, ctx ); } static int -serialNumberAndIssuerValidate( +sidPretty( Syntax *syntax, - struct berval *in ) + struct berval *val, + struct berval *out, + void *ctx ) { - int rc; - int state; - ber_len_t n; - struct berval sn, i; - if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX; + return sidNormalize( SLAP_MR_VALUE_OF_SYNTAX, NULL, NULL, val, out, ctx ); +} - i.bv_val = strchr( in->bv_val, '$' ); - if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX; +/* Normalize a SID as used inside a CSN, either as-is + * (assertion value) or extracted from the CSN + * (attribute value) */ +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 ]; - sn.bv_val = in->bv_val; - sn.bv_len = i.bv_val - in->bv_val; - i.bv_val++; - i.bv_len = in->bv_len - (sn.bv_len + 1); + if ( BER_BVISEMPTY( val ) ) { + return LDAP_INVALID_SYNTAX; + } - /* validate serial number (strict for now) */ - for( n=0; n < sn.bv_len; n++ ) { - if( !ASCII_DIGIT(sn.bv_val[n]) ) return LDAP_INVALID_SYNTAX; + if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { + return sidNormalize( 0, NULL, NULL, val, normalized, ctx ); } - /* validate DN */ - rc = dnValidate( NULL, &i ); - if( rc ) return LDAP_INVALID_SYNTAX; + assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) != 0 ); - return LDAP_SUCCESS; + 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 ) { + /* OpenLDAP 2.3 SID */ + 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 ); } -int -serialNumberAndIssuerPretty( +static int +csnValidate( Syntax *syntax, - struct berval *val, - struct berval *out, - void *ctx ) + struct berval *in ) { - int rc; - int state; - ber_len_t n; - struct berval sn, i, newi; + struct berval bv; + char *ptr; + int rc; - assert( val ); - assert( out ); + assert( in != NULL ); + assert( !BER_BVISNULL( in ) ); - Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n", - val->bv_val, 0, 0 ); + if ( BER_BVISEMPTY( in ) ) { + return LDAP_INVALID_SYNTAX; + } - if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX; + bv = *in; - i.bv_val = strchr( val->bv_val, '$' ); - if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX; + 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; + } - sn.bv_val = val->bv_val; - sn.bv_len = i.bv_val - val->bv_val; + rc = generalizedTimeValidate( NULL, &bv ); + if ( rc != LDAP_SUCCESS ) { + return rc; + } - i.bv_val++; - i.bv_len = val->bv_len - (sn.bv_len + 1); + bv.bv_val = ptr + 1; + bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); - /* eat leading zeros */ - for( n=0; n < (sn.bv_len-1); n++ ) { - if( sn.bv_val[n] != '0' ) break; + ptr = ber_bvchr( &bv, '#' ); + if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) { + return LDAP_INVALID_SYNTAX; } - 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; + bv.bv_len = ptr - bv.bv_val; + if ( bv.bv_len != 6 ) { + return LDAP_INVALID_SYNTAX; } - /* pretty DN */ - rc = dnPretty( syntax, &i, &newi, ctx ); - if( rc ) return LDAP_INVALID_SYNTAX; + rc = hexValidate( NULL, &bv ); + if ( rc != LDAP_SUCCESS ) { + return rc; + } - /* make room from sn + "$" */ - out->bv_len = sn.bv_len + newi.bv_len + 1; - out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx ); + bv.bv_val = ptr + 1; + bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val ); - if( out->bv_val == NULL ) { - slap_sl_free( newi.bv_val, ctx ); - return LDAP_OTHER; + ptr = ber_bvchr( &bv, '#' ); + if ( ptr == NULL || ptr - in->bv_val == in->bv_len ) { + return LDAP_INVALID_SYNTAX; } - /* push issuer over */ - AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len ); - /* insert sn and "$" */ - AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len ); - out->bv_val[sn.bv_len] = '$'; - /* terminate */ - out->bv_val[out->bv_len] = '\0'; + bv.bv_len = ptr - bv.bv_val; + if ( bv.bv_len == 2 ) { + /* tolerate old 2-digit replica-id */ + rc = hexValidate( NULL, &bv ); - Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n", - out->bv_val, 0, 0 ); + } else { + rc = sidValidate( NULL, &bv ); + } + if ( rc != LDAP_SUCCESS ) { + return rc; + } - return LDAP_SUCCESS; + 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 ); } -/* - * This routine is called by certificateExactNormalize when - * certificateExactNormalize receives a search string instead of - * a certificate. This routine checks if the search value is valid - * and then returns the normalized value - */ +/* Normalize a CSN in OpenLDAP 2.3 format */ static int -serialNumberAndIssuerNormalize( +csnNormalize23( slap_mask_t usage, Syntax *syntax, MatchingRule *mr, struct berval *val, - struct berval *out, + struct berval *normalized, void *ctx ) { - int rc; - int state; - ber_len_t n; - struct berval sn, i, newi; - - assert( val ); - assert( out ); + struct berval gt, cnt, sid, mod; + char *ptr; + int i; - Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n", - val->bv_val, 0, 0 ); + assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); + assert( !BER_BVISEMPTY( val ) ); - if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX; + gt = *val; - i.bv_val = strchr( val->bv_val, '$' ); - if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX; + ptr = ber_bvchr( >, '#' ); + if ( ptr == NULL || ptr - gt.bv_val == gt.bv_len ) { + return LDAP_INVALID_SYNTAX; + } - sn.bv_val = val->bv_val; - sn.bv_len = i.bv_val - val->bv_val; + gt.bv_len = ptr - gt.bv_val; + assert( gt.bv_len == STRLENOF( "YYYYmmddHHMMSSZ" ) ); - i.bv_val++; - i.bv_len = val->bv_len - (sn.bv_len + 1); + cnt.bv_val = ptr + 1; + cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); - /* eat leading zeros */ - for( n=0; n < (sn.bv_len-1); n++ ) { - if( sn.bv_val[n] != '0' ) break; + ptr = ber_bvchr( &cnt, '#' ); + if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { + return LDAP_INVALID_SYNTAX; } - 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; - } + cnt.bv_len = ptr - cnt.bv_val; + assert( cnt.bv_len == STRLENOF( "000000" ) ); + + 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; } - /* pretty DN */ - rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx ); - if( rc ) return LDAP_INVALID_SYNTAX; + sid.bv_len = ptr - sid.bv_val; + assert( sid.bv_len == STRLENOF( "00" ) ); - /* make room from sn + "$" */ - out->bv_len = sn.bv_len + newi.bv_len + 1; - out->bv_val = slap_sl_realloc( newi.bv_val, out->bv_len + 1, ctx ); + mod.bv_val = ptr + 1; + mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); + assert( mod.bv_len == STRLENOF( "000000" ) ); - if( out->bv_val == NULL ) { - slap_sl_free( newi.bv_val, ctx ); - return LDAP_OTHER; - } + normalized->bv_len = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ); + normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx ); - /* push issuer over */ - AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len ); - /* insert sn and "$" */ - AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len ); - out->bv_val[sn.bv_len] = '$'; - /* terminate */ - out->bv_val[out->bv_len] = '\0'; + ptr = normalized->bv_val; + ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 ); + ptr = lutil_strcopy( ptr, ".000000Z#" ); + ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len ); + *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'; - Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n", - out->bv_val, 0, 0 ); + assert( ptr - normalized->bv_val == normalized->bv_len ); - return rc; + return LDAP_SUCCESS; } -#ifdef HAVE_TLS +/* Normalize a CSN */ static int -certificateExactNormalize( +csnNormalize( slap_mask_t usage, Syntax *syntax, MatchingRule *mr, @@ -2306,60 +3647,81 @@ certificateExactNormalize( struct berval *normalized, void *ctx ) { - int rc = LDAP_INVALID_SYNTAX; - unsigned char *p; - char *serial = NULL; - ber_len_t seriallen; - struct berval issuer_dn = BER_BVNULL; - X509_NAME *name = NULL; - ASN1_INTEGER *sn = NULL; - X509 *xcert = NULL; + struct berval cnt, sid, mod; + char *ptr; + int i; - if( val->bv_len == 0 ) goto done; + assert( val != NULL ); + assert( normalized != NULL ); - if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { - return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx); + assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage ) != 0 ); + + if ( BER_BVISEMPTY( val ) ) { + return LDAP_INVALID_SYNTAX; } - assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) ); + if ( val->bv_len == STRLENOF( "YYYYmmddHHMMSSZ#SSSSSS#ID#ssssss" ) ) { + /* Openldap <= 2.3 */ - p = (unsigned char *)val->bv_val; - xcert = d2i_X509( NULL, &p, val->bv_len); - if( xcert == NULL ) goto done; + return csnNormalize23( usage, syntax, mr, val, normalized, ctx ); + } - sn=X509_get_serialNumber(xcert); - if ( sn == NULL ) goto done; - serial=i2s_ASN1_INTEGER(0, sn ); - if( serial == NULL ) goto done; - seriallen=strlen(serial); + assert( val->bv_len == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#SID#ssssss" ) ); - name=X509_get_issuer_name(xcert); - if( name == NULL ) goto done; - rc = dnX509normalize( name, &issuer_dn ); - if( rc != LDAP_SUCCESS ) goto done; + ptr = ber_bvchr( val, '#' ); + if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { + return LDAP_INVALID_SYNTAX; + } - normalized->bv_len = seriallen + issuer_dn.bv_len + 1; - normalized->bv_val = ch_malloc(normalized->bv_len+1); - p = (unsigned char *)normalized->bv_val; - AC_MEMCPY(p, serial, seriallen); - p += seriallen; - *p++ = '$'; - AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len); - p += issuer_dn.bv_len; - *p = '\0'; + assert( ptr - val->bv_val == STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ" ) ); - Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n", - normalized->bv_val, NULL, NULL ); + cnt.bv_val = ptr + 1; + cnt.bv_len = val->bv_len - ( cnt.bv_val - val->bv_val ); -done: - if (xcert) X509_free(xcert); - if (serial) ch_free(serial); - if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val); + ptr = ber_bvchr( &cnt, '#' ); + if ( ptr == NULL || ptr - val->bv_val == val->bv_len ) { + return LDAP_INVALID_SYNTAX; + } - return rc; + assert( ptr - cnt.bv_val == STRLENOF( "000000" ) ); + + 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; + assert( sid.bv_len == STRLENOF( "000" ) ); + + mod.bv_val = ptr + 1; + mod.bv_len = val->bv_len - ( mod.bv_val - val->bv_val ); + + assert( mod.bv_len == STRLENOF( "000000" ) ); + + ber_dupbv_x( normalized, val, ctx ); + + for ( i = STRLENOF( "YYYYmmddHHMMSS.uuuuuuZ#SSSSSS#" ); + i < normalized->bv_len; i++ ) + { + /* assume it's already validated that's all hex digits */ + normalized->bv_val[ i ] = TOLOWER( normalized->bv_val[ i ] ); + } + + return LDAP_SUCCESS; } -#endif /* HAVE_TLS */ +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 /* slight optimization - does not need the start parameter */ @@ -2610,19 +3972,19 @@ generalizedTimeNormalize( return rc; } - len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len; + len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len; normalized->bv_val = slap_sl_malloc( len + 1, ctx ); - if ( normalized->bv_val == NULL ) { + 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 ( fraction.bv_len ) { - memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2, + if ( !BER_BVISEMPTY( &fraction ) ) { + memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1, fraction.bv_val, fraction.bv_len ); - normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.'; + normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.'; } strcpy( normalized->bv_val + len-1, "Z" ); normalized->bv_len = len; @@ -2664,7 +4026,6 @@ int generalizedTimeIndexer( void *ctx ) { int i, j; - size_t slen, mlen; BerVarray keys; char tmp[5]; BerValue bvtmp; /* 40 bit index */ @@ -2729,12 +4090,11 @@ int generalizedTimeFilter( bvtmp.bv_len = sizeof(tmp); bvtmp.bv_val = tmp; - keys = slap_sl_malloc( sizeof( struct berval ) * 2, ctx ); - /* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) */ - assert(value->bv_val != NULL && value->bv_len >= 10); /* Use 40 bits of time for key */ - if ( lutil_parsetime( value->bv_val, &tm ) == 0 ) { + 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; @@ -2745,15 +4105,14 @@ int generalizedTimeFilter( 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[0].bv_val = NULL; - keys[0].bv_len = 0; + keys = NULL; } - keys[1].bv_val = NULL; - keys[1].bv_len = 0; - *keysp = keys; return LDAP_SUCCESS; @@ -2872,19 +4231,19 @@ again: return LDAP_INVALID_SYNTAX; } - if( tmp.bv_len == 0 ) return LDAP_SUCCESS; + if( BER_BVISEMPTY( &tmp ) ) return LDAP_SUCCESS; - while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) { + while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) { tmp.bv_len++; tmp.bv_val--; } - if( tmp.bv_len && ( tmp.bv_val[0] == '$' )) { + if( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == '$' ) ) { tmp.bv_len++; tmp.bv_val--; } else { return LDAP_INVALID_SYNTAX; } - while( tmp.bv_len && ( tmp.bv_val[0] == ' ' )) { + while( !BER_BVISEMPTY( &tmp ) && ( tmp.bv_val[0] == ' ' ) ) { tmp.bv_len++; tmp.bv_val--; } @@ -2900,7 +4259,7 @@ nisNetgroupTripleValidate( char *p, *e; int commas = 0; - if ( val->bv_len == 0 ) { + if ( BER_BVISEMPTY( val ) ) { return LDAP_INVALID_SYNTAX; } @@ -2943,7 +4302,7 @@ bootParameterValidate( { char *p, *e; - if ( val->bv_len == 0 ) { + if ( BER_BVISEMPTY( val ) ) { return LDAP_INVALID_SYNTAX; } @@ -3019,7 +4378,7 @@ firstComponentNormalize( /* grab next word */ comp.bv_val = &val->bv_val[len]; len = val->bv_len - len; - for( comp.bv_len=0; + for( comp.bv_len = 0; !ASCII_SPACE(comp.bv_val[comp.bv_len]) && comp.bv_len < len; comp.bv_len++ ) { @@ -3042,6 +4401,12 @@ firstComponentNormalize( 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' " @@ -3049,169 +4414,195 @@ firstComponentNormalize( 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}, + 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}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'Attribute Type Description' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' " X_NOT_H_R ")", - SLAP_SYNTAX_BLOB, blobValidate, NULL}, + 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, berValidate, NULL}, + SLAP_SYNTAX_BER, NULL, berValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )", - 0, bitStringValidate, NULL }, + 0, NULL, bitStringValidate, NULL }, {"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )", - 0, booleanValidate, NULL}, + 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, certificateValidate, NULL}, + 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, sequenceValidate, NULL}, + 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, sequenceValidate, NULL}, + SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, + NULL, sequenceValidate, NULL}, +#if 0 /* need to go __after__ printableString */ {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )", - 0, countryStringValidate, NULL}, + 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' )", - 0, dnValidate, dnPretty}, + 0, NULL, dnValidate, dnPretty}, {"( 1.2.36.79672281.1.5.0 DESC 'RDN' )", - 0, rdnValidate, rdnPretty}, + 0, NULL, rdnValidate, rdnPretty}, #ifdef LDAP_COMP_MATCH - {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )", - 0, allComponentsValidate, NULL}, + {"( 1.2.36.79672281.1.5.3 DESC 'allComponents' )", + 0, NULL, allComponentsValidate, NULL}, {"( 1.2.36.79672281.1.5.2 DESC 'componentFilterMatch assertion') ", - 0, componentFilterValidate, NULL}, + 0, NULL, componentFilterValidate, NULL}, #endif {"( 1.3.6.1.4.1.1466.115.121.1.13 DESC 'Data Quality' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'Delivery Method' )", - 0, deliveryMethodValidate, NULL}, + 0, NULL, deliveryMethodValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'Directory String' )", - 0, UTF8StringValidate, NULL}, + 0, NULL, UTF8StringValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DIT Content Rule Description' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DIT Structure Rule Description' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.19 DESC 'DSA Quality' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.20 DESC 'DSE Type' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'Enhanced Guide' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'Facsimile Telephone Number' )", - 0, printablesStringValidate, NULL}, + 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}, + SLAP_SYNTAX_BLOB, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )", - 0, generalizedTimeValidate, NULL}, + 0, NULL, generalizedTimeValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )", - 0, IA5StringValidate, NULL}, + 0, NULL, IA5StringValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )", - 0, integerValidate, NULL}, + 0, NULL, integerValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' " X_NOT_H_R ")", - SLAP_SYNTAX_BLOB, blobValidate, NULL}, + 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}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'Matching Rule Description' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'Matching Rule Use Description' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'Mail Preference' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )", - 0, nameUIDValidate, nameUIDPretty }, + 0, NULL, nameUIDValidate, nameUIDPretty }, {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )", - 0, numericStringValidate, NULL}, + 0, NULL, numericStringValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'Object Class Description' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.38 DESC 'OID' )", - 0, numericoidValidate, NULL}, + 0, NULL, numericoidValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.39 DESC 'Other Mailbox' )", - 0, IA5StringValidate, NULL}, + 0, NULL, IA5StringValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.40 DESC 'Octet String' )", - 0, blobValidate, NULL}, + 0, NULL, blobValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.41 DESC 'Postal Address' )", - 0, UTF8StringValidate, NULL}, + 0, NULL, UTF8StringValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.42 DESC 'Protocol Information' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.43 DESC 'Presentation Address' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.44 DESC 'Printable String' )", - 0, printableStringValidate, NULL}, + 0, NULL, printableStringValidate, NULL}, + /* moved here because now depends on Directory String, IA5 String + * and Printable String */ + {"( 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 /* FIXME */ - 0, subtreeSpecificationValidate, NULL}, + 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, berValidate, NULL}, + SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, berValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.50 DESC 'Telephone Number' )", - 0, printableStringValidate, NULL}, + 0, NULL, printableStringValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.51 DESC 'Teletex Terminal Identifier' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )", - 0, printablesStringValidate, NULL}, + 0, NULL, printablesStringValidate, NULL}, #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX {"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )", - 0, utcTimeValidate, NULL}, + 0, NULL, utcTimeValidate, NULL}, #endif {"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.56 DESC 'LDAP Schema Definition' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.57 DESC 'LDAP Schema Description' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.58 DESC 'Substring Assertion' )", - 0, NULL, NULL}, + 0, NULL, NULL, NULL}, /* RFC 2307 NIS Syntaxes */ {"( 1.3.6.1.1.1.0.0 DESC 'RFC2307 NIS Netgroup Triple' )", - 0, nisNetgroupTripleValidate, NULL}, + 0, NULL, nisNetgroupTripleValidate, NULL}, {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )", - 0, bootParameterValidate, NULL}, + 0, NULL, bootParameterValidate, NULL}, - /* From PKIX *//* This OID is not published yet. */ - {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )", - SLAP_SYNTAX_HIDE, + /* draft-zeilenga-ldap-x509 */ + {"( 1.3.6.1.1.15.1 DESC 'Certificate Exact Assertion' )", + SLAP_SYNTAX_HIDE, NULL, serialNumberAndIssuerValidate, serialNumberAndIssuerPretty}, - -#ifdef SLAPD_ACI_ENABLED - /* OpenLDAP Experimental Syntaxes */ - {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )", - SLAP_SYNTAX_HIDE, - UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */, - NULL}, -#endif + {"( 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, NULL, NULL}, + {"( 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}, #ifdef SLAPD_AUTHPASSWD /* needs updating */ {"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )", - SLAP_SYNTAX_HIDE, NULL, NULL}, + SLAP_SYNTAX_HIDE, NULL, NULL, NULL}, #endif - {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )", - SLAP_SYNTAX_HIDE, UUIDValidate, NULL}, + {"( 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, csnValidate, NULL}, + 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 }, /* OpenLDAP Void Syntax */ {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" , - SLAP_SYNTAX_HIDE, inValidate, NULL}, - {NULL, 0, NULL, NULL} + SLAP_SYNTAX_HIDE, NULL, inValidate, NULL}, + + /* FIXME: OID is unused, but not registered yet */ + {"( 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" /* csn */, + NULL +}; char *certificateExactMatchSyntaxes[] = { "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */, NULL @@ -3228,13 +4619,13 @@ char *directoryStringSyntaxes[] = { }; char *integerFirstComponentMatchSyntaxes[] = { "1.3.6.1.4.1.1466.115.121.1.27" /* INTEGER */, - "1.3.6.1.4.1.1466.115.121.1.17" /* ditStructureRuleDescription */, + "1.3.6.1.4.1.1466.115.121.1.17" /* dITStructureRuleDescription */, NULL }; char *objectIdentifierFirstComponentMatchSyntaxes[] = { "1.3.6.1.4.1.1466.115.121.1.38" /* OID */, "1.3.6.1.4.1.1466.115.121.1.3" /* attributeTypeDescription */, - "1.3.6.1.4.1.1466.115.121.1.16" /* ditContentRuleDescription */, + "1.3.6.1.4.1.1466.115.121.1.16" /* dITContentRuleDescription */, "1.3.6.1.4.1.1466.115.121.1.54" /* ldapSyntaxDescription */, "1.3.6.1.4.1.1466.115.121.1.30" /* matchingRuleDescription */, "1.3.6.1.4.1.1466.115.121.1.31" /* matchingRuleUseDescription */, @@ -3251,17 +4642,18 @@ char *objectIdentifierFirstComponentMatchSyntaxes[] = { * 2.5.13.31* directoryStringFirstComponentMatch * 2.5.13.32* wordMatch * 2.5.13.33* keywordMatch - * 2.5.13.36 certificatePairExactMatch - * 2.5.13.37 certificatePairMatch - * 2.5.13.38 certificateListExactMatch - * 2.5.13.39 certificateListMatch - * 2.5.13.40 algorithmIdentifierMatch + * 2.5.13.36+ certificatePairExactMatch + * 2.5.13.37+ certificatePairMatch + * 2.5.13.38+ certificateListExactMatch + * 2.5.13.39+ certificateListMatch + * 2.5.13.40+ algorithmIdentifierMatch * 2.5.13.41* storedPrefixMatch * 2.5.13.42 attributeCertificateMatch * 2.5.13.43 readerAndKeyIDMatch * 2.5.13.44 attributeIntegrityMatch * * (*) described in RFC 3698 (LDAP: Additional Matching Rules) + * (+) described in draft-zeilenga-ldap-x509 */ static slap_mrule_defs_rec mrule_defs[] = { /* @@ -3375,7 +4767,7 @@ static slap_mrule_defs_rec mrule_defs[] = { {"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", SLAP_MR_SUBSTR, directoryStringSyntaxes, - NULL, UTF8StringNormalize, octetStringSubstringsMatch, + NULL, UTF8StringNormalize, directoryStringSubstringsMatch, octetStringSubstringsIndexer, octetStringSubstringsFilter, "caseIgnoreMatch" }, @@ -3396,7 +4788,7 @@ static slap_mrule_defs_rec mrule_defs[] = { {"( 2.5.13.7 NAME 'caseExactSubstringsMatch' " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", SLAP_MR_SUBSTR, directoryStringSyntaxes, - NULL, UTF8StringNormalize, octetStringSubstringsMatch, + NULL, UTF8StringNormalize, directoryStringSubstringsMatch, octetStringSubstringsIndexer, octetStringSubstringsFilter, "caseExactMatch" }, @@ -3441,14 +4833,14 @@ static slap_mrule_defs_rec mrule_defs[] = { {"( 2.5.13.14 NAME 'integerMatch' " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", - SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, + SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL, NULL, NULL, integerMatch, - octetStringIndexer, octetStringFilter, + integerIndexer, integerFilter, NULL }, {"( 2.5.13.15 NAME 'integerOrderingMatch' " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", - SLAP_MR_ORDERING, NULL, + SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL, NULL, NULL, integerMatch, NULL, NULL, "integerMatch" }, @@ -3505,7 +4897,7 @@ static slap_mrule_defs_rec mrule_defs[] = { "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, NULL, uniqueMemberNormalize, uniqueMemberMatch, - NULL, NULL, + uniqueMemberIndexer, uniqueMemberFilter, NULL }, {"( 2.5.13.24 NAME 'protocolInformationMatch' " @@ -3544,25 +4936,16 @@ static slap_mrule_defs_rec mrule_defs[] = { NULL }, {"( 2.5.13.34 NAME 'certificateExactMatch' " - "SYNTAX 1.2.826.0.1.3344810.7.1 )", + "SYNTAX 1.3.6.1.1.15.1 )", SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes, -#ifdef HAVE_TLS NULL, certificateExactNormalize, octetStringMatch, octetStringIndexer, octetStringFilter, -#else - NULL, NULL, NULL, NULL, NULL, -#endif NULL }, {"( 2.5.13.35 NAME 'certificateMatch' " - "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )", + "SYNTAX 1.3.6.1.1.15.2 )", SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, -#ifdef HAVE_TLS - NULL, NULL, octetStringMatch, - octetStringIndexer, octetStringFilter, -#else NULL, NULL, NULL, NULL, NULL, -#endif NULL }, {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' " @@ -3582,14 +4965,14 @@ static slap_mrule_defs_rec mrule_defs[] = { {"( 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, octetStringSubstringsMatch, + 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, octetStringSubstringsMatch, + NULL, IA5StringNormalize, directoryStringSubstringsMatch, octetStringSubstringsIndexer, octetStringSubstringsFilter, "caseExactIA5Match" }, @@ -3603,15 +4986,6 @@ static slap_mrule_defs_rec mrule_defs[] = { NULL}, #endif -#ifdef SLAPD_ACI_ENABLED - {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' " - "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )", - SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, - NULL, NULL, OpenLDAPaciMatch, - 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, @@ -3626,16 +5000,16 @@ static slap_mrule_defs_rec mrule_defs[] = { NULL, NULL, "integerMatch" }, - {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' " - "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )", - SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, + {"( 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.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' " - "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )", - SLAP_MR_HIDE | SLAP_MR_ORDERING, 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"}, @@ -3643,7 +5017,7 @@ static slap_mrule_defs_rec mrule_defs[] = { {"( 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, NULL, csnMatch, + NULL, csnNormalize, csnMatch, csnIndexer, csnFilter, NULL}, @@ -3654,6 +5028,21 @@ static slap_mrule_defs_rec mrule_defs[] = { 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 }, + + /* FIXME: OID is unused, but not registered yet */ + {"( 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 } @@ -3712,4 +5101,9 @@ schema_destroy( void ) mr_destroy(); mru_destroy(); syn_destroy(); + + if( schema_init_done ) { + ldap_pvt_thread_mutex_destroy( &ad_undef_mutex ); + ldap_pvt_thread_mutex_destroy( &oc_undef_mutex ); + } }