Skip to content

Commit 1793b3b

Browse files
authored
bugfix: improve HTTP/3 SSL Lua callback yield handling.
1 parent 4e40c13 commit 1793b3b

File tree

8 files changed

+1371
-22
lines changed

8 files changed

+1371
-22
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ script:
137137
- cd lua-cjson/ && make -j$JOBS && sudo make install && cd ..
138138
#- if [ -n "$PCRE2_VER" ]; then tar zxf download-cache/pcre2-$PCRE2_VER.tar.gz; cd pcre2-$PCRE2_VER/; ./configure --prefix=$PCRE2_PREFIX --enable-jit --enable-utf > build.log 2>&1 || (cat build.log && exit 1); make -j$JOBS > build.log 2>&1 || (cat build.log && exit 1); sudo PATH=$PATH make install > build.log 2>&1 || (cat build.log && exit 1); cd ..; fi
139139
#- if [ -n "$OPENSSL_VER" ]; then tar zxf download-cache/openssl-$OPENSSL_VER.tar.gz; cd openssl-$OPENSSL_VER/; patch -p1 < ../../openresty/patches/openssl-$OPENSSL_PATCH_VER-sess_set_get_cb_yield.patch; ./config shared enable-ssl3 enable-ssl3-method -g --prefix=$OPENSSL_PREFIX --libdir=lib -DPURIFY > build.log 2>&1 || (cat build.log && exit 1); make -j$JOBS > build.log 2>&1 || (cat build.log && exit 1); sudo make PATH=$PATH install_sw > build.log 2>&1 || (cat build.log && exit 1); cd ..; fi
140-
- if [ -n "$BORINGSSL" ]; then sudo rm -fr /usr/local/openresty/openssl3/ && sudo tar -C /usr/local/openresty/openssl3 -xf boringssl-20230902-x64-focal.tar.gz --strip-components=1; fi
140+
- if [ -n "$BORINGSSL" ]; then sudo rm -fr /usr/local/openresty/openssl3/ && sudo mkdir -p /usr/local/openresty/openssl3 && sudo tar -C /usr/local/openresty/openssl3 -xf boringssl-20230902-x64-focal.tar.gz --strip-components=1; fi
141141
- export NGX_BUILD_CC=$CC
142142
- sh util/build-without-ssl.sh $NGINX_VERSION > build.log 2>&1 || (cat build.log && exit 1)
143143
- sh util/build-with-dd.sh $NGINX_VERSION > build.log 2>&1 || (cat build.log && exit 1)

src/ngx_http_lua_ssl_certby.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,6 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data)
346346

347347
return -1;
348348

349-
#if 1
350349
failed:
351350

352351
if (r && r->pool) {
@@ -358,15 +357,14 @@ ngx_http_lua_ssl_cert_handler(ngx_ssl_conn_t *ssl_conn, void *data)
358357
}
359358

360359
return 0;
361-
#endif
362360
}
363361

364362

365363
static void
366364
ngx_http_lua_ssl_cert_done(void *data)
367365
{
368-
ngx_connection_t *c;
369-
ngx_http_lua_ssl_ctx_t *cctx = data;
366+
ngx_connection_t *c;
367+
ngx_http_lua_ssl_ctx_t *cctx = data;
370368

371369
dd("lua ssl cert done");
372370

@@ -387,6 +385,12 @@ ngx_http_lua_ssl_cert_done(void *data)
387385
c->log->action = "SSL handshaking";
388386

389387
ngx_post_event(c->write, &ngx_posted_events);
388+
389+
#if (NGX_HTTP_V3) && OPENSSL_VERSION_NUMBER >= 0x1000205fL
390+
# if (NGX_QUIC_OPENSSL_COMPAT)
391+
ngx_http_lua_resume_quic_ssl_handshake(c);
392+
# endif
393+
#endif
390394
}
391395

392396

src/ngx_http_lua_ssl_client_helloby.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,6 @@ ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
341341

