Improve ASN1_TIME_print documentation and output

This adds missing GMT indication when printing the local time as
it is converted to the UTC timezone before printing.

Also fixing the fractional seconds printing on EBCDIC platforms.

Fixes #26313

Reviewed-by: Todd Short <todd.short@me.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26344)

(cherry picked from commit c81ff97866)
This commit is contained in:
Michael Baentsch 2025-01-08 12:57:28 +01:00 committed by Tomas Mraz
parent ca27dcf9da
commit 0a08a5cc69
2 changed files with 31 additions and 32 deletions

View file

@ -490,9 +490,9 @@ int ASN1_TIME_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
int ossl_asn1_time_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
{
char *v;
int gmt = 0, l;
int l;
struct tm stm;
const char upper_z = 0x5A, period = 0x2E;
const char period = 0x2E;
/* ossl_asn1_time_to_tm will check the time type */
if (!ossl_asn1_time_to_tm(&stm, tm))
@ -500,8 +500,6 @@ int ossl_asn1_time_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
l = tm->length;
v = (char *)tm->data;
if (v[l - 1] == upper_z)
gmt = 1;
if (tm->type == V_ASN1_GENERALIZEDTIME) {
char *f = NULL;
@ -512,39 +510,36 @@ int ossl_asn1_time_print_ex(BIO *bp, const ASN1_TIME *tm, unsigned long flags)
* 'fraction point' in a GeneralizedTime string.
*/
if (tm->length > 15 && v[14] == period) {
f = &v[14];
f_len = 1;
while (14 + f_len < l && ossl_ascii_isdigit(f[f_len]))
/* exclude the . itself */
f = &v[15];
f_len = 0;
while (15 + f_len < l && ossl_ascii_isdigit(f[f_len]))
++f_len;
}
if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%.*s%s",
if (f_len > 0) {
if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d.%.*sZ",
stm.tm_year + 1900, stm.tm_mon + 1,
stm.tm_mday, stm.tm_hour,
stm.tm_min, stm.tm_sec, f_len, f) > 0;
} else {
return BIO_printf(bp, "%s %2d %02d:%02d:%02d.%.*s %d GMT",
_asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
stm.tm_min, stm.tm_sec, f_len, f,
stm.tm_year + 1900) > 0;
}
}
}
if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02dZ",
stm.tm_year + 1900, stm.tm_mon + 1,
stm.tm_mday, stm.tm_hour,
stm.tm_min, stm.tm_sec, f_len, f,
(gmt ? "Z" : "")) > 0;
}
else {
return BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
_asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
stm.tm_min, stm.tm_sec, f_len, f, stm.tm_year + 1900,
(gmt ? " GMT" : "")) > 0;
}
stm.tm_min, stm.tm_sec) > 0;
} else {
if ((flags & ASN1_DTFLGS_TYPE_MASK) == ASN1_DTFLGS_ISO8601) {
return BIO_printf(bp, "%4d-%02d-%02d %02d:%02d:%02d%s",
stm.tm_year + 1900, stm.tm_mon + 1,
stm.tm_mday, stm.tm_hour,
stm.tm_min, stm.tm_sec,
(gmt ? "Z" : "")) > 0;
}
else {
return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s",
return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d GMT",
_asn1_mon[stm.tm_mon], stm.tm_mday, stm.tm_hour,
stm.tm_min, stm.tm_sec, stm.tm_year + 1900,
(gmt ? " GMT" : "")) > 0;
}
stm.tm_min, stm.tm_sec, stm.tm_year + 1900) > 0;
}
}

View file

@ -102,8 +102,8 @@ functions check the syntax of the time structure I<s>.
The ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print()
functions print the time structure I<s> to BIO I<b> in human readable
format. It will be of the format MMM DD HH:MM:SS YYYY [GMT], for example
"Feb 3 00:55:52 2015 GMT", which does not include a newline.
format. It will be of the format MMM DD HH:MM:SS[.s*] YYYY GMT, for example
"Feb E<32>3 00:55:52 2015 GMT", which does not include a newline.
If the time structure has invalid format it prints out "Bad time value" and
returns an error. The output for generalized time may include a fractional part
following the second.
@ -179,6 +179,10 @@ starting with B<ASN1_UTCTIME> and B<ASN1_GENERALIZEDTIME> act only on that
specific time format. The functions starting with B<ASN1_TIME> will operate on
either format.
Users familiar with RFC822 should note that when specifying the flag
B<ASN1_DTFLGS_RFC822> the year will be formatted as documented above,
i.e., using 4 digits, not 2 as specified in RFC822.
=head1 BUGS
ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print() do