Skip to content

Commit

Permalink
feature: lua-nginx-module built with boringssl supports client_hello_…
Browse files Browse the repository at this point in the history
…by_lua
  • Loading branch information
swananan committed Dec 17, 2023
1 parent 3a0b823 commit 391639b
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 29 deletions.
7 changes: 6 additions & 1 deletion src/ngx_http_lua_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -1249,8 +1249,13 @@ ngx_http_lua_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_http_lua_ssl_client_hello_handler,
NULL);

#else
#elif defined(OPENSSL_IS_BORINGSSL)

SSL_CTX_set_select_certificate_cb(sscf->ssl.ctx,
ngx_http_lua_ssl_client_hello_handler);


#else
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"OpenSSL too old to support "
"ssl_client_hello_by_lua*");
Expand Down
4 changes: 4 additions & 0 deletions src/ngx_http_lua_ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ typedef struct {
request ctx data in lua
registry */

#ifdef OPENSSL_IS_BORINGSSL
const SSL_CLIENT_HELLO *client_hello;
#endif

unsigned done:1;
unsigned aborted:1;

Expand Down
122 changes: 114 additions & 8 deletions src/ngx_http_lua_ssl_client_helloby.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@
#include "ngx_http_lua_ssl.h"


#ifdef OPENSSL_IS_BORINGSSL
#define NGX_HTTP_LUA_CLIENT_HELLO_PENDING_STATUS ssl_select_cert_retry
#else
#define NGX_HTTP_LUA_CLIENT_HELLO_PENDING_STATUS -1
#endif


static void ngx_http_lua_ssl_client_hello_done(void *data);
static void ngx_http_lua_ssl_client_hello_aborted(void *data);
static u_char *ngx_http_lua_log_ssl_client_hello_error(ngx_log_t *log,
Expand Down Expand Up @@ -96,7 +103,7 @@ char *
ngx_http_lua_ssl_client_hello_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf)
{
#ifndef SSL_ERROR_WANT_CLIENT_HELLO_CB
#if !defined(SSL_ERROR_WANT_CLIENT_HELLO_CB) && !defined(OPENSSL_IS_BORINGSSL)

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


#ifdef OPENSSL_IS_BORINGSSL
int
ngx_http_lua_ssl_client_hello_handler(const SSL_CLIENT_HELLO *client_hello)
#else
int
ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
int *al, void *arg)
#endif
{
lua_State *L;
ngx_int_t rc;
Expand All @@ -193,7 +205,11 @@ ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
ngx_http_lua_ssl_ctx_t *cctx;
ngx_http_core_srv_conf_t *cscf;

#ifdef OPENSSL_IS_BORINGSSL
c = ngx_ssl_get_connection(client_hello->ssl);
#else
c = ngx_ssl_get_connection(ssl_conn);
#endif

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

return -1;
return NGX_HTTP_LUA_CLIENT_HELLO_PENDING_STATUS;
}

dd("first time");
Expand Down Expand Up @@ -274,6 +290,10 @@ ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
cctx->entered_client_hello_handler = 1;
cctx->done = 0;

#ifdef OPENSSL_IS_BORINGSSL
cctx->client_hello = client_hello;
#endif

dd("setting cctx");

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

*cctx->cleanup = ngx_http_lua_ssl_client_hello_aborted;

return -1;
return NGX_HTTP_LUA_CLIENT_HELLO_PENDING_STATUS;

#if 1
failed:
Expand Down Expand Up @@ -537,15 +557,67 @@ ngx_http_lua_ssl_client_hello_by_chunk(lua_State *L, ngx_http_request_t *r)
}


