|
@@ -54,6 +54,7 @@ |
|
|
* copied and put under another distribution licence |
|
|
* copied and put under another distribution licence |
|
|
* [including the GNU Public Licence.] */ |
|
|
* [including the GNU Public Licence.] */ |
|
|
|
|
|
|
|
|
|
|
|
#include <ctype.h> |
|
|
#include <openssl/asn1.h> |
|
|
#include <openssl/asn1.h> |
|
|
#include <openssl/bio.h> |
|
|
#include <openssl/bio.h> |
|
|
#include <openssl/digest.h> |
|
|
#include <openssl/digest.h> |
|
@@ -415,45 +416,84 @@ int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm) |
|
|
return (0); |
|
|
return (0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) |
|
|
|
|
|
{ |
|
|
|
|
|
const char *v; |
|
|
|
|
|
int gmt = 0; |
|
|
|
|
|
int i; |
|
|
|
|
|
int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0; |
|
|
|
|
|
|
|
|
// consume_two_digits is a helper function for ASN1_UTCTIME_print. If |*v|, |
|
|
|
|
|
// assumed to be |*len| bytes long, has two leading digits, updates |*out| with |
|
|
|
|
|
// their value, updates |v| and |len|, and returns one. Otherwise, returns |
|
|
|
|
|
// zero. |
|
|
|
|
|
static int consume_two_digits(int* out, const char **v, int *len) { |
|
|
|
|
|
if (*len < 2|| !isdigit((*v)[0]) || !isdigit((*v)[1])) { |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
*out = ((*v)[0] - '0') * 10 + ((*v)[1] - '0'); |
|
|
|
|
|
*len -= 2; |
|
|
|
|
|
*v += 2; |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
i = tm->length; |
|
|
|
|
|
v = (const char *)tm->data; |
|
|
|
|
|
|
|
|
// consume_zulu_timezone is a helper function for ASN1_UTCTIME_print. If |*v|, |
|
|
|
|
|
// assumed to be |*len| bytes long, starts with "Z" then it updates |*v| and |
|
|
|
|
|
// |*len| and returns one. Otherwise returns zero. |
|
|
|
|
|
static int consume_zulu_timezone(const char **v, int *len) { |
|
|
|
|
|
if (*len == 0 || (*v)[0] != 'Z') { |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*len -= 1; |
|
|
|
|
|
*v += 1; |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (i < 10) |
|
|
|
|
|
goto err; |
|
|
|
|
|
if (v[i - 1] == 'Z') |
|
|
|
|
|
gmt = 1; |
|
|
|
|
|
for (i = 0; i < 10; i++) |
|
|
|
|
|
if ((v[i] > '9') || (v[i] < '0')) |
|
|
|
|
|
goto err; |
|
|
|
|
|
y = (v[0] - '0') * 10 + (v[1] - '0'); |
|
|
|
|
|
if (y < 50) |
|
|
|
|
|
y += 100; |
|
|
|
|
|
M = (v[2] - '0') * 10 + (v[3] - '0'); |
|
|
|
|
|
if ((M > 12) || (M < 1)) |
|
|
|
|
|
goto err; |
|
|
|
|
|
d = (v[4] - '0') * 10 + (v[5] - '0'); |
|
|
|
|
|
h = (v[6] - '0') * 10 + (v[7] - '0'); |
|
|
|
|
|
m = (v[8] - '0') * 10 + (v[9] - '0'); |
|
|
|
|
|
if (tm->length >= 12 && |
|
|
|
|
|
(v[10] >= '0') && (v[10] <= '9') && (v[11] >= '0') && (v[11] <= '9')) |
|
|
|
|
|
s = (v[10] - '0') * 10 + (v[11] - '0'); |
|
|
|
|
|
|
|
|
|
|
|
if (BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s", |
|
|
|
|
|
mon[M - 1], d, h, m, s, y + 1900, |
|
|
|
|
|
(gmt) ? " GMT" : "") <= 0) |
|
|
|
|
|
return (0); |
|
|
|
|
|
else |
|
|
|
|
|
return (1); |
|
|
|
|
|
err: |
|
|
|
|
|
BIO_write(bp, "Bad time value", 14); |
|
|
|
|
|
return (0); |
|
|
|
|
|
|
|
|
int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) { |
|
|
|
|
|
const char *v = (const char *)tm->data; |
|
|
|
|
|
int len = tm->length; |
|
|
|
|
|
int Y = 0, M = 0, D = 0, h = 0, m = 0, s = 0; |
|
|
|
|
|
|
|
|
|
|
|
// YYMMDDhhmm are required to be present. |
|
|
|
|
|
if (!consume_two_digits(&Y, &v, &len) || |
|
|
|
|
|
!consume_two_digits(&M, &v, &len) || |
|
|
|
|
|
!consume_two_digits(&D, &v, &len) || |
|
|
|
|
|
!consume_two_digits(&h, &v, &len) || |
|
|
|
|
|
!consume_two_digits(&m, &v, &len)) { |
|
|
|
|
|
goto err; |
|
|
|
|
|
} |
|
|
|
|
|
// https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, requires seconds |
|
|
|
|
|
// to be present, but historically this code has forgiven its absence. |
|
|
|
|
|
consume_two_digits(&s, &v, &len); |
|
|
|
|
|
|
|
|
|
|
|
// https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, specifies this |
|
|
|
|
|
// interpretation of the year. |
|
|
|
|
|
if (Y < 50) { |
|
|
|
|
|
Y += 2000; |
|
|
|
|
|
} else { |
|
|
|
|
|
Y += 1900; |
|
|
|
|
|
} |
|
|
|
|
|
if (M > 12 || M == 0) { |
|
|
|
|
|
goto err; |
|
|
|
|
|
} |
|
|
|
|
|
if (D > 31 || D == 0) { |
|
|
|
|
|
goto err; |
|
|
|
|
|
} |
|
|
|
|
|
if (h > 23 || m > 59 || s > 60) { |
|
|
|
|
|
goto err; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, requires the "Z" |
|
|
|
|
|
// to be present, but historically this code has forgiven its absence. |
|
|
|
|
|
const int is_gmt = consume_zulu_timezone(&v, &len); |
|
|
|
|
|
|
|
|
|
|
|
// https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, does not permit |
|
|
|
|
|
// the specification of timezones using the +hhmm / -hhmm syntax, which is |
|
|
|
|
|
// the only other thing that might legitimately be found at the end. |
|
|
|
|
|
if (len) { |
|
|
|
|
|
goto err; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s", mon[M - 1], D, h, m, s, Y, |
|
|
|
|
|
is_gmt ? " GMT" : "") > 0; |
|
|
|
|
|
|
|
|
|
|
|
err: |
|
|
|
|
|
BIO_write(bp, "Bad time value", 14); |
|
|
|
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int X509_NAME_print(BIO *bp, X509_NAME *name, int obase) |
|
|
int X509_NAME_print(BIO *bp, X509_NAME *name, int obase) |
|
|