[PATCH] (re-post) Add "optional_no_ca" option to ssl_verify_client to enable app-only CA chain validation
Mike Kazantsev
mk.fraggod at gmail.com
Sat Sep 22 11:09:53 UTC 2012
Apologies for a bit late answer, managed to miss (or forgot to check
option for) thread update notification from a forum, my bad.
On Tue, 18 Sep 2012 11:43:55 +0400
Maxim Dounin <mdounin-ux0u7sevaKovJsYlp49lxw at public.gmane.org> wrote:
> Hello!
>
> On Sat, Sep 15, 2012 at 07:52:30AM -0400, mk.fg wrote:
>
> > Re-post of patch from
> > http://forum.nginx.org/read.php?2,228761,229586#msg-229586
...
>
> You may want to join discussion here, about the similar patch
> submitted:
>
> http://mailman.nginx.org/pipermail/nginx-devel/2012-August/002643.html
>
I hope you don't mind if I'll continue it in this thread, adding Cc to
Eric.
After my latest failure to get forum notification, and because I've
managed to find a gmane archive for this list (don't think I've seen it
there in the not-so-distant past), I'd prefer to use email, but alas,
indicated thread was rotated-out from even latest-300 on gmane, so I
can't easily find original message to reply to.
> In particular, I would like someone to actually test if the
> error_page 495 aproach works instead as suggested here:
>
> http://mailman.nginx.org/pipermail/nginx-devel/2012-August/002650.html
>
It doesn't seem to be of much use in current state, problems:
- Requires "ssl_client_certificate" to be set to some valid
certificate, which then shouldn't actually never be used in this
case.
- In case of "ssl_verify_client" set to "on" or "optional", setting
"error_page 400 495 496 =200 /altpath;" doesn't seem to stop nginx
from returning "HTTP/1.1 400 Bad Request" response with "400 The SSL
certificate error" in html body.
This code in ngx_http_request.c is probable cause of that:
if (sscf->verify) {
rc = SSL_get_verify_result(c->ssl->connection);
if (rc != X509_V_OK) {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client SSL certificate verify error: (%l:%s)",
rc, X509_verify_cert_error_string(rc));
ngx_ssl_remove_cached_session(sscf->ssl.ctx,
(SSL_get0_session(c->ssl->connection)));
ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
return;
}
I'm still unsure if it's a general bug in ssl module or some error
in my configuration above, because docs clearly state that error
should be handled by error_page and it doesn't seem to be.
- "ssl_verify_client off;" isn't much useful, because it doesn't return
clent certificate and doesn't check it in any way.
- "ssl_verify_client on;", still gives all-or-nothing check, though
I see that it's what might indeed be desirable, as Eric indicated.
- I think it's really non-obvious way to do it.
> And a quick comment for your patch: I tend to think that
> introduction of ngx_http_ssl_variable_get_client_verify() is
> misleading. We shouldn't try to claim the certificate was
> verified unless it actually was.
It might be misleading, indeed, I see your point.
Attached patch doesn't try to alter ssl_client_verify result.
On a completely unrelated note - nginx fails to build from svn here due
to 'Exception in thread "main" java.lang.NoClassDefFoundError:
com/pault/StyleSheet' (so I just disabled building changelog for tests).
URL for the revised patch: https://gist.github.com/3319062
Inline patch follows.
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index cd6d885..97da051 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -141,6 +141,14 @@ ngx_int_t ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
+#define ngx_ssl_verify_error_is_optional(errnum) \
+ ((errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) \
+ || (errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) \
+ || (errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) \
+ || (errnum == X509_V_ERR_CERT_UNTRUSTED) \
+ || (errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE))
+
+
ngx_int_t ngx_ssl_handshake(ngx_connection_t *c);
ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size);
ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size);
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index d759489..ab91670 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -48,6 +48,7 @@ static ngx_conf_enum_t ngx_http_ssl_verify[] = {
{ ngx_string("off"), 0 },
{ ngx_string("on"), 1 },
{ ngx_string("optional"), 2 },
+ { ngx_string("optional_no_ca"), 3 },
{ ngx_null_string, 0 }
};
@@ -466,7 +467,7 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->verify) {
- if (conf->client_certificate.len == 0) {
+ if (conf->verify != 3 && conf->client_certificate.len == 0) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no ssl_client_certificate for ssl_client_verify");
return NGX_CONF_ERROR;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index cb970c5..96cec55 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1642,7 +1642,9 @@ ngx_http_process_request(ngx_http_request_t *r)
if (sscf->verify) {
rc = SSL_get_verify_result(c->ssl->connection);
- if (rc != X509_V_OK) {
+ if ((sscf->verify != 3 && rc != X509_V_OK)
+ || !(sscf->verify == 3 && ngx_ssl_verify_error_is_optional(rc)))
+ {
ngx_log_error(NGX_LOG_INFO, c->log, 0,
"client SSL certificate verify error: (%l:%s)",
rc, X509_verify_cert_error_string(rc));
--
1.7.12
--
Mike Kazantsev // fraggod.net
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20120922/999285f6/attachment.bin>
More information about the nginx-devel
mailing list