[PATCH 2 of 6] SSL Stapling : ...

Filipe DA SILVA fdasilva at ingima.com
Thu Apr 16 10:10:17 UTC 2015


# HG changeset patch
# User Filipe da Silva <fdasilva at ingima.com>
# Date 1429178261 -7200
#      Thu Apr 16 11:57:41 2015 +0200
# Node ID 85fb1b1e922fd95ef0df3c7f8bc9625af3054002
# Parent  d201e4afd59eaf79419836c1dcdec83e141d3f67
SSL Stapling: attach stapling_t context to X509 cert, instead of ssl_ctx.
Keep a common part of stapling config attached to initial SSL_CTX context.

diff -r d201e4afd59e -r 85fb1b1e922f src/event/ngx_event_openssl_stapling.c
--- a/src/event/ngx_event_openssl_stapling.c	Thu Apr 16 11:57:41 2015 +0200
+++ b/src/event/ngx_event_openssl_stapling.c	Thu Apr 16 11:57:41 2015 +0200
@@ -14,13 +14,23 @@
 #if (!defined OPENSSL_NO_OCSP && defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
 
 
+/* OCSP stapling configuration per server */
 typedef struct {
+    /* OCSP response to staple from file */
     ngx_str_t                    staple;
     ngx_msec_t                   timeout;
 
     ngx_resolver_t              *resolver;
     ngx_msec_t                   resolver_timeout;
 
+    unsigned                     verify:1;
+} ngx_ssl_staple_t;
+
+
+/* OCSP stapling context per certificate */
+typedef struct {
+    ngx_str_t                    staple;    /* OCSP response from responder */
+
     ngx_addr_t                  *addrs;
     ngx_str_t                    host;
     ngx_str_t                    uri;
@@ -33,7 +43,6 @@ typedef struct {
 
     time_t                       valid;
 
-    unsigned                     verify:1;
     unsigned                     loading:1;
 } ngx_ssl_stapling_t;
 
@@ -53,6 +62,7 @@ struct ngx_ssl_ocsp_ctx_s {
 
     ngx_resolver_t              *resolver;
     ngx_msec_t                   resolver_timeout;
+    unsigned                     verify:1;
 
     ngx_msec_t                   timeout;
 
@@ -83,14 +93,15 @@ struct ngx_ssl_ocsp_ctx_s {
 
 
 static ngx_int_t ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl,
-    ngx_str_t *file);
+    ngx_str_t *file, ngx_ssl_staple_t *conf);
 static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl);
 static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
     ngx_str_t *responder);
 
 static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
     void *data);
-static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple);
+static void ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple,
+    ngx_ssl_staple_t *conf);
 static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
 
 static void ngx_ssl_stapling_cleanup(void *data);
@@ -119,23 +130,14 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl
     ngx_str_t *responder, ngx_uint_t verify)
 {
     ngx_int_t                  rc;
-    ngx_pool_cleanup_t        *cln;
-    ngx_ssl_stapling_t        *staple;
+    ngx_ssl_staple_t          *conf;
 
-    staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
-    if (staple == NULL) {
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_staple_t));
+    if (conf == NULL) {
         return NGX_ERROR;
     }
 
-    cln = ngx_pool_cleanup_add(cf->pool, 0);
-    if (cln == NULL) {
-        return NGX_ERROR;
-    }
-
-    cln->handler = ngx_ssl_stapling_cleanup;
-    cln->data = staple;
-
-    if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_stapling_index, staple)
+    if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_stapling_index, conf)
         == 0)
     {
         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
@@ -143,14 +145,13 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl
         return NGX_ERROR;
     }
 
