Proposed changeset to fix client cert from ngx_ssl_get_certificate passed as HTTP header value
Maxim Dounin
mdounin at mdounin.ru
Sat Feb 13 05:29:05 UTC 2016
Hello!
On Wed, Feb 10, 2016 at 02:38:43PM -0800, Sam McKelvie wrote:
> OK, sorry for the delay.
>
> Here is a changeset that implements $ssl_client_escaped_certificate,
> following your latest comments. It works well with node/express. OK
> with this?
See review below.
>
> ~Sam
>
>
> # HG changeset patch
> # User Sam McKelvie <sam at surround.io>
> # Date 1455143619 28800
> # Wed Feb 10 14:33:39 2016 -0800
> # Node ID f3f2dbd8340f04adccd805ff5a8547e10e6fa874
> # Parent e0d7c2f718515d4c48e5ed2a0643294da60cf2ba
> Define a new $ssl_client_escaped_certificate variable that is the
> URL-encoded form of the raw PEM client certificate. This variable
> is always appropriate for inclusion in proxy_set_header values,
> unlike the $ssl_client_cert variable, which includes '\n'
> characters that are not prefixed by '\r', breaking some http
> servers (e.g., node/express).
>
> Per Maxim, $ssl_client_cert should eventually be deprecated. Users
> of $ssl_client_cert should move to ssl_client_scaped_certificate.
>
> Tested with node/express and nginx-tests.
This should be rewritten to contain less typos and better match
recommended format, see some hints here:
http://nginx.org/en/docs/contributing_changes.html
Additionally, instead of focusing on badly-written servers which
don't handle "\n" you may want to focus on header folding being
deprecated in general.
>
> diff -r e0d7c2f71851 -r f3f2dbd8340f src/event/ngx_event_openssl.c
> --- a/src/event/ngx_event_openssl.c Fri Feb 05 14:02:54 2016 +0300
> +++ b/src/event/ngx_event_openssl.c Wed Feb 10 14:33:39 2016 -0800
> @@ -3273,6 +3273,42 @@
>
>
> ngx_int_t
> +ngx_ssl_get_escaped_certificate(ngx_connection_t *c, ngx_pool_t *pool,
> + ngx_str_t *s)
Style: function definition/declaration arguments are wrapped with
4-space indent.
> +{
> + size_t len;
> + ngx_str_t cert;
> + uintptr_t escape;
> +
> + s->data = NULL;
> + s->len = 0;
These initializations look unneeded.
Both s->data and s->len are always set if NGX_OK is returned.
> +
> + if (ngx_ssl_get_raw_certificate(c, pool, &cert) != NGX_OK) {
> + return NGX_ERROR;
> + }
> +
You may want to add (cert.len == 0) special case here, much like
in ngx_ssl_get_certificate().
> + escape = ngx_escape_uri(NULL, cert.data, cert.len,
> + NGX_ESCAPE_URI_COMPONENT);
> +
> + /* Each escaped character adds 2 characters to result */
> + len = cert.len + 2 * escape;
Just using
escape = 2 * ngx_escape_uri(...);
or even
len = cert.len + 2 * ngx_escape_uri(...);
as in other places is much better idea than adding an obvious
comment.
> +
> + s->data = ngx_pnalloc(pool, len);
> + if (s->data == NULL) {
> + ngx_pfree(pool, cert.data);
There is no need to free small/non-recurring allocations from
pool. Especially when returning errors - as this usually means
that nginx will just terminate the request and will free the pool.
> + return NGX_ERROR;
> + }
> + s->len = len;
Something like:
s->len = len;
s->data = ngx_pnalloc(pool, len);
if (s->data == NULL) {
return NGX_ERROR;
}
as in ngx_ssl_get_certificate() should be a bit more readable.
> +
> + ngx_escape_uri(s->data, cert.data, cert.len, NGX_ESCAPE_URI_COMPONENT);
> +
> + ngx_pfree(pool, cert.data);
There is no need to free small/non-recurring allocations from
pool.
> +
> + return NGX_OK;
> +}
> +
> +
> +ngx_int_t
> ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
> {
> char *p;
> diff -r e0d7c2f71851 -r f3f2dbd8340f src/event/ngx_event_openssl.h
> --- a/src/event/ngx_event_openssl.h Fri Feb 05 14:02:54 2016 +0300
> +++ b/src/event/ngx_event_openssl.h Wed Feb 10 14:33:39 2016 -0800
> @@ -180,6 +180,8 @@
> ngx_str_t *s);
> ngx_int_t ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool,
> ngx_str_t *s);
> +ngx_int_t ngx_ssl_get_escaped_certificate(ngx_connection_t *c,
> ngx_pool_t *pool,
> + ngx_str_t *s);
The patch seems to be currupted by your mail client here.
> ngx_int_t ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool,
> ngx_str_t *s);
> ngx_int_t ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool,
> diff -r e0d7c2f71851 -r f3f2dbd8340f src/http/modules/ngx_http_ssl_module.c
> --- a/src/http/modules/ngx_http_ssl_module.c Fri Feb 05 14:02:54 2016 +0300
> +++ b/src/http/modules/ngx_http_ssl_module.c Wed Feb 10 14:33:39 2016 -0800
> @@ -292,6 +292,9 @@
> (uintptr_t) ngx_ssl_get_raw_certificate,
> NGX_HTTP_VAR_CHANGEABLE, 0 },
>
> + { ngx_string("ssl_client_escaped_cert"), NULL, ngx_http_ssl_variable,
> + (uintptr_t) ngx_ssl_get_escaped_certificate,
> NGX_HTTP_VAR_CHANGEABLE, 0 },
> +
And here.
> { ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_variable,
> (uintptr_t) ngx_ssl_get_subject_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
>
[...]
--
Maxim Dounin
http://nginx.org/
More information about the nginx-devel
mailing list