[PATCH] Proxy SSL Verify

W. Andrew Loe III andrew at andrewloe.com
Thu Sep 15 19:23:28 UTC 2011


I have a patch working against nginx 1.1.3. I'm not entirely happy
with having to set verification_failed on ngx_ssl_connection_t,
however returning 0 from the verify callback did not stop processing
as documented (http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html),
so I captured and check before the handshake is complete. If anyone
has an alternative solution that is more elegant I will gladly
refactor.

-- Andrew

http://trac.nginx.org/nginx/ticket/13

diff --git a/src/event/ngx_event_openssl.c
b/src/event/ngx_event_openssl.cindex 259b1d8..05b49dd 100644---
a/src/event/ngx_event_openssl.c+++ b/src/event/ngx_event_openssl.c@@
-216,13 +216,10 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_str_t *cert,     return NGX_OK; } -
ngx_int_t-ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl,
ngx_str_t *cert,+ngx_ssl_set_verify_options(ngx_ssl_t *ssl, ngx_str_t
*cert,     ngx_int_t depth) {-    STACK_OF(X509_NAME)  *list;-
SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER,
ngx_http_ssl_verify_callback);      SSL_CTX_set_verify_depth(ssl->ctx,
depth);@@ -231,10 +228,6 @@ ngx_ssl_client_certificate(ngx_conf_t *cf,
ngx_ssl_t *ssl, ngx_str_t *cert,         return NGX_OK;     } -    if
(ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {-        return
NGX_ERROR;-    }-     if (SSL_CTX_load_verify_locations(ssl->ctx,
(char *) cert->data, NULL)         == 0)     {@@ -244,6 +237,23 @@
ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t
*cert,         return NGX_ERROR;     } +    return
NGX_OK;+}++ngx_int_t+ngx_ssl_client_certificate(ngx_conf_t *cf,
ngx_ssl_t *ssl, ngx_str_t *cert,+    ngx_int_t depth)+{+
STACK_OF(X509_NAME)  *list;++    if (ngx_ssl_set_verify_options(ssl,
cert, depth) != NGX_OK) {+        return NGX_ERROR;+    }++    if
(ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {+        return
NGX_ERROR;+    }+     list = SSL_load_client_CA_file((char *)
cert->data);      if (list == NULL) {@@ -313,11 +323,6 @@
ngx_ssl_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl) static int
ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store) {-#if
(NGX_DEBUG)-    char              *subject, *issuer;-    int
     err, depth;-    X509              *cert;-    X509_NAME
*sname, *iname;     ngx_connection_t  *c;     ngx_ssl_conn_t
*ssl_conn; @@ -326,6 +331,12 @@ ngx_http_ssl_verify_callback(int ok,
X509_STORE_CTX *x509_store)      c = ngx_ssl_get_connection(ssl_conn);
+#if (NGX_DEBUG)+    char              *subject, *issuer;+    int
          err, depth;+    X509              *cert;+    X509_NAME
  *sname, *iname;+     cert =
X509_STORE_CTX_get_current_cert(x509_store);     err =
X509_STORE_CTX_get_error(x509_store);     depth =
X509_STORE_CTX_get_error_depth(x509_store);@@ -350,6 +361,13 @@
ngx_http_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store)     }
#endif +    if (ok != 1)+    {+        ngx_ssl_error(NGX_LOG_EMERG,
c->log, 0, "ngx_http_ssl_verify_callback failed");+
c->ssl->verification_failed = 1;+        return 0;+    }+     return
1; } @@ -575,6 +593,11 @@ ngx_ssl_handshake(ngx_connection_t *c)
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d",
n); +    if (c->ssl->verification_failed != NGX_OK)+    {+      return
NGX_ERROR;+    }+     if (n == 1) {          if
(ngx_handle_read_event(c->read, 0) != NGX_OK) {diff --git
a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.hindex
33cab7b..b59baf9 100644--- a/src/event/ngx_event_openssl.h+++
b/src/event/ngx_event_openssl.h@@ -46,6 +46,8 @@ typedef struct {
unsigned                    buffer:1;     unsigned
no_wait_shutdown:1;     unsigned
no_send_shutdown:1;++    ngx_int_t
verification_failed; } ngx_ssl_connection_t;  @@ -96,6 +98,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_int_t
ngx_ssl_set_verify_options(ngx_ssl_t *ssl, ngx_str_t *cert,+
ngx_int_t depth); 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_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl);diff --git
a/src/http/modules/ngx_http_proxy_module.c
b/src/http/modules/ngx_http_proxy_module.cindex 902cfb8..834301e
100644--- a/src/http/modules/ngx_http_proxy_module.c+++
b/src/http/modules/ngx_http_proxy_module.c@@ -440,7 +440,27 @@ static
ngx_command_t  ngx_http_proxy_commands[] = {
NGX_HTTP_LOC_CONF_OFFSET,       offsetof(ngx_http_proxy_loc_conf_t,
upstream.ssl_session_reuse),       NULL },+    +    {
ngx_string("proxy_ssl_verify_peer"),+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,+
     ngx_conf_set_flag_slot,+      NGX_HTTP_LOC_CONF_OFFSET,+
offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify_peer),+
NULL },++    { ngx_string("proxy_ssl_verify_depth"),+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,+
     ngx_conf_set_num_slot,+      NGX_HTTP_LOC_CONF_OFFSET,+
offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify_depth),+
NULL }, +    { ngx_string("proxy_ssl_ca_certificate"),+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,+
     ngx_conf_set_str_slot,+      NGX_HTTP_LOC_CONF_OFFSET,+
offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_ca_certificate),+
 NULL }, #endif        ngx_null_command@@ -1697,6 +1717,8 @@
ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->upstream.intercept_errors = NGX_CONF_UNSET; #if (NGX_HTTP_SSL)
  conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;+