-    staple->ssl_ctx = ssl->ctx;
-    staple->timeout = 60000;
-    staple->verify = verify;
+    conf->timeout = 60000;
+    conf->verify = verify;
 
     if (file->len) {
         /* use OCSP response from the file */
 
-        if (ngx_ssl_stapling_file(cf, ssl, file) != NGX_OK) {
+        if (ngx_ssl_stapling_file(cf, ssl, file, conf) != NGX_OK) {
             return NGX_ERROR;
         }
 
@@ -180,22 +181,20 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl
 done:
 
     SSL_CTX_set_tlsext_status_cb(ssl->ctx, ngx_ssl_certificate_status_callback);
-    SSL_CTX_set_tlsext_status_arg(ssl->ctx, staple);
+    SSL_CTX_set_tlsext_status_arg(ssl->ctx, conf);
 
     return NGX_OK;
 }
 
 
 static ngx_int_t
-ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file)
+ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file,
+    ngx_ssl_staple_t *conf)
 {
     BIO                 *bio;
     int                  len;
     u_char              *p, *buf;
     OCSP_RESPONSE       *response;
-    ngx_ssl_stapling_t  *staple;
-
-    staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
 
     if (ngx_conf_full_name(cf->cycle, file, 1) != NGX_OK) {
         return NGX_ERROR;
@@ -223,7 +222,8 @@ ngx_ssl_stapling_file(ngx_conf_t *cf, ng
         goto failed;
     }
 
-    buf = ngx_alloc(len, ssl->log);
+    /* File content buffer allocated from pool to avoid additional cleanup */
+    buf = ngx_palloc(cf->pool, len);
     if (buf == NULL) {
         goto failed;
     }
@@ -240,8 +240,8 @@ ngx_ssl_stapling_file(ngx_conf_t *cf, ng
     OCSP_RESPONSE_free(response);
     BIO_free(bio);
 
-    staple->staple.data = buf;
-    staple->staple.len = len;
+    conf->staple.data = buf;
+    conf->staple.len = len;
 
     return NGX_OK;
 
@@ -263,9 +263,32 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, 
     X509_STORE_CTX      *store_ctx;
     STACK_OF(X509)      *chain;
     ngx_ssl_stapling_t  *staple;
+    ngx_pool_cleanup_t  *cln;
 
-    staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
-    cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
+    cert = ngx_ssl_get_server_certificate(ssl, NGX_SSL_FIRST_CERT);
+
+    staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
+    if (staple == NULL) {
+        return NGX_ERROR;
+    }
+
+    cln = ngx_pool_cleanup_add(cf->pool, 0);
+    if (cln == NULL) {
+        return NGX_ERROR;
+    }
+
+    cln->handler = ngx_ssl_stapling_cleanup;
+    cln->data = staple;
+
+    if (X509_set_ex_data(cert, ngx_ssl_cert_stapling_index, staple)
+        == 0)
+    {
+        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                      "X509_set_ex_data() failed");
+        return NGX_ERROR;
+    }
+
+    staple->ssl_ctx = ssl->ctx;
 
 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
     SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
@@ -348,9 +371,11 @@ ngx_ssl_stapling_responder(ngx_conf_t *c
     ngx_url_t                  u;
     char                      *s;
     ngx_ssl_stapling_t        *staple;
+    X509                      *cert;
     STACK_OF(OPENSSL_STRING)  *aia;
 
-    staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
+    cert = ngx_ssl_get_server_certificate(ssl, NGX_SSL_FIRST_CERT);
+    staple = X509_get_ex_data(cert, ngx_ssl_cert_stapling_index);
 
     if (responder->len == 0) {
 
@@ -435,7 +460,7 @@ ngx_int_t
 ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
     ngx_resolver_t *resolver, ngx_msec_t resolver_timeout)
 {
-    ngx_ssl_stapling_t  *staple;
+    ngx_ssl_staple_t    *staple;
 
     staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
 
@@ -451,41 +476,54 @@ ngx_ssl_certificate_status_callback(ngx_
 {
     int                  rc;
     u_char              *p;
+    ngx_str_t           resp;
     ngx_connection_t    *c;
+    ngx_ssl_staple_t    *conf;
     ngx_ssl_stapling_t  *staple;
+    X509                *cert;
 
     c = ngx_ssl_get_connection(ssl_conn);
+    cert = SSL_get_certificate(ssl_conn);
 
     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                    "SSL certificate status callback");
 
-    staple = data;
+    staple = X509_get_ex_data(cert, ngx_ssl_cert_stapling_index);
+    conf = data;
     rc = SSL_TLSEXT_ERR_NOACK;
+    resp.len = 0;
 
-    if (staple->staple.len) {
-        /* we have to copy ocsp response as OpenSSL will free it by itself */
+    if (conf->staple.len) {
+        resp = conf->staple;
+    }
+    else if (staple && staple->staple.len) {
+        resp = staple->staple;
+    }
 
-        p = OPENSSL_malloc(staple->staple.len);
+    if (resp.len) {
+        /* We have to copy ocsp response as OpenSSL will free it by itself */
+        p = OPENSSL_malloc(resp.len);
         if (p == NULL) {
             ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "OPENSSL_malloc() failed");
             return SSL_TLSEXT_ERR_NOACK;
         }
 
-        ngx_memcpy(p, staple->staple.data, staple->staple.len);
+        ngx_memcpy(p, resp.data, resp.len);
 
-        SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, staple->staple.len);
+        SSL_set_tlsext_status_ocsp_resp(ssl_conn, p, resp.len);
 
         rc = SSL_TLSEXT_ERR_OK;
     }
 
-    ngx_ssl_stapling_update(staple);
+    if (staple)
+        ngx_ssl_stapling_update(staple, conf);
 
     return rc;
 }
 
 
 static void
-ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
+ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple, ngx_ssl_staple_t *conf)
 {
     ngx_ssl_ocsp_ctx_t  *ctx;
 
@@ -509,10 +547,10 @@ ngx_ssl_stapling_update(ngx_ssl_stapling
     ctx->host = staple->host;
     ctx->uri = staple->uri;
     ctx->port = staple->port;
-    ctx->timeout = staple->timeout;
+    ctx->timeout = conf->timeout;
 
-    ctx->resolver = staple->resolver;
-    ctx->resolver_timeout = staple->resolver_timeout;
+    ctx->resolver = conf->resolver;
+    ctx->resolver_timeout = conf->resolver_timeout;
 
     ctx->handler = ngx_ssl_stapling_ocsp_handler;
     ctx->data = staple;
@@ -592,7 +630,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_oc
 #endif
 
     if (OCSP_basic_verify(basic, chain, store,
-                          staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
+                          ctx->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
         != 1)
     {
         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,



More information about the nginx-devel mailing list