342342
return -1;
343343

344-
#if 1
345344
failed:
346345

347346
if (r && r->pool) {
@@ -353,15 +352,14 @@ ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
353352
}
354353

355354
return 0;
356-
#endif
357355
}
358356

359357

360358
static void
361359
ngx_http_lua_ssl_client_hello_done(void *data)
362360
{
363-
ngx_connection_t *c;
364-
ngx_http_lua_ssl_ctx_t *cctx = data;
361+
ngx_connection_t *c;
362+
ngx_http_lua_ssl_ctx_t *cctx = data;
365363

366364
dd("lua ssl client hello done");
367365

@@ -382,6 +380,12 @@ ngx_http_lua_ssl_client_hello_done(void *data)
382380
c->log->action = "SSL handshaking";
383381

384382
ngx_post_event(c->write, &ngx_posted_events);
383+
384+
#if (NGX_HTTP_V3) && defined(SSL_ERROR_WANT_CLIENT_HELLO_CB)
385+
# if (NGX_QUIC_OPENSSL_COMPAT)
386+
ngx_http_lua_resume_quic_ssl_handshake(c);
387+
# endif
388+
#endif
385389
}
386390

387391

@@ -666,6 +670,7 @@ int
666670
ngx_http_lua_ffi_ssl_get_client_hello_ext_present(ngx_http_request_t *r,
667671
int **extensions, size_t *extensions_len, char **err)
668672
{
673+
#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
669674
ngx_ssl_conn_t *ssl_conn;
670675
int got_extensions;
671676
size_t ext_len;
@@ -684,7 +689,6 @@ ngx_http_lua_ffi_ssl_get_client_hello_ext_present(ngx_http_request_t *r,
684689
return NGX_ERROR;
685690
}
686691

687-
#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
688692
got_extensions = SSL_client_hello_get1_extensions_present(ssl_conn,
689693
&ext_out, &ext_len);
690694
if (!got_extensions || !ext_out || !ext_len) {
@@ -710,6 +714,7 @@ ngx_http_lua_ffi_ssl_get_client_hello_ext_present(ngx_http_request_t *r,
710714
int ngx_http_lua_ffi_ssl_get_client_hello_ciphers(ngx_http_request_t *r,
711715
unsigned short *ciphers, size_t ciphers_size, char **err)
712716
{
717+
#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
713718
int i;
714719
size_t ciphers_cnt;
715720
size_t ciphersuites_bytes;
@@ -727,8 +732,6 @@ int ngx_http_lua_ffi_ssl_get_client_hello_ciphers(ngx_http_request_t *r,
727732
return NGX_ERROR;
728733
}
729734

730-
731-
#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
732735
ciphersuites_bytes = SSL_client_hello_get0_ciphers(ssl_conn, &ciphers_raw);
733736

734737
if (ciphersuites_bytes == 0) {

src/ngx_http_lua_util.c

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949
#if (NGX_THREADS)
5050
#include "ngx_http_lua_worker_thread.h"
5151
#endif
52+
#if (NGX_HTTP_V3)
53+
#include <ngx_event_quic.h>
54+
#include <ngx_event_quic_connection.h>
55+
#endif
5256

5357

5458
#if 1
@@ -3826,6 +3830,18 @@ ngx_http_lua_close_fake_connection(ngx_connection_t *c)
38263830
c->read->closed = 1;
38273831
c->write->closed = 1;
38283832

3833+
/* When destroying the pool, the registered clean callbacks will be
3834+
* executed. If the ngx_connection_t is freed before these callbacks are
3835+
* run, and a new ngx_connection_t is created within a clean callback,
3836+
* it is possible for the freed ngx_connection_t to be reused again.
3837+
* If this reused ngx_connection_t is destroyed again within the clean
3838+
* callback logic, it may result in other clean callbacks holding a
3839+
* ngx_connection_t that has already been destroyed.
3840+
*/
3841+
if (pool) {
3842+
ngx_destroy_pool(pool);
3843+
}
3844+
38293845
/* we temporarily use a valid fd (0) to make ngx_free_connection happy */
38303846

38313847
c->fd = 0;
@@ -3841,10 +3857,6 @@ ngx_http_lua_close_fake_connection(ngx_connection_t *c)
38413857
if (ngx_cycle->files) {
38423858
ngx_cycle->files[0] = saved_c;
38433859
}
3844-
3845-
if (pool) {
3846-
ngx_destroy_pool(pool);
3847-
}
38483860
}
38493861

38503862

@@ -4561,4 +4573,63 @@ ngx_http_lua_ffi_bypass_if_checks(ngx_http_request_t *r)
45614573
r->disable_not_modified = 1;
45624574
}
45634575

4576+
4577+
#if (NGX_HTTP_V3)
4578+
void
4579+
ngx_http_lua_resume_quic_ssl_handshake(ngx_connection_t *c)
4580+
{
4581+
ngx_int_t rc, sslerr;
4582+
ngx_ssl_conn_t *ssl_conn;
4583+
4584+
if (c == NULL || c->ssl == NULL || c->ssl->connection == NULL) {
4585+
return;
4586+
}
4587+
4588+
if (!c->udp || c->read == NULL
4589+
|| c->read->handler != ngx_quic_input_handler)
4590+
{
4591+
return;
4592+
}
4593+
4594+
ssl_conn = c->ssl->connection;
4595+
4596+
/* Openresty ssl lua scripts are triggered by registering callbacks into
4597+
* openssl. If a lua script calls a yield api during execution, openssl's
4598+
* SSL_do_handshake will return a specific error code. The application
4599+
* should not treat these codes as fatal. The lua script will resume on
4600+
* yield-related events until it finishes. After completion,
4601+
* SSL_do_handshake should be called again to advance openssl's state
4602+
* machine.
4603+
*
4604+
* Note that nginx quic and openresty ssl lua scripts are independent. When
4605+
* openresty ssl lua runs, the client is waiting for a server response, so
4606+
* nginx quic does not affect the execution of the lua script. After the lua
4607+
* script finishes, SSL_do_handshake is called again, and nginx quic's
4608+
* registered callback continues the handshake.
4609+
*/
4610+
rc = SSL_do_handshake(ssl_conn);
4611+
sslerr = SSL_get_error(ssl_conn, rc);
4612+
4613+
if (rc <= 0 && sslerr != SSL_ERROR_WANT_READ
4614+
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
4615+
&& sslerr != SSL_ERROR_WANT_X509_LOOKUP
4616+
#endif
4617+
#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
4618+
&& sslerr != SSL_ERROR_WANT_CLIENT_HELLO_CB
4619+
#endif
4620+
) {
4621+
/* If a fatal error occurs or lua script exits with error during quic
4622+
* handshake, the quic connection will be closed immediately.
4623+
*/
4624+
ngx_quic_close_connection(c, NGX_ERROR);
4625+
4626+
} else {
4627+
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
4628+
"lua resuming quic ssl handshake: rc %d, err %d, will "
4629+
"continue driving handshake or next lua script phase",
4630+
rc, sslerr);
4631+
}
4632+
}
4633+
#endif
4634+
45644635
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

src/ngx_http_lua_util.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,10 @@ ngx_addr_t *ngx_http_lua_parse_addr(lua_State *L, u_char *text, size_t len);
267267

268268
size_t ngx_http_lua_escape_log(u_char *dst, u_char *src, size_t size);
269269

270+
#if (NGX_HTTP_V3)
271+
void ngx_http_lua_resume_quic_ssl_handshake(ngx_connection_t *c);
272+
#endif
273+
270274

271275
static ngx_inline void
272276
ngx_http_lua_init_ctx(ngx_http_request_t *r, ngx_http_lua_ctx_t *ctx)

0 commit comments

Comments
 (0)