Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: support client_hello_by_lua with boringssl #2266

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
20 changes: 9 additions & 11 deletions t/166-ssl-client-hello.t
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ 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);
}
Expand Down Expand Up @@ -580,8 +578,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 +719,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 +790,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 +862,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 +1049,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
Loading