BBlack has submitted this change and it was merged.

Change subject: Port Filipe da Silva's multicert patches, bump libssl to 1.0.2
......................................................................


Port Filipe da Silva's multicert patches, bump libssl to 1.0.2

Bug: T86654
Change-Id: I4c28c06ddebbcb37a0f3ade35c3a26834df80401
---
M debian/control
A debian/patches/1001-SSL-refactor-and-split-ngx_ssl_certificate-in-two.patch
A debian/patches/1002-SSL-introduce-ngx_ssl_certificate_t-array-list.patch
A debian/patches/1003-Stapling-SSL-add-Multiple-SSL-certificate-support.patch
A debian/patches/1004-Stapling-fixing-indentation.patch
A debian/patches/1005-SSL-add-Multiple-SSL-certificate-support-to-http-mod.patch
A debian/patches/1006-SSL-add-Multiple-SSL-certificate-support-to-other-mo.patch
M debian/patches/series
8 files changed, 1,394 insertions(+), 1 deletion(-)

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



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-SSL-refactor-and-split-ngx_ssl_certificate-in-two.patch 
b/debian/patches/1001-SSL-refactor-and-split-ngx_ssl_certificate-in-two.patch
new file mode 100644
index 0000000..dadac83
--- /dev/null
+++ 
b/debian/patches/1001-SSL-refactor-and-split-ngx_ssl_certificate-in-two.patch
@@ -0,0 +1,80 @@
+From 35a3bd2fedf2a821d0e50a7934f32a0bce0bd2a7 Mon Sep 17 00:00:00 2001
+From: Brandon L Black <[email protected]>
+Date: Thu, 18 Jun 2015 14:06:05 +0000
+Subject: [PATCH 2/7] SSL: refactor and split ngx_ssl_certificate in two.
+ Preparation for Multiple SSL certificate support.
+
+These patches are based on the ones from Filipe da Silva here:
+http://mailman.nginx.org/pipermail/nginx-devel/2015-March/006734.html
+00-SplitMethod.diff
+ # HG changeset patch
+ # Parent  953ef81705e1e2d735e956e5fc6406a862e29419
+---
+ src/event/ngx_event_openssl.c | 34 ++++++++++++++++++++++++++++++++--
+ 1 file changed, 32 insertions(+), 2 deletions(-)
+
+diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
+index 1b789e6..3fee271 100644
+--- a/src/event/ngx_event_openssl.c
++++ b/src/event/ngx_event_openssl.c
+@@ -18,6 +18,10 @@ typedef struct {
+ } ngx_openssl_conf_t;
+ 
+ 
++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 int ngx_ssl_password_callback(char *buf, int size, int rwflag,
+     void *userdata);
+ static int ngx_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store);
+@@ -301,11 +305,26 @@ 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)
+ {
++    /* load server certificate */
++    if (ngx_ssl_server_certificate(cf, ssl, cert) != NGX_OK)
++    {
++        return NGX_ERROR;
++    }
++    /* load private key */
++    if (ngx_ssl_private_key(cf, ssl, key, passwords) != NGX_OK)
++    {
++        return NGX_ERROR;
++    }
++    return NGX_OK;
++}
++
++
++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;
+@@ -388,6 +407,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
+-- 
+2.1.0
+
diff --git 
a/debian/patches/1002-SSL-introduce-ngx_ssl_certificate_t-array-list.patch 
b/debian/patches/1002-SSL-introduce-ngx_ssl_certificate_t-array-list.patch
new file mode 100644
index 0000000..55ec7ce
--- /dev/null
+++ b/debian/patches/1002-SSL-introduce-ngx_ssl_certificate_t-array-list.patch
@@ -0,0 +1,234 @@
+From bd83ca9aaf28e2f5a8efe941208a99d624206f82 Mon Sep 17 00:00:00 2001
+From: Brandon L Black <[email protected]>
+Date: Thu, 18 Jun 2015 14:08:17 +0000
+Subject: [PATCH 3/7] SSL: introduce ngx_ssl_certificate_t array list.
+ Preparation for Multi Server-Cert support.
+
+These patches are based on the ones from Filipe da Silva here:
+http://mailman.nginx.org/pipermail/nginx-devel/2015-March/006734.html
+01-AddCertList.diff
+ # HG changeset patch
+ # Parent  7f818f872a33fa2ab0c09942a17901a10bc8acf7
+---
+ src/event/ngx_event_openssl.c          | 71 +++++++++++++++++++++++++++++++---
+ src/event/ngx_event_openssl.h          |  5 +++
+ src/event/ngx_event_openssl_stapling.c | 41 ++++++++++++++++++--
+ 3 files changed, 108 insertions(+), 9 deletions(-)
+
+diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
+index 3fee271..54507b9 100644
+--- a/src/event/ngx_event_openssl.c
++++ b/src/event/ngx_event_openssl.c
+@@ -18,6 +18,10 @@ typedef struct {
+ } ngx_openssl_conf_t;
+ 
+ 
++static ngx_int_t ngx_ssl_certificate_init(ngx_conf_t *cf, ngx_ssl_t *ssl,
++    ngx_uint_t nbcerts);
++static ngx_uint_t ngx_ssl_certificate_push(ngx_conf_t *cf, ngx_ssl_t *ssl,
++    X509 * x509);
+ 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,
+@@ -301,10 +305,57 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, 
void *data)
+ }
+ 
+ 
++ngx_int_t 
++ngx_ssl_certificate_init(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_uint_t nbcerts)
++{
++    ngx_array_t    *certificates;
++
++    certificates = ngx_array_create(cf->pool, nbcerts,
++                                    sizeof(ngx_ssl_certificate_t));
++    if (certificates == NULL) {
++        return NGX_ERROR;
++    }
++
++    if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, certificates)
++        == 0)
++    {
++        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
++                         "SSL_CTX_set_ex_data() failed");
++        return NGX_ERROR;
++    }
++
++    return NGX_OK;
++}
++
++
++ngx_uint_t
++ngx_ssl_certificate_push(ngx_conf_t *cf, ngx_ssl_t *ssl, X509 * x509)
++{
++    ngx_array_t            *certificates;
++    ngx_ssl_certificate_t  *cert;
++
++    certificates = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
++
++    cert = ngx_array_push(certificates);
++    if (cert == NULL) {
++        return -1;
++    }
++
++    cert->x509 = x509;
++
++    return certificates->nelts;
++}
++
++
+ 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)
+ {
++    /* Init server certificate list */
++    if (ngx_ssl_certificate_init(cf, ssl, 1U) != NGX_OK)
++    {
++        return NGX_ERROR;
++    }
+     /* load server certificate */
+     if (ngx_ssl_server_certificate(cf, ssl, cert) != NGX_OK)
+     {
+@@ -325,6 +376,7 @@ ngx_ssl_server_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, 
ngx_str_t *cert)
+     BIO         *bio;
+     X509        *x509;
+     u_long       n;
++    ngx_uint_t   count;
+ 
+     if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
+         return NGX_ERROR;
+@@ -359,11 +411,8 @@ ngx_ssl_server_certificate(ngx_conf_t *cf, ngx_ssl_t 
*ssl, ngx_str_t *cert)
+         return NGX_ERROR;
+     }
+ 
+-    if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_certificate_index, x509)
+-        == 0)
+-    {
+-        ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,
+-                      "SSL_CTX_set_ex_data() failed");
++    /* store cert for future use in stapling and sessions */
++    if ((count = ngx_ssl_certificate_push(cf, ssl,  x509)) <= 0) {
+         X509_free(x509);
+         BIO_free(bio);
+         return NGX_ERROR;
+@@ -2161,6 +2210,9 @@ ngx_ssl_session_id_context(ngx_ssl_t *ssl, ngx_str_t 
*sess_ctx)
+     STACK_OF(X509_NAME)  *list;
+     u_char                buf[EVP_MAX_MD_SIZE];
+ 
++    ngx_array_t            *certificates;
++    ngx_ssl_certificate_t  *certificate;
++
+     /*
+      * Session ID context is set based on the string provided,
+      * the server certificate, and the client CA list.
+@@ -2180,7 +2232,14 @@ 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);
++    certificates = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
++    if (!certificates || certificates->nelts == 0) {
++        goto failed;
++    }
++    certificate = certificates->elts;
++
++    /* TOFIX: not only use just first one */
++    cert = certificate[0].x509;
+ 
+     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..004100c 100644
+--- a/src/event/ngx_event_openssl.h
++++ b/src/event/ngx_event_openssl.h
+@@ -45,6 +45,11 @@ typedef struct {
+ 
+ 
+ typedef struct {
++    X509                       *x509;
++} ngx_ssl_certificate_t;
++
++
++typedef struct {
+     ngx_ssl_conn_t             *connection;
+ 
+     ngx_int_t                   last;
+diff --git a/src/event/ngx_event_openssl_stapling.c 
b/src/event/ngx_event_openssl_stapling.c
+index 60051ad..5971668 100644
+--- a/src/event/ngx_event_openssl_stapling.c
++++ b/src/event/ngx_event_openssl_stapling.c
+@@ -86,6 +86,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);
+ static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl);
++static ngx_int_t ngx_ssl_stapling_issuer_lookup(ngx_conf_t *cf, 
++    ngx_ssl_t *ssl, ngx_ssl_certificate_t *certificate);
++static ngx_int_t ngx_ssl_stapling_certid_push(ngx_ssl_stapling_t *staple, 
++    X509 *cert, X509 *issuer);
+ static ngx_int_t ngx_ssl_stapling_responder(ngx_conf_t *cf, ngx_ssl_t *ssl,
+     ngx_str_t *responder);
+ 
+@@ -261,6 +265,29 @@ failed:
+ static ngx_int_t
+ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
+ {
++    ngx_array_t            *certificates;
++    ngx_ssl_certificate_t  *certificate;
++
++    certificates = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_certificate_index);
++    if (!certificates || certificates->nelts == 0) {
++        return NGX_ERROR;
++    }
++
++    /* TOFIX: not only use just first one */
++    certificate = certificates->elts;
++
++    if (ngx_ssl_stapling_issuer_lookup(cf, ssl, certificate) != NGX_OK) {
++        return NGX_ERROR;
++    }
++    
++    return NGX_OK; 
++}
++
++
++static ngx_int_t
++ngx_ssl_stapling_issuer_lookup(ngx_conf_t *cf, ngx_ssl_t *ssl, 
++    ngx_ssl_certificate_t *certificate)
++{
+     int                  i, n, rc;
+     X509                *cert, *issuer;
+     X509_STORE          *store;
+@@ -269,7 +296,7 @@ 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 = certificate->x509;
+ 
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L
+     SSL_CTX_get_extra_chain_certs(ssl->ctx, &chain);
+@@ -290,8 +317,7 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
+             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
+                            "SSL get issuer: found %p in extra certs", issuer);
+ 
+-            staple->cert = cert;
+-            staple->issuer = issuer;
++            ngx_ssl_stapling_certid_push(staple, cert, issuer); 
+ 
+             return NGX_OK;
+         }
+@@ -339,6 +365,15 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
+     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ssl->log, 0,
+                    "SSL get issuer: found %p in cert store", issuer);
+ 
++    ngx_ssl_stapling_certid_push(staple, cert, issuer); 
++
++    return NGX_OK;
++}
++
++
++static ngx_int_t ngx_ssl_stapling_certid_push(ngx_ssl_stapling_t *staple, 
++    X509 *cert, X509 *issuer)
++{
+     staple->cert = cert;
+     staple->issuer = issuer;
+ 
diff --git 
a/debian/patches/1003-Stapling-SSL-add-Multiple-SSL-certificate-support.patch 
b/debian/patches/1003-Stapling-SSL-add-Multiple-SSL-certificate-support.patch
new file mode 100644
index 0000000..0394ed5
--- /dev/null
+++ 
b/debian/patches/1003-Stapling-SSL-add-Multiple-SSL-certificate-support.patch
@@ -0,0 +1,252 @@
+From a6b2c78935c88614a2c74870bde8d5b5ed0baa5b Mon Sep 17 00:00:00 2001
+From: Brandon L Black <[email protected]>
+Date: Thu, 18 Jun 2015 14:10:42 +0000
+Subject: [PATCH 4/7] Stapling SSL: add Multiple SSL certificate support.
+ OpenSSL >= 1.0.2 required. Only OCSP responder URL from first certificate
+ will be contacted.
+
+These patches are based on the ones from Filipe da Silva here:
+http://mailman.nginx.org/pipermail/nginx-devel/2015-March/006734.html
+02-AddStaplingCertIssuerList.diff
+ # HG changeset patch
+ # Parent  816e9d420de0e74e86f6cd4cecd578d57fac60e3
+---
+ src/event/ngx_event_openssl_stapling.c | 108 +++++++++++++++++++++++++++------
+ 1 file changed, 89 insertions(+), 19 deletions(-)
+
+diff --git a/src/event/ngx_event_openssl_stapling.c 
b/src/event/ngx_event_openssl_stapling.c
+index 5971668..72392a8 100644
+--- a/src/event/ngx_event_openssl_stapling.c
++++ b/src/event/ngx_event_openssl_stapling.c
+@@ -28,8 +28,8 @@ typedef struct {
+ 
+     SSL_CTX                     *ssl_ctx;
+ 
+-    X509                        *cert;
+-    X509                        *issuer;
++    ngx_array_t                 *certs;
++    ngx_array_t                 *issuers;
+ 
+     time_t                       valid;
+     time_t                       refresh;
+@@ -42,8 +42,8 @@ typedef struct {
+ typedef struct ngx_ssl_ocsp_ctx_s  ngx_ssl_ocsp_ctx_t;
+ 
+ struct ngx_ssl_ocsp_ctx_s {
+-    X509                        *cert;
+-    X509                        *issuer;
++    ngx_array_t                 *certs;
++    ngx_array_t                 *issuers;
+ 
+     ngx_uint_t                   naddrs;
+ 
+@@ -86,6 +86,8 @@ 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);
+ static ngx_int_t ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl);
++static ngx_int_t ngx_ssl_stapling_issuer_init(ngx_conf_t *cf, ngx_ssl_t *ssl,
++    ngx_int_t nbcerts);
+ static ngx_int_t ngx_ssl_stapling_issuer_lookup(ngx_conf_t *cf, 
+     ngx_ssl_t *ssl, ngx_ssl_certificate_t *certificate);
+ static ngx_int_t ngx_ssl_stapling_certid_push(ngx_ssl_stapling_t *staple, 
+@@ -263,6 +265,28 @@ failed:
+ 
+ 
+ static ngx_int_t
++ngx_ssl_stapling_issuer_init(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_int_t 
nbcerts)
++{
++    ngx_ssl_stapling_t  *staple;
++
++    staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
++
++    staple->certs = ngx_array_create(cf->pool, nbcerts,
++                                    sizeof(ngx_ssl_certificate_t));
++
++    staple->issuers = ngx_array_create(cf->pool, nbcerts,
++                                    sizeof(ngx_ssl_certificate_t));
++
++    if (staple->certs == NULL || staple->issuers == NULL) {
++        staple->certs = staple->issuers = NULL;
++        return NGX_ERROR;
++    }
++
++    return NGX_OK;
++}
++
++
++static ngx_int_t
+ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
+ {
+     ngx_array_t            *certificates;
+@@ -273,6 +297,7 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
+         return NGX_ERROR;
+     }
+ 
++    ngx_ssl_stapling_issuer_init(cf, ssl, certificates->nelts);
+     /* TOFIX: not only use just first one */
+     certificate = certificates->elts;
+ 
+@@ -374,8 +399,19 @@ ngx_ssl_stapling_issuer_lookup(ngx_conf_t *cf, ngx_ssl_t 
*ssl,
+ static ngx_int_t ngx_ssl_stapling_certid_push(ngx_ssl_stapling_t *staple, 
+     X509 *cert, X509 *issuer)
+ {
+-    staple->cert = cert;
+-    staple->issuer = issuer;
++    ngx_ssl_certificate_t  *item;
++
++    item = ngx_array_push(staple->certs);
++    if (item == NULL) {
++        return NGX_ERROR;
++    }
++    item->x509 = cert;
++
++    item = ngx_array_push(staple->issuers);
++    if (item == NULL) {
++        return NGX_ERROR;
++    }
++    item->x509 = issuer;
+ 
+     return NGX_OK;
+ }
+@@ -387,15 +423,17 @@ 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;
++    ngx_ssl_certificate_t     *cert;
+     STACK_OF(OPENSSL_STRING)  *aia;
+ 
+     staple = SSL_CTX_get_ex_data(ssl->ctx, ngx_ssl_stapling_index);
+ 
+     if (responder->len == 0) {
+ 
+-        /* extract OCSP responder URL from certificate */
++        /* extract OCSP responder URL from *first* certificate */
++        cert = staple->certs->elts;
+ 
+-        aia = X509_get1_ocsp(staple->cert);
++        aia = X509_get1_ocsp(cert->x509);
+         if (aia == NULL) {
+             ngx_log_error(NGX_LOG_WARN, ssl->log, 0,
+                           "\"ssl_stapling\" ignored, "
+@@ -543,8 +581,8 @@ ngx_ssl_stapling_update(ngx_ssl_stapling_t *staple)
+         return;
+     }
+ 
+-    ctx->cert = staple->cert;
+-    ctx->issuer = staple->issuer;
++    ctx->certs = staple->certs;
++    ctx->issuers = staple->issuers;
+ 
+     ctx->addrs = staple->addrs;
+     ctx->host = staple->host;
+@@ -575,6 +613,7 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
+     size_t                 len;
+     time_t                 now, valid;
+     ngx_str_t              response;
++    ngx_uint_t             i, nelts;
+     X509_STORE            *store;
+     STACK_OF(X509)        *chain;
+     OCSP_CERTID           *id;
+@@ -582,6 +621,8 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
+     OCSP_BASICRESP        *basic;
+     ngx_ssl_stapling_t    *staple;
+     ASN1_GENERALIZEDTIME  *thisupdate, *nextupdate;
++    ngx_ssl_certificate_t *cert;
++    ngx_ssl_certificate_t *issuer;
+ 
+     staple = ctx->data;
+     now = ngx_time();
+@@ -635,15 +676,25 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
+ #endif
+ 
+     if (OCSP_basic_verify(basic, chain, store,
+-                          staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY)
+-        != 1)
+-    {
++                          staple->verify ? OCSP_TRUSTOTHER : OCSP_NOVERIFY
++#if OPENSSL_VERSION_NUMBER < 0x10000000L
++        /* ECDSA/SHA-2 signature verification not supported */
++                          | OCSP_NOSIGS
++#endif
++        ) != 1)
++   {
+         ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
+                       "OCSP_basic_verify() failed");
+         goto error;
+     }
+ 
+-    id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
++    nelts = ctx->certs->nelts;
++    cert = ctx->certs->elts;
++    issuer = ctx->issuers->elts;
++
++    for (i = 0; i < nelts; i++, cert++, issuer++) {
++
++    id = OCSP_cert_to_id(NULL, cert->x509, issuer->x509);
+     if (id == NULL) {
+         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
+                       "OCSP_cert_to_id() failed");
+@@ -685,6 +736,8 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
+     }
+ 
+     OCSP_CERTID_free(id);
++    }   /* END OF For each 'cert/issuer' pair */
++   
+     OCSP_BASICRESP_free(basic);
+     OCSP_RESPONSE_free(ocsp);
+ 
+@@ -783,10 +836,16 @@ ngx_ssl_stapling_time(ASN1_GENERALIZEDTIME *asn1time)
+ static void
+ ngx_ssl_stapling_cleanup(void *data)
+ {
+-    ngx_ssl_stapling_t  *staple = data;
+-
+-    if (staple->issuer) {
+-        X509_free(staple->issuer);
++    ngx_uint_t              i, nelts;
++    ngx_ssl_stapling_t     *staple = data;
++    ngx_ssl_certificate_t  *issuer;
++
++    if (staple->issuers) {
++        issuer = staple->issuers->elts;
++        nelts = staple->issuers->nelts;
++        for (i = 0; i < nelts; i++, issuer++) {
++            X509_free(issuer->x509);
++        }
+     }
+ 
+     if (staple->staple.data) {
+@@ -1199,6 +1258,10 @@ ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
+     OCSP_CERTID   *id;
+     OCSP_REQUEST  *ocsp;
+ 
++    ngx_uint_t              i, nelts;
++    ngx_ssl_certificate_t  *cert;
++    ngx_ssl_certificate_t  *issuer;
++
+     ocsp = OCSP_REQUEST_new();
+     if (ocsp == NULL) {
+         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
+@@ -1206,7 +1269,13 @@ ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
+         return NGX_ERROR;
+     }
+ 
+-    id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
++    nelts = ctx->certs->nelts;
++    cert = ctx->certs->elts;
++    issuer = ctx->issuers->elts;
++
++    for (i = 0; i < nelts; i++, cert++, issuer++) {
++
++    id = OCSP_cert_to_id(NULL, cert->x509, issuer->x509);
+     if (id == NULL) {
+         ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
+                       "OCSP_cert_to_id() failed");
+@@ -1219,6 +1288,7 @@ ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
+         OCSP_CERTID_free(id);
+         goto failed;
+     }
++    }   /* END OF For each 'cert/issuer' pair */
+ 
+     len = i2d_OCSP_REQUEST(ocsp, NULL);
+     if (len <= 0) {
diff --git a/debian/patches/1004-Stapling-fixing-indentation.patch 
b/debian/patches/1004-Stapling-fixing-indentation.patch
new file mode 100644
index 0000000..9f3e3c0
--- /dev/null
+++ b/debian/patches/1004-Stapling-fixing-indentation.patch
@@ -0,0 +1,164 @@
+From 4a3e6d915f03d69954961d3d21f6088ce516e196 Mon Sep 17 00:00:00 2001
+From: Brandon L Black <[email protected]>
+Date: Thu, 18 Jun 2015 14:29:24 +0000
+Subject: [PATCH 5/7] Stapling : fixing indentation
+
+NOTE: This was the only patch in this series which didn't apply
+cleanly to 1.9.2.  I had to do a pair of fixups for new code added
+since, but they were was trivial (just indented the new code as
+well, so that this is still a whitespace-only commit, aside from
+the (existing) reordering of local variable declarations in one
+file).
+
+These patches are based on the ones from Filipe da Silva here:
+http://mailman.nginx.org/pipermail/nginx-devel/2015-March/006734.html
+03-FixIndentation.diff
+ # HG changeset patch
+ # Parent  3e2f451bd0366149bb0d56782351ad69fd05a9b9
+---
+ src/event/ngx_event_openssl_stapling.c | 103 ++++++++++++++++-----------------
+ 1 file changed, 51 insertions(+), 52 deletions(-)
+
+diff --git a/src/event/ngx_event_openssl_stapling.c 
b/src/event/ngx_event_openssl_stapling.c
+index 72392a8..5622b65 100644
+--- a/src/event/ngx_event_openssl_stapling.c
++++ b/src/event/ngx_event_openssl_stapling.c
+@@ -694,48 +694,48 @@ ngx_ssl_stapling_ocsp_handler(ngx_ssl_ocsp_ctx_t *ctx)
+ 
+     for (i = 0; i < nelts; i++, cert++, issuer++) {
+ 
+-    id = OCSP_cert_to_id(NULL, cert->x509, issuer->x509);
+-    if (id == NULL) {
+-        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
+-                      "OCSP_cert_to_id() failed");
+-        goto error;
+-    }
+-
+-    if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
+-                              &thisupdate, &nextupdate)
+-        != 1)
+-    {
+-        ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
+-                      "certificate status not found in the OCSP response");
+-        goto error;
+-    }
+-
+-    if (n != V_OCSP_CERTSTATUS_GOOD) {
+-        ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
+-                      "certificate status \"%s\" in the OCSP response",
+-                      OCSP_cert_status_str(n));
+-        goto error;
+-    }
++        id = OCSP_cert_to_id(NULL, cert->x509, issuer->x509);
++        if (id == NULL) {
++            ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
++                          "OCSP_cert_to_id() failed");
++            goto error;
++        }
+ 
+-    if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
+-        ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
+-                      "OCSP_check_validity() failed");
+-        goto error;
+-    }
++        if (OCSP_resp_find_status(basic, id, &n, NULL, NULL,
++                                  &thisupdate, &nextupdate)
++            != 1)
++        {
++            ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
++                          "certificate status not found in the OCSP 
response");
++            goto error;
++        }
+ 
+-    if (nextupdate) {
+-        valid = ngx_ssl_stapling_time(nextupdate);
+-        if (valid == (time_t) NGX_ERROR) {
++        if (n != V_OCSP_CERTSTATUS_GOOD) {
+             ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
+-                          "invalid nextUpdate time in certificate status");
++                          "certificate status \"%s\" in the OCSP response",
++                          OCSP_cert_status_str(n));
+             goto error;
+         }
+ 
+-    } else {
+-        valid = NGX_MAX_TIME_T_VALUE;
+-    }
++        if (OCSP_check_validity(thisupdate, nextupdate, 300, -1) != 1) {
++            ngx_ssl_error(NGX_LOG_ERR, ctx->log, 0,
++                          "OCSP_check_validity() failed");
++            goto error;
++        }
++
++        if (nextupdate) {
++            valid = ngx_ssl_stapling_time(nextupdate);
++            if (valid == (time_t) NGX_ERROR) {
++                ngx_log_error(NGX_LOG_ERR, ctx->log, 0,
++                              "invalid nextUpdate time in certificate 
status");
++                goto error;
++            }
++
++        } else {
++            valid = NGX_MAX_TIME_T_VALUE;
++        }
+ 
+-    OCSP_CERTID_free(id);
++        OCSP_CERTID_free(id);
+     }   /* END OF For each 'cert/issuer' pair */
+    
+     OCSP_BASICRESP_free(basic);
+@@ -1250,15 +1250,14 @@ ngx_ssl_ocsp_dummy_handler(ngx_event_t *ev)
+ static ngx_int_t
+ ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
+ {
+-    int            len;
+-    u_char        *p;
+-    uintptr_t      escape;
+-    ngx_str_t      binary, base64;
+-    ngx_buf_t     *b;
+-    OCSP_CERTID   *id;
+-    OCSP_REQUEST  *ocsp;
+-
++    int                     len;
++    u_char                 *p;
++    uintptr_t               escape;
+     ngx_uint_t              i, nelts;
++    ngx_str_t               binary, base64;
++    ngx_buf_t              *b;
++    OCSP_CERTID            *id;
++    OCSP_REQUEST           *ocsp;
+     ngx_ssl_certificate_t  *cert;
+     ngx_ssl_certificate_t  *issuer;
+ 
+@@ -1275,19 +1274,19 @@ ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
+ 
+     for (i = 0; i < nelts; i++, cert++, issuer++) {
+ 
+-    id = OCSP_cert_to_id(NULL, cert->x509, issuer->x509);
+-    if (id == NULL) {
+-        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
+-                      "OCSP_cert_to_id() failed");
+-        goto failed;
+-    }
++        id = OCSP_cert_to_id(NULL, cert->x509, issuer->x509);
++        if (id == NULL) {
++            ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
++                          "OCSP_cert_to_id() failed");
++            goto failed;
++        }
+ 
+-    if (OCSP_request_add0_id(ocsp, id) == NULL) {
+-        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
+-                      "OCSP_request_add0_id() failed");
+-        OCSP_CERTID_free(id);
+-        goto failed;
+-    }
++        if (OCSP_request_add0_id(ocsp, id) == NULL) {
++            ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
++                          "OCSP_request_add0_id() failed");
++            OCSP_CERTID_free(id);
++            goto failed;
++        }
+     }   /* END OF For each 'cert/issuer' pair */
+ 
+     len = i2d_OCSP_REQUEST(ocsp, NULL);
diff --git 
a/debian/patches/1005-SSL-add-Multiple-SSL-certificate-support-to-http-mod.patch
 
