From a8411f7cf4289049f0bd3e8e40088e7256389ed3 Mon Sep 17 00:00:00 2001 From: Water-Melon Date: Mon, 8 Apr 2024 10:45:24 +0000 Subject: [PATCH] feat(ssl): add function to get socket ssl KAG-3791 --- README.md | 16 ++++++++++ config | 8 ++++- lualib/resty/kong/tls.lua | 30 ++++++++++++++++++ src/ngx_http_lua_kong_ssl.c | 24 ++++++++++++++ stream/config | 8 +++++ stream/src/ngx_stream_lua_kong_module.c | 26 +++++++++++++++ t/001-tls.t | 40 ++++++++++++++++++++++- t/stream/003-tls.t | 42 ++++++++++++++++++++++++- 8 files changed, 191 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d43bbca7..5dc6f2aa 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Table of Contents * [resty.kong.tls.set\_upstream\_ssl\_trusted\_store](#restykongtlsset_upstream_ssl_trusted_store) * [resty.kong.tls.set\_upstream\_ssl\_verify](#restykongtlsset_upstream_ssl_verify) * [resty.kong.tls.set\_upstream\_ssl\_verify\_depth](#restykongtlsset_upstream_ssl_verify_depth) + * [resty.kong.tls.get\_ssl\_pointer](#restykongtlsget_ssl_pointer) * [resty.kong.grpc.set\_authority](#restykonggrpcset_authority) * [resty.kong.tls.disable\_proxy\_ssl](#restykongtlsdisable_proxy_ssl) * [resty.kong.var.patch\_metatable](#restykongvarpatch_metatable) @@ -351,6 +352,21 @@ previous ones. [Back to TOC](#table-of-contents) +resty.kong.tls.get\_ssl\_pointer +---------------------------------------------------- +**syntax:** *ssl_ptr, err = resty.kong.tls.get\_ssl\_pointer(sock)* + +**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, log_by_lua**, *preread_by_lua** + +**subsystems:** *http* *stream* + +Retrieves the OpenSSL `SSL*` object for the current tcpsock `sock`. + +On success, this function returns the pointer of type `SSL`. Otherwise `nil` and a string +describing the error will be returned. + +[Back to TOC](#table-of-contents) + resty.kong.grpc.set\_authority ------------------------------ **syntax:** *ok, err = resty.kong.grpc.set_authority(new_authority)* diff --git a/config b/config index 043ec536..03d660a9 100644 --- a/config +++ b/config @@ -13,7 +13,13 @@ ngx_module_srcs=" \ $ngx_addon_dir/src/ssl/ngx_lua_kong_ssl.c \ " -ngx_module_incs="$ngx_addon_dir/src" +if [ -z "$NGX_LUA_LOC" ]; then + ngx_lua_loc="../ngx_lua-*" +else + ngx_lua_loc="$NGX_LUA_LOC" +fi + +ngx_module_incs="$ngx_addon_dir/src $ngx_lua_loc/src" . auto/module diff --git a/lualib/resty/kong/tls.lua b/lualib/resty/kong/tls.lua index c56b0085..23c591ce 100644 --- a/lualib/resty/kong/tls.lua +++ b/lualib/resty/kong/tls.lua @@ -24,6 +24,8 @@ local type = type local error = error local tostring = tostring local C = ffi.C +local ffi_cast = ffi.cast +local SOCKET_CTX_INDEX = 1 local ffi_string = ffi.string local get_string_buf = base.get_string_buf local size_ptr = base.get_size_ptr() @@ -37,9 +39,13 @@ local kong_lua_kong_ffi_set_upstream_client_cert_and_key local kong_lua_kong_ffi_set_upstream_ssl_trusted_store local kong_lua_kong_ffi_set_upstream_ssl_verify local kong_lua_kong_ffi_set_upstream_ssl_verify_depth +local kong_lua_kong_ffi_get_socket_ssl if subsystem == "http" then ffi.cdef([[ + typedef struct ssl_st SSL; + typedef struct ngx_http_lua_socket_tcp_upstream_s ngx_http_lua_socket_tcp_upstream_t; + int ngx_http_lua_kong_ffi_get_full_client_certificate_chain( ngx_http_request_t *r, char *buf, size_t *buf_len); const char *ngx_http_lua_kong_ffi_disable_session_reuse(ngx_http_request_t *r); @@ -51,6 +57,8 @@ if subsystem == "http" then int verify); int ngx_http_lua_kong_ffi_set_upstream_ssl_verify_depth(ngx_http_request_t *r, int depth); + int ngx_http_lua_kong_ffi_get_socket_ssl(ngx_http_lua_socket_tcp_upstream_t *u, + void **ssl_conn); ]]) kong_lua_kong_ffi_get_full_client_certificate_chain = C.ngx_http_lua_kong_ffi_get_full_client_certificate_chain @@ -59,9 +67,13 @@ if subsystem == "http" then kong_lua_kong_ffi_set_upstream_ssl_trusted_store = C.ngx_http_lua_kong_ffi_set_upstream_ssl_trusted_store kong_lua_kong_ffi_set_upstream_ssl_verify = C.ngx_http_lua_kong_ffi_set_upstream_ssl_verify kong_lua_kong_ffi_set_upstream_ssl_verify_depth = C.ngx_http_lua_kong_ffi_set_upstream_ssl_verify_depth + kong_lua_kong_ffi_get_socket_ssl = C.ngx_http_lua_kong_ffi_get_socket_ssl elseif subsystem == 'stream' then ffi.cdef([[ + typedef struct ssl_st SSL; + typedef struct ngx_stream_lua_socket_tcp_upstream_s ngx_stream_lua_socket_tcp_upstream_t; + int ngx_stream_lua_kong_ffi_proxy_ssl_disable(ngx_stream_lua_request_t *r); int ngx_stream_lua_kong_ffi_get_full_client_certificate_chain(ngx_stream_lua_request_t *r, char *buf, size_t *buf_len); @@ -74,6 +86,8 @@ elseif subsystem == 'stream' then int verify); int ngx_stream_lua_kong_ffi_set_upstream_ssl_verify_depth(ngx_stream_lua_request_t *r, int depth); + int ngx_stream_lua_kong_get_socket_ssl(ngx_stream_lua_socket_tcp_upstream_t *u, + void **ssl_conn); ]]) kong_lua_kong_ffi_get_full_client_certificate_chain = C.ngx_stream_lua_kong_ffi_get_full_client_certificate_chain @@ -82,6 +96,7 @@ elseif subsystem == 'stream' then kong_lua_kong_ffi_set_upstream_ssl_trusted_store = C.ngx_stream_lua_kong_ffi_set_upstream_ssl_trusted_store kong_lua_kong_ffi_set_upstream_ssl_verify = C.ngx_stream_lua_kong_ffi_set_upstream_ssl_verify kong_lua_kong_ffi_set_upstream_ssl_verify_depth = C.ngx_stream_lua_kong_ffi_set_upstream_ssl_verify_depth + kong_lua_kong_ffi_get_socket_ssl = C.ngx_stream_lua_kong_get_socket_ssl else error("unknown subsystem: " .. subsystem) end @@ -121,6 +136,21 @@ function _M.disable_session_reuse() end +local ssl_type = ffi.typeof("SSL*") +local void_pp = ffi.new("void *[1]") + +function _M.get_ssl_pointer(sock) + local u = sock[SOCKET_CTX_INDEX] + + local ret = kong_lua_kong_ffi_get_socket_ssl(u, void_pp) + if ret ~= NGX_OK then + return nil, "no ssl object" + end + + return ffi_cast(ssl_type, void_pp[0]) +end + + do local ALLOWED_PHASES = { ['rewrite'] = true, diff --git a/src/ngx_http_lua_kong_ssl.c b/src/ngx_http_lua_kong_ssl.c index daf263ab..b0d3e8cf 100644 --- a/src/ngx_http_lua_kong_ssl.c +++ b/src/ngx_http_lua_kong_ssl.c @@ -16,6 +16,7 @@ #include "ngx_http_lua_kong_common.h" +#include "ngx_http_lua_socket_tcp.h" /* @@ -46,6 +47,29 @@ ngx_http_lua_kong_ffi_get_full_client_certificate_chain(ngx_http_request_t *r, } +int +ngx_http_lua_kong_ffi_get_socket_ssl(ngx_http_lua_socket_tcp_upstream_t *u, void **ssl_conn) +{ +#if (NGX_SSL) + ngx_connection_t *uc = u->peer.connection; + + if (ssl_conn == NULL) { + return NGX_ABORT; + } + + if (uc && (uc->ssl) && (uc->ssl->connection)) { + *ssl_conn = uc->ssl->connection; + return NGX_OK; + } + + return NGX_ERROR; + +#else + return NGX_ABORT; +#endif +} + + #if (NGX_HTTP_SSL) /* diff --git a/stream/config b/stream/config index 08c4a810..1f679093 100644 --- a/stream/config +++ b/stream/config @@ -3,6 +3,14 @@ ngx_module_name=ngx_stream_lua_kong_module ngx_module_srcs="$ngx_addon_dir/src/ngx_stream_lua_kong_module.c" ngx_module_incs="$ngx_addon_dir/src" +if [ -z "$NGX_LUA_LOC" ]; then + ngx_lua_loc="../ngx_stream_lua-*" +else + ngx_lua_loc="$NGX_LUA_LOC" +fi + +ngx_module_incs="$ngx_addon_dir/src $ngx_lua_loc/src" + . auto/module ngx_addon_name=$ngx_module_name diff --git a/stream/src/ngx_stream_lua_kong_module.c b/stream/src/ngx_stream_lua_kong_module.c index f6100d1f..41b8b7f0 100644 --- a/stream/src/ngx_stream_lua_kong_module.c +++ b/stream/src/ngx_stream_lua_kong_module.c @@ -16,6 +16,7 @@ #include "ngx_stream_lua_kong_module.h" +#include "ngx_stream_lua_socket_tcp.h" static void* ngx_stream_lua_kong_create_srv_conf(ngx_conf_t* cf); @@ -297,3 +298,28 @@ ngx_stream_lua_kong_get_upstream_ssl_verify(ngx_stream_session_t *s, return ngx_lua_kong_ssl_get_upstream_ssl_verify(&ctx->ssl_ctx, proxy_ssl_verify); } #endif + + +int +ngx_stream_lua_kong_get_socket_ssl(ngx_stream_lua_socket_tcp_upstream_t *u, +void **ssl_conn) +{ +#if (NGX_SSL) + ngx_connection_t *uc = u->peer.connection; + + if (ssl_conn == NULL) { + return NGX_ABORT; + } + + if (uc && (uc->ssl) && (uc->ssl->connection)) { + *ssl_conn = uc->ssl->connection; + return NGX_OK; + } + + return NGX_ERROR; + +#else + return NGX_ABORT; +#endif +} + diff --git a/t/001-tls.t b/t/001-tls.t index 217173e1..ada5e479 100644 --- a/t/001-tls.t +++ b/t/001-tls.t @@ -5,7 +5,7 @@ use Cwd qw(cwd); repeat_each(2); -plan tests => repeat_each() * (blocks() * 7 - 1); +plan tests => repeat_each() * (blocks() * 7 - 4); my $pwd = cwd(); @@ -457,3 +457,41 @@ nil, connection is not TLS or TLS support for Nginx not enabled [alert] [warn] [crit] + + + +=== TEST 7: ssl.get_ssl_pointer works well +--- http_config + lua_package_path "../lua-resty-core/lib/?.lua;lualib/?.lua;;"; + lua_ssl_protocols SSLV3 TLSv1 TLSv1.1 TLSv1.2; + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name example.com; + ssl_certificate ../../cert/example.com.crt; + ssl_certificate_key ../../cert/example.com.key; + ssl_session_cache off; + ssl_session_tickets on; + server_tokens off; + } +--- config + server_tokens off; + location /t { + content_by_lua_block { + local sock = ngx.socket.tcp() + assert(sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")) + assert(sock:sslhandshake(nil, "example.com")) + local ssl = require "resty.kong.tls" + if ssl.get_ssl_pointer(sock) == nil then + ngx.say("cannot get socket") + else + ngx.say("ok") + end + } + } +--- request +GET /t +--- response_body +ok +--- no_error_log +[error] +[emerg] diff --git a/t/stream/003-tls.t b/t/stream/003-tls.t index 57dce60f..0d86c3c7 100644 --- a/t/stream/003-tls.t +++ b/t/stream/003-tls.t @@ -6,7 +6,7 @@ use Cwd qw(cwd); repeat_each(2); -plan tests => repeat_each() * (blocks() * 7 - 1); +plan tests => repeat_each() * (blocks() * 7 - 4); my $pwd = cwd(); @@ -400,3 +400,43 @@ nil, connection is not TLS or TLS support for Nginx not enabled [crit] --- skip_nginx 6: < 1.21.4 + + + + +=== TEST 7: ssl.get_ssl_pointer works well +--- stream_config + lua_package_path "../lua-resty-core/lib/?.lua;lualib/?.lua;;"; + + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + ssl_certificate ../../cert/example.com.crt; + ssl_certificate_key ../../cert/example.com.key; + ssl_session_cache off; + ssl_session_tickets on; + + content_by_lua_block { + ngx.say("it works") + } + } + +--- stream_server_config + content_by_lua_block { + local sock = ngx.socket.tcp() + assert(sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")) + assert(sock:sslhandshake(nil, "example.com")) + local ssl = require "resty.kong.tls" + if ssl.get_ssl_pointer(sock) == nil then + ngx.say("cannot get socket") + else + ngx.say("ok") + end + } + +--- response_body +ok +--- no_error_log +[error] +[emerg] +--- skip_nginx +7: < 1.21.4