[nginx] OCSP stapling: avoid sending expired responses (ticket #...
Maxim Dounin
mdounin at mdounin.ru
Thu Jun 11 18:56:47 UTC 2015
details: http://hg.nginx.org/nginx/rev/6893a1007a7c
branches:
changeset: 6181:6893a1007a7c
user: Maxim Dounin <mdounin at mdounin.ru>
date: Thu Jun 11 20:42:39 2015 +0300
description:
OCSP stapling: avoid sending expired responses (ticket #425).
diffstat:
src/event/ngx_event_openssl_stapling.c | 68 +++++++++++++++++++++++++++++++---
1 files changed, 62 insertions(+), 6 deletions(-)
diffs (154 lines):
diff --git a/src/event/ngx_event_openssl_stapling.c b/src/event/ngx_event_openssl_stapling.c
--- a/src/event/ngx_event_openssl_stapling.c
+++ b/src/event/ngx_event_openssl_stapling.c
@@ -32,6 +32,7 @@ typedef struct {
X509 *issuer;
time_t valid;
+ time_t refresh;
unsigned verify:1;
unsigned loading:1;
@@ -93,6 +94,8 @@ static int ngx_ssl_certificate_status_ca
static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple);
static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
+static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
+
static void ngx_ssl_stapling_cleanup(void *data);
static ngx_ssl_ocsp_ctx_t *ngx_ssl_ocsp_start(void);
@@ -462,7 +465,9 @@ ngx_ssl_certificate_status_callback(ngx_
staple = data;
rc = SSL_TLSEXT_ERR_NOACK;
- if (staple->staple.len) {
+ if (staple->staple.len
+ && staple->valid >= ngx_time())
+ {
/* we have to copy ocsp response as OpenSSL will free it by itself */
p = OPENSSL_malloc(staple->staple.len);
@@ -490,7 +495,7 @@ ngx_ssl_stapling_update(ngx_ssl_stapling
ngx_ssl_ocsp_ctx_t *ctx;
if (staple->host.len == 0
- || staple->loading || staple->valid >= ngx_time())
+ || staple->loading || staple->refresh >= ngx_time())
{
return;
}
@@ -532,6 +537,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc
u_char *p;
int n;
size_t len;
+ time_t now, valid;
ngx_str_t response;
X509_STORE *store;
STACK_OF(X509) *chain;
@@ -542,6 +548,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc
ASN1_GENERALIZEDTIME *thisupdate, *nextupdate;
staple = ctx->data;
+ now = ngx_time();
ocsp = NULL;
basic = NULL;
id = NULL;
@@ -629,17 +636,28 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc
goto error;
}
+ valid = ngx_ssl_stapling_time(nextupdate);
+ if (valid == (time_t) NGX_ERROR) {
+ ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
+ "invalid nextUpdate time in certificate status");
+ goto error;
+ }
+
OCSP_CERTID_free(id);
OCSP_BASICRESP_free(basic);
OCSP_RESPONSE_free(ocsp);
+ id = NULL;
+ basic = NULL;
+ ocsp = NULL;
+
/* copy the response to memory not in ctx->pool */
response.len = len;
response.data = ngx_alloc(response.len, ctx->log);
if (response.data == NULL) {
- goto done;
+ goto error;
}
ngx_memcpy(response.data, ctx->response->pos, response.len);
@@ -653,11 +671,15 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc
}
staple->staple = response;
+ staple->valid = valid;
-done:
+ /*
+ * refresh before the response expires,
+ * but not earlier than in 5 minutes, and at least in an hour
+ */
staple->loading = 0;
- staple->valid = ngx_time() + 3600; /* ssl_stapling_valid */
+ staple->refresh = ngx_max(ngx_min(valid - 300, now + 3600), now + 300);
ngx_ssl_ocsp_done(ctx);
return;
@@ -665,7 +687,7 @@ done:
error:
staple->loading = 0;
- staple->valid = ngx_time() + 300; /* ssl_stapling_err_valid */
+ staple->refresh = now + 300;
if (id) {
OCSP_CERTID_free(id);
@@ -683,6 +705,40 @@ error:
}
+static time_t
+ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time)
+{
+ u_char *value;
+ size_t len;
+ time_t time;
+ BIO *bio;
+
+ /*
+ * OpenSSL doesn't provide a way to convert ASN1_GENERALIZEDTIME
+ * into time_t. To do this, we use ASN1_GENERALIZEDTIME_print(),
+ * which uses the "MMM DD HH:MM:SS YYYY [GMT]" format (e.g.,
+ * "Feb 3 00:55:52 2015 GMT"), and parse the result.
+ */
+
+ bio = BIO_new(BIO_s_mem());
+ if (bio == NULL) {
+ return NGX_ERROR;
+ }
+
+ /* fake weekday prepended to match C asctime() format */
+
+ BIO_write(bio, "Tue ", sizeof("Tue ") - 1);
+ ASN1_GENERALIZEDTIME_print(bio, asn1time);
+ len = BIO_get_mem_data(bio, &value);
+
+ time = ngx_parse_http_time(value, len);
+
+ BIO_free(bio);
+
+ return time;
+}
+
+
static void
ngx_ssl_stapling_cleanup(void *data)
{
More information about the nginx-devel
mailing list