mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-20 22:59:34 -05:00
ITS#9358 Fix reqStart normalizer
Don't truncate trailing zeroes in reqStart/reqEnd timestamps
This commit is contained in:
parent
67d005ee65
commit
2bbb51e20b
1 changed files with 177 additions and 0 deletions
|
|
@ -2413,9 +2413,167 @@ accesslog_db_open(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum { start = 0 };
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_rdntime_syntax (struct berval *val,
|
||||||
|
int *parts,
|
||||||
|
struct berval *fraction)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
|
||||||
|
* GeneralizedTime supports leap seconds, UTCTime does not.
|
||||||
|
*/
|
||||||
|
static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 };
|
||||||
|
static const int mdays[2][12] = {
|
||||||
|
/* non-leap years */
|
||||||
|
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||||
|
/* leap years */
|
||||||
|
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||||
|
};
|
||||||
|
char *p, *e;
|
||||||
|
int part, c, c1, c2, tzoffset, leapyear = 0;
|
||||||
|
|
||||||
|
p = val->bv_val;
|
||||||
|
e = p + val->bv_len;
|
||||||
|
|
||||||
|
for (part = start; part < 7 && p < e; part++) {
|
||||||
|
c1 = *p;
|
||||||
|
if (!ASCII_DIGIT(c1)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
if (p == e) {
|
||||||
|
return LDAP_INVALID_SYNTAX;
|
||||||
|
}
|
||||||
|
c = *p++;
|
||||||
|
if (!ASCII_DIGIT(c)) {
|
||||||
|
return LDAP_INVALID_SYNTAX;
|
||||||
|
}
|
||||||
|
c += c1 * 10 - '0' * 11;
|
||||||
|
if ((part | 1) == 3) {
|
||||||
|
--c;
|
||||||
|
if (c < 0) {
|
||||||
|
return LDAP_INVALID_SYNTAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c >= ceiling[part]) {
|
||||||
|
if (! (c == 60 && part == 6 && start == 0))
|
||||||
|
return LDAP_INVALID_SYNTAX;
|
||||||
|
}
|
||||||
|
parts[part] = c;
|
||||||
|
}
|
||||||
|
if (part < 5 + start) {
|
||||||
|
return LDAP_INVALID_SYNTAX;
|
||||||
|
}
|
||||||
|
for (; part < 9; part++) {
|
||||||
|
parts[part] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* leapyear check for the Gregorian calendar (year>1581) */
|
||||||
|
if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) {
|
||||||
|
leapyear = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parts[3] >= mdays[leapyear][parts[2]]) {
|
||||||
|
return LDAP_INVALID_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start == 0) {
|
||||||
|
fraction->bv_val = p;
|
||||||
|
fraction->bv_len = 0;
|
||||||
|
if (p < e && (*p == '.' || *p == ',')) {
|
||||||
|
char *end_num;
|
||||||
|
while (++p < e && ASCII_DIGIT(*p)) {
|
||||||
|
/* EMPTY */;
|
||||||
|
}
|
||||||
|
if (p - fraction->bv_val == 1) {
|
||||||
|
return LDAP_INVALID_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 /* don't truncate trailing zeros */
|
||||||
|
for (end_num = p; end_num[-1] == '0'; --end_num) {
|
||||||
|
/* EMPTY */;
|
||||||
|
}
|
||||||
|
c = end_num - fraction->bv_val;
|
||||||
|
#else
|
||||||
|
c = p - fraction->bv_val;
|
||||||
|
#endif
|
||||||
|
if (c != 1) fraction->bv_len = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == e) {
|
||||||
|
/* no time zone */
|
||||||
|
return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
tzoffset = *p++;
|
||||||
|
switch (tzoffset) {
|
||||||
|
case 'Z':
|
||||||
|
/* UTC */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return LDAP_INVALID_SYNTAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rdnTimestampValidate(
|
||||||
|
Syntax *syntax,
|
||||||
|
struct berval *in )
|
||||||
|
{
|
||||||
|
int parts[9];
|
||||||
|
struct berval fraction;
|
||||||
|
return check_rdntime_syntax(in, parts, &fraction);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rdnTimestampNormalize(
|
||||||
|
slap_mask_t usage,
|
||||||
|
Syntax *syntax,
|
||||||
|
MatchingRule *mr,
|
||||||
|
struct berval *val,
|
||||||
|
struct berval *normalized,
|
||||||
|
void *ctx )
|
||||||
|
{
|
||||||
|
int parts[9], rc;
|
||||||
|
unsigned int len;
|
||||||
|
struct berval fraction;
|
||||||
|
|
||||||
|
rc = check_rdntime_syntax(val, parts, &fraction);
|
||||||
|
if (rc != LDAP_SUCCESS) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = STRLENOF("YYYYmmddHHMMSSZ") + fraction.bv_len;
|
||||||
|
normalized->bv_val = slap_sl_malloc( len + 1, ctx );
|
||||||
|
if ( BER_BVISNULL( normalized ) ) {
|
||||||
|
return LBER_ERROR_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d",
|
||||||
|
parts[0], parts[1], parts[2] + 1, parts[3] + 1,
|
||||||
|
parts[4], parts[5], parts[6] );
|
||||||
|
if ( !BER_BVISEMPTY( &fraction ) ) {
|
||||||
|
memcpy( normalized->bv_val + STRLENOF("YYYYmmddHHMMSSZ")-1,
|
||||||
|
fraction.bv_val, fraction.bv_len );
|
||||||
|
normalized->bv_val[STRLENOF("YYYYmmddHHMMSSZ")-1] = '.';
|
||||||
|
}
|
||||||
|
strcpy( normalized->bv_val + len-1, "Z" );
|
||||||
|
normalized->bv_len = len;
|
||||||
|
|
||||||
|
return LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int accesslog_initialize()
|
int accesslog_initialize()
|
||||||
{
|
{
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
Syntax *rdnTimestampSyntax;
|
||||||
|
MatchingRule *rdnTimestampMatch;
|
||||||
|
|
||||||
accesslog.on_bi.bi_type = "accesslog";
|
accesslog.on_bi.bi_type = "accesslog";
|
||||||
accesslog.on_bi.bi_db_init = accesslog_db_init;
|
accesslog.on_bi.bi_db_init = accesslog_db_init;
|
||||||
|
|
@ -2476,6 +2634,25 @@ int accesslog_initialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Inject custom normalizer for reqStart/reqEnd */
|
||||||
|
rdnTimestampMatch = ch_malloc( sizeof( MatchingRule ));
|
||||||
|
rdnTimestampSyntax = ch_malloc( sizeof( Syntax ));
|
||||||
|
*rdnTimestampMatch = *ad_reqStart->ad_type->sat_equality;
|
||||||
|
rdnTimestampMatch->smr_normalize = rdnTimestampNormalize;
|
||||||
|
*rdnTimestampSyntax = *ad_reqStart->ad_type->sat_syntax;
|
||||||
|
rdnTimestampSyntax->ssyn_validate = rdnTimestampValidate;
|
||||||
|
ad_reqStart->ad_type->sat_equality = rdnTimestampMatch;
|
||||||
|
ad_reqStart->ad_type->sat_syntax = rdnTimestampSyntax;
|
||||||
|
|
||||||
|
rdnTimestampMatch = ch_malloc( sizeof( MatchingRule ));
|
||||||
|
rdnTimestampSyntax = ch_malloc( sizeof( Syntax ));
|
||||||
|
*rdnTimestampMatch = *ad_reqStart->ad_type->sat_equality;
|
||||||
|
rdnTimestampMatch->smr_normalize = rdnTimestampNormalize;
|
||||||
|
*rdnTimestampSyntax = *ad_reqStart->ad_type->sat_syntax;
|
||||||
|
rdnTimestampSyntax->ssyn_validate = rdnTimestampValidate;
|
||||||
|
ad_reqEnd->ad_type->sat_equality = rdnTimestampMatch;
|
||||||
|
ad_reqEnd->ad_type->sat_syntax = rdnTimestampSyntax;
|
||||||
|
|
||||||
for ( i=0; locs[i].ot; i++ ) {
|
for ( i=0; locs[i].ot; i++ ) {
|
||||||
int code;
|
int code;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue