summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorBob Beck <beck@cvs.openbsd.org>2017-05-04 12:36:14 +0000
committerBob Beck <beck@cvs.openbsd.org>2017-05-04 12:36:14 +0000
commitb6f11f216c6deb8bbd19fac4a0b44e5ec623f5d1 (patch)
tree60031c20b9852d07481c0e934898bebc8bf09396 /usr.bin
parent48506b35933f157f784d48891363b867264ab5df (diff)
Fix the ca command so that certs it generates have RFC5280 conformant time.
Problem noticed by Harald Dunkel <harald.dunkel@aixigo.de>
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/openssl/ca.c72
1 files changed, 56 insertions, 16 deletions
diff --git a/usr.bin/openssl/ca.c b/usr.bin/openssl/ca.c
index a3e779da333..9ed7c59caa5 100644
--- a/usr.bin/openssl/ca.c
+++ b/usr.bin/openssl/ca.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ca.c,v 1.23 2017/01/20 08:57:11 deraadt Exp $ */
+/* $OpenBSD: ca.c,v 1.24 2017/05/04 12:36:13 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -207,6 +207,48 @@ static int preserve = 0;
static int msie_hack = 0;
+/*
+ * Set a certificate time based on user provided input. Make sure
+ * what we put in the certificate is legit for RFC 5280. Returns
+ * 0 on success, -1 on an invalid time string. Strings must be
+ * YYYYMMDDHHMMSSZ for post 2050 dates. YYYYMMDDHHMMSSZ or
+ * YYMMDDHHMMSSZ is accepted for pre 2050 dates, and fixed up to
+ * be the correct format in the certificate.
+ */
+static int
+setCertificateTime(ASN1_TIME *x509time, char *timestring)
+{
+ struct tm tm1, tm2;
+ char *rfctime = timestring;
+ int type;
+
+ memset(&tm1, 0, sizeof(tm1));
+ memset(&tm2, 0, sizeof(tm2));
+ type = ASN1_time_parse(timestring, strlen(timestring), &tm1, 0);
+ if (type == -1) {
+ return (-1);
+ }
+
+ /* RFC 5280 section 4.1.2.5 */
+ if (tm1.tm_year < 150 && type != V_ASN1_UTCTIME) {
+ if (strlen(timestring) == 15) {
+ /* Fix date if possible */
+ rfctime = timestring + 2;
+ type = ASN1_time_parse(rfctime, strlen(rfctime),
+ &tm2, 0);
+ if (type != V_ASN1_UTCTIME ||
+ tm1.tm_year != tm2.tm_year)
+ return (-1);
+ } else
+ return (-1);
+ }
+ if (tm1.tm_year >= 150 && type != V_ASN1_GENERALIZEDTIME)
+ return (-1);
+ ASN1_TIME_set_string(x509time, rfctime);
+ return (0);
+}
+
+
int
ca_main(int argc, char **argv)
{
@@ -905,10 +947,6 @@ bad:
if (startdate == NULL)
ERR_clear_error();
}
- if (startdate && !ASN1_TIME_set_string(NULL, startdate)) {
- BIO_printf(bio_err, "start date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
- goto err;
- }
if (startdate == NULL)
startdate = "today";
@@ -918,16 +956,12 @@ bad:
if (enddate == NULL)
ERR_clear_error();
}
- if (enddate && !ASN1_TIME_set_string(NULL, enddate)) {
- BIO_printf(bio_err, "end date is invalid, it should be YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ\n");
- goto err;
- }
- if (days == 0) {
+ if (days == 0 && enddate == NULL) {
if (!NCONF_get_number(conf, section,
- ENV_DEFAULT_DAYS, &days))
+ ENV_DEFAULT_DAYS, &days))
days = 0;
}
- if (!enddate && (days == 0)) {
+ if (enddate == NULL && days == 0) {
BIO_printf(bio_err,
"cannot lookup how many days to certify for\n");
goto err;
@@ -1774,13 +1808,19 @@ again2:
if (strcmp(startdate, "today") == 0)
X509_gmtime_adj(X509_get_notBefore(ret), 0);
- else
- ASN1_TIME_set_string(X509_get_notBefore(ret), startdate);
+ else if (setCertificateTime(X509_get_notBefore(ret), startdate) == -1) {
+ BIO_printf(bio_err, "Invalid start date %s\n",
+ startdate);
+ goto err;
+ }
if (enddate == NULL)
X509_time_adj_ex(X509_get_notAfter(ret), days, 0, NULL);
- else
- ASN1_TIME_set_string(X509_get_notAfter(ret), enddate);
+ else if (setCertificateTime(X509_get_notAfter(ret), enddate) == -1) {
+ BIO_printf(bio_err, "Invalid end date %s\n",
+ enddate);
+ goto err;
+ }
if (!X509_set_subject_name(ret, subject))
goto err;