summaryrefslogtreecommitdiff
path: root/lib/libssl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libssl')
-rw-r--r--lib/libssl/src/crypto/asn1/a_gentm.c106
-rw-r--r--lib/libssl/src/crypto/asn1/a_time.c25
-rw-r--r--lib/libssl/src/crypto/asn1/a_time_tm.c257
-rw-r--r--lib/libssl/src/crypto/asn1/a_utctm.c80
-rw-r--r--lib/libssl/src/crypto/asn1/asn1_locl.h6
-rw-r--r--lib/libssl/src/crypto/x509/x509_lcl.h1
-rw-r--r--lib/libssl/src/crypto/x509/x509_vfy.c128
7 files changed, 332 insertions, 271 deletions
diff --git a/lib/libssl/src/crypto/asn1/a_gentm.c b/lib/libssl/src/crypto/asn1/a_gentm.c
index 4cee40437cc..594eb630580 100644
--- a/lib/libssl/src/crypto/asn1/a_gentm.c
+++ b/lib/libssl/src/crypto/asn1/a_gentm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: a_gentm.c,v 1.24 2015/09/30 18:04:02 jsing Exp $ */
+/* $OpenBSD: a_gentm.c,v 1.25 2015/10/02 15:04:45 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -66,86 +66,14 @@
#include <openssl/err.h>
#include "o_time.h"
+#include "asn1_locl.h"
int
ASN1_GENERALIZEDTIME_check(ASN1_GENERALIZEDTIME *d)
{
- static const int min[9] = {0, 0, 1, 1, 0, 0, 0, 0, 0};
- static const int max[9] = {99, 99, 12, 31, 23, 59, 59, 12, 59};
- char *a;
- int n, i, l, o;
-
if (d->type != V_ASN1_GENERALIZEDTIME)
return (0);
- l = d->length;
- a = (char *)d->data;
- o = 0;
- /* GENERALIZEDTIME is similar to UTCTIME except the year is
- * represented as YYYY. This stuff treats everything as a two digit
- * field so make first two fields 00 to 99
- */
- if (l < 13)
- goto err;
- for (i = 0; i < 7; i++) {
- if ((i == 6) && ((a[o] == 'Z') ||
- (a[o] == '+') || (a[o] == '-'))) {
- i++;
- break;
- }
- if ((a[o] < '0') || (a[o] > '9'))
- goto err;
- n= a[o]-'0';
- if (++o > l)
- goto err;
-
- if ((a[o] < '0') || (a[o] > '9'))
- goto err;
- n = (n * 10)+ a[o] - '0';
- if (++o > l)
- goto err;
-
- if ((n < min[i]) || (n > max[i]))
- goto err;
- }
- /* Optional fractional seconds: decimal point followed by one
- * or more digits.
- */
- if (a[o] == '.') {
- if (++o > l)
- goto err;
- i = o;
- while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
- o++;
- /* Must have at least one digit after decimal point */
- if (i == o)
- goto err;
- }
-
- if (a[o] == 'Z')
- o++;
- else if ((a[o] == '+') || (a[o] == '-')) {
- o++;
- if (o + 4 > l)
- goto err;
- for (i = 7; i < 9; i++) {
- if ((a[o] < '0') || (a[o] > '9'))
- goto err;
- n = a[o] - '0';
- o++;
- if ((a[o] < '0') || (a[o] > '9'))
- goto err;
- n = (n * 10) + a[o] - '0';
- if ((n < min[i]) || (n > max[i]))
- goto err;
- o++;
- }
- } else {
- /* Missing time zone information. */
- goto err;
- }
- return (o == l);
-err:
- return (0);
+ return (d->type == asn1_time_parse(d->data, d->length, NULL, d->type));
}
int
@@ -179,34 +107,26 @@ ASN1_GENERALIZEDTIME_adj_internal(ASN1_GENERALIZEDTIME *s, time_t t,
int offset_day, long offset_sec)
{
char *p;
- struct tm *ts;
+ struct tm *tm;
struct tm data;
- size_t len = 20;
- ts = gmtime_r(&t, &data);
- if (ts == NULL)
+ tm = gmtime_r(&t, &data);
+ if (tm == NULL)
return (NULL);
if (offset_day || offset_sec) {
- if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
+ if (!OPENSSL_gmtime_adj(tm, offset_day, offset_sec))
return NULL;
}
- p = (char *)s->data;
- if ((p == NULL) || ((size_t)s->length < len)) {
- p = malloc(len);
- if (p == NULL) {
- ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ,
- ERR_R_MALLOC_FAILURE);
- return (NULL);
- }
- free(s->data);
- s->data = (unsigned char *)p;
+ if ((p = gentime_string_from_tm(tm)) == NULL) {
+ ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, ERR_R_MALLOC_FAILURE);
+ return (NULL);
}
-
- snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900,
- ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec);
+ free(s->data);
+ s->data = p;
s->length = strlen(p);
+
s->type = V_ASN1_GENERALIZEDTIME;
return (s);
}
diff --git a/lib/libssl/src/crypto/asn1/a_time.c b/lib/libssl/src/crypto/asn1/a_time.c
index 25a1805640e..a6c7c8e736a 100644
--- a/lib/libssl/src/crypto/asn1/a_time.c
+++ b/lib/libssl/src/crypto/asn1/a_time.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: a_time.c,v 1.25 2015/09/30 18:04:02 jsing Exp $ */
+/* $OpenBSD: a_time.c,v 1.26 2015/10/02 15:04:45 beck Exp $ */
/* ====================================================================
* Copyright (c) 1999 The OpenSSL Project. All rights reserved.
*
@@ -68,7 +68,7 @@
#include <openssl/err.h>
#include "o_time.h"
-
+#include "asn1_locl.h"
const ASN1_ITEM ASN1_TIME_it = {
.itype = ASN1_ITYPE_MSTRING,
@@ -135,11 +135,9 @@ ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day, long offset_sec)
int
ASN1_TIME_check(ASN1_TIME *t)
{
- if (t->type == V_ASN1_GENERALIZEDTIME)
- return ASN1_GENERALIZEDTIME_check(t);
- else if (t->type == V_ASN1_UTCTIME)
- return ASN1_UTCTIME_check(t);
- return 0;
+ if (t->type != V_ASN1_GENERALIZEDTIME && t->type != V_ASN1_UTCTIME)
+ return 0;
+ return (t->type == asn1_time_parse(t->data, t->length, NULL, t->type));
}
/* Convert an ASN1_TIME structure to GeneralizedTime */
@@ -210,13 +208,12 @@ ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
t.data = (unsigned char *)str;
t.flags = 0;
- t.type = V_ASN1_UTCTIME;
-
- if (!ASN1_TIME_check(&t)) {
- t.type = V_ASN1_GENERALIZEDTIME;
- if (!ASN1_TIME_check(&t))
- return 0;
- }
+ t.type = asn1_time_parse(t.data, t.length, NULL, V_ASN1_UTCTIME);
+ if (t.type == -1)
+ t.type = asn1_time_parse(t.data, t.length, NULL,
+ V_ASN1_GENERALIZEDTIME);
+ if (t.type == -1)
+ return 0;
if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
return 0;
diff --git a/lib/libssl/src/crypto/asn1/a_time_tm.c b/lib/libssl/src/crypto/asn1/a_time_tm.c
new file mode 100644
index 00000000000..65f75c68cc6
--- /dev/null
+++ b/lib/libssl/src/crypto/asn1/a_time_tm.c
@@ -0,0 +1,257 @@
+/* $OpenBSD: a_time_tm.c,v 1.1 2015/10/02 15:04:45 beck Exp $ */
+/*
+ * Copyright (c) 2015 Bob Beck <beck@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+#include <sys/limits.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/err.h>
+
+#include "o_time.h"
+#include "asn1_locl.h"
+
+char *
+gentime_string_from_tm(struct tm *tm)
+{
+ char *ret = NULL;
+ int year;
+ year = tm->tm_year + 1900;
+ if (year < 0 || year > 9999)
+ return (NULL);
+ if (asprintf(&ret, "%04u%02u%02u%02u%02u%02uZ", year,
+ tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min,
+ tm->tm_sec) == -1)
+ ret = NULL;
+ return (ret);
+}
+
+char *
+utctime_string_from_tm(struct tm *tm)
+{
+ char *ret = NULL;
+ if (tm->tm_year >= 150 || tm->tm_year < 50)
+ return (NULL);
+ if (asprintf(&ret, "%02u%02u%02u%02u%02u%02uZ",
+ tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec) == -1)
+ ret = NULL;
+ return (ret);
+}
+
+/*
+ * Parse an ASN.1 time string.
+ *
+ * mode must be:
+ * 0 if we expect to parse a time as specified in RFC 5280 from an
+ * X509 certificate.
+ * V_ASN1_UTCTIME if we wish to parse a legacy ASN1 UTC time.
+ * V_ASN1_GENERALIZEDTIME if we wish to parse a legacy ASN1
+ * Generalizd time.
+ *
+ * Returns:
+ * -1 if the string was invalid.
+ * V_ASN1_UTCTIME if the string validated as a UTC time string.
+ * V_ASN1_GENERALIZEDTIME if the string validated as a Generalized time string.
+ *
+ * Fills in *tm with the corresponding time if tm is non NULL.
+ */
+#define RFC5280 0
+#define ATOI2(ar) ((ar) += 2, ((ar)[-2] - '0') * 10 + ((ar)[-1] - '0'))
+int asn1_time_parse(const char * bytes, size_t len, struct tm *tm, int mode)
+{
+ char *p, *buf = NULL, *dot = NULL, *tz = NULL;
+ int i, offset, noseconds = 0, type = 0;
+ struct tm ltm;
+ struct tm *lt;
+ size_t tlen;
+ char tzc;
+
+ if (bytes == NULL)
+ goto err;
+
+ if (len > INT_MAX)
+ goto err;
+
+ /* Constrain the RFC5280 case within max/min valid lengths. */
+ if (mode == RFC5280 && (len > 15 || len < 13))
+ goto err;
+
+ if ((buf = strndup(bytes, len)) == NULL)
+ goto err;
+ lt = tm;
+ if (lt == NULL) {
+ time_t t = time(NULL);
+ lt = gmtime_r(&t, &ltm);
+ if (lt == NULL)
+ goto err;
+ }
+
+ /*
+ * Find position of the optional fractional seconds, and the
+ * start of the timezone, while ensuring everything else is
+ * digits.
+ */
+ for (i = 0; i < len; i++) {
+ char *t = buf + i;
+ if (isdigit((unsigned char)*t))
+ continue;
+ if (*t == '.' && dot == NULL) {
+ dot = t;
+ continue;
+ }
+ if ((*t == 'Z' || *t == '+' || *t == '-') && tz == NULL) {
+ tz = t;
+ continue;
+ }
+ goto err;
+ }
+
+ /*
+ * Timezone is required. For the non-RFC case it may be
+ * either Z or +- HHMM, but for RFC5280 it may be only Z.
+ */
+ if (tz == NULL)
+ goto err;
+ tzc = *tz;
+ *tz++ = '\0';
+ if (tzc == 'Z') {
+ if (*tz != '\0')
+ goto err;
+ offset = 0;
+ } else if (mode != RFC5280 && (tzc == '+' || tzc == '-') &&
+ (strlen(tz) == 4)) {
+ int hours, mins;
+ hours = ATOI2(tz);
+ mins = ATOI2(tz);
+ if (hours > 12 || mins > 59)
+ goto err;
+ offset = hours * 3600 + mins * 60;
+ if (tzc == '-')
+ offset = -offset;
+ } else
+ goto err;
+
+ if (mode != RFC5280) {
+ /* XXX - yuck - OPENSSL_gmtime_adj should go away */
+ if (!OPENSSL_gmtime_adj(lt, 0, offset))
+ goto err;
+ }
+
+ /*
+ * We only allow fractional seconds to be present if we are in
+ * the non-RFC case of a Generalized time. RFC 5280 forbids
+ * fractional seconds.
+ */
+ if (dot != NULL) {
+ if (mode != V_ASN1_GENERALIZEDTIME)
+ goto err;
+ *dot++ = '\0';
+ if (!isdigit((unsigned char)*dot))
+ goto err;
+ }
+
+ /*
+ * Validate and convert the time
+ */
+ p = buf;
+ tlen = strlen(buf);
+ switch (tlen) {
+ case 14:
+ lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */
+ if (mode == RFC5280 || mode == V_ASN1_GENERALIZEDTIME)
+ type = V_ASN1_GENERALIZEDTIME;
+ else
+ goto err;
+ /* FALLTHROUGH */
+ case 12:
+ if (type == 0 && mode == V_ASN1_GENERALIZEDTIME) {
+ /*
+ * In the non-RFC case of a Generalized time
+ * seconds may not have been provided. RFC
+ * 5280 mandates that seconds must be present.
+ */
+ noseconds = 1;
+ lt->tm_year = (ATOI2(p) * 100) - 1900; /* cc */
+ type = V_ASN1_GENERALIZEDTIME;
+ }
+ /* FALLTHROUGH */
+ case 10:
+ if (type == 0) {
+ /*
+ * At this point we must have a UTC time.
+ * In the RFC 5280 case it must have the
+ * seconds present. In the non-RFC case
+ * may have no seconds.
+ */
+ if (mode == V_ASN1_GENERALIZEDTIME)
+ goto err;
+ if (tlen == 10) {
+ if (mode == V_ASN1_UTCTIME)
+ noseconds = 1;
+ else
+ goto err;
+ }
+ type = V_ASN1_UTCTIME;
+ }
+ lt->tm_year += ATOI2(p); /* yy */
+ if (type == V_ASN1_UTCTIME) {
+ if (lt->tm_year < 50)
+ lt->tm_year += 100;
+ }
+ lt->tm_mon = ATOI2(p); /* mm */
+ if ((lt->tm_mon > 12) || !lt->tm_mon)
+ goto err;
+ --lt->tm_mon; /* struct tm is 0 - 11 */
+ lt->tm_mday = ATOI2(p); /* dd */
+ if ((lt->tm_mday > 31) || !lt->tm_mday)
+ goto err;
+ lt->tm_hour = ATOI2(p); /* HH */
+ if (lt->tm_hour > 23)
+ goto err;
+ lt->tm_min = ATOI2(p); /* MM */
+ if (lt->tm_min > 59)
+ goto err;
+ lt->tm_sec = 0; /* SS */
+ if (noseconds)
+ break;
+ lt->tm_sec = ATOI2(p);
+ /* Leap second 60 is not accepted. Reconsider later? */
+ if (lt->tm_sec > 59)
+ goto err;
+ break;
+ default:
+ goto err;
+ }
+
+ /* RFC 5280 section 4.1.2.5 */
+ if (mode == RFC5280 && lt->tm_year < 150 &&
+ type != V_ASN1_UTCTIME)
+ goto err;
+ if (mode == RFC5280 && lt->tm_year >= 150 &&
+ type != V_ASN1_GENERALIZEDTIME)
+ goto err;
+
+ free(buf);
+ return type;
+
+err:
+ free(buf);
+ return -1;
+}
diff --git a/lib/libssl/src/crypto/asn1/a_utctm.c b/lib/libssl/src/crypto/asn1/a_utctm.c
index ca19a8c7a00..c208d494c3a 100644
--- a/lib/libssl/src/crypto/asn1/a_utctm.c
+++ b/lib/libssl/src/crypto/asn1/a_utctm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: a_utctm.c,v 1.28 2015/09/30 18:26:07 jsing Exp $ */
+/* $OpenBSD: a_utctm.c,v 1.29 2015/10/02 15:04:45 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -64,66 +64,14 @@
#include <openssl/err.h>
#include "o_time.h"
+#include "asn1_locl.h"
int
ASN1_UTCTIME_check(ASN1_UTCTIME *d)
{
- static const int min[8] = {0, 1, 1, 0, 0, 0, 0, 0};
- static const int max[8] = {99, 12, 31, 23, 59, 59, 12, 59};
- char *a;
- int n, i, l, o;
-
if (d->type != V_ASN1_UTCTIME)
return (0);
- l = d->length;
- a = (char *)d->data;
- o = 0;
-
- if (l < 11)
-
- goto err;
- for (i = 0; i < 6; i++) {
- if ((i == 5) && ((a[o] == 'Z') ||
- (a[o] == '+') || (a[o] == '-'))) {
- i++;
- break;
- }
- if ((a[o] < '0') || (a[o] > '9'))
- goto err;
- n = a[o]-'0';
- if (++o > l)
- goto err;
- if ((a[o] < '0') || (a[o] > '9'))
- goto err;
- n = (n * 10) + a[o] - '0';
- if (++o > l)
- goto err;
- if ((n < min[i]) || (n > max[i]))
- goto err;
- }
- if (a[o] == 'Z')
- o++;
- else if ((a[o] == '+') || (a[o] == '-')) {
- o++;
- if (o + 4 > l)
- goto err;
- for (i = 6; i < 8; i++) {
- if ((a[o] < '0') || (a[o] > '9'))
- goto err;
- n = a[o] -'0';
- o++;
- if ((a[o] < '0') || (a[o] > '9'))
- goto err;
- n = (n * 10) + a[o] - '0';
- if ((n < min[i]) || (n > max[i]))
- goto err;
- o++;
- }
- }
- return (o == l);
-
-err:
- return (0);
+ return(d->type == asn1_time_parse(d->data, d->length, NULL, d->type));
}
int
@@ -159,7 +107,6 @@ ASN1_UTCTIME_adj_internal(ASN1_UTCTIME *s, time_t t, int offset_day,
char *p;
struct tm *ts;
struct tm data;
- size_t len = 20;
ts = gmtime_r(&t, &data);
if (ts == NULL)
@@ -170,23 +117,14 @@ ASN1_UTCTIME_adj_internal(ASN1_UTCTIME *s, time_t t, int offset_day,
return NULL;
}
- if ((ts->tm_year < 50) || (ts->tm_year >= 150))
- return NULL;
-
- p = (char *)s->data;
- if ((p == NULL) || ((size_t)s->length < len)) {
- p = malloc(len);
- if (p == NULL) {
- ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE);
- return (NULL);
- }
- free(s->data);
- s->data = (unsigned char *)p;
+ if ((p = utctime_string_from_tm(ts)) == NULL) {
+ ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE);
+ return (NULL);
}
-
- snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100,
- ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, ts->tm_sec);
+ free(s->data);
+ s->data = p;
s->length = strlen(p);
+
s->type = V_ASN1_UTCTIME;
return (s);
}
diff --git a/lib/libssl/src/crypto/asn1/asn1_locl.h b/lib/libssl/src/crypto/asn1/asn1_locl.h
index c6c80aa6aa2..d4994c7cee5 100644
--- a/lib/libssl/src/crypto/asn1/asn1_locl.h
+++ b/lib/libssl/src/crypto/asn1/asn1_locl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: asn1_locl.h,v 1.5 2014/06/12 15:49:27 deraadt Exp $ */
+/* $OpenBSD: asn1_locl.h,v 1.6 2015/10/02 15:04:45 beck Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
@@ -58,6 +58,10 @@
/* Internal ASN1 structures and functions: not for application use */
+char * gentime_string_from_tm(struct tm *tm);
+char * utctime_string_from_tm(struct tm *tm);
+int asn1_time_parse(const char *, size_t, struct tm *, int);
+
/* ASN1 print context structure */
struct asn1_pctx_st {
diff --git a/lib/libssl/src/crypto/x509/x509_lcl.h b/lib/libssl/src/crypto/x509/x509_lcl.h
index b16df78ad7c..0c1c130d5c8 100644
--- a/lib/libssl/src/crypto/x509/x509_lcl.h
+++ b/lib/libssl/src/crypto/x509/x509_lcl.h
@@ -57,3 +57,4 @@
*/
int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet);
+int asn1_time_parse(const char *, size_t, struct tm *, int);
diff --git a/lib/libssl/src/crypto/x509/x509_vfy.c b/lib/libssl/src/crypto/x509/x509_vfy.c
index 8d4d15668ec..c48143f3517 100644
--- a/lib/libssl/src/crypto/x509/x509_vfy.c
+++ b/lib/libssl/src/crypto/x509/x509_vfy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: x509_vfy.c,v 1.45 2015/09/14 16:13:39 jsing Exp $ */
+/* $OpenBSD: x509_vfy.c,v 1.46 2015/10/02 15:04:45 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -1631,106 +1631,50 @@ X509_cmp_current_time(const ASN1_TIME *ctm)
return X509_cmp_time(ctm, NULL);
}
+/*
+ * Compare a possibly unvalidated ASN1_TIME string against a time_t
+ * using RFC 5280 rules for the time string. If *cmp_time is NULL
+ * the current system time is used.
+ *
+ * XXX NOTE that unlike what you expect a "cmp" function to do in C,
+ * XXX this one is "special", and returns 0 for error.
+ *
+ * Returns:
+ * -1 if the ASN1_time is earlier than OR the same as *cmp_time.
+ * 1 if the ASN1_time is later than *cmp_time.
+ * 0 on error.
+ */
int
X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
{
- char *str;
- ASN1_TIME atm;
- long offset;
- char buff1[24], buff2[24], *p;
- int i, j;
+ time_t time1, time2;
+ struct tm tm1;
+ int ret = 0;
- p = buff1;
- i = ctm->length;
- str = (char *)ctm->data;
- if (ctm->type == V_ASN1_UTCTIME) {
- if ((i < 11) || (i > 17))
- return 0;
- memcpy(p, str, 10);
- p += 10;
- str += 10;
- i -= 10;
- } else {
- if (i < 13)
- return 0;
- memcpy(p, str, 12);
- p += 12;
- str += 12;
- i -= 12;
- }
+ if (cmp_time == NULL)
+ time2 = time(NULL);
+ else
+ time2 = *cmp_time;
- if (i < 1)
- return 0;
- if ((*str == 'Z') || (*str == '-') || (*str == '+')) {
- *(p++) = '0';
- *(p++) = '0';
- } else {
- if (i < 2)
- return 0;
- *(p++) = *(str++);
- *(p++) = *(str++);
- i -= 2;
- if (i < 1)
- return 0;
- /* Skip any fractional seconds... */
- if (*str == '.') {
- str++;
- i--;
- while (i > 1 && (*str >= '0') && (*str <= '9')) {
- str++;
- i--;
- }
- }
- }
- *(p++) = 'Z';
- *(p++) = '\0';
+ memset(&tm1, 0, sizeof(tm1));
- if (i < 1)
- return 0;
- if (*str == 'Z') {
- if (i != 1)
- return 0;
- offset = 0;
- } else {
- if (i != 5)
- return 0;
- if ((*str != '+') && (*str != '-'))
- return 0;
- if (str[1] < '0' || str[1] > '9' ||
- str[2] < '0' || str[2] > '9' ||
- str[3] < '0' || str[3] > '9' ||
- str[4] < '0' || str[4] > '9')
- return 0;
- offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60;
- offset += (str[3] - '0') * 10 + (str[4] - '0');
- if (*str == '-')
- offset = -offset;
- }
- atm.type = ctm->type;
- atm.flags = 0;
- atm.length = sizeof(buff2);
- atm.data = (unsigned char *)buff2;
+ if (asn1_time_parse(ctm->data, ctm->length, &tm1, 0) == -1)
+ goto out; /* invalid time */
- if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL)
- return 0;
+ /*
+ * Defensively fail if the time string is not representable as
+ * a time_t. A time_t must be sane if you care about times after
+ * Jan 19 2038.
+ */
+ if ((time1 = timegm(&tm1)) == -1)
+ goto out;
- if (ctm->type == V_ASN1_UTCTIME) {
- i = (buff1[0] - '0') * 10 + (buff1[1] - '0');
- if (i < 50)
- i += 100; /* cf. RFC 2459 */
- j = (buff2[0] - '0') * 10 + (buff2[1] - '0');
- if (j < 50)
- j += 100;
- if (i < j)
- return -1;
- if (i > j)
- return 1;
- }
- i = strcmp(buff1, buff2);
- if (i == 0) /* wait a second then return younger :-) */
- return -1;
+ if (time1 <= time2)
+ ret = -1;
else
- return i;
+ ret = 1;
+ out:
+ return (ret);
}
ASN1_TIME *