Skip to content

Commit 391639b

Browse files
committed
feature: lua-nginx-module built with boringssl supports client_hello_by_lua
1 parent 3a0b823 commit 391639b

6 files changed

+153
-29
lines changed

src/ngx_http_lua_module.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1249,8 +1249,13 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
12491249
ngx_http_lua_ssl_client_hello_handler,
12501250
NULL);
12511251

1252-
#else
1252+
#elif defined(OPENSSL_IS_BORINGSSL)
1253+
1254+
SSL_CTX_set_select_certificate_cb(sscf->ssl.ctx,
1255+
ngx_http_lua_ssl_client_hello_handler);
12531256

1257+
1258+
#else
12541259
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
12551260
"OpenSSL too old to support "
12561261
"ssl_client_hello_by_lua*");

src/ngx_http_lua_ssl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ typedef struct {
3232
request ctx data in lua
3333
registry */
3434

35+
#ifdef OPENSSL_IS_BORINGSSL
36+
const SSL_CLIENT_HELLO *client_hello;
37+
#endif
38+
3539
unsigned done:1;
3640
unsigned aborted:1;
3741

src/ngx_http_lua_ssl_client_helloby.c

Lines changed: 114 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@
2121
#include "ngx_http_lua_ssl.h"
2222

2323

24+
#ifdef OPENSSL_IS_BORINGSSL
25+
#define NGX_HTTP_LUA_CLIENT_HELLO_PENDING_STATUS ssl_select_cert_retry
26+
#else
27+
#define NGX_HTTP_LUA_CLIENT_HELLO_PENDING_STATUS -1
28+
#endif
29+
30+
2431
static void ngx_http_lua_ssl_client_hello_done(void *data);
2532
static void ngx_http_lua_ssl_client_hello_aborted(void *data);
2633
static u_char *ngx_http_lua_log_ssl_client_hello_error(ngx_log_t *log,
@@ -96,7 +103,7 @@ char *
96103
ngx_http_lua_ssl_client_hello_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
97104
void *conf)
98105
{
99-
#ifndef SSL_ERROR_WANT_CLIENT_HELLO_CB
106+
#if !defined(SSL_ERROR_WANT_CLIENT_HELLO_CB) && !defined(OPENSSL_IS_BORINGSSL)
100107

101108
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
102109
"at least OpenSSL 1.1.1 required but found "
@@ -178,9 +185,14 @@ ngx_http_lua_ssl_client_hello_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
178185
}
179186

180187

188+
#ifdef OPENSSL_IS_BORINGSSL
189+
int
190+
ngx_http_lua_ssl_client_hello_handler(const SSL_CLIENT_HELLO *client_hello)
191+
#else
181192
int
182193
ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
183194
int *al, void *arg)
195+
#endif
184196
{
185197
lua_State *L;
186198
ngx_int_t rc;
@@ -193,7 +205,11 @@ ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
193205
ngx_http_lua_ssl_ctx_t *cctx;
194206
ngx_http_core_srv_conf_t *cscf;
195207

208+
#ifdef OPENSSL_IS_BORINGSSL
209+
c = ngx_ssl_get_connection(client_hello->ssl);
210+
#else
196211
c = ngx_ssl_get_connection(ssl_conn);
212+
#endif
197213

198214
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
199215
"ssl client hello: connection reusable: %ud", c->reusable);
@@ -215,7 +231,7 @@ ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
215231
return cctx->exit_code;
216232
}
217233

218-
return -1;
234+
return NGX_HTTP_LUA_CLIENT_HELLO_PENDING_STATUS;
219235
}
220236

221237
dd("first time");
@@ -274,6 +290,10 @@ ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
274290
cctx->entered_client_hello_handler = 1;
275291
cctx->done = 0;
276292

293+
#ifdef OPENSSL_IS_BORINGSSL
294+
cctx->client_hello = client_hello;
295+
#endif
296+
277297
dd("setting cctx");
278298

