[PATCH 2 of 2] Proxy: add support for OCSP stapling verification from upstream

Alessandro Ghedini alessandro at cloudflare.com
Fri Jan 22 17:38:06 UTC 2016


# HG changeset patch
# User Alessandro Ghedini <alessandro at cloudflare.com>
# Date 1453481233 0
#      Fri Jan 22 16:47:13 2016 +0000
# Node ID c6668c14a2d168307bcfade0cc2e01c92c31312a
# Parent  a8c4f65236ad90138863d5295ca059a3d37da37e
Proxy: add support for OCSP stapling verification from upstream

This patch adds the "proxy_ssl_stapling_verify" option that controls OCSP
stapling verification from an upstream server.

The option allows three values:

 - "off" (default): disable OCSP stapling completely.
 - "on": request OCSP stapling from upstream and verify response if
         provided.
 - "full": same as "on", but fail also when no response is received.

Signed-off-by: Alessandro Ghedini <alessandro at cloudflare.com>

diff -r a8c4f65236ad -r c6668c14a2d1 src/event/ngx_event_openssl.h
--- a/src/event/ngx_event_openssl.h	Fri Jan 22 16:46:35 2016 +0000
+++ b/src/event/ngx_event_openssl.h	Fri Jan 22 16:47:13 2016 +0000
@@ -121,6 +121,11 @@
 #define NGX_SSL_BUFSIZE  16384
 
 
+#define NGX_SSL_STAPLING_VERIFY_OFF   0
+#define NGX_SSL_STAPLING_VERIFY_ON    1
+#define NGX_SSL_STAPLING_VERIFY_FULL  2
+
+
 ngx_int_t ngx_ssl_init(ngx_log_t *log);
 ngx_int_t ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data);
 ngx_int_t ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
@@ -132,6 +137,7 @@
 ngx_int_t ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl);
 ngx_int_t ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl,
     ngx_str_t *file, ngx_str_t *responder, ngx_uint_t verify);
+ngx_int_t ngx_ssl_stapling_verify(ngx_connection_t *c, ngx_int_t strict);
 ngx_int_t ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout);
 RSA *ngx_ssl_rsa512_key_callback(ngx_ssl_conn_t *ssl_conn, int is_export,
diff -r a8c4f65236ad -r c6668c14a2d1 src/event/ngx_event_openssl_stapling.c
--- a/src/event/ngx_event_openssl_stapling.c	Fri Jan 22 16:46:35 2016 +0000
+++ b/src/event/ngx_event_openssl_stapling.c	Fri Jan 22 16:47:13 2016 +0000
@@ -194,6 +194,48 @@
 }
 
 
