[PATCH] QUIC: OpenSSL compatibility layer
Roman Arutyunyan
arut at nginx.com
Thu Mar 23 13:53:57 UTC 2023
Hi,
On Thu, Mar 23, 2023 at 05:18:00PM +0400, Sergey Kandaurov wrote:
> On Wed, Feb 08, 2023 at 06:41:38PM +0400, Roman Arutyunyan wrote:
> > # HG changeset patch
> > # User Roman Arutyunyan <arut at nginx.com>
> > # Date 1675867049 -14400
> > # Wed Feb 08 18:37:29 2023 +0400
> > # Branch quic
> > # Node ID a3142c8833f5bf1186599e7938141f5062fac4a2
> > # Parent 3c33d39a51d334d99fcc7d2b45e8d8190c431492
> > QUIC: OpenSSL compatibility layer.
> >
> > The change allows to compile QUIC with OpenSSL which lacks BoringSSL QUIC API.
> >
> > This implementation does not support 0-RTT.
>
> [..]
>
> > diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
> > --- a/src/http/modules/ngx_http_ssl_module.c
> > +++ b/src/http/modules/ngx_http_ssl_module.c
> > @@ -9,6 +9,10 @@
> > #include <ngx_core.h>
> > #include <ngx_http.h>
> >
> > +#if (NGX_QUIC_OPENSSL_COMPAT)
> > +#include <ngx_event_quic_openssl_compat.h>
> > +#endif
> > +
> >
> > typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
> > ngx_pool_t *pool, ngx_str_t *s);
> > @@ -1317,16 +1321,22 @@ ngx_http_ssl_init(ngx_conf_t *cf)
> > continue;
> > }
> >
> > + cscf = addr[a].default_server;
> > + sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
> > +
> > if (addr[a].opt.http3) {
> > name = "http3";
> >
> > +#if (NGX_QUIC_OPENSSL_COMPAT)
> > + if (ngx_quic_compat_init(cf, sscf->ssl.ctx) != NGX_OK) {
> > + return NGX_ERROR;
> > + }
> > +#endif
> > +
> > } else {
> > name = "ssl";
> > }
> >
> > - cscf = addr[a].default_server;
> > - sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
> > -
> > if (sscf->certificates) {
> >
> > if (addr[a].opt.http3 && !(sscf->protocols & NGX_SSL_TLSv1_3)) {
> > diff --git a/src/stream/ngx_stream_ssl_module.c b/src/stream/ngx_stream_ssl_module.c
> > --- a/src/stream/ngx_stream_ssl_module.c
> > +++ b/src/stream/ngx_stream_ssl_module.c
> > @@ -9,6 +9,10 @@
> > #include <ngx_core.h>
> > #include <ngx_stream.h>
> >
> > +#if (NGX_QUIC_OPENSSL_COMPAT)
> > +#include <ngx_event_quic_openssl_compat.h>
> > +#endif
> > +
> >
> > typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
> > ngx_pool_t *pool, ngx_str_t *s);
> > @@ -1218,6 +1222,12 @@ ngx_stream_ssl_init(ngx_conf_t *cf)
> >
> > scf = listen[i].ctx->srv_conf[ngx_stream_ssl_module.ctx_index];
> >
> > +#if (NGX_QUIC_OPENSSL_COMPAT)
> > + if (ngx_quic_compat_init(cf, scf->ssl.ctx) != NGX_OK) {
> > + return NGX_ERROR;
> > + }
> > +#endif
> > +
> > if (scf->certificates && !(scf->protocols & NGX_SSL_TLSv1_3)) {
> > ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
> > "\"ssl_protocols\" must enable TLSv1.3 for "
>
> Following internal discussion with Roman, below is a fix for compat
> layer initialization. This is a fallout after moving initialization
> from ngx_ssl_create(). Although that change was justified, it has
> left a couple of issues:
> - SSL context can be NULL (normally caught later in function)
> - only the default server was initialized, breaks with SNI.
> The latter was caught by h3_ssl_reject_handshake.t
>
> The fix is to initialize all servers that have SSL context.
> The postconfiguration function is quite large, so this is moved
> to the separate function. While here, moved back assignments
> closer to the place of their use.
>
> # HG changeset patch
> # User Sergey Kandaurov <pluknet at nginx.com>
> # Date 1679577205 -14400
> # Thu Mar 23 17:13:25 2023 +0400
> # Branch quic
> # Node ID dcef88bdea77cf84b97580f21fbe05cc05ab631d
> # Parent f4279edda9fdbbd836a86926d86cdc727492e94c
> HTTP/3: fixed OpenSSL compatibility layer initialization.
>
> SSL context is not present if the default server has neither certificates nor
> ssl_reject_handshake enabled. Previously, this led to null pointer dereference
> before it would be caught with configuration checks.
>
> Additionally, virtual servers with distinct SSL contexts need to initialize
> compatibility layer in order to complete a QUIC handshake.
>
> diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
> --- a/src/http/modules/ngx_http_ssl_module.c
> +++ b/src/http/modules/ngx_http_ssl_module.c
> @@ -56,6 +56,10 @@ static char *ngx_http_ssl_conf_command_c
> void *data);
>
> static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
> +#if (NGX_QUIC_OPENSSL_COMPAT)
> +static ngx_int_t ngx_http_ssl_quic_compat_init(ngx_conf_t *cf,
> + ngx_http_conf_addr_t *addr);
> +#endif
>
>
> static ngx_conf_bitmask_t ngx_http_ssl_protocols[] = {
> @@ -1328,14 +1332,11 @@ ngx_http_ssl_init(ngx_conf_t *cf)
> continue;
> }
>
> - cscf = addr[a].default_server;
> - sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
> -
> if (addr[a].opt.quic) {
> name = "quic";
>
> #if (NGX_QUIC_OPENSSL_COMPAT)
> - if (ngx_quic_compat_init(cf, sscf->ssl.ctx) != NGX_OK) {
> + if (ngx_http_ssl_quic_compat_init(cf, &addr[a]) != NGX_OK) {
> return NGX_ERROR;
> }
> #endif
> @@ -1344,6 +1345,9 @@ ngx_http_ssl_init(ngx_conf_t *cf)
> name = "ssl";
> }
>
> + cscf = addr[a].default_server;
> + sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
> +
> if (sscf->certificates) {
>
> if (addr[a].opt.quic && !(sscf->protocols & NGX_SSL_TLSv1_3)) {
> @@ -1391,3 +1395,27 @@ ngx_http_ssl_init(ngx_conf_t *cf)
>
> return NGX_OK;
> }
> +
> +
> +static ngx_int_t
> +ngx_http_ssl_quic_compat_init(ngx_conf_t *cf, ngx_http_conf_addr_t *addr)
> +{
> + ngx_uint_t s;
> + ngx_http_ssl_srv_conf_t *sscf;
> + ngx_http_core_srv_conf_t **cscfp, *cscf;
> +
> + cscfp = addr->servers.elts;
> + for (s = 0; s < addr->servers.nelts; s++) {
> +
> + cscf = cscfp[s];
> + sscf = cscf->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
> +
> + if (sscf->certificates || sscf->reject_handshake) {
> + if (ngx_quic_compat_init(cf, sscf->ssl.ctx) != NGX_OK) {
> + return NGX_ERROR;
> + }
> + }
> + }
> +
> + return NGX_OK;
> +}
Looks good
More information about the nginx-devel
mailing list