279299
if (SSL_set_ex_data(c->ssl->connection, ngx_http_lua_ssl_ctx_index, cctx)
@@ -339,7 +359,7 @@ ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
339359

340360
*cctx->cleanup = ngx_http_lua_ssl_client_hello_aborted;
341361

342-
return -1;
362+
return NGX_HTTP_LUA_CLIENT_HELLO_PENDING_STATUS;
343363

344364
#if 1
345365
failed:
@@ -537,15 +557,67 @@ ngx_http_lua_ssl_client_hello_by_chunk(lua_State *L, ngx_http_request_t *r)
537557
}
538558

539559

560+
static int
561+
ngx_http_lua_ssl_client_hello_get_ext(const uint8_t *exts, ngx_int_t exts_size,
562+
ngx_int_t target_type, const unsigned char **out, size_t *out_len,
563+
char **err)
564+
{
565+
uint8_t *p, *last;
566+
ngx_int_t ext_len, ext_type;
567+
568+
if (err == NULL) {
569+
return NGX_ERROR;
570+
}
571+
572+
if (exts == NULL) {
573+
*err = "bad boringssl exts";
574+
return NGX_ERROR;
575+
}
576+
577+
if (out == NULL || out_len == NULL) {
578+
*err = "invalid args";
579+
return NGX_ERROR;
580+
}
581+
582+
p = (uint8_t *) exts;
583+
last = (uint8_t *) exts + exts_size;
584+
585+
while (p < last) {
586+
ext_type = *p++;
587+
ext_type = (ext_type << 8) + *p++;
588+
ext_len = *p++;
589+
ext_len = (ext_len << 8) + *p++;
590+
if (p + ext_len > last) {
591+
*err = "invalid boringssl exts";
592+
return NGX_ERROR;
593+
}
594+
595+
if (ext_type == target_type) {
596+
*out = p;
597+
*out_len = ext_len;
598+
return NGX_OK;
599+
}
600+
601+
p += ext_len;
602+
}
603+
604+
/* found nothing */
605+
return NGX_DECLINED;
606+
}
607+
608+
540609
int
541610
ngx_http_lua_ffi_ssl_get_client_hello_server_name(ngx_http_request_t *r,
542611
const char **name, size_t *namelen, char **err)
543612
{
544-
ngx_ssl_conn_t *ssl_conn;
545613
#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
546-
const unsigned char *p;
547-
size_t remaining, len;
614+
size_t remaining, len;
615+
const unsigned char *p;
616+
#elif defined(OPENSSL_IS_BORINGSSL)
617+
size_t remaining;
618+
const char *p;
548619
#endif
620+
ngx_ssl_conn_t *ssl_conn;
549621

550622
if (r->connection == NULL || r->connection->ssl == NULL) {
551623
*err = "bad request";
@@ -560,17 +632,27 @@ ngx_http_lua_ffi_ssl_get_client_hello_server_name(ngx_http_request_t *r,
560632

561633
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
562634

563-
#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
635+
#if defined(SSL_ERROR_WANT_CLIENT_HELLO_CB) || defined(OPENSSL_IS_BORINGSSL)
564636
remaining = 0;
565637

638+
#ifdef OPENSSL_IS_BORINGSSL
639+
p = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
640+
if (p == NULL) {
641+
return NGX_DECLINED;
642+
}
643+
remaining = ngx_strlen(p);
644+
645+
#else
566646
/* This code block is taken from OpenSSL's client_hello_select_server_ctx()
567647
* */
568648
if (!SSL_client_hello_get0_ext(ssl_conn, TLSEXT_TYPE_server_name, &p,
569649
&remaining))
570650
{
571651
return NGX_DECLINED;
572652
}
653+
#endif
573654

655+
#ifndef OPENSSL_IS_BORINGSSL
574656
if (remaining <= 2) {
575657
*err = "Bad SSL Client Hello Extension";
576658
return NGX_ERROR;
@@ -603,8 +685,10 @@ ngx_http_lua_ffi_ssl_get_client_hello_server_name(ngx_http_request_t *r,
603685
}
604686

605687
remaining = len;
688+
#endif
689+
606690
*name = (const char *) p;
607-
*namelen = len;
691+
*namelen = remaining;
608692

609693
return NGX_OK;
610694

@@ -627,6 +711,11 @@ ngx_http_lua_ffi_ssl_get_client_hello_ext(ngx_http_request_t *r,
627711
unsigned int type, const unsigned char **out, size_t *outlen, char **err)
628712
{
629713
ngx_ssl_conn_t *ssl_conn;
714+
#ifdef OPENSSL_IS_BORINGSSL
715+
ngx_int_t rc;
716+
const SSL_CLIENT_HELLO *client_hello;
717+
ngx_http_lua_ssl_ctx_t *cctx;
718+
#endif
630719

631720
if (r->connection == NULL || r->connection->ssl == NULL) {
632721
*err = "bad request";
@@ -645,6 +734,23 @@ ngx_http_lua_ffi_ssl_get_client_hello_ext(ngx_http_request_t *r,
645734
}
646735

647736
return NGX_OK;
737+
#elif defined(OPENSSL_IS_BORINGSSL)
738+
cctx = ngx_http_lua_ssl_get_ctx(r->connection->ssl->connection);
739+
if (cctx == NULL) {
740+
*err = "bad lua ssl ctx";
741+
return NGX_ERROR;
742+
}
743+
744+
if (cctx->client_hello == NULL) {
745+
*err = "bad boringssl client hello ctx";
746+
return NGX_ERROR;
747+
}
748+
749+
client_hello = cctx->client_hello;
750+
rc = ngx_http_lua_ssl_client_hello_get_ext(client_hello->extensions,
751+
client_hello->extensions_len,
752+
type, out, outlen, err);
753+
return rc;
648754
#else
649755
*err = "OpenSSL too old to support this function";
650756
return NGX_ERROR;

src/ngx_http_lua_ssl_client_helloby.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@ char *ngx_http_lua_ssl_client_hello_by_lua_block(ngx_conf_t *cf,
2323
char *ngx_http_lua_ssl_client_hello_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
2424
void *conf);
2525

26+
#ifdef OPENSSL_IS_BORINGSSL
27+
int ngx_http_lua_ssl_client_hello_handler(const SSL_CLIENT_HELLO *);
28+
#else
2629
int ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
2730
int *al, void *arg);
31+
#endif
32+
2833

2934

3035
#endif /* NGX_HTTP_SSL */

src/ngx_http_lua_util.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3686,8 +3686,10 @@ ngx_http_lua_finalize_fake_request(ngx_http_request_t *r, ngx_int_t rc)
36863686
ngx_ssl_conn_t *ssl_conn;
36873687
ngx_http_lua_ssl_ctx_t *cctx;
36883688
#endif
3689+
ngx_http_lua_ctx_t *ctx;
36893690

36903691
c = r->connection;
3692+
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
36913693

36923694
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
36933695
"http lua finalize fake request: %d, a:%d, c:%d",
@@ -3710,7 +3712,19 @@ ngx_http_lua_finalize_fake_request(ngx_http_request_t *r, ngx_int_t rc)
37103712
if (c && c->ssl) {
37113713
cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection);
37123714
if (cctx != NULL) {
3715+
#if defined(OPENSSL_IS_BORINGSSL)
3716+
if (ctx
3717+
&& ctx->context
3718+
& NGX_HTTP_LUA_CONTEXT_SSL_CLIENT_HELLO)
3719+
{
3720+
cctx->exit_code = ssl_select_cert_error;
3721+
3722+
} else {
3723+
cctx->exit_code = 0;
3724+
}
3725+
#else
37133726
cctx->exit_code = 0;
3727+
#endif
37143728
}
37153729
}
37163730
}

t/166-ssl-client-hello.t

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,7 @@ use Test::Nginx::Socket::Lua;
44

55
repeat_each(3);
66

7-
# All these tests need to have new openssl
8-
my $NginxBinary = $ENV{'TEST_NGINX_BINARY'} || 'nginx';
9-
my $openssl_version = eval { `$NginxBinary -V 2>&1` };
10-
11-
if ($openssl_version =~ m/built with OpenSSL (0\S*|1\.0\S*|1\.1\.0\S*)/) {
12-
plan(skip_all => "too old OpenSSL, need 1.1.1, was $1");
13-
} elsif ($openssl_version =~ m/running with BoringSSL/) {
14-
plan(skip_all => "does not support BoringSSL");
15-
} else {
16-
plan tests => repeat_each() * (blocks() * 6 + 8);
17-
}
7+
plan tests => repeat_each() * (blocks() * 6 + 8);
188

199
$ENV{TEST_NGINX_HTML_DIR} ||= html_dir();
2010
$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211;
@@ -580,8 +570,8 @@ failed to do SSL handshake: handshake failed
580570

581571
--- error_log eval
582572
[
583-
'lua_client_hello_by_lua: handler return value: -1, client hello cb exit code: 0',
584-
qr/\[info\] .*? SSL_do_handshake\(\) failed .*?callback failed/,
573+
'lua_client_hello_by_lua: handler return value: -1, client hello cb exit code: ',
574+
qr/.*? SSL_do_handshake\(\) failed .*?/,
585575
'lua exit with code -1',
586576
]
587577

@@ -721,8 +711,8 @@ failed to do SSL handshake: handshake failed
721711

722712
--- error_log eval
723713
[
724-
'lua_client_hello_by_lua: client hello cb exit code: 0',
725-
qr/\[info\] .*? SSL_do_handshake\(\) failed .*?callback failed/,
714+
'lua_client_hello_by_lua: client hello cb exit code: ',
715+
qr/.*? SSL_do_handshake\(\) failed .*?/,
726716
'lua exit with code -1',
727717
]
728718

@@ -792,8 +782,8 @@ failed to do SSL handshake: handshake failed
792782
--- error_log eval
793783
[
794784
'runtime error: ssl_client_hello_by_lua(nginx.conf:28):2: bad bad bad',
795-
'lua_client_hello_by_lua: handler return value: 500, client hello cb exit code: 0',
796-
qr/\[info\] .*? SSL_do_handshake\(\) failed .*?callback failed/,
785+
'lua_client_hello_by_lua: handler return value: 500, client hello cb exit code:',
786+
qr/.*? SSL_do_handshake\(\) failed .*?/,
797787
qr/context: ssl_client_hello_by_lua\*, client: \d+\.\d+\.\d+\.\d+, server: \d+\.\d+\.\d+\.\d+:\d+/,
798788
]
799789

@@ -864,8 +854,8 @@ failed to do SSL handshake: handshake failed
864854
--- error_log eval
865855
[
866856
'runtime error: ssl_client_hello_by_lua(nginx.conf:28):3: bad bad bad',
867-
'lua_client_hello_by_lua: client hello cb exit code: 0',
868-
qr/\[info\] .*? SSL_do_handshake\(\) failed .*?callback failed/,
857+
'lua_client_hello_by_lua: client hello cb exit code: ',
858+
qr/.*? SSL_do_handshake\(\) failed .*?/,
869859
]
870860

871861
--- no_error_log
@@ -1051,7 +1041,7 @@ failed to do SSL handshake: handshake failed
10511041
[
10521042
'lua ssl server name: "test.com"',
10531043
'ssl_client_hello_by_lua(nginx.conf:28):1: API disabled in the context of ssl_client_hello_by_lua*',
1054-
qr/\[info\] .*?callback failed/,
1044+
qr/.*? SSL_do_handshake\(\) failed .*?/,
10551045
]
10561046

10571047
--- no_error_log

0 commit comments

Comments
 (0)