mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-12-23 08:09:34 -05:00
Handle full syntax of Generalized Time and UTC Time.
No longer accept initial and trailing spaces in these syntaxes.
This commit is contained in:
parent
281627d81d
commit
2d48b5dc99
1 changed files with 185 additions and 134 deletions
|
|
@ -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]) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (start == 0) {
|
||||
fraction->bv_val = p;
|
||||
fraction->bv_len = 0;
|
||||
if (p < e && (*p == '.' || *p == ',')) {
|
||||
char *end_num;
|
||||
while (++p < e && ASCII_DIGIT(*p))
|
||||
;
|
||||
if (p - fraction->bv_val == 1) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
for (end_num = p; end_num[-1] == '0'; --end_num)
|
||||
;
|
||||
c = end_num - fraction->bv_val;
|
||||
if (c != 1)
|
||||
fraction->bv_len = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (p == e) {
|
||||
/* 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
for (part = 7; part < 9; part++) {
|
||||
c = *p++ - '0';
|
||||
if (c < 0 || c > 9) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
if (tzoffset == '-') {
|
||||
/* negative offset to UTC, ie west of Greenwich */
|
||||
parts[4] += parts[7];
|
||||
parts[5] += parts[8];
|
||||
/* 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) {
|
||||
if (part == 0) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
parts[part] -= c;
|
||||
parts[part - 1]++;
|
||||
continue;
|
||||
} else if (part != 5) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
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]) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
} else {
|
||||
/* positive offset to UTC, ie east of Greenwich */
|
||||
parts[4] -= parts[7];
|
||||
parts[5] -= parts[8];
|
||||
for (part = 6; --part >= 0; ) {
|
||||
if (parts[part] < 0) {
|
||||
if (part == 0) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
if (part != 3) {
|
||||
c = ceiling[part];
|
||||
} else {
|
||||
/* make first arg to % non-negative */
|
||||
c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
|
||||
}
|
||||
parts[part] += c;
|
||||
parts[part - 1]--;
|
||||
continue;
|
||||
} else if (part != 5) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ignore trailing whitespace */
|
||||
while ( ( p < e ) && ASCII_SPACE( *p ) ) {
|
||||
p++;
|
||||
}
|
||||
if (p != e) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
switch ( tzoffset ) {
|
||||
case -1: /* negativ 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 */
|
||||
if (part != 3) {
|
||||
c = ceiling[part];
|
||||
} else {
|
||||
c = mdays[leapyear][parts[2]];
|
||||
}
|
||||
if (parts[part] > c) {
|
||||
parts[part] -= c + 1;
|
||||
parts[part - 1]++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: /* positive offset to UTC, ie east of Greenwich */
|
||||
parts[4] -= parts[7];
|
||||
parts[5] -= parts[8];
|
||||
for (part = 6; --part > 0; ) {
|
||||
if (part != 3) {
|
||||
c = ceiling[part];
|
||||
} else {
|
||||
/* first arg to % needs to be non negativ */
|
||||
c = mdays[leapyear][(parts[2] - 1 + 12) % 12];
|
||||
}
|
||||
if (parts[part] < 0) {
|
||||
parts[part] += c + 1;
|
||||
parts[part - 1]--;
|
||||
}
|
||||
}
|
||||
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" },
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue