BBlack has submitted this change and it was merged.

Change subject: multicert + libssl1.0.2 patches for 1.10.0
......................................................................


multicert + libssl1.0.2 patches for 1.10.0

Note these patchfiles were taken from our previous 1.9.4-1+wmf1
release.  They mostly only needed minor offset corrections to
apply cleanly to 1.10.0 (those offset corrections are already
applied in the patchfiles in this commit).  In one case there was
a very tiny obvious update to an argument type.

Bug: T96848
Change-Id: Ida2b3deffc97ef40704a32581e824723267df700
---
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(-)

Approvals:
  BBlack: Verified; Looks good to me, approved



diff --git a/debian/control b/debian/control
index 52baf37..94185cb 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..7d85c55
--- /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 de10296..9ff3545 100644
+--- a/src/event/ngx_event_openssl.c
++++ b/src/event/ngx_event_openssl.c
+@@ -179,6 +179,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) {
+@@ -186,7 +187,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) {
+@@ -194,6 +197,7 @@ ngx_ssl_init(ngx_log_t *log)
+                       "SSL_CTX_get_ex_new_index() failed");
+         return NGX_ERROR;
+     }
++#endif
+ 
+     return NGX_OK;
+ }
+@@ -308,6 +312,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)
+@@ -351,6 +382,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)
+     {
+@@ -360,6 +392,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);
+ 
+@@ -387,10 +420,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;
+@@ -2184,7 +2228,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 09654db..6d5eae3 100644
+--- a/src/event/ngx_event_openssl.h
++++ b/src/event/ngx_event_openssl.h
+@@ -207,6 +207,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);
+@@ -226,7 +228,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 5322b1b..1e21891 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;
+@@ -542,6 +544,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;
+@@ -597,15 +600,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..1828268
--- /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 9ff3545..81b1848 100644
+--- a/src/event/ngx_event_openssl.c
++++ b/src/event/ngx_event_openssl.c
+@@ -106,6 +106,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
+@@ -197,6 +198,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 6d5eae3..a4c9adf 100644
+--- a/src/event/ngx_event_openssl.h
++++ b/src/event/ngx_event_openssl.h
+@@ -229,6 +229,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 1e21891..0798462 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
+@@ -358,9 +379,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) {
+ 
+@@ -445,7 +468,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);
+ 
+@@ -459,45 +482,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;
+ 
+@@ -521,10 +557,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;
+@@ -608,7 +644,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..13dfb0c
--- /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 0798462..32d3c80 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;
+@@ -374,22 +380,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..de215bc
--- /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 81b1848..b4423c9 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);
+@@ -349,14 +353,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;
+@@ -452,6 +481,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
+@@ -2239,18 +2279,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 a4c9adf..5fab4fd 100644
+--- a/src/event/ngx_event_openssl.h
++++ b/src/event/ngx_event_openssl.h
+@@ -140,8 +140,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..cfdaf47
--- /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 c24ef17..5d425a4 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;
+@@ -680,16 +680,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"),
+@@ -2868,6 +2868,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 */
+@@ -3194,10 +3196,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) {
+@@ -4284,6 +4287,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) {
+@@ -4306,18 +4310,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 6a4108c..6b7d34a 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"),
+@@ -508,8 +508,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 };
+@@ -526,6 +524,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;
+@@ -573,8 +573,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);
+ 
+@@ -601,7 +602,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",
+@@ -609,7 +610,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",
+@@ -619,18 +620,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;
+     }
+@@ -666,8 +687,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 fef2c46..baf0a74 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;
+@@ -518,16 +518,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"),
+@@ -1432,6 +1432,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 */
+@@ -1745,11 +1747,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) {
+@@ -2286,6 +2287,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) {
+@@ -2308,17 +2310,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 ff5c141..137dd10 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..d489c99
--- /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 6c535fd..c2b7452 100644
+--- a/src/stream/ngx_stream_proxy_module.c
++++ b/src/stream/ngx_stream_proxy_module.c
+@@ -35,8 +35,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;
+@@ -277,16 +277,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"),
+@@ -1405,8 +1405,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;
+@@ -1430,6 +1428,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
+ 
+@@ -1500,11 +1500,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);
+ 
+@@ -1524,6 +1524,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) {
+@@ -1544,17 +1545,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 e12da1b..360db17 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 04b971f..250ff54 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,2 +1,12 @@
 perl-use-dpkg-buildflags.patch
 0002-Make-sure-signature-stays-the-same-in-all-nginx-buil.patch
+# 1001-1005 is forward ports of multi-cert patches from Filipe da Silva
+# circa 2015-04-27, onto nginx-1.9.14, 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/286506
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ida2b3deffc97ef40704a32581e824723267df700
Gerrit-PatchSet: 1
Gerrit-Project: operations/software/nginx
Gerrit-Branch: wmf-1.10.0-1
Gerrit-Owner: BBlack <[email protected]>
Gerrit-Reviewer: BBlack <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to