BBlack has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/235739

Change subject: multicert + libssl1.0.2 diffs rebased onto 1.9.4-1
......................................................................

multicert + libssl1.0.2 diffs rebased onto 1.9.4-1

Change-Id: I67b67af2280c94c15cd1d74696672d674a2d3e6c
---
M debian/control
A debian/patches/1001-openssl102.patch
A debian/patches/1002-stapling-per-cert.patch
A debian/patches/1003-stapling-multi-cert.patch
A debian/patches/1004-cert-list.patch
A debian/patches/1005-multicert-modules.patch
A debian/patches/1006-multicert-stream-modules.patch
M debian/patches/series
8 files changed, 1,686 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.wikimedia.org:29418/operations/software/nginx 
refs/changes/39/235739/1

diff --git a/debian/control b/debian/control
index b3bfcc3..1548aef 100644
--- a/debian/control
+++ b/debian/control
@@ -20,7 +20,7 @@
                libpam0g-dev,
                libpcre3-dev,
                libperl-dev,
-               libssl-dev,
+               libssl-dev (>= 1.0.2),
                libxslt1-dev,
                po-debconf,
                zlib1g-dev
diff --git a/debian/patches/1001-openssl102.patch 
b/debian/patches/1001-openssl102.patch
new file mode 100644
index 0000000..e78e7d3
--- /dev/null
+++ b/debian/patches/1001-openssl102.patch
@@ -0,0 +1,231 @@
+----------- Original nginx-devel post --------------------------------------
+Hi, 
+
+This is my last  version of 'Multiple server certificates support ' patches.
+
+I restaged the changes in a more smart way.
+It is more respectful of 'contributing' requirements.
+
+It relies on OpenSSL to maintain a list of server certificates.
+It now stores a stapling context within/for each server certificate. 
+
+Reviews and comments are welcome.
+
+Regards,
+Filipe da Silva
+Ingima
+
+---
+# HG changeset patch
+# User Filipe da Silva <fdasilva at ingima.com>
+# Date 1430147821 -7200
+#      Mon Apr 27 17:17:01 2015 +0200
+# Node ID 0ac2a8668f852b604d46ff858199650bd3003fdb
+# Parent  fc99323a3d790dcc7b87121261b4236d098336de
+SSL: introduce support of last openssl 1.0.2 features.
+
+Rely on openSSL 1.0.2 internals to manage the server certificate list and
+replace the previous SSL_CTX_ex_data(ngx_ssl_certificate_index, ...) storage.
+
+Add two new server certificate accessor methods to encapsulate this change:
+ngx_ssl_get_server_certificate & ngx_ssl_get_next_server_certificate.
+
+Add guards around ngx_ssl_stapling_index init when OCSP stapling is 
unsupported.
+
+Compatible with 'stable-1.8'.
+------- End original nginx-devel post --------------------------------------
+
+WMF notes: applied to 1.9.3 with only one trivial manual context fixup, patch
+below is amended to apply cleanly
+
+diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
+index 1b789e6..982ef24 100644
+--- a/src/event/ngx_event_openssl.c
++++ b/src/event/ngx_event_openssl.c
+@@ -168,6 +168,7 @@ ngx_ssl_init(ngx_log_t *log)
+         return NGX_ERROR;
+     }
+ 
++#if OPENSSL_VERSION_NUMBER < 0x10002000L
+     ngx_ssl_certificate_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
+                                                          NULL);
+     if (ngx_ssl_certificate_index == -1) {
+@@ -175,7 +176,9 @@ ngx_ssl_init(ngx_log_t *log)
+                       "SSL_CTX_get_ex_new_index() failed");
+         return NGX_ERROR;
+     }
++#endif
+ 
++#if (!defined OPENSSL_NO_OCSP && defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
+     ngx_ssl_stapling_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,
+                                                       NULL);
+     if (ngx_ssl_stapling_index == -1) {
+@@ -183,6 +186,7 @@ ngx_ssl_init(ngx_log_t *log)
+                       "SSL_CTX_get_ex_new_index() failed");
+         return NGX_ERROR;
+     }
++#endif
+ 
+     return NGX_OK;
+ }
+@@ -297,6 +301,33 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void 
*data)
+ }
+ 
+ 
++X509*
++ngx_ssl_get_server_certificate(ngx_ssl_t *ssl)
++{
++#if OPENSSL_VERSION_NUMBER >= 0x10002000L
++    if (SSL_CTX_set_current_cert(ssl->ctx, SSL_CERT_SET_FIRST)) {
++        return (SSL_CTX_get0_certificate(ssl->ctx));
++    }
++    return NULL;
++#else
++
++    return (SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index));
++#endif
++}
++
++
++X509*
++ngx_ssl_get_next_server_certificate(ngx_ssl_t *ssl)
++{
++#if OPENSSL_VERSION_NUMBER >= 0x10002000L
++    if (SSL_CTX_set_current_cert(ssl->ctx, SSL_CERT_SET_NEXT)) {
++        return (SSL_CTX_get0_certificate(ssl->ctx));
++    }
++#endif
++    return NULL;
++}
++
++
+ ngx_int_t
+ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
+     ngx_str_t *key, ngx_array_t *passwords)
+@@ -340,6 +371,7 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, 
ngx_str_t *cert,
+         return NGX_ERROR;
+     }
+ 
++#if OPENSSL_VERSION_NUMBER < 0x10002000L
+     if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
+         == 0)
+     {
+@@ -349,6 +381,7 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, 
ngx_str_t *cert,
+         BIO_free(bio);
+         return NGX_ERROR;
+     }
++#endif
+ 
+     X509_free(x509);
+ 
+@@ -376,10 +409,21 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, 
ngx_str_t *cert,
+             return NGX_ERROR;
+         }
+ 
++#ifdef SSL_CTX_add0_chain_cert
++        /*
++         * OpenSSL >=1.0.2 allows multiple server certificates in a single
++         * SSL_CTX to each have a different chain
++         */
++        if (SSL_CTX_add0_chain_cert(ssl->ctx, x509) == 0) {
++            ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
++                          "SSL_CTX_add0_chain_cert(\"%s\") failed",
++                          cert->data);
++#else
+         if (SSL_CTX_add_extra_chain_cert(ssl->ctx, x509) == 0) {
+             ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+                           "SSL_CTX_add_extra_chain_cert(\"%s\") failed",
+                           cert->data);
++#endif
+             X509_free(x509);
+             BIO_free(bio);
+             return NGX_ERROR;
+@@ -2150,7 +2194,7 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t 
*sess_ctx)
+         goto failed;
+     }
+ 
+-    cert = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
++    cert = ngx_ssl_get_server_certificate(ssl);
+ 
+     if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) {
+         ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
+index 08eff64..d7d0381 100644
+--- a/src/event/ngx_event_openssl.h
++++ b/src/event/ngx_event_openssl.h
+@@ -189,6 +189,8 @@ ngx_int_t ngx_ssl_get_fingerprint(ngx_connection_t *c, 
ngx_pool_t *pool,
+     ngx_str_t *s);
+ ngx_int_t ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool,
+     ngx_str_t *s);
++X509* ngx_ssl_get_server_certificate(ngx_ssl_t *ssl);
++X509* ngx_ssl_get_next_server_certificate(ngx_ssl_t *ssl);
+ 
+ 
+ ngx_int_t ngx_ssl_handshake(ngx_connection_t *c);
+@@ -208,7 +210,6 @@ extern int  ngx_ssl_connection_index;
+ extern int  ngx_ssl_server_conf_index;
+ extern int  ngx_ssl_session_cache_index;
+ extern int  ngx_ssl_session_ticket_keys_index;
+-extern int  ngx_ssl_certificate_index;
+ extern int  ngx_ssl_stapling_index;
+ 
+ 
+diff --git a/src/event/ngx_event_openssl_stapling.c 
b/src/event/ngx_event_openssl_stapling.c
+index fa77678..a4f5679 100644
+--- a/src/event/ngx_event_openssl_stapling.c
++++ b/src/event/ngx_event_openssl_stapling.c
+@@ -269,9 +269,11 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
+     ngx_ssl_stapling_t  *staple;
+ 
+     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->ctx);
+ 
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++#ifdef SSL_CTX_get0_chain_certs
++    SSL_CTX_get0_chain_certs(ssl->ctx, &chain);
++#elif OPENSSL_VERSION_NUMBER >= 0x10001000L
+     SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
+ #else
+     chain = ssl->ctx->extra_certs;
+@@ -538,6 +540,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
+     u_char                *p;
+     int                    n;
+     size_t                 len;
++    unsigned long          flags;
+     time_t                 now, valid;
+     ngx_str_t              response;
+     X509_STORE            *store;
+@@ -593,15 +596,28 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
+         goto error;
+     }
+ 
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++#ifdef SSL_CTX_get0_chain_certs
++    SSL_CTX_get0_chain_certs(staple->ssl_ctx, &chain);
++#elif OPENSSL_VERSION_NUMBER >= 0x10001000L
+     SSL_CTX_get_extra_chain_certs(staple->ssl_ctx, &chain);
+ #else
+     chain = staple->ssl_ctx->extra_certs;
+ #endif
+ 
+-    if (OCSP_basic_verify(basic, chain, store,
+-                          staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
+-        != 1)
++    flags = staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY;
++
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++    /*
++     * ECDSA/SHA-2 signature verification not supported.
++     * Released with OpenSSL 1.0.0 [29 Mar 2010]
++     *  *) Add support for dsa-with-SHA224 and dsa-with-SHA256.
++     * See openssl commit 06e2dd037e29f82b92e1d1b9454f1595e602fb94
++     */
++    flags = flags | OCSP_NOSIGS;
++    /* TODO: improve case handling */
++#endif
++
++    if (OCSP_basic_verify(basic, chain, store, flags) != 1)
+     {
+         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
+                       "OCSP_basic_verify() failed");
diff --git a/debian/patches/1002-stapling-per-cert.patch 
b/debian/patches/1002-stapling-per-cert.patch
new file mode 100644
index 0000000..f993b18
--- /dev/null
+++ b/debian/patches/1002-stapling-per-cert.patch
@@ -0,0 +1,379 @@
+----------- Original nginx-devel post --------------------------------------
+# HG changeset patch
+# User Filipe da Silva <fdasilva at ingima.com>
+# Date 1430147821 -7200
+#      Mon Apr 27 17:17:01 2015 +0200
+# Node ID caabe5c77b51274237d7c49fffb864a27ca0a25f
+# Parent  0ac2a8668f852b604d46ff858199650bd3003fdb
+OCSP Stapling: attach one stapling_t context per server certificate.
+
+Prepare for multiple server certificate support.
+Split common stapling settings from per-certificate settings.
+Keep common stapling settings attached to initial SSL server
+context, as before.
+
+Know limit: the staple file must contain a response with as much CERTID as
+server certificate. This means that one OCSP request must be made about
+all the certificates at once.
+
+Compatible with 'stable-1.8'
+------- End original nginx-devel post --------------------------------------
+
+WMF notes: This one didn't apply completely cleanly, so the patch below
+differs in non-trivial ways from the original mailing list patch.  The issues
+were related to the recent staple->valid changes in 1.9.
+
+In the interest of keeping this diff closer to the original from the mailing
+list it's based on, I removed 1.9.3's setting of staple->valid to
+NGX_MAX_TIME_T_VALUE for the ssl_stapling_file case, and in the _status
+callback I moved the "staple->valid >= ngx_time()" check to only apply to
+the non-ssl_stapling_file case.
+
+diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
+index 982ef24..0dbb203 100644
+--- a/src/event/ngx_event_openssl.c
++++ b/src/event/ngx_event_openssl.c
+@@ -103,6 +103,7 @@ int  ngx_ssl_session_cache_index;
+ int  ngx_ssl_session_ticket_keys_index;
+ int  ngx_ssl_certificate_index;
+ int  ngx_ssl_stapling_index;
++int  ngx_ssl_cert_stapling_index;
+ 
+ 
+ ngx_int_t
+@@ -186,6 +187,14 @@ ngx_ssl_init(ngx_log_t *log)
+                       "SSL_CTX_get_ex_new_index() failed");
+         return NGX_ERROR;
+     }
++
++    ngx_ssl_cert_stapling_index = X509_get_ex_new_index(0, NULL, NULL, NULL,
++                                                        NULL);
++    if (ngx_ssl_cert_stapling_index == -1) {
++        ngx_ssl_error(NGX_LOG_ALERT, log, 0,
++                      "X509_get_ex_new_index() failed");
++        return NGX_ERROR;
++    }
+ #endif
+ 
+     return NGX_OK;
+diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
+index d7d0381..21e40ec 100644
+--- a/src/event/ngx_event_openssl.h
++++ b/src/event/ngx_event_openssl.h
+@@ -211,6 +211,7 @@ extern int  ngx_ssl_server_conf_index;
+ extern int  ngx_ssl_session_cache_index;
+ extern int  ngx_ssl_session_ticket_keys_index;
+ extern int  ngx_ssl_stapling_index;
++extern int  ngx_ssl_cert_stapling_index;
+ 
+ 
+ #endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */
+diff --git a/src/event/ngx_event_openssl_stapling.c 
b/src/event/ngx_event_openssl_stapling.c
+index a4f5679..16ddf18 100644
+--- a/src/event/ngx_event_openssl_stapling.c
++++ b/src/event/ngx_event_openssl_stapling.c
+@@ -14,13 +14,22 @@
+ #if (!defined OPENSSL_NO_OCSP && defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB)
+ 
+ 
++/* OCSP stapling configuration per server */
+ typedef struct {
+-    ngx_str_t                    staple;
++    ngx_str_t                    staple_file;
+     ngx_msec_t                   timeout;
+ 
+     ngx_resolver_t              *resolver;
+     ngx_msec_t                   resolver_timeout;
+ 
++    unsigned                     verify:1;
++} ngx_ssl_staple_conf_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;
+@@ -34,7 +43,6 @@ typedef struct {
+     time_t                       valid;
+     time_t                       refresh;
+ 
+-    unsigned                     verify:1;
+     unsigned                     loading:1;
+ } ngx_ssl_stapling_t;
+ 
+@@ -54,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;
+ 
+@@ -84,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_conf_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_conf_t *conf);
+ static void ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx);
+ 
+ static time_t ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time);
+@@ -122,23 +132,14 @@ 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                  rc;
+-    ngx_pool_cleanup_t        *cln;
+-    ngx_ssl_stapling_t        *staple;
++    ngx_ssl_staple_conf_t     *conf;
+ 
+-    staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
+-    if (staple == NULL) {
++    conf = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_staple_conf_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,
+@@ -146,14 +147,13 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, 
ngx_str_t *file,
+         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;
+         }
+ 
+@@ -183,22 +183,20 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, 
ngx_str_t *file,
+ 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_conf_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;
+@@ -226,7 +224,8 @@ ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, 
ngx_str_t *file)
+         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;
+     }
+@@ -243,9 +242,8 @@ ngx_ssl_stapling_file(ngx_conf_t *cf, ngx_ssl_t *ssl, 
ngx_str_t *file)
+     OCSP_RESPONSE_free(response);
+     BIO_free(bio);
+ 
+-    staple->staple.data = buf;
+-    staple->staple.len = len;
+-    staple->valid = NGX_MAX_TIME_T_VALUE;
++    conf->staple_file.data = buf;
++    conf->staple_file.len = len;
+ 
+     return NGX_OK;
+ 
+@@ -267,10 +265,33 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
+     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 = ngx_ssl_get_server_certificate(ssl->ctx);
+ 
++    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;
++
+ #ifdef SSL_CTX_get0_chain_certs
+     SSL_CTX_get0_chain_certs(ssl->ctx, &chain);
+ #elif OPENSSL_VERSION_NUMBER >= 0x10001000L
+@@ -354,9 +375,11 @@ ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t 
*ssl, ngx_str_t *responder)
+     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);
++    staple = X509_get_ex_data(cert, ngx_ssl_cert_stapling_index);
+ 
+     if (responder->len == 0) {
+ 
+@@ -441,7 +464,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_conf_t    *staple;
+ 
+     staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
+ 
+@@ -455,45 +478,58 @@ ngx_ssl_stapling_resolver(ngx_conf_t *cf, ngx_ssl_t *ssl,
+ static int
+ ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn, void *data)
+ {
+-    int                  rc;
+-    u_char              *p;
+-    ngx_connection_t    *c;
+-    ngx_ssl_stapling_t  *staple;
++    int                     rc;
++    u_char                 *p;
++    ngx_str_t               resp;
++    ngx_connection_t       *c;
++    ngx_ssl_staple_conf_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
+-        && staple->valid >= ngx_time())
+-    {
+-        /* we have to copy ocsp response as OpenSSL will free it by itself */
++    if (conf->staple_file.len) {
++        resp = conf->staple_file;
++    }
++    else if (staple && staple->staple.len && staple->valid >= ngx_time()) {
++        resp = staple->staple;
++    }
++
++    if (resp.len) {
++        /* We have to copy ocsp response as OpenSSL will free it by itself */
++        p = OPENSSL_malloc(resp.len);
+ 
+-        p = OPENSSL_malloc(staple->staple.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_conf_t 
*conf)
+ {
+     ngx_ssl_ocsp_ctx_t  *ctx;
+ 
+@@ -517,10 +553,10 @@ ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
+     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;
+@@ -604,7 +640,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
+     chain = staple->ssl_ctx->extra_certs;
+ #endif
+ 
+-    flags = staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY;
++    flags = ctx->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY;
+ 
+ #if OPENSSL_VERSION_NUMBER < 0x10000000L
+     /*
diff --git a/debian/patches/1003-stapling-multi-cert.patch 
b/debian/patches/1003-stapling-multi-cert.patch
new file mode 100644
index 0000000..cccd037
--- /dev/null
+++ b/debian/patches/1003-stapling-multi-cert.patch
@@ -0,0 +1,134 @@
+----------- Original nginx-devel post --------------------------------------
+# HG changeset patch
+# User Filipe da Silva <fdasilva at ingima.com>
+# Date 1430147821 -7200
+#      Mon Apr 27 17:17:01 2015 +0200
+# Node ID 1b79826c93a4822fa3c11bc4139ca76e5189b14c
+# Parent  caabe5c77b51274237d7c49fffb864a27ca0a25f
+OCSP Stapling: introduce multiple cert support.
+
+Loop on each certificate to init his respective stapling context.
+
+Compatible with 'stable-1.8'
+------- End original nginx-devel post --------------------------------------
+
+WMF notes: applied to 1.9.3 without failure, this patch just readjusts offsets
+
+diff --git a/src/event/ngx_event_openssl_stapling.c 
b/src/event/ngx_event_openssl_stapling.c
+index 16ddf18..91573aa 100644
+--- a/src/event/ngx_event_openssl_stapling.c
++++ b/src/event/ngx_event_openssl_stapling.c
+@@ -94,9 +94,10 @@ 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_ssl_staple_conf_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_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl,
++    X509 *cert);
+ static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
+-    ngx_str_t *responder);
++    ngx_str_t *responder, X509 *cert);
+ 
+ static int ngx_ssl_certificate_status_callback(ngx_ssl_conn_t *ssl_conn,
+     void *data);
+@@ -131,8 +132,9 @@ 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                  rc;
++    ngx_int_t                  rc, res;
+     ngx_ssl_staple_conf_t     *conf;
++    X509                      *cert;
+ 
+     conf = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_staple_conf_t));
+     if (conf == NULL) {
+@@ -160,24 +162,30 @@ ngx_ssl_stapling(ngx_conf_t *cf, ngx_ssl_t *ssl, 
ngx_str_t *file,
+         goto done;
+     }
+ 
+-    rc = ngx_ssl_stapling_issuer(cf, ssl);
++    res = NGX_DECLINED;
++    cert = ngx_ssl_get_server_certificate(ssl);
+ 
+-    if (rc == NGX_DECLINED) {
+-        return NGX_OK;
+-    }
++    while (cert) {
++        rc = ngx_ssl_stapling_issuer(cf, ssl, cert);
+ 
+-    if (rc != NGX_OK) {
+-        return NGX_ERROR;
+-    }
++        if (rc == NGX_OK) {
++            rc = ngx_ssl_stapling_responder(cf, ssl, responder, cert);
++        }
+ 
+-    rc = ngx_ssl_stapling_responder(cf, ssl, responder);
++        if (rc == NGX_OK) {
++            /* result becomes OK when at least one cert is OK */
++            res = NGX_OK;
++        } else if (rc == NGX_DECLINED) {
++            rc = NGX_OK;
++        } else {
++            return NGX_ERROR;
++        }
+ 
+-    if (rc == NGX_DECLINED) {
+-        return NGX_OK;
++        cert = ngx_ssl_get_next_server_certificate(ssl);
+     }
+ 
+-    if (rc != NGX_OK) {
+-        return NGX_ERROR;
++    if (res == NGX_DECLINED) {
++        return NGX_OK;
+     }
+ 
+ done:
+@@ -257,18 +265,16 @@ failed:
+ 
+ 
+ static ngx_int_t
+-ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
++ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 *cert)
+ {
+     int                  i, n, rc;
+-    X509                *cert, *issuer;
++    X509                *issuer;
+     X509_STORE          *store;
+     X509_STORE_CTX      *store_ctx;
+     STACK_OF(X509)      *chain;
+     ngx_ssl_stapling_t  *staple;
+     ngx_pool_cleanup_t  *cln;
+ 
+-    cert = ngx_ssl_get_server_certificate(ssl->ctx);
+-
+     staple = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_stapling_t));
+     if (staple == NULL) {
+         return NGX_ERROR;
+@@ -370,22 +376,21 @@ 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)
++ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t 
*responder,
++    X509 *cert)
+ {
+     ngx_url_t                  u;
+     char                      *s;
+     ngx_ssl_stapling_t        *staple;
+-    X509                      *cert;
+     STACK_OF(OPENSSL_STRING)  *aia;
+ 
+-    cert = ngx_ssl_get_server_certificate(ssl);
+     staple = X509_get_ex_data(cert, ngx_ssl_cert_stapling_index);
+ 
+     if (responder->len == 0) {
+ 
+         /* extract OCSP responder URL from certificate */
+ 
+-        aia = X509_get1_ocsp(staple->cert);
++        aia = X509_get1_ocsp(cert);
+         if (aia == NULL) {
+             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
+                           "\"ssl_stapling\" ignored, "
diff --git a/debian/patches/1004-cert-list.patch 
b/debian/patches/1004-cert-list.patch
new file mode 100644
index 0000000..f302ca6
--- /dev/null
+++ b/debian/patches/1004-cert-list.patch
@@ -0,0 +1,144 @@
+----------- Original nginx-devel post --------------------------------------
+# HG changeset patch
+# User Filipe da Silva <fdasilva at ingima.com>
+# Date 1430147821 -7200
+#      Mon Apr 27 17:17:01 2015 +0200
+# Node ID e465a170ec3889eef1ab2d5d9f59cf8b12e97055
+# Parent  1b79826c93a4822fa3c11bc4139ca76e5189b14c
+SSL: introduce certificate list support.
+
+Arguments are now a list of certificates and list of keys.
+Split ngx_ssl_certificate to loop separately on cert and keys.
+SSL session_id_context value is build with every configured certificate.
+
+Compatible with 'stable-1.8'
+------- End original nginx-devel post --------------------------------------
+
+WMF notes: applied to 1.9.3 completely clean
+
+diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
+index 0dbb203..867bd4f 100644
+--- a/src/event/ngx_event_openssl.c
++++ b/src/event/ngx_event_openssl.c
+@@ -33,6 +33,10 @@ static void ngx_ssl_connection_error(ngx_connection_t *c, 
int sslerr,
+     ngx_err_t err, char *text);
+ static void ngx_ssl_clear_error(ngx_log_t *log);
+ 
++static ngx_int_t ngx_ssl_server_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
++    ngx_str_t *cert);
++static ngx_int_t ngx_ssl_private_key(ngx_conf_t *cf, ngx_ssl_t *ssl,
++    ngx_str_t *key, ngx_array_t *passwords);
+ static ngx_int_t ngx_ssl_session_id_context(ngx_ssl_t *ssl,
+     ngx_str_t *sess_ctx);
+ ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data);
+@@ -338,14 +342,39 @@ ngx_ssl_get_next_server_certificate(ngx_ssl_t *ssl)
+ 
+ 
+ ngx_int_t
+-ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
+-    ngx_str_t *key, ngx_array_t *passwords)
++ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_array_t *certs,
++    ngx_array_t *keys, ngx_array_t *passwords)
++{
++    ngx_uint_t  i, j;
++    ngx_str_t  *cert;
++    ngx_str_t  *key;
++
++    /* Load server certificates */
++    cert = certs->elts;
++    for (i = 0; i < certs->nelts; i++, cert++) {
++        if (ngx_ssl_server_certificate(cf, ssl, cert) != NGX_OK) {
++            return NGX_ERROR;
++        }
++    }
++
++    /* Load private keys */
++    key = keys->elts;
++    for (j = 0; j < keys->nelts; j++, key++) {
++        if (ngx_ssl_private_key(cf, ssl, key, passwords) != NGX_OK) {
++            return NGX_ERROR;
++        }
++    }
++
++    return NGX_OK;
++}
++
++
++static ngx_int_t
++ngx_ssl_server_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert)
+ {
+     BIO         *bio;
+     X509        *x509;
+     u_long       n;
+-    ngx_str_t   *pwd;
+-    ngx_uint_t   tries;
+ 
+     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
+         return NGX_ERROR;
+@@ -441,6 +470,17 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, 
ngx_str_t *cert,
+ 
+     BIO_free(bio);
+ 
++    return NGX_OK;
++}
++
++
++static ngx_int_t
++ngx_ssl_private_key(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *key,
++    ngx_array_t *passwords)
++{
++    ngx_str_t   *pwd;
++    ngx_uint_t   tries;
++
+     if (ngx_strncmp(key->data, "engine:", sizeof("engine:") - 1) == 0) {
+ 
+ #ifndef OPENSSL_NO_ENGINE
+@@ -2205,18 +2245,24 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t 
*sess_ctx)
+ 
+     cert = ngx_ssl_get_server_certificate(ssl);
+ 
+-    if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) {
+-        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+-                      "X509_digest() failed");
+-        goto failed;
+-    }
++    while (cert) {
+ 
+-    if (EVP_DigestUpdate(&md, buf, len) == 0) {
+-        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+-                      "EVP_DigestUpdate() failed");
+-        goto failed;
++        if (X509_digest(cert, EVP_sha1(), buf, &len) == 0) {
++            ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
++                          "X509_digest() failed");
++            goto failed;
++        }
++
++        if (EVP_DigestUpdate(&md, buf, len) == 0) {
++            ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
++                          "EVP_DigestUpdate() failed");
++            goto failed;
++        }
++
++        cert = ngx_ssl_get_next_server_certificate(ssl);
+     }
+ 
++
+     list = SSL_CTX_get_client_CA_list(ssl->ctx);
+ 
+     if (list != NULL) {
+diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
+index 21e40ec..96517af 100644
+--- a/src/event/ngx_event_openssl.h
++++ b/src/event/ngx_event_openssl.h
+@@ -122,8 +122,8 @@ typedef struct {
+ 
+ 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,
+-    ngx_str_t *cert, ngx_str_t *key, ngx_array_t *passwords);
++ngx_int_t ngx_ssl_certificates(ngx_conf_t *cf, ngx_ssl_t *ssl,
++    ngx_array_t *certs, ngx_array_t *keys, ngx_array_t *passwords);
+ ngx_int_t ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
+     ngx_str_t *cert, ngx_int_t depth);
+ ngx_int_t ngx_ssl_trusted_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
diff --git a/debian/patches/1005-multicert-modules.patch 
b/debian/patches/1005-multicert-modules.patch
new file mode 100644
index 0000000..869e285
--- /dev/null
+++ b/debian/patches/1005-multicert-modules.patch
@@ -0,0 +1,536 @@
+----------- Original nginx-devel post --------------------------------------
+# HG changeset patch
+# User Filipe da Silva <fdasilva at ingima.com>
+# Date 1430148930 -7200
+#      Mon Apr 27 17:35:30 2015 +0200
+# Node ID 64aad233af2e71b17d6ef8c7c021b701c83d578d
+# Parent  f4975130e1101c4003a0ce4e5422990b780d50fe
+SSL: add Multiple SSL certificate support to other modules.
+
+Multiple entries are now possible for ssl_certificate and ssl_certificate_key
+settings.
+Fix compilation of previous patch changes.
+
+Compatible with 'stable-1.8'
+------- End original nginx-devel post --------------------------------------
+
+WMF notes: applied to 1.9.3 without failure, this patch just readjusts offsets
+
+diff --git a/src/http/modules/ngx_http_proxy_module.c 
b/src/http/modules/ngx_http_proxy_module.c
+index 514c23b..305ad41 100644
+--- a/src/http/modules/ngx_http_proxy_module.c
++++ b/src/http/modules/ngx_http_proxy_module.c
+@@ -97,8 +97,8 @@ typedef struct {
+     ngx_uint_t                     ssl_verify_depth;
+     ngx_str_t                      ssl_trusted_certificate;
+     ngx_str_t                      ssl_crl;
+-    ngx_str_t                      ssl_certificate;
+-    ngx_str_t                      ssl_certificate_key;
++    ngx_array_t                   *ssl_certificates;
++    ngx_array_t                   *ssl_certificate_keys;
+     ngx_array_t                   *ssl_passwords;
+ #endif
+ } ngx_http_proxy_loc_conf_t;
+@@ -672,16 +672,16 @@ static ngx_command_t  ngx_http_proxy_commands[] = {
+ 
+     { ngx_string("proxy_ssl_certificate"),
+       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_HTTP_LOC_CONF_OFFSET,
+-      offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate),
++      offsetof(ngx_http_proxy_loc_conf_t, ssl_certificates),
+       NULL },
+ 
+     { ngx_string("proxy_ssl_certificate_key"),
+       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_HTTP_LOC_CONF_OFFSET,
+-      offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate_key),
++      offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate_keys),
+       NULL },
+ 
+     { ngx_string("proxy_ssl_password_file"),
+@@ -2858,6 +2858,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
+     conf->upstream.ssl_verify = NGX_CONF_UNSET;
+     conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
+     conf->ssl_passwords = NGX_CONF_UNSET_PTR;
++    conf->ssl_certificates = NGX_CONF_UNSET_PTR;
++    conf->ssl_certificate_keys = NGX_CONF_UNSET_PTR;
+ #endif
+ 
+     /* "proxy_cyclic_temp_file" is disabled */
+@@ -3188,10 +3190,11 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void 
*parent, void *child)
+                               prev->ssl_trusted_certificate, "");
+     ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
+ 
+-    ngx_conf_merge_str_value(conf->ssl_certificate,
+-                              prev->ssl_certificate, "");
+-    ngx_conf_merge_str_value(conf->ssl_certificate_key,
+-                              prev->ssl_certificate_key, "");
++    ngx_conf_merge_ptr_value(conf->ssl_certificates,
++                              prev->ssl_certificates, NULL);
++    ngx_conf_merge_ptr_value(conf->ssl_certificate_keys,
++                              prev->ssl_certificate_keys, NULL);
++
+     ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
+ 
+     if (conf->ssl && ngx_http_proxy_set_ssl(cf, conf) != NGX_OK) {
+@@ -4278,6 +4281,7 @@ static ngx_int_t
+ ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
+ {
+     ngx_pool_cleanup_t  *cln;
++    ngx_str_t *oddkey;
+ 
+     plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
+     if (plcf->upstream.ssl == NULL) {
+@@ -4300,18 +4304,43 @@ ngx_http_proxy_set_ssl(ngx_conf_t *cf, 
ngx_http_proxy_loc_conf_t *plcf)
+     cln->handler = ngx_ssl_cleanup_ctx;
+     cln->data = plcf->upstream.ssl;
+ 
+-    if (plcf->ssl_certificate.len) {
++    if (plcf->ssl_certificates && plcf->ssl_certificates->nelts > 0) {
++
++        if (!plcf->ssl_certificate_keys
++            || plcf->ssl_certificate_keys->nelts
++                < plcf->ssl_certificates->nelts)
++        {
++
++            oddkey = plcf->ssl_certificates->elts;
+ 
+-        if (plcf->ssl_certificate_key.len == 0) {
+             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                           "no \"proxy_ssl_certificate_key\" is defined "
+-                          "for certificate \"%V\"", &plcf->ssl_certificate);
++                          "for ssl certificate \"%V\"",
++                          oddkey[(plcf->ssl_certificate_keys)
++                                 ? plcf->ssl_certificate_keys->nelts
++                                 : 0]);
++
+             return NGX_ERROR;
+         }
+ 
+-        if (ngx_ssl_certificate(cf, plcf->upstream.ssl, 
&plcf->ssl_certificate,
+-                                &plcf->ssl_certificate_key, 
plcf->ssl_passwords)
+-            != NGX_OK)
++#ifndef SSL_CTX_add0_chain_cert
++        if (plcf->ssl_certificates->nelts > 1) {
++            /*
++             *   no multiple certificates support for OpenSSL < 1.0.2,
++             *   so we need to alarm user
++             */
++            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
++                         "Multiple certificate configured "
++                         "in \"proxy_ssl_certificate\", "
++                         "but OpenSSL version < 1.0.2 used");
++            return NGX_ERROR;
++        }
++#endif
++
++        if (ngx_ssl_certificates(cf, plcf->upstream.ssl, 
plcf->ssl_certificates,
++                                 plcf->ssl_certificate_keys,
++                                 plcf->ssl_passwords)
++           != NGX_OK)
+         {
+             return NGX_ERROR;
+         }
+diff --git a/src/http/modules/ngx_http_ssl_module.c 
b/src/http/modules/ngx_http_ssl_module.c
+index d6a1794..35b6de7 100644
+--- a/src/http/modules/ngx_http_ssl_module.c
++++ b/src/http/modules/ngx_http_ssl_module.c
+@@ -81,16 +81,16 @@ static ngx_command_t  ngx_http_ssl_commands[] = {
+ 
+     { ngx_string("ssl_certificate"),
+       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_HTTP_SRV_CONF_OFFSET,
+-      offsetof(ngx_http_ssl_srv_conf_t, certificate),
++      offsetof(ngx_http_ssl_srv_conf_t, certificates),
+       NULL },
+ 
+     { ngx_string("ssl_certificate_key"),
+       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_HTTP_SRV_CONF_OFFSET,
+-      offsetof(ngx_http_ssl_srv_conf_t, certificate_key),
++      offsetof(ngx_http_ssl_srv_conf_t, certificate_keys),
+       NULL },
+ 
+     { ngx_string("ssl_password_file"),
+@@ -505,8 +505,6 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
+      * set by ngx_pcalloc():
+      *
+      *     sscf->protocols = 0;
+-     *     sscf->certificate = { 0, NULL };
+-     *     sscf->certificate_key = { 0, NULL };
+      *     sscf->dhparam = { 0, NULL };
+      *     sscf->ecdh_curve = { 0, NULL };
+      *     sscf->client_certificate = { 0, NULL };
+@@ -523,6 +521,8 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
+     sscf->buffer_size = NGX_CONF_UNSET_SIZE;
+     sscf->verify = NGX_CONF_UNSET_UINT;
+     sscf->verify_depth = NGX_CONF_UNSET_UINT;
++    sscf->certificates = NGX_CONF_UNSET_PTR;
++    sscf->certificate_keys = NGX_CONF_UNSET_PTR;
+     sscf->passwords = NGX_CONF_UNSET_PTR;
+     sscf->builtin_session_cache = NGX_CONF_UNSET;
+     sscf->session_timeout = NGX_CONF_UNSET;
+@@ -570,8 +570,9 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, 
void *child)
+     ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
+     ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
+ 
+-    ngx_conf_merge_str_value(conf->certificate, prev->certificate, "");
+-    ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, 
"");
++    ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
++    ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
++                         NULL);
+ 
+     ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
+ 
+@@ -598,7 +599,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, 
void *child)
+ 
+     if (conf->enable) {
+ 
+-        if (conf->certificate.len == 0) {
++        if (!conf->certificates || conf->certificates->nelts == 0) {
+             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                           "no \"ssl_certificate\" is defined for "
+                           "the \"ssl\" directive in %s:%ui",
+@@ -606,7 +607,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, 
void *child)
+             return NGX_CONF_ERROR;
+         }
+ 
+-        if (conf->certificate_key.len == 0) {
++        if (!conf->certificate_keys || conf->certificate_keys->nelts == 0) {
+             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                           "no \"ssl_certificate_key\" is defined for "
+                           "the \"ssl\" directive in %s:%ui",
+@@ -616,18 +617,38 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void 
*parent, void *child)
+ 
+     } else {
+ 
+-        if (conf->certificate.len == 0) {
++        if (!conf->certificates || conf->certificates->nelts == 0) {
+             return NGX_CONF_OK;
+         }
+ 
+-        if (conf->certificate_key.len == 0) {
++        if (!conf->certificate_keys || conf->certificate_keys->nelts == 0) {
++            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
++                          "no \"ssl_certificate_key\" is defined "
++                          "for certificate \"%V\"", &conf->certificates[0]);
++            return NGX_CONF_ERROR;
++        }
++        if (conf->certificate_keys->nelts < conf->certificates->nelts) {
+             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                           "no \"ssl_certificate_key\" is defined "
+-                          "for certificate \"%V\"", &conf->certificate);
++                          "for certificate \"%V\"",
++                          &conf->certificates[conf->certificate_keys->nelts]);
+             return NGX_CONF_ERROR;
+         }
+     }
+ 
++#ifndef SSL_CTX_add0_chain_cert
++    if (conf->certificates->nelts > 1) {
++        /*
++         *   no multiple certificates support for OpenSSL < 1.0.2,
++         *   so we need to alarm user
++         */
++        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
++                        "Multiple certificate configured in "
++                        "\"ssl_certificate\", but OpenSSL < 1.0.2 used");
++        return NGX_CONF_ERROR;
++    }
++#endif
++
+     if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) {
+         return NGX_CONF_ERROR;
+     }
+@@ -663,8 +684,8 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, 
void *child)
+     cln->handler = ngx_ssl_cleanup_ctx;
+     cln->data = &conf->ssl;
+ 
+-    if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate,
+-                            &conf->certificate_key, conf->passwords)
++    if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
++                             conf->certificate_keys, conf->passwords)
+         != NGX_OK)
+     {
+         return NGX_CONF_ERROR;
+diff --git a/src/http/modules/ngx_http_ssl_module.h 
b/src/http/modules/ngx_http_ssl_module.h
+index 8e69e9e..d4d1397 100644
+--- a/src/http/modules/ngx_http_ssl_module.h
++++ b/src/http/modules/ngx_http_ssl_module.h
+@@ -32,8 +32,8 @@ typedef struct {
+ 
+     time_t                          session_timeout;
+ 
+-    ngx_str_t                       certificate;
+-    ngx_str_t                       certificate_key;
++    ngx_array_t                    *certificates;
++    ngx_array_t                    *certificate_keys;
+     ngx_str_t                       dhparam;
+     ngx_str_t                       ecdh_curve;
+     ngx_str_t                       client_certificate;
+diff --git a/src/http/modules/ngx_http_uwsgi_module.c 
b/src/http/modules/ngx_http_uwsgi_module.c
+index a50c553..e37f5f2 100644
+--- a/src/http/modules/ngx_http_uwsgi_module.c
++++ b/src/http/modules/ngx_http_uwsgi_module.c
+@@ -54,8 +54,8 @@ typedef struct {
+     ngx_uint_t                 ssl_verify_depth;
+     ngx_str_t                  ssl_trusted_certificate;
+     ngx_str_t                  ssl_crl;
+-    ngx_str_t                  ssl_certificate;
+-    ngx_str_t                  ssl_certificate_key;
++    ngx_array_t               *ssl_certificates;
++    ngx_array_t               *ssl_certificate_keys;
+     ngx_array_t               *ssl_passwords;
+ #endif
+ } ngx_http_uwsgi_loc_conf_t;
+@@ -517,16 +517,16 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
+ 
+     { ngx_string("uwsgi_ssl_certificate"),
+       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_HTTP_LOC_CONF_OFFSET,
+-      offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate),
++      offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificates),
+       NULL },
+ 
+     { ngx_string("uwsgi_ssl_certificate_key"),
+       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_HTTP_LOC_CONF_OFFSET,
+-      offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate_key),
++      offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate_keys),
+       NULL },
+ 
+     { ngx_string("uwsgi_ssl_password_file"),
+@@ -1430,6 +1430,8 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
+     conf->upstream.ssl_verify = NGX_CONF_UNSET;
+     conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
+     conf->ssl_passwords = NGX_CONF_UNSET_PTR;
++    conf->ssl_certificates = NGX_CONF_UNSET_PTR;
++    conf->ssl_certificate_keys = NGX_CONF_UNSET_PTR;
+ #endif
+ 
+     /* "uwsgi_cyclic_temp_file" is disabled */
+@@ -1743,11 +1745,10 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void 
*parent, void *child)
+     ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
+                               prev->ssl_trusted_certificate, "");
+     ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
+-
+-    ngx_conf_merge_str_value(conf->ssl_certificate,
+-                              prev->ssl_certificate, "");
+-    ngx_conf_merge_str_value(conf->ssl_certificate_key,
+-                              prev->ssl_certificate_key, "");
++    ngx_conf_merge_ptr_value(conf->ssl_certificates,
++                             prev->ssl_certificates, NULL);
++    ngx_conf_merge_ptr_value(conf->ssl_certificate_keys,
++                             prev->ssl_certificate_keys, NULL);
+     ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
+ 
+     if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) {
+@@ -2284,6 +2285,7 @@ static ngx_int_t
+ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
+ {
+     ngx_pool_cleanup_t  *cln;
++    ngx_str_t           *oddkey;
+ 
+     uwcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
+     if (uwcf->upstream.ssl == NULL) {
+@@ -2306,17 +2308,42 @@ ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, 
ngx_http_uwsgi_loc_conf_t *uwcf)
+     cln->handler = ngx_ssl_cleanup_ctx;
+     cln->data = uwcf->upstream.ssl;
+ 
+-    if (uwcf->ssl_certificate.len) {
++    if (uwcf->ssl_certificates && uwcf->ssl_certificates->nelts > 0) {
++
++        if (!uwcf->ssl_certificate_keys
++            || uwcf->ssl_certificate_keys->nelts
++                < uwcf->ssl_certificates->nelts)
++        {
++
++            oddkey = uwcf->ssl_certificates->elts;
+ 
+-        if (uwcf->ssl_certificate_key.len == 0) {
+             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                           "no \"uwsgi_ssl_certificate_key\" is defined "
+-                          "for certificate \"%V\"", &uwcf->ssl_certificate);
++                          "for ssl certificate \"%V\"",
++                          oddkey[(uwcf->ssl_certificate_keys)
++                                 ? uwcf->ssl_certificate_keys->nelts
++                                 : 0]);
++
+             return NGX_ERROR;
+         }
+ 
+-        if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, 
&uwcf->ssl_certificate,
+-                                &uwcf->ssl_certificate_key, 
uwcf->ssl_passwords)
++#ifndef SSL_CTX_add0_chain_cert
++        if (uwcf->ssl_certificates->nelts > 1) {
++            /*
++             *   no multiple certificates support for OpenSSL < 1.0.2,
++             *   so we need to alarm user
++             */
++            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
++                            "Multiple certificate configured "
++                            "in \"uwsgi_ssl_certificate\", but "
++                            "OpenSSL < 1.0.2 used");
++            return NGX_ERROR;
++        }
++#endif
++
++        if (ngx_ssl_certificates(cf, uwcf->upstream.ssl, 
uwcf->ssl_certificates,
++                                 uwcf->ssl_certificate_keys,
++                                 uwcf->ssl_passwords)
+             != NGX_OK)
+         {
+             return NGX_ERROR;
+diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c
+index 1075410..ebe4ac8 100644
+--- a/src/mail/ngx_mail_ssl_module.c
++++ b/src/mail/ngx_mail_ssl_module.c
+@@ -73,16 +73,16 @@ static ngx_command_t  ngx_mail_ssl_commands[] = {
+ 
+     { ngx_string("ssl_certificate"),
+       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_MAIL_SRV_CONF_OFFSET,
+-      offsetof(ngx_mail_ssl_conf_t, certificate),
++      offsetof(ngx_mail_ssl_conf_t, certificates),
+       NULL },
+ 
+     { ngx_string("ssl_certificate_key"),
+       NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_MAIL_SRV_CONF_OFFSET,
+-      offsetof(ngx_mail_ssl_conf_t, certificate_key),
++      offsetof(ngx_mail_ssl_conf_t, certificate_keys),
+       NULL },
+ 
+     { ngx_string("ssl_password_file"),
+@@ -238,8 +238,6 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf)
+      * set by ngx_pcalloc():
+      *
+      *     scf->protocols = 0;
+-     *     scf->certificate = { 0, NULL };
+-     *     scf->certificate_key = { 0, NULL };
+      *     scf->dhparam = { 0, NULL };
+      *     scf->ecdh_curve = { 0, NULL };
+      *     scf->client_certificate = { 0, NULL };
+@@ -250,6 +248,8 @@ ngx_mail_ssl_create_conf(ngx_conf_t *cf)
+      */
+ 
+     scf->enable = NGX_CONF_UNSET;
++    scf->certificates = NGX_CONF_UNSET_PTR;
++    scf->certificate_keys = NGX_CONF_UNSET_PTR;
+     scf->starttls = NGX_CONF_UNSET_UINT;
+     scf->passwords = NGX_CONF_UNSET_PTR;
+     scf->prefer_server_ciphers = NGX_CONF_UNSET;
+@@ -290,8 +290,9 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void 
*child)
+     ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
+     ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
+ 
+-    ngx_conf_merge_str_value(conf->certificate, prev->certificate, "");
+-    ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, 
"");
++    ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
++    ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
++                        NULL);
+ 
+     ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
+ 
+@@ -328,7 +329,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void 
*child)
+ 
+     if (*mode) {
+ 
+-        if (conf->certificate.len == 0) {
++        if (!conf->certificates || conf->certificates->nelts == 0) {
+             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                           "no \"ssl_certificate\" is defined for "
+                           "the \"%s\" directive in %s:%ui",
+@@ -336,7 +337,7 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void 
*child)
+             return NGX_CONF_ERROR;
+         }
+ 
+-        if (conf->certificate_key.len == 0) {
++        if (!conf->certificate_keys || conf->certificate_keys->nelts == 0) {
+             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                           "no \"ssl_certificate_key\" is defined for "
+                           "the \"%s\" directive in %s:%ui",
+@@ -344,17 +345,24 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, 
void *child)
+             return NGX_CONF_ERROR;
+         }
+ 
++        if (conf->certificate_keys->nelts < conf->certificates->nelts) {
++            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
++                          "no \"ssl_certificate_key\" is defined "
++                          "for certificate \"%V\"",
++                          &conf->certificates[conf->certificate_keys->nelts]);
++             return NGX_CONF_ERROR;
++        }
++
+     } else {
+ 
+-        if (conf->certificate.len == 0) {
++        if (!conf->certificates || conf->certificates->nelts == 0) {
+             return NGX_CONF_OK;
+         }
+ 
+-        if (conf->certificate_key.len == 0) {
++        if (!conf->certificate_keys || conf->certificate_keys->nelts == 0) {
+             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                           "no \"ssl_certificate_key\" is defined "
+-                          "for certificate \"%V\"",
+-                          &conf->certificate);
++                          "for certificate \"%V\"", &conf->certificates[0]);
+             return NGX_CONF_ERROR;
+         }
+     }
+@@ -371,8 +379,21 @@ ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, 
void *child)
+     cln->handler = ngx_ssl_cleanup_ctx;
+     cln->data = &conf->ssl;
+ 
+-    if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate,
+-                            &conf->certificate_key, conf->passwords)
++#ifndef SSL_CTX_add0_chain_cert
++    if (conf->certificates->nelts > 1) {
++        /*
++         *   no multiple certificates support for OpenSSL < 1.0.2,
++         *   so we need to alarm user
++         */
++        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
++                        "Multiple certificate configured in "
++                        "\"ssl_certificate\", but OpenSSL < 1.0.2 used");
++        return NGX_CONF_ERROR;
++    }
++#endif
++
++    if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
++                            conf->certificate_keys, conf->passwords)
+         != NGX_OK)
+     {
+         return NGX_CONF_ERROR;
+diff --git a/src/mail/ngx_mail_ssl_module.h b/src/mail/ngx_mail_ssl_module.h
+index 296a6a2..0753e26 100644
+--- a/src/mail/ngx_mail_ssl_module.h
++++ b/src/mail/ngx_mail_ssl_module.h
+@@ -35,8 +35,8 @@ typedef struct {
+ 
+     time_t           session_timeout;
+ 
+-    ngx_str_t        certificate;
+-    ngx_str_t        certificate_key;
++    ngx_array_t     *certificates;
++    ngx_array_t     *certificate_keys;
+     ngx_str_t        dhparam;
+     ngx_str_t        ecdh_curve;
+     ngx_str_t        client_certificate;
diff --git a/debian/patches/1006-multicert-stream-modules.patch 
b/debian/patches/1006-multicert-stream-modules.patch
new file mode 100644
index 0000000..1d16a41
--- /dev/null
+++ b/debian/patches/1006-multicert-stream-modules.patch
@@ -0,0 +1,251 @@
+This is basically a cargo-culting of the changes in
+1005-multicert-modules.patch that makes very very similar changes to the
+stream_proxy and stream_ssl modules, which are newer than the nginx 1.8
+originally targeted by Filipe's patch set. --bblack
+
+diff --git a/src/stream/ngx_stream_proxy_module.c 
b/src/stream/ngx_stream_proxy_module.c
+index 68af5a8..93106b5 100644
+--- a/src/stream/ngx_stream_proxy_module.c
++++ b/src/stream/ngx_stream_proxy_module.c
+@@ -37,8 +37,8 @@ typedef struct {
+     ngx_uint_t                       ssl_verify_depth;
+     ngx_str_t                        ssl_trusted_certificate;
+     ngx_str_t                        ssl_crl;
+-    ngx_str_t                        ssl_certificate;
+-    ngx_str_t                        ssl_certificate_key;
++    ngx_array_t                     *ssl_certificates;
++    ngx_array_t                     *ssl_certificate_keys;
+     ngx_array_t                     *ssl_passwords;
+ 
+     ngx_ssl_t                       *ssl;
+@@ -272,16 +272,16 @@ static ngx_command_t  ngx_stream_proxy_commands[] = {
+ 
+     { ngx_string("proxy_ssl_certificate"),
+       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_STREAM_SRV_CONF_OFFSET,
+-      offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate),
++      offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificates),
+       NULL },
+ 
+     { ngx_string("proxy_ssl_certificate_key"),
+       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_STREAM_SRV_CONF_OFFSET,
+-      offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate_key),
++      offsetof(ngx_stream_proxy_srv_conf_t, ssl_certificate_keys),
+       NULL },
+ 
+     { ngx_string("proxy_ssl_password_file"),
+@@ -1319,8 +1319,6 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
+      *     conf->ssl_name = { 0, NULL };
+      *     conf->ssl_trusted_certificate = { 0, NULL };
+      *     conf->ssl_crl = { 0, NULL };
+-     *     conf->ssl_certificate = { 0, NULL };
+-     *     conf->ssl_certificate_key = { 0, NULL };
+      *
+      *     conf->ssl = NULL;
+      *     conf->upstream = NULL;
+@@ -1343,6 +1341,8 @@ ngx_stream_proxy_create_srv_conf(ngx_conf_t *cf)
+     conf->ssl_server_name = NGX_CONF_UNSET;
+     conf->ssl_verify = NGX_CONF_UNSET;
+     conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
++    conf->ssl_certificates = NGX_CONF_UNSET_PTR;
++    conf->ssl_certificate_keys = NGX_CONF_UNSET_PTR;
+     conf->ssl_passwords = NGX_CONF_UNSET_PTR;
+ #endif
+ 
+@@ -1410,11 +1410,11 @@ ngx_stream_proxy_merge_srv_conf(ngx_conf_t *cf, void 
*parent, void *child)
+ 
+     ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
+ 
+-    ngx_conf_merge_str_value(conf->ssl_certificate,
+-                              prev->ssl_certificate, "");
++    ngx_conf_merge_ptr_value(conf->ssl_certificates,
++                              prev->ssl_certificates, NULL);
+ 
+-    ngx_conf_merge_str_value(conf->ssl_certificate_key,
+-                              prev->ssl_certificate_key, "");
++    ngx_conf_merge_ptr_value(conf->ssl_certificate_keys,
++                              prev->ssl_certificate_keys, NULL);
+ 
+     ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
+ 
+@@ -1434,6 +1434,7 @@ static ngx_int_t
+ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, ngx_stream_proxy_srv_conf_t *pscf)
+ {
+     ngx_pool_cleanup_t  *cln;
++    ngx_str_t *oddkey;
+ 
+     pscf->ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
+     if (pscf->ssl == NULL) {
+@@ -1454,17 +1455,41 @@ ngx_stream_proxy_set_ssl(ngx_conf_t *cf, 
ngx_stream_proxy_srv_conf_t *pscf)
+     cln->handler = ngx_ssl_cleanup_ctx;
+     cln->data = pscf->ssl;
+ 
+-    if (pscf->ssl_certificate.len) {
++    if (pscf->ssl_certificates && pscf->ssl_certificates->nelts > 0) {
++
++        if (!pscf->ssl_certificate_keys
++            || pscf->ssl_certificate_keys->nelts
++                < pscf->ssl_certificates->nelts)
++        {
++
++            oddkey = pscf->ssl_certificates->elts;
+ 
+-        if (pscf->ssl_certificate_key.len == 0) {
+             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                           "no \"proxy_ssl_certificate_key\" is defined "
+-                          "for certificate \"%V\"", &pscf->ssl_certificate);
++                          "for ssl certificate \"%V\"",
++                          oddkey[(pscf->ssl_certificate_keys)
++                                 ? pscf->ssl_certificate_keys->nelts
++                                 : 0]);
+             return NGX_ERROR;
+         }
+ 
+-        if (ngx_ssl_certificate(cf, pscf->ssl, &pscf->ssl_certificate,
+-                                &pscf->ssl_certificate_key, 
pscf->ssl_passwords)
++#ifndef SSL_CTX_add0_chain_cert
++        if (pscf->ssl_certificates->nelts > 1) {
++            /*
++             *   no multiple certificates support for OpenSSL < 1.0.2,
++             *   so we need to alarm user
++             */
++            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
++                         "Multiple certificates configured "
++                         "in \"proxy_ssl_certificates\", "
++                         "but OpenSSL version < 1.0.2 used");
++            return NGX_ERROR;
++        }
++#endif
++
++        if (ngx_ssl_certificates(cf, pscf->ssl, pscf->ssl_certificates,
++                                 pscf->ssl_certificate_keys,
++                                 pscf->ssl_passwords)
+             != NGX_OK)
+         {
+             return NGX_ERROR;
+diff --git a/src/stream/ngx_stream_ssl_module.c 
b/src/stream/ngx_stream_ssl_module.c
+index 7abd9e1..216cb40 100644
+--- a/src/stream/ngx_stream_ssl_module.c
++++ b/src/stream/ngx_stream_ssl_module.c
+@@ -45,16 +45,16 @@ static ngx_command_t  ngx_stream_ssl_commands[] = {
+ 
+     { ngx_string("ssl_certificate"),
+       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_STREAM_SRV_CONF_OFFSET,
+-      offsetof(ngx_stream_ssl_conf_t, certificate),
++      offsetof(ngx_stream_ssl_conf_t, certificates),
+       NULL },
+ 
+     { ngx_string("ssl_certificate_key"),
+       NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
+-      ngx_conf_set_str_slot,
++      ngx_conf_set_str_array_slot,
+       NGX_STREAM_SRV_CONF_OFFSET,
+-      offsetof(ngx_stream_ssl_conf_t, certificate_key),
++      offsetof(ngx_stream_ssl_conf_t, certificate_keys),
+       NULL },
+ 
+     { ngx_string("ssl_password_file"),
+@@ -175,8 +175,6 @@ ngx_stream_ssl_create_conf(ngx_conf_t *cf)
+      * set by ngx_pcalloc():
+      *
+      *     scf->protocols = 0;
+-     *     scf->certificate = { 0, NULL };
+-     *     scf->certificate_key = { 0, NULL };
+      *     scf->dhparam = { 0, NULL };
+      *     scf->ecdh_curve = { 0, NULL };
+      *     scf->ciphers = { 0, NULL };
+@@ -184,6 +182,8 @@ ngx_stream_ssl_create_conf(ngx_conf_t *cf)
+      */
+ 
+     scf->handshake_timeout = NGX_CONF_UNSET_MSEC;
++    scf->certificates = NGX_CONF_UNSET_PTR;
++    scf->certificate_keys = NGX_CONF_UNSET_PTR;
+     scf->passwords = NGX_CONF_UNSET_PTR;
+     scf->prefer_server_ciphers = NGX_CONF_UNSET;
+     scf->builtin_session_cache = NGX_CONF_UNSET;
+@@ -216,8 +216,9 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, 
void *child)
+                          (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
+                           |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
+ 
+-    ngx_conf_merge_str_value(conf->certificate, prev->certificate, "");
+-    ngx_conf_merge_str_value(conf->certificate_key, prev->certificate_key, 
"");
++    ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
++    ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
++                             NULL);
+ 
+     ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
+ 
+@@ -231,17 +232,36 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, 
void *child)
+ 
+     conf->ssl.log = cf->log;
+ 
+-    if (conf->certificate.len == 0) {
++    if (!conf->certificates || conf->certificates->nelts == 0) {
+         return NGX_CONF_OK;
+     }
+ 
+-    if (conf->certificate_key.len == 0) {
++    if (!conf->certificate_keys || conf->certificate_keys->nelts == 0) {
++        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
++                      "no \"ssl_certificate_key\" is defined "
++                      "for certificate \"%V\"", &conf->certificates[0]);
++        return NGX_CONF_ERROR;
++    }
++    if (conf->certificate_keys->nelts < conf->certificates->nelts) {
+         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                       "no \"ssl_certificate_key\" is defined "
+                       "for certificate \"%V\"",
+-                      &conf->certificate);
++                      &conf->certificates[conf->certificate_keys->nelts]);
++        return NGX_CONF_ERROR;
++    }
++
++#ifndef SSL_CTX_add0_chain_cert
++    if (conf->certificates->nelts > 1) {
++        /*
++         *   no multiple certificates support for OpenSSL < 1.0.2,
++         *   so we need to alarm user
++         */
++        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
++                        "Multiple certificate configured in "
++                        "\"ssl_certificate\", but OpenSSL < 1.0.2 used");
+         return NGX_CONF_ERROR;
+     }
++#endif
+ 
+     if (ngx_ssl_create(&conf->ssl, conf->protocols, NULL) != NGX_OK) {
+         return NGX_CONF_ERROR;
+@@ -255,8 +275,8 @@ ngx_stream_ssl_merge_conf(ngx_conf_t *cf, void *parent, 
void *child)
+     cln->handler = ngx_ssl_cleanup_ctx;
+     cln->data = &conf->ssl;
+ 
+-    if (ngx_ssl_certificate(cf, &conf->ssl, &conf->certificate,
+-                            &conf->certificate_key, conf->passwords)
++    if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
++                             conf->certificate_keys, conf->passwords)
+         != NGX_OK)
+     {
+         return NGX_CONF_ERROR;
+diff --git a/src/stream/ngx_stream_ssl_module.h 
b/src/stream/ngx_stream_ssl_module.h
+index 85e8b6e..331341f 100644
+--- a/src/stream/ngx_stream_ssl_module.h
++++ b/src/stream/ngx_stream_ssl_module.h
+@@ -27,8 +27,8 @@ typedef struct {
+ 
+     time_t           session_timeout;
+ 
+-    ngx_str_t        certificate;
+-    ngx_str_t        certificate_key;
++    ngx_array_t     *certificates;
++    ngx_array_t     *certificate_keys;
+     ngx_str_t        dhparam;
+     ngx_str_t        ecdh_curve;
+ 
diff --git a/debian/patches/series b/debian/patches/series
index 73f535e..c447936 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,11 @@
 perl-use-dpkg-buildflags.patch
+# 1001-1005 is forward ports of multi-cert patches from Filipe da Silva
+# circa 2015-04-27, onto nginx-1.9.4, from the 5 posts starting here:
+# http://mailman.nginx.org/pipermail/nginx-devel/2015-April/006863.html
+1001-openssl102.patch
+1002-stapling-per-cert.patch
+1003-stapling-multi-cert.patch
+1004-cert-list.patch
+1005-multicert-modules.patch
+# 1006 is a local cargo-cult of 1005's changes into the newer stream modules
+1006-multicert-stream-modules.patch

-- 
To view, visit https://gerrit.wikimedia.org/r/235739
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I67b67af2280c94c15cd1d74696672d674a2d3e6c
Gerrit-PatchSet: 1
Gerrit-Project: operations/software/nginx
Gerrit-Branch: wmf-1.9.4-1
Gerrit-Owner: BBlack <bbl...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to