conf->upstream.ssl_verify_peer = NGX_CONF_UNSET;+
conf->upstream.ssl_verify_depth = NGX_CONF_UNSET_UINT; #endif      /*
"proxy_cyclic_temp_file" is disabled */@@ -1955,6 +1977,22 @@
ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void
*child) #if (NGX_HTTP_SSL)
ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
              prev->upstream.ssl_session_reuse, 1);+
ngx_conf_merge_value(conf->upstream.ssl_verify_peer,+
            prev->upstream.ssl_verify_peer, 0);+
ngx_conf_merge_uint_value(conf->upstream.ssl_verify_depth,+
                  prev->upstream.ssl_verify_depth, 1);+
ngx_conf_merge_str_value(conf->upstream.ssl_ca_certificate,+
                   prev->upstream.ssl_ca_certificate, "");++    if
(conf->upstream.ssl_verify_peer) {+      if
(conf->upstream.ssl_ca_certificate.len == 0) {+
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,+            "no
\"proxy_ssl_ca_certificate\" is defined for "+            "the
\"proxy_ssl_verify_peer\" directive");++        return
NGX_CONF_ERROR;+      }+    } #endif
ngx_conf_merge_value(conf->redirect, prev->redirect, 1);diff --git
a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.cindex
29432dc..474cf0d 100644--- a/src/http/ngx_http_upstream.c+++
b/src/http/ngx_http_upstream.c@@ -1210,6 +1210,15 @@
ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, {
ngx_int_t   rc; +    if (ngx_ssl_set_verify_options(u->conf->ssl,+
     &u->conf->ssl_ca_certificate, u->conf->ssl_verify_depth)+
!= NGX_OK)+    {+      ngx_http_upstream_finalize_request(r, u,+
   NGX_HTTP_INTERNAL_SERVER_ERROR);+      return;+    }+     if
(ngx_ssl_create_connection(u->conf->ssl, c,
       NGX_SSL_BUFFER|NGX_SSL_CLIENT)         != NGX_OK)@@ -4527,3
+4536,4 @@ ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void
*conf)      return NGX_CONF_OK; }+diff --git
a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.hindex
fa848c0..cc71ba9 100644--- a/src/http/ngx_http_upstream.h+++
b/src/http/ngx_http_upstream.h@@ -177,6 +177,9 @@ typedef struct { #if
(NGX_HTTP_SSL)     ngx_ssl_t                       *ssl;
ngx_flag_t                       ssl_session_reuse;+    ngx_flag_t
                  ssl_verify_peer;+    ngx_uint_t
 ssl_verify_depth;+    ngx_str_t
ssl_ca_certificate; #endif      ngx_str_t
module;

On Wed, Sep 14, 2011 at 5:47 PM, W. Andrew Loe III <andrew at andrewloe.com> wrote:
> Thank you for the help! I am now working against 1.1.2 which was the
> latest release this morning. My code is available on github
> (https://github.com/loe/nginx/tree/proxy_ssl_verify) but I will also
> include it here.
>
> I am having an issue with SSL_get_verify_result never failing, it
> always returns 0 even with ngx_http_verify_callback logs that the
> certificate has not been verified. I have inserted a few debugging
> statements to illustrate the behavior. I have also included a location
> you can put in the default nginx.conf that will proxy to an SSL
> server.
>
> diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
> index 259b1d8..078978b 100644
> --- a/src/event/ngx_event_openssl.c
> +++ b/src/event/ngx_event_openssl.c
> @@ -216,13 +216,10 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ssl_t
> *ssl, ngx_str_t *cert,
>     return NGX_OK;
>  }
>
> -
>  ngx_int_t
> -ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
> +ngx_ssl_set_verify_options(ngx_ssl_t *ssl, ngx_str_t *cert,
>     ngx_int_t depth)
>  {
> -    STACK_OF(X509_NAME)  *list;
> -
>     SSL_CTX_set_verify(ssl->ctx, SSL_VERIFY_PEER,
> ngx_http_ssl_verify_callback);
>
>     SSL_CTX_set_verify_depth(ssl->ctx, depth);
> @@ -231,10 +228,6 @@ ngx_ssl_client_certificate(ngx_conf_t *cf,
> ngx_ssl_t *ssl, ngx_str_t *cert,
>         return NGX_OK;
>     }
>
> -    if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
> -        return NGX_ERROR;
> -    }
> -
>     if (SSL_CTX_load_verify_locations(ssl->ctx, (char *) cert->data, NULL)
>         == 0)
>     {
> @@ -244,6 +237,23 @@ ngx_ssl_client_certificate(ngx_conf_t *cf,
> ngx_ssl_t *ssl, ngx_str_t *cert,
>         return NGX_ERROR;
>     }
>
> +    return NGX_OK;
> +}
> +
> +ngx_int_t
> +ngx_ssl_client_certificate(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *cert,
> +    ngx_int_t depth)
> +{
> +    STACK_OF(X509_NAME)  *list;
> +
> +    if (ngx_ssl_set_verify_options(ssl, cert, depth) != NGX_OK) {
> +        return NGX_ERROR;
> +    }
> +
> +    if (ngx_conf_full_name(cf->cycle, cert, 1) != NGX_OK) {
> +        return NGX_ERROR;
> +    }
> +
>     list = SSL_load_client_CA_file((char *) cert->data);
>
>     if (list == NULL) {
> @@ -350,7 +360,7 @@ ngx_http_ssl_verify_callback(int ok,
> X509_STORE_CTX *x509_store)
>     }
>  #endif
>
> -    return 1;
> +    return ok;
>  }
>
>
> @@ -566,7 +576,7 @@ ngx_ssl_set_session(ngx_connection_t *c,
> ngx_ssl_session_t *session)
>  ngx_int_t
>  ngx_ssl_handshake(ngx_connection_t *c)
>  {
> -    int        n, sslerr;
> +    int        n, sslerr, verify_err, verify_mode;
>     ngx_err_t  err;
>
>     ngx_ssl_clear_error(c->log);
> @@ -577,6 +587,22 @@ ngx_ssl_handshake(ngx_connection_t *c)
>
>     if (n == 1) {
>
> +        if (SSL_get_peer_certificate(c->ssl->connection) != NULL)
> +        {
> +            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
> "SSL_get_peer_certificate is present");
> +        }
> +
> +        verify_mode = SSL_get_verify_mode(c->ssl->connection);
> +        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
> "SSL_get_verify_mode: %d", verify_mode);
> +
> +        verify_err = SSL_get_verify_result(c->ssl->connection);
> +        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
> "SSL_get_verify_result: %d", verify_err);
> +        if (verify_err != X509_V_OK)
> +        {
> +            ngx_ssl_error(NGX_LOG_ALERT, c->log, 0,
> "SSL_get_verify_result() failed");
> +            return NGX_ERROR;
> +        }
> +
>         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
>             return NGX_ERROR;
>         }
> @@ -2354,3 +2380,4 @@ ngx_openssl_exit(ngx_cycle_t *cycle)
>     EVP_cleanup();
>     ENGINE_cleanup();
>  }
> +
> diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
> index 33cab7b..0aac3e8 100644
> --- a/src/event/ngx_event_openssl.h
> +++ b/src/event/ngx_event_openssl.h
> @@ -96,6 +96,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_int_t ngx_ssl_set_verify_options(ngx_ssl_t *ssl, ngx_str_t *cert,
> +    ngx_int_t depth);
>  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_crl(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *crl);
> diff --git a/src/http/modules/ngx_http_proxy_module.c
> b/src/http/modules/ngx_http_proxy_module.c
> index 902cfb8..834301e 100644
> --- a/src/http/modules/ngx_http_proxy_module.c
> +++ b/src/http/modules/ngx_http_proxy_module.c
> @@ -440,7 +440,27 @@ static ngx_command_t  ngx_http_proxy_commands[] = {
>       NGX_HTTP_LOC_CONF_OFFSET,
>       offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse),
>       NULL },
> +
> +    { ngx_string("proxy_ssl_verify_peer"),
> +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
> +      ngx_conf_set_flag_slot,
> +      NGX_HTTP_LOC_CONF_OFFSET,
> +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify_peer),
> +      NULL },
> +
> +    { ngx_string("proxy_ssl_verify_depth"),
> +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
> +      ngx_conf_set_num_slot,
> +      NGX_HTTP_LOC_CONF_OFFSET,
> +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify_depth),
> +      NULL },
>
> +    { ngx_string("proxy_ssl_ca_certificate"),
> +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
> +      ngx_conf_set_str_slot,
> +      NGX_HTTP_LOC_CONF_OFFSET,
> +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_ca_certificate),
> +      NULL },
>  #endif
>
>       ngx_null_command
> @@ -1697,6 +1717,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
>     conf->upstream.intercept_errors = NGX_CONF_UNSET;
>  #if (NGX_HTTP_SSL)
>     conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
> +    conf->upstream.ssl_verify_peer = NGX_CONF_UNSET;
> +    conf->upstream.ssl_verify_depth = NGX_CONF_UNSET_UINT;
>  #endif
>
>     /* "proxy_cyclic_temp_file" is disabled */
> @@ -1955,6 +1977,22 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
> void *parent, void *child)
>  #if (NGX_HTTP_SSL)
>     ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
>                               prev->upstream.ssl_session_reuse, 1);
> +    ngx_conf_merge_value(conf->upstream.ssl_verify_peer,
> +                              prev->upstream.ssl_verify_peer, 0);
> +    ngx_conf_merge_uint_value(conf->upstream.ssl_verify_depth,
> +                              prev->upstream.ssl_verify_depth, 1);
> +    ngx_conf_merge_str_value(conf->upstream.ssl_ca_certificate,
> +                              prev->upstream.ssl_ca_certificate, "");
> +
> +    if (conf->upstream.ssl_verify_peer) {
> +      if (conf->upstream.ssl_ca_certificate.len == 0) {
> +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
> +            "no \"proxy_ssl_ca_certificate\" is defined for "
> +            "the \"proxy_ssl_verify_peer\" directive");
> +
> +        return NGX_CONF_ERROR;
> +      }
> +    }
>  #endif
>
>     ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
> diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
> index 29432dc..474cf0d 100644
> --- a/src/http/ngx_http_upstream.c
> +++ b/src/http/ngx_http_upstream.c
> @@ -1210,6 +1210,15 @@
> ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
>  {
>     ngx_int_t   rc;
>
> +    if (ngx_ssl_set_verify_options(u->conf->ssl,
> +          &u->conf->ssl_ca_certificate, u->conf->ssl_verify_depth)
> +        != NGX_OK)
> +    {
> +      ngx_http_upstream_finalize_request(r, u,
> +          NGX_HTTP_INTERNAL_SERVER_ERROR);
> +      return;
> +    }
> +
>     if (ngx_ssl_create_connection(u->conf->ssl, c,
>                                   NGX_SSL_BUFFER|NGX_SSL_CLIENT)
>         != NGX_OK)
> @@ -4527,3 +4536,4 @@ ngx_http_upstream_init_main_conf(ngx_conf_t *cf,
> void *conf)
>
>     return NGX_CONF_OK;
>  }
> +
> diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
> index fa848c0..cc71ba9 100644
> --- a/src/http/ngx_http_upstream.h
> +++ b/src/http/ngx_http_upstream.h
> @@ -177,6 +177,9 @@ typedef struct {
>  #if (NGX_HTTP_SSL)
>     ngx_ssl_t                       *ssl;
>     ngx_flag_t                       ssl_session_reuse;
> +    ngx_flag_t                       ssl_verify_peer;
> +    ngx_uint_t                       ssl_verify_depth;
> +    ngx_str_t                        ssl_ca_certificate;
>  #endif
>
>     ngx_str_t                        module;
>
> On Tue, Sep 13, 2011 at 5:17 PM, Maxim Dounin <mdounin at mdounin.ru> wrote:
>> Hello!
>>
>> On Tue, Sep 13, 2011 at 02:44:48PM -0700, W. Andrew Loe III wrote:
>>
>>> This patch allows you to force OpenSSL to validate the certificate of
>>> the server the http_proxy module is communicating with. Originally
>>> built against 0.7.x branch, I will forward port when I can. I would
>>> appreciate if anyone else has input on how to do this more elegantly,
>>> my skills are rudimentary at best.
>>>
>>>
>>> diff -uNr ../nginx-0.7.67/src/event/ngx_event_openssl.c
>>> src/event/ngx_event_openssl.c
>>> --- ../nginx-0.7.67/src/event/ngx_event_openssl.c     2010-06-07
>>> 04:55:20.000000000 -0700
>>> +++ src/event/ngx_event_openssl.c     2011-09-13 14:17:05.000000000 -0700
>>> @@ -157,6 +157,12 @@
>>>      SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_CHALLENGE_BUG);
>>>      SSL_CTX_set_options(ssl->ctx, SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
>>>
>>> +    /* verification options */
>>> +
>>> +    SSL_CTX_load_verify_locations(ssl->ctx, (const char
>>> *)ssl->ca_certificate.data, NULL);
>>> +    SSL_CTX_set_verify(ssl->ctx, ssl->verify, NULL);
>>> +    SSL_CTX_set_verify_depth(ssl->ctx, ssl->verify_depth);
>>> +
>>
>> This should be done in separate function, similar to
>> ngx_ssl_client_certificate() (actually, subset of it).  And with
>> appropriate error checking.
>>
>>>      /* server side options */
>>>
>>>      SSL_CTX_set_options(ssl->ctx, SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
>>> diff -uNr ../nginx-0.7.67/src/event/ngx_event_openssl.h
>>> src/event/ngx_event_openssl.h
>>> --- ../nginx-0.7.67/src/event/ngx_event_openssl.h     2010-06-07
>>> 03:09:14.000000000 -0700
>>> +++ src/event/ngx_event_openssl.h     2011-09-13 14:17:05.000000000 -0700
>>> @@ -27,6 +27,9 @@
>>>  typedef struct {
>>>      SSL_CTX                    *ctx;
>>>      ngx_log_t                  *log;
>>> +    ngx_uint_t                  verify;
>>> +    ngx_uint_t                  verify_depth;
>>> +    ngx_str_t                   ca_certificate;
>>>  } ngx_ssl_t;
>>
>> This shouldn't be here at all.
>>
>>>
>>>
>>> diff -uNr ../nginx-0.7.67/src/http/modules/ngx_http_proxy_module.c
>>> src/http/modules/ngx_http_proxy_module.c
>>> --- ../nginx-0.7.67/src/http/modules/ngx_http_proxy_module.c  2010-06-07
>>> 05:23:23.000000000 -0700
>>> +++ src/http/modules/ngx_http_proxy_module.c  2011-09-13 14:17:05.000000000 -0700
>>> @@ -466,6 +466,27 @@
>>>        offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse),
>>>        NULL },
>>>
>>> +      { ngx_string("proxy_ssl_verify"),
>>> +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
>>> +      ngx_conf_set_num_slot,
>>> +      NGX_HTTP_LOC_CONF_OFFSET,
>>> +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify),
>>> +      NULL },
>>
>> You don't want to let users to control binary arguments passed to
>> openssl.
>>
>> It should be either on/off switch (flag slot), or should go away
>> completely, switched on by certificate file presense.
>>
>> If it stays, it probably should be named as
>> "proxy_ssl_verify_peer" to be in line with "ssl_verify_client"
>> directive (and see below).
>>
>>> +
>>> +      { ngx_string("proxy_ssl_verify_depth"),
>>> +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
>>> +      ngx_conf_set_num_slot,
>>> +      NGX_HTTP_LOC_CONF_OFFSET,
>>> +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify_depth),
>>> +      NULL },
>>> +
>>> +      { ngx_string("proxy_ssl_ca_certificate"),
>>
>> Probably "proxy_ssl_peer_certificate" would be a better directive
>> name.  Not sure.
>>
>>> +      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
>>> +      ngx_conf_set_str_slot,
>>> +      NGX_HTTP_LOC_CONF_OFFSET,
>>> +      offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_ca_certificate),
>>> +      NULL },
>>> +
>>>  #endif
>>>
>>>        ngx_null_command
>>> @@ -1950,6 +1971,8 @@
>>>      conf->upstream.intercept_errors = NGX_CONF_UNSET;
>>>  #if (NGX_HTTP_SSL)
>>>      conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
>>> +    conf->upstream.ssl_verify = NGX_CONF_UNSET_UINT;
>>> +    conf->upstream.ssl_verify_depth = NGX_CONF_UNSET_UINT;
>>>  #endif
>>>
>>>      /* "proxy_cyclic_temp_file" is disabled */
>>> @@ -2196,6 +2219,22 @@
>>>  #if (NGX_HTTP_SSL)
>>>      ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
>>>                                prev->upstream.ssl_session_reuse, 1);
>>> +    ngx_conf_merge_uint_value(conf->upstream.ssl_verify,
>>> +                              prev->upstream.ssl_verify, 0);
>>> +    ngx_conf_merge_uint_value(conf->upstream.ssl_verify_depth,
>>> +                              prev->upstream.ssl_verify_depth, 1);
>>> +    ngx_conf_merge_str_value(conf->upstream.ssl_ca_certificate,
>>> +                              prev->upstream.ssl_ca_certificate, "");
>>> +
>>> +    if (conf->upstream.ssl_verify) {
>>> +      if (conf->upstream.ssl_ca_certificate.len == 0) {
>>> +        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
>>> +            "no \"proxy_ssl_ca_certificate\" is defined for "
>>> +            "the \"proxy_ssl_verify\" directive");
>>> +
>>> +        return NGX_CONF_ERROR;
>>> +      }
>>
>> No 2-space indentation, please.
>>
>>> +    }
>>>  #endif
>>>
>>>      ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
>>> @@ -3011,6 +3050,12 @@
>>>
>>>      plcf->upstream.ssl->log = cf->log;
>>>
>>> +    plcf->upstream.ssl->ca_certificate.len =
>>> plcf->upstream.ssl_ca_certificate.len;
>>> +    plcf->upstream.ssl->ca_certificate.data =
>>> plcf->upstream.ssl_ca_certificate.data;
>>> +
>>> +    plcf->upstream.ssl->verify = plcf->upstream.ssl_verify;
>>> +    plcf->upstream.ssl->verify_depth = plcf->upstream.ssl_verify_depth;
>>> +
>>>      if (ngx_ssl_create(plcf->upstream.ssl,
>>>                         NGX_SSL_SSLv2|NGX_SSL_SSLv3|NGX_SSL_TLSv1, NULL)
>>>          != NGX_OK)
>>> diff -uNr ../nginx-0.7.67/src/http/ngx_http_upstream.h
>>> src/http/ngx_http_upstream.h
>>> --- ../nginx-0.7.67/src/http/ngx_http_upstream.h      2010-06-07
>>> 05:23:23.000000000 -0700
>>> +++ src/http/ngx_http_upstream.h      2011-09-13 14:17:05.000000000 -0700
>>> @@ -173,6 +173,9 @@
>>>  #if (NGX_HTTP_SSL)
>>>      ngx_ssl_t                       *ssl;
>>>      ngx_flag_t                       ssl_session_reuse;
>>> +    ngx_uint_t                       ssl_verify;
>>> +    ngx_uint_t                       ssl_verify_depth;
>>> +    ngx_str_t                        ssl_ca_certificate;
>>>  #endif
>>>
>>>  } ngx_http_upstream_conf_t;
>>
>> You may also want to add "proxy_ssl_crl" directive (trivial), as
>> well as some form of remote CN checking.
>>
>> Please also note that posting patches against 0.7.* (as well as
>> 0.8.*), isn't meaningful.  Development branch is 1.1.*.
>>
>> Maxim Dounin
>>
>> _______________________________________________
>> nginx-devel mailing list
>> nginx-devel at nginx.org
>> http://mailman.nginx.org/mailman/listinfo/nginx-devel
>>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: proxy_ssl_verify-1.1.3.patch
Type: application/octet-stream
Size: 8015 bytes
Desc: not available
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20110915/b4f29320/attachment-0001.obj>


More information about the nginx-devel mailing list