static int
ngx_http_lua_ssl_client_hello_get_ext(const uint8_t *exts, ngx_int_t exts_size,
ngx_int_t target_type, const unsigned char **out, size_t *out_len,
char **err)
{
uint8_t *p, *last;
ngx_int_t ext_len, ext_type;

if (err == NULL) {
return NGX_ERROR;
}

if (exts == NULL) {
*err = "bad boringssl exts";
return NGX_ERROR;
}

if (out == NULL || out_len == NULL) {
*err = "invalid args";
return NGX_ERROR;
}

p = (uint8_t *) exts;
last = (uint8_t *) exts + exts_size;

while (p < last) {
ext_type = *p++;
ext_type = (ext_type << 8) + *p++;
ext_len = *p++;
ext_len = (ext_len << 8) + *p++;
if (p + ext_len > last) {
*err = "invalid boringssl exts";
return NGX_ERROR;
}

if (ext_type == target_type) {
*out = p;
*out_len = ext_len;
return NGX_OK;
}

p += ext_len;
}

/* found nothing */
return NGX_DECLINED;
}


int
ngx_http_lua_ffi_ssl_get_client_hello_server_name(ngx_http_request_t *r,
const char **name, size_t *namelen, char **err)
{
ngx_ssl_conn_t *ssl_conn;
#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
const unsigned char *p;
size_t remaining, len;
size_t remaining, len;
const unsigned char *p;
#elif defined(OPENSSL_IS_BORINGSSL)
size_t remaining;
const char *p;
#endif
ngx_ssl_conn_t *ssl_conn;

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

#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME

#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
#if defined(SSL_ERROR_WANT_CLIENT_HELLO_CB) || defined(OPENSSL_IS_BORINGSSL)
remaining = 0;

#ifdef OPENSSL_IS_BORINGSSL
p = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
if (p == NULL) {
return NGX_DECLINED;
}
remaining = ngx_strlen(p);

#else
/* This code block is taken from OpenSSL's client_hello_select_server_ctx()
* */
if (!SSL_client_hello_get0_ext(ssl_conn, TLSEXT_TYPE_server_name, &p,
&remaining))
{
return NGX_DECLINED;
}
#endif

#ifndef OPENSSL_IS_BORINGSSL
if (remaining <= 2) {
*err = "Bad SSL Client Hello Extension";
return NGX_ERROR;
Expand Down Expand Up @@ -603,8 +685,10 @@ ngx_http_lua_ffi_ssl_get_client_hello_server_name(ngx_http_request_t *r,
}

remaining = len;
#endif

*name = (const char *) p;
*namelen = len;
*namelen = remaining;

return NGX_OK;

Expand All @@ -627,6 +711,11 @@ ngx_http_lua_ffi_ssl_get_client_hello_ext(ngx_http_request_t *r,
unsigned int type, const unsigned char **out, size_t *outlen, char **err)
{
ngx_ssl_conn_t *ssl_conn;
#ifdef OPENSSL_IS_BORINGSSL
ngx_int_t rc;
const SSL_CLIENT_HELLO *client_hello;
ngx_http_lua_ssl_ctx_t *cctx;
#endif

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

return NGX_OK;
#elif defined(OPENSSL_IS_BORINGSSL)
cctx = ngx_http_lua_ssl_get_ctx(r->connection->ssl->connection);
if (cctx == NULL) {
*err = "bad lua ssl ctx";
return NGX_ERROR;
}

if (cctx->client_hello == NULL) {
*err = "bad boringssl client hello ctx";
return NGX_ERROR;
}

client_hello = cctx->client_hello;
rc = ngx_http_lua_ssl_client_hello_get_ext(client_hello->extensions,
client_hello->extensions_len,
type, out, outlen, err);
return rc;
#else
*err = "OpenSSL too old to support this function";
return NGX_ERROR;
Expand Down
5 changes: 5 additions & 0 deletions src/ngx_http_lua_ssl_client_helloby.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ char *ngx_http_lua_ssl_client_hello_by_lua_block(ngx_conf_t *cf,
char *ngx_http_lua_ssl_client_hello_by_lua(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);

#ifdef OPENSSL_IS_BORINGSSL
int ngx_http_lua_ssl_client_hello_handler(const SSL_CLIENT_HELLO *);
#else
int ngx_http_lua_ssl_client_hello_handler(ngx_ssl_conn_t *ssl_conn,
int *al, void *arg);
#endif



#endif /* NGX_HTTP_SSL */
Expand Down
14 changes: 14 additions & 0 deletions src/ngx_http_lua_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -3686,8 +3686,10 @@ ngx_http_lua_finalize_fake_request(ngx_http_request_t *r, ngx_int_t rc)
ngx_ssl_conn_t *ssl_conn;
ngx_http_lua_ssl_ctx_t *cctx;
#endif
ngx_http_lua_ctx_t *ctx;

c = r->connection;
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);

ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http lua finalize fake request: %d, a:%d, c:%d",
Expand All @@ -3710,7 +3712,19 @@ ngx_http_lua_finalize_fake_request(ngx_http_request_t *r, ngx_int_t rc)
if (c && c->ssl) {
cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection);
if (cctx != NULL) {
#if defined(OPENSSL_IS_BORINGSSL)
if (ctx
&& ctx->context
& NGX_HTTP_LUA_CONTEXT_SSL_CLIENT_HELLO)
{
cctx->exit_code = ssl_select_cert_error;

} else {
cctx->exit_code = 0;
}
#else
cctx->exit_code = 0;
#endif
}
}
}
Expand Down
30 changes: 10 additions & 20 deletions t/166-ssl-client-hello.t
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,7 @@ use Test::Nginx::Socket::Lua;

repeat_each(3);

# All these tests need to have new openssl
my $NginxBinary = $ENV{'TEST_NGINX_BINARY'} || 'nginx';
my $openssl_version = eval { `$NginxBinary -V 2>&1` };

if ($openssl_version =~ m/built with OpenSSL (0\S*|1\.0\S*|1\.1\.0\S*)/) {
plan(skip_all => "too old OpenSSL, need 1.1.1, was $1");
} elsif ($openssl_version =~ m/running with BoringSSL/) {
plan(skip_all => "does not support BoringSSL");
} else {
plan tests => repeat_each() * (blocks() * 6 + 8);
}
plan tests => repeat_each() * (blocks() * 6 + 8);

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

--- error_log eval
[
'lua_client_hello_by_lua: handler return value: -1, client hello cb exit code: 0',
qr/\[info\] .*? SSL_do_handshake\(\) failed .*?callback failed/,
'lua_client_hello_by_lua: handler return value: -1, client hello cb exit code: ',
qr/.*? SSL_do_handshake\(\) failed .*?/,
'lua exit with code -1',
]

Expand Down Expand Up @@ -721,8 +711,8 @@ failed to do SSL handshake: handshake failed

--- error_log eval
[
'lua_client_hello_by_lua: client hello cb exit code: 0',
qr/\[info\] .*? SSL_do_handshake\(\) failed .*?callback failed/,
'lua_client_hello_by_lua: client hello cb exit code: ',
qr/.*? SSL_do_handshake\(\) failed .*?/,
'lua exit with code -1',
]

Expand Down Expand Up @@ -792,8 +782,8 @@ failed to do SSL handshake: handshake failed
--- error_log eval
[
'runtime error: ssl_client_hello_by_lua(nginx.conf:28):2: bad bad bad',
'lua_client_hello_by_lua: handler return value: 500, client hello cb exit code: 0',
qr/\[info\] .*? SSL_do_handshake\(\) failed .*?callback failed/,
'lua_client_hello_by_lua: handler return value: 500, client hello cb exit code:',
qr/.*? SSL_do_handshake\(\) failed .*?/,
qr/context: ssl_client_hello_by_lua\*, client: \d+\.\d+\.\d+\.\d+, server: \d+\.\d+\.\d+\.\d+:\d+/,
]

Expand Down Expand Up @@ -864,8 +854,8 @@ failed to do SSL handshake: handshake failed
--- error_log eval
[
'runtime error: ssl_client_hello_by_lua(nginx.conf:28):3: bad bad bad',
'lua_client_hello_by_lua: client hello cb exit code: 0',
qr/\[info\] .*? SSL_do_handshake\(\) failed .*?callback failed/,
'lua_client_hello_by_lua: client hello cb exit code: ',
qr/.*? SSL_do_handshake\(\) failed .*?/,
]

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

--- no_error_log
Expand Down

0 comments on commit 391639b

Please sign in to comment.