134 lines
4.1 KiB
Diff
134 lines
4.1 KiB
Diff
From 5848437fa171c593f777226306b146d02a09f70e Mon Sep 17 00:00:00 2001
|
|
From: Emeric Brun <ebrun@haproxy.com>
|
|
Date: Fri, 20 Jun 2014 15:46:13 +0200
|
|
Subject: [PATCH 3/5] BUG/MEDIUM: ssl: Fix to not serve expired OCSP responses.
|
|
|
|
For some browsers (firefox), an expired OCSP Response causes unwanted behavior.
|
|
|
|
Haproxy stops serving OCSP response if nextupdate date minus
|
|
the supported time skew (#define OCSP_MAX_RESPONSE_TIME_SKEW) is
|
|
in the past.
|
|
(cherry picked from commit 4f3c87a5d942d4d0649c35805ff4e335970b87d4)
|
|
---
|
|
src/ssl_sock.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
|
|
1 file changed, 87 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
|
|
index 278af8b..9eacf9f 100644
|
|
--- a/src/ssl_sock.c
|
|
+++ b/src/ssl_sock.c
|
|
@@ -110,9 +110,91 @@ struct certificate_ocsp {
|
|
struct ebmb_node key;
|
|
unsigned char key_data[OCSP_MAX_CERTID_ASN1_LENGTH];
|
|
struct chunk response;
|
|
-
|
|
+ long expire;
|
|
};
|
|
|
|
+/*
|
|
+ * This function returns the number of seconds elapsed
|
|
+ * since the Epoch, 1970-01-01 00:00:00 +0000 (UTC) and the
|
|
+ * date presented un ASN1_GENERALIZEDTIME.
|
|
+ *
|
|
+ * In parsing error case, it returns -1.
|
|
+ */
|
|
+static long asn1_generalizedtime_to_epoch(ASN1_GENERALIZEDTIME *d)
|
|
+{
|
|
+ long epoch;
|
|
+ char *p, *end;
|
|
+ const unsigned short month_offset[12] = {
|
|
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
|
|
+ };
|
|
+ int year, month;
|
|
+
|
|
+ if (!d || (d->type != V_ASN1_GENERALIZEDTIME)) return -1;
|
|
+
|
|
+ p = (char *)d->data;
|
|
+ end = p + d->length;
|
|
+
|
|
+ if (end - p < 4) return -1;
|
|
+ year = 1000 * (p[0] - '0') + 100 * (p[1] - '0') + 10 * (p[2] - '0') + p[3] - '0';
|
|
+ p += 4;
|
|
+ if (end - p < 2) return -1;
|
|
+ month = 10 * (p[0] - '0') + p[1] - '0';
|
|
+ if (month < 1 || month > 12) return -1;
|
|
+ /* Compute the number of seconds since 1 jan 1970 and the beginning of current month
|
|
+ We consider leap years and the current month (<marsh or not) */
|
|
+ epoch = ( ((year - 1970) * 365)
|
|
+ + ((year - (month < 3)) / 4 - (year - (month < 3)) / 100 + (year - (month < 3)) / 400)
|
|
+ - ((1970 - 1) / 4 - (1970 - 1) / 100 + (1970 - 1) / 400)
|
|
+ + month_offset[month-1]
|
|
+ ) * 24 * 60 * 60;
|
|
+ p += 2;
|
|
+ if (end - p < 2) return -1;
|
|
+ /* Add the number of seconds of completed days of current month */
|
|
+ epoch += (10 * (p[0] - '0') + p[1] - '0' - 1) * 24 * 60 * 60;
|
|
+ p += 2;
|
|
+ if (end - p < 2) return -1;
|
|
+ /* Add the completed hours of the current day */
|
|
+ epoch += (10 * (p[0] - '0') + p[1] - '0') * 60 * 60;
|
|
+ p += 2;
|
|
+ if (end - p < 2) return -1;
|
|
+ /* Add the completed minutes of the current hour */
|
|
+ epoch += (10 * (p[0] - '0') + p[1] - '0') * 60;
|
|
+ p += 2;
|
|
+ if (p == end) return -1;
|
|
+ /* Test if there is available seconds */
|
|
+ if (p[0] < '0' || p[0] > '9')
|
|
+ goto nosec;
|
|
+ if (end - p < 2) return -1;
|
|
+ /* Add the seconds of the current minute */
|
|
+ epoch += 10 * (p[0] - '0') + p[1] - '0';
|
|
+ p += 2;
|
|
+ if (p == end) return -1;
|
|
+ /* Ignore seconds float part if present */
|
|
+ if (p[0] == '.') {
|
|
+ do {
|
|
+ if (++p == end) return -1;
|
|
+ } while (p[0] >= '0' && p[0] <= '9');
|
|
+ }
|
|
+
|
|
+nosec:
|
|
+ if (p[0] == 'Z') {
|
|
+ if (end - p != 1) return -1;
|
|
+ return epoch;
|
|
+ }
|
|
+ else if (p[0] == '+') {
|
|
+ if (end - p != 5) return -1;
|
|
+ /* Apply timezone offset */
|
|
+ return epoch - ((10 * (p[1] - '0') + p[2] - '0') * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
|
|
+ }
|
|
+ else if (p[0] == '-') {
|
|
+ if (end - p != 5) return -1;
|
|
+ /* Apply timezone offset */
|
|
+ return epoch + ((10 * (p[1] - '0') + p[2] - '0') * 60 + (10 * (p[3] - '0') + p[4] - '0')) * 60;
|
|
+ }
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
static struct eb_root cert_ocsp_tree;
|
|
|
|
/* This function starts to check if the OCSP response (in DER format) contained
|
|
@@ -229,6 +311,8 @@ static int ssl_sock_load_ocsp_response(struct chunk *ocsp_response, struct certi
|
|
goto out;
|
|
}
|
|
|
|
+ ocsp->expire = asn1_generalizedtime_to_epoch(nextupd) - OCSP_MAX_RESPONSE_TIME_SKEW;
|
|
+
|
|
ret = 0;
|
|
out:
|
|
if (bs)
|
|
@@ -306,7 +390,8 @@ int ssl_sock_ocsp_stapling_cbk(SSL *ssl, void *arg)
|
|
|
|
if (!ocsp ||
|
|
!ocsp->response.str ||
|
|
- !ocsp->response.len)
|
|
+ !ocsp->response.len ||
|
|
+ (ocsp->expire < now.tv_sec))
|
|
return SSL_TLSEXT_ERR_NOACK;
|
|
|
|
ssl_buf = OPENSSL_malloc(ocsp->response.len);
|
|
--
|
|
1.8.5.5
|
|
|