b/debian/patches/1005-SSL-add-Multiple-SSL-certificate-support-to-http-mod.patch
new file mode 100644
index 0000000..a6e2ebe
--- /dev/null
+++ 
b/debian/patches/1005-SSL-add-Multiple-SSL-certificate-support-to-http-mod.patch
@@ -0,0 +1,279 @@
+From d2d00f06cd89a2a4b856934f1d92a56207911ae4 Mon Sep 17 00:00:00 2001
+From: Brandon L Black <[email protected]>
+Date: Thu, 18 Jun 2015 14:32:18 +0000
+Subject: [PATCH 6/7] SSL: add Multiple SSL certificate support to http module.
+ OpenSSL >= 1.0.2 required.
+
+These patches are based on the ones from Filipe da Silva here:
+http://mailman.nginx.org/pipermail/nginx-devel/2015-March/006734.html
+04-MultiCertSupport.diff
+ # HG changeset patch
+ # Parent  21ada59fc75291c5bc9c6a158261899f763018fc
+---
+ src/event/ngx_event_openssl.c          | 48 ++++++++++++++++++++++++++++++++
+ src/event/ngx_event_openssl.h          |  2 ++
+ src/event/ngx_event_openssl_stapling.c | 16 ++++++++---
+ src/http/modules/ngx_http_ssl_module.c | 51 ++++++++++++++++++++++++----------
+ src/http/modules/ngx_http_ssl_module.h |  4 +--
+ 5 files changed, 100 insertions(+), 21 deletions(-)
+
+diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
+index 54507b9..37038ae 100644
+--- a/src/event/ngx_event_openssl.c
++++ b/src/event/ngx_event_openssl.c
+@@ -347,6 +347,42 @@ ngx_ssl_certificate_push(ngx_conf_t *cf, ngx_ssl_t *ssl, 
X509 * x509)
+ }
+ 
+ 
++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_uint_t  i, j;
++    ngx_str_t  *cert;
++    ngx_str_t  *key;
++
++    /* Init server certificate list */
++    if (ngx_ssl_certificate_init(cf, ssl, certs->nelts) != NGX_OK)
++    {
++        return NGX_ERROR;
++    }
++
++    /* 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;
++}
++
++
+ 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)
+@@ -444,10 +480,22 @@ ngx_ssl_server_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 (n == 0) { */
++        /* same as count == 1 -> always true, as case is rejected by config 
code */ 
+         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;
+diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
+index 004100c..fbbbc0c 100644
+--- a/src/event/ngx_event_openssl.h
++++ b/src/event/ngx_event_openssl.h
+@@ -129,6 +129,8 @@ 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/src/event/ngx_event_openssl_stapling.c 
b/src/event/ngx_event_openssl_stapling.c
+index 5622b65..715390f 100644
+--- a/src/event/ngx_event_openssl_stapling.c
++++ b/src/event/ngx_event_openssl_stapling.c
+@@ -289,6 +289,7 @@ ngx_ssl_stapling_issuer_init(ngx_conf_t *cf, ngx_ssl_t 
*ssl, ngx_int_t nbcerts)
+ static ngx_int_t
+ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
+ {
++    ngx_uint_t             i, nelts;
+     ngx_array_t            *certificates;
+     ngx_ssl_certificate_t  *certificate;
+ 
+@@ -297,12 +298,19 @@ ngx_ssl_stapling_issuer(ngx_conf_t *cf, ngx_ssl_t *ssl)
+         return NGX_ERROR;
+     }
+ 
+-    ngx_ssl_stapling_issuer_init(cf, ssl, certificates->nelts);
+-    /* TOFIX: not only use just first one */
++    nelts = certificates->nelts;
++    if (ngx_ssl_stapling_issuer_init(cf, ssl, nelts) != NGX_OK)
++    {
++        return NGX_ERROR;
++    }
++
+     certificate = certificates->elts;
+ 
+-    if (ngx_ssl_stapling_issuer_lookup(cf, ssl, certificate) != NGX_OK) {
+-        return NGX_ERROR;
++    for (i = 0; i < nelts; i++, certificate++) {
++        if (ngx_ssl_stapling_issuer_lookup(cf, ssl, certificate) != NGX_OK)
++        {
++            return NGX_ERROR;
++        }
+     }
+     
+     return NGX_OK; 
+diff --git a/src/http/modules/ngx_http_ssl_module.c 
b/src/http/modules/ngx_http_ssl_module.c
+index d6a1794..a9d6d0e 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/debian/patches/1006-SSL-add-Multiple-SSL-certificate-support-to-other-mo.patch
 
b/debian/patches/1006-SSL-add-Multiple-SSL-certificate-support-to-other-mo.patch
new file mode 100644
index 0000000..e7df934
--- /dev/null
+++ 
b/debian/patches/1006-SSL-add-Multiple-SSL-certificate-support-to-other-mo.patch
@@ -0,0 +1,377 @@
+From 46b4de4d5cf5e7996871023af2912f889beb00d4 Mon Sep 17 00:00:00 2001
+From: Brandon L Black <[email protected]>
+Date: Thu, 18 Jun 2015 14:34:01 +0000
+Subject: [PATCH 7/7] SSL: add Multiple SSL certificate support to other
+ modules. OpenSSL >= 1.0.2 required.
+
+These patches are based on the ones from Filipe da Silva here:
+http://mailman.nginx.org/pipermail/nginx-devel/2015-March/006734.html
+05-MultiCertSupport2.patch
+ # HG changeset patch
+ # Parent  4a901ee83540eae0e3e7091bdc1b8d2c6dae33ef
+---
+ src/http/modules/ngx_http_proxy_module.c | 63 +++++++++++++++++++++++---------
+ src/http/modules/ngx_http_uwsgi_module.c | 61 ++++++++++++++++++++++---------
+ src/mail/ngx_mail_ssl_module.c           | 32 ++++++++--------
+ src/mail/ngx_mail_ssl_module.h           |  4 +-
+ 4 files changed, 108 insertions(+), 52 deletions(-)
+
+diff --git a/src/http/modules/ngx_http_proxy_module.c 
b/src/http/modules/ngx_http_proxy_module.c
+index 514c23b..70e8c93 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);
++                          "no \"proxy_ssl_certificate_key\" is defined 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_uwsgi_module.c 
b/src/http/modules/ngx_http_uwsgi_module.c
+index a50c553..96913f1 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);
++                          "no \"uwsgi_ssl_certificate_key\" is defined 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..3869243 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",
+@@ -346,15 +347,14 @@ ngx_mail_ssl_merge_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->certificate);
++                          "for certificate \"%V\"", &conf->certificates[0]);
+             return NGX_CONF_ERROR;
+         }
+     }
+@@ -371,8 +371,8 @@ 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)
++    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;
+-- 
+2.1.0
+
diff --git a/debian/patches/series b/debian/patches/series
index 73f535e..86f8eff 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,8 @@
 perl-use-dpkg-buildflags.patch
+# 1000-series is forward ports of 
http://mailman.nginx.org/pipermail/nginx-devel/2015-March/006734.html cleanly 
onto 1.9.2-1+wmf1 baseline
+1001-SSL-refactor-and-split-ngx_ssl_certificate-in-two.patch
+1002-SSL-introduce-ngx_ssl_certificate_t-array-list.patch
+1003-Stapling-SSL-add-Multiple-SSL-certificate-support.patch
+1004-Stapling-fixing-indentation.patch
+1005-SSL-add-Multiple-SSL-certificate-support-to-http-mod.patch
+1006-SSL-add-Multiple-SSL-certificate-support-to-other-mo.patch

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I4c28c06ddebbcb37a0f3ade35c3a26834df80401
Gerrit-PatchSet: 1
Gerrit-Project: operations/software/nginx
Gerrit-Branch: wmf-1.9.3-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