Handle full syntax of Generalized Time and UTC Time.

No longer accept initial and trailing spaces in these syntaxes.
This commit is contained in:
Hallvard Furuseth 2003-08-13 20:04:59 +00:00
parent 281627d81d
commit 2d48b5dc99

View file

@ -1996,172 +1996,189 @@ certificateExactNormalize(
#endif /* HAVE_TLS */
#ifndef SUPPORT_OBSOLETE_UTC_SYNTAX
/* slight optimization - does not need the start parameter */
#define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f)
enum { start = 0 };
#endif
static int
check_time_syntax (struct berval *val,
int start,
int *parts)
int *parts,
struct berval *fraction)
{
static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
static int mdays[2][12] = {
/*
* start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM])
* start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM]
* 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 */
{ 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 },
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
/* leap years */
{ 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
char *p, *e;
int part, c, tzoffset, leapyear = 0 ;
int part, c, c1, c2, tzoffset, leapyear = 0;
if( val->bv_len == 0 ) {
return LDAP_INVALID_SYNTAX;
}
p = (char *)val->bv_val;
p = val->bv_val;
e = p + val->bv_len;
/* Ignore initial whitespace */
while ( ( p < e ) && ASCII_SPACE( *p ) ) {
p++;
}
if (e - p < 13 - (2 * start)) {
return LDAP_INVALID_SYNTAX;
}
for (part = 0; part < 9; part++) {
parts[part] = 0;
}
for (part = start; part < 7; part++) {
c = *p;
if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) {
part++;
#ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */
#endif
for (part = start; part < 7 && p < e; part++) {
c1 = *p;
if (!ASCII_DIGIT(c1)) {
break;
}
p++;
c -= '0';
if (p == e) {
return LDAP_INVALID_SYNTAX;
}
if (c < 0 || c > 9) {
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;
c = *p++ - '0';
if (p == e) {
return LDAP_INVALID_SYNTAX;
}
if (c < 0 || c > 9) {
return LDAP_INVALID_SYNTAX;
}
parts[part] *= 10;
parts[part] += c;
if (part == 2 || part == 3) {
parts[part]--;
}
if (parts[part] < 0) {
return LDAP_INVALID_SYNTAX;
}
if (parts[part] > ceiling[part]) {
}
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[1] % 4 == 0) && (parts[1] != 0)) ||
((parts[0] % 4 == 0) && (parts[1] == 0)))
if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0)
{
leapyear = 1;
}
if (parts[3] > mdays[leapyear][parts[2]]) {
if (parts[3] >= mdays[leapyear][parts[2]]) {
return LDAP_INVALID_SYNTAX;
}
c = *p++;
if (c == 'Z') {
tzoffset = 0; /* UTC */
} else if (c != '+' && c != '-') {
return LDAP_INVALID_SYNTAX;
} else {
if (c == '-') {
tzoffset = -1;
} else /* c == '+' */ {
tzoffset = 1;
}
if (p > e - 4) {
return LDAP_INVALID_SYNTAX;
}
for (part = 7; part < 9; part++) {
c = *p++ - '0';
if (c < 0 || c > 9) {
return LDAP_INVALID_SYNTAX;
}
parts[part] = c;
c = *p++ - '0';
if (c < 0 || c > 9) {
return LDAP_INVALID_SYNTAX;
}
parts[part] *= 10;
parts[part] += c;
if (parts[part] < 0 || parts[part] > ceiling[part]) {
if (start == 0) {
fraction->bv_val = p;
fraction->bv_len = 0;
if (p < e && (*p == '.' || *p == ',')) {
char *end_num;
while (++p < e && ASCII_DIGIT(*p))
;
if (p - fraction->bv_val == 1) {
return LDAP_INVALID_SYNTAX;
}
for (end_num = p; end_num[-1] == '0'; --end_num)
;
c = end_num - fraction->bv_val;
if (c != 1)
fraction->bv_len = c;
}
}
/* Ignore trailing whitespace */
while ( ( p < e ) && ASCII_SPACE( *p ) ) {
if (p == e) {
/* no time zone */
return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
}
tzoffset = *p++;
switch (tzoffset) {
default:
return LDAP_INVALID_SYNTAX;
case 'Z':
/* UTC */
break;
case '+':
case '-':
for (part = 7; part < 9 && p < e; part++) {
c1 = *p;
if (!ASCII_DIGIT(c1)) {
break;
}
p++;
if (p == e) {
return LDAP_INVALID_SYNTAX;
}
if (p != e) {
c2 = *p++;
if (!ASCII_DIGIT(c2)) {
return LDAP_INVALID_SYNTAX;
}
parts[part] = c1 * 10 + c2 - '0' * 11;
if (parts[part] >= ceiling[part]) {
return LDAP_INVALID_SYNTAX;
}
}
if (part < 8 + start) {
return LDAP_INVALID_SYNTAX;
}
switch ( tzoffset ) {
case -1: /* negativ offset to UTC, ie west of Greenwich */
if (tzoffset == '-') {
/* negative offset to UTC, ie west of Greenwich */
parts[4] += parts[7];
parts[5] += parts[8];
for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */
/* offset is just hhmm, no seconds */
for (part = 6; --part >= 0; ) {
if (part != 3) {
c = ceiling[part];
} else {
c = mdays[leapyear][parts[2]];
}
if (parts[part] > c) {
parts[part] -= c + 1;
if (parts[part] >= c) {
if (part == 0) {
return LDAP_INVALID_SYNTAX;
}
parts[part] -= c;
parts[part - 1]++;
}
}
continue;
} else if (part != 5) {
break;
case 1: /* positive offset to UTC, ie east of Greenwich */
}
}
} else {
/* positive offset to UTC, ie east of Greenwich */
parts[4] -= parts[7];
parts[5] -= parts[8];
for (part = 6; --part > 0; ) {
for (part = 6; --part >= 0; ) {
if (parts[part] < 0) {
if (part == 0) {
return LDAP_INVALID_SYNTAX;
}
if (part != 3) {
c = ceiling[part];
} else {
/* first arg to % needs to be non negativ */
/* make first arg to % non-negative */
c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
}
if (parts[part] < 0) {
parts[part] += c + 1;
parts[part] += c;
parts[part - 1]--;
continue;
} else if (part != 5) {
break;
}
}
}
break;
case 0: /* already UTC */
break;
}
return LDAP_SUCCESS;
return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS;
}
#ifdef SUPPORT_OBSOLETE_UTC_SYNTAX
#if 0
static int
xutcTimeNormalize(
Syntax *syntax,
@ -2170,7 +2187,7 @@ xutcTimeNormalize(
{
int parts[9], rc;
rc = check_time_syntax(val, 1, parts);
rc = check_time_syntax(val, 1, parts, NULL);
if (rc != LDAP_SUCCESS) {
return rc;
}
@ -2187,6 +2204,7 @@ xutcTimeNormalize(
return LDAP_SUCCESS;
}
#endif /* 0 */
static int
utcTimeValidate(
@ -2194,9 +2212,10 @@ utcTimeValidate(
struct berval *in )
{
int parts[9];
return check_time_syntax(in, 1, parts);
return check_time_syntax(in, 1, parts, NULL);
}
#endif
#endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */
static int
generalizedTimeValidate(
@ -2204,7 +2223,8 @@ generalizedTimeValidate(
struct berval *in )
{
int parts[9];
return check_time_syntax(in, 0, parts);
struct berval fraction;
return check_time_syntax(in, 0, parts, &fraction);
}
static int
@ -2217,25 +2237,56 @@ generalizedTimeNormalize(
void *ctx )
{
int parts[9], rc;
unsigned int len;
struct berval fraction;
rc = check_time_syntax(val, 0, parts);
rc = check_time_syntax(val, 0, parts, &fraction);
if (rc != LDAP_SUCCESS) {
return rc;
}
normalized->bv_val = sl_malloc( sizeof("YYYYmmddHHMMSSZ"), ctx );
len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len;
normalized->bv_val = sl_malloc( len + 1, ctx );
if ( normalized->bv_val == NULL ) {
return LBER_ERROR_MEMORY;
}
sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
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] );
normalized->bv_len = 15;
if ( fraction.bv_len ) {
memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2,
fraction.bv_val, fraction.bv_len );
normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.';
}
strcpy( normalized->bv_val + len-1, "Z" );
normalized->bv_len = len;
return LDAP_SUCCESS;
}
static int
generalizedTimeOrderingMatch(
int *matchp,
slap_mask_t flags,
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
void *assertedValue )
{
struct berval *asserted = (struct berval *) assertedValue;
ber_len_t v_len = value->bv_len;
ber_len_t av_len = asserted->bv_len;
/* ignore trailing 'Z' when comparing */
int match = memcmp( value->bv_val, asserted->bv_val,
(v_len < av_len ? v_len : av_len) - 1 );
if ( match == 0 ) match = v_len - av_len;
*matchp = match;
return LDAP_SUCCESS;
}
static int
nisNetgroupTripleValidate(
Syntax *syntax,
@ -2781,7 +2832,7 @@ static slap_mrule_defs_rec mrule_defs[] = {
{"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
SLAP_MR_ORDERING, NULL,
NULL, generalizedTimeNormalize, octetStringOrderingMatch,
NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
NULL, NULL,
"generalizedTimeMatch" },