+ngx_int_t
+ngx_ssl_stapling_verify(ngx_connection_t *c, ngx_int_t strict)
+{
+    int                   rc;
+    long                  len;
+    time_t                valid;
+    ngx_str_t             ocsp_resp;
+    STACK_OF(X509)       *chain;
+    ngx_ssl_stapling_t    staple;
+
+    staple.ssl_ctx = c->ssl->connection->ctx;
+
+    len = SSL_get_tlsext_status_ocsp_resp(c->ssl->connection, &ocsp_resp.data);
+    if (len < 0) {
+        if (strict) {
+            ngx_log_error(NGX_LOG_ERR, c->log, 0, "missing OCSP response");
+            return NGX_ERROR;
+        }
+
+        return NGX_OK;
+    }
+
+    ocsp_resp.len = len;
+
+    chain = SSL_get_peer_cert_chain(c->ssl->connection);
+
+    rc = ngx_ssl_stapling_find_issuer(&staple, c->log, c->ssl->connection->ctx,
+                                      sk_X509_value(chain, 0), chain);
+    if (rc != NGX_OK) {
+        return NGX_ERROR;
+    }
+
+    rc = ngx_ssl_stapling_verify_response(c->log, &ocsp_resp, &staple,
+                                          chain, 0, &valid);
+    if (rc != NGX_OK) {
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
+
+
 static ngx_int_t
 ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
 {
@@ -1860,6 +1902,12 @@
 }
 
 ngx_int_t
+ngx_ssl_stapling_verify(ngx_connection_t *c, ngx_int_t strict)
+{
+    return NGX_OK;
+}
+
+ngx_int_t
 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
 {
diff -r a8c4f65236ad -r c6668c14a2d1 src/http/modules/ngx_http_proxy_module.c
--- a/src/http/modules/ngx_http_proxy_module.c	Fri Jan 22 16:46:35 2016 +0000
+++ b/src/http/modules/ngx_http_proxy_module.c	Fri Jan 22 16:47:13 2016 +0000
@@ -236,6 +236,14 @@
     { ngx_null_string, 0 }
 };
 
+
+static ngx_conf_enum_t  ngx_http_proxy_ssl_stapling_verify[] = {
+    { ngx_string("off"), NGX_SSL_STAPLING_VERIFY_OFF },
+    { ngx_string("on"), NGX_SSL_STAPLING_VERIFY_ON },
+    { ngx_string("full"), NGX_SSL_STAPLING_VERIFY_FULL },
+    { ngx_null_string, 0 }
+};
+
 #endif
 
 
@@ -698,6 +706,13 @@
       0,
       NULL },
 
+    { ngx_string("proxy_ssl_stapling_verify"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_enum_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_stapling_verify),
+      &ngx_http_proxy_ssl_stapling_verify },
+
 #endif
 
       ngx_null_command
@@ -2865,6 +2880,7 @@
     conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
     conf->upstream.ssl_server_name = NGX_CONF_UNSET;
     conf->upstream.ssl_verify = NGX_CONF_UNSET;
+    conf->upstream.ssl_stapling_verify = NGX_CONF_UNSET;
     conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
     conf->ssl_passwords = NGX_CONF_UNSET_PTR;
 #endif
@@ -3187,6 +3203,8 @@
                               prev->upstream.ssl_server_name, 0);
     ngx_conf_merge_value(conf->upstream.ssl_verify,
                               prev->upstream.ssl_verify, 0);
+    ngx_conf_merge_value(conf->upstream.ssl_stapling_verify,
+                              prev->upstream.ssl_stapling_verify, 0);
     ngx_conf_merge_uint_value(conf->ssl_verify_depth,
                               prev->ssl_verify_depth, 1);
     ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
diff -r a8c4f65236ad -r c6668c14a2d1 src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c	Fri Jan 22 16:46:35 2016 +0000
+++ b/src/http/ngx_http_upstream.c	Fri Jan 22 16:47:13 2016 +0000
@@ -1496,6 +1496,12 @@
         }
     }
 
+#if (!defined OPENSSL_NO_OCSP && defined TLSEXT_STATUSTYPE_ocsp)
+    if (u->conf->ssl_stapling_verify) {
+        SSL_set_tlsext_status_type(c->ssl->connection, TLSEXT_STATUSTYPE_ocsp);
+    }
+#endif
+
     if (u->conf->ssl_session_reuse) {
         if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
             ngx_http_upstream_finalize_request(r, u,
@@ -1548,6 +1554,7 @@
 ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
 {
     long                  rc;
+    ngx_int_t             ocsp_strict;
     ngx_http_request_t   *r;
     ngx_http_upstream_t  *u;
 
@@ -1576,6 +1583,16 @@
             }
         }
 
+        if (u->conf->ssl_stapling_verify) {
+            ocsp_strict =
+                u->conf->ssl_stapling_verify == NGX_SSL_STAPLING_VERIFY_FULL;
+
+            rc = ngx_ssl_stapling_verify(c, ocsp_strict);
+            if (rc != NGX_OK) {
+                goto failed;
+            }
+        }
+
         if (u->conf->ssl_session_reuse) {
             u->peer.save_session(&u->peer, u->peer.data);
         }
diff -r a8c4f65236ad -r c6668c14a2d1 src/http/ngx_http_upstream.h
--- a/src/http/ngx_http_upstream.h	Fri Jan 22 16:46:35 2016 +0000
+++ b/src/http/ngx_http_upstream.h	Fri Jan 22 16:47:13 2016 +0000
@@ -217,6 +217,7 @@
     ngx_http_complex_value_t        *ssl_name;
     ngx_flag_t                       ssl_server_name;
     ngx_flag_t                       ssl_verify;
+    ngx_int_t                        ssl_stapling_verify;
 #endif
 
     ngx_str_t                        module;



More information about the nginx-devel mailing list