summaryrefslogtreecommitdiffstats
path: root/server/resty/openssl/auxiliary/nginx.lua
diff options
context:
space:
mode:
Diffstat (limited to 'server/resty/openssl/auxiliary/nginx.lua')
-rw-r--r--server/resty/openssl/auxiliary/nginx.lua318
1 files changed, 318 insertions, 0 deletions
diff --git a/server/resty/openssl/auxiliary/nginx.lua b/server/resty/openssl/auxiliary/nginx.lua
new file mode 100644
index 0000000..8adeceb
--- /dev/null
+++ b/server/resty/openssl/auxiliary/nginx.lua
@@ -0,0 +1,318 @@
+local get_req_ssl, get_req_ssl_ctx
+local get_socket_ssl, get_socket_ssl_ctx
+
+local pok, nginx_c = pcall(require, "resty.openssl.auxiliary.nginx_c")
+
+if pok and not os.getenv("CI_SKIP_NGINX_C") then
+ get_req_ssl = nginx_c.get_req_ssl
+ get_req_ssl_ctx = nginx_c.get_req_ssl_ctx
+ get_socket_ssl = nginx_c.get_socket_ssl
+ get_socket_ssl_ctx = nginx_c.get_socket_ssl
+else
+ local ffi = require "ffi"
+
+ ffi.cdef [[
+ // Nginx seems to always config _FILE_OFFSET_BITS=64, this should always be 8 byte
+ typedef long long off_t;
+ typedef unsigned int socklen_t; // windows uses int, same size
+ typedef unsigned short in_port_t;
+
+ typedef struct ssl_st SSL;
+ typedef struct ssl_ctx_st SSL_CTX;
+
+ typedef long (*ngx_recv_pt)(void *c, void *buf, size_t size);
+ typedef long (*ngx_recv_chain_pt)(void *c, void *in,
+ off_t limit);
+ typedef long (*ngx_send_pt)(void *c, void *buf, size_t size);
+ typedef void *(*ngx_send_chain_pt)(void *c, void *in,
+ off_t limit);
+
+ typedef struct {
+ size_t len;
+ void *data;
+ } ngx_str_t;
+
+ typedef struct {
+ SSL *connection;
+ SSL_CTX *session_ctx;
+ // trimmed
+ } ngx_ssl_connection_s;
+ ]]
+
+ local ngx_version = ngx.config.nginx_version
+ if ngx_version == 1017008 or ngx_version == 1019003 or ngx_version == 1019009
+ or ngx_version == 1021004 then
+ -- 1.17.8, 1.19.3, 1.19.9, 1.21.4
+ -- https://github.com/nginx/nginx/blob/master/src/core/ngx_connection.h
+ ffi.cdef [[
+ typedef struct {
+ ngx_str_t src_addr;
+ ngx_str_t dst_addr;
+ in_port_t src_port;
+ in_port_t dst_port;
+ } ngx_proxy_protocol_t;
+
+ typedef struct {
+ void *data;
+ void *read;
+ void *write;
+
+ int fd;
+
+ ngx_recv_pt recv;
+ ngx_send_pt send;
+ ngx_recv_chain_pt recv_chain;
+ ngx_send_chain_pt send_chain;
+
+ void *listening;
+
+ off_t sent;
+
+ void *log;
+
+ void *pool;
+
+ int type;
+
+ void *sockaddr;
+ socklen_t socklen;
+ ngx_str_t addr_text;
+
+ // https://github.com/nginx/nginx/commit/be932e81a1531a3ba032febad968fc2006c4fa48
+ ngx_proxy_protocol_t *proxy_protocol;
+
+ ngx_ssl_connection_s *ssl;
+ // trimmed
+ } ngx_connection_s;
+ ]]
+ else
+ error("resty.openssl.auxiliary.nginx doesn't support Nginx version " .. ngx_version, 2)
+ end
+
+ ffi.cdef [[
+ typedef struct {
+ ngx_connection_s *connection;
+ // trimmed
+ } ngx_stream_lua_request_s;
+
+ typedef struct {
+ unsigned int signature; /* "HTTP" */
+
+ ngx_connection_s *connection;
+ // trimmed
+ } ngx_http_request_s;
+ ]]
+
+ local get_request
+ do
+ local ok, exdata = pcall(require, "thread.exdata")
+ if ok and exdata then
+ function get_request()
+ local r = exdata()
+ if r ~= nil then
+ return r
+ end
+ end
+
+ else
+ local getfenv = getfenv
+
+ function get_request()
+ return getfenv(0).__ngx_req
+ end
+ end
+ end
+
+ local SOCKET_CTX_INDEX = 1
+
+ local NO_C_MODULE_WARNING_MSG_SHOWN = false
+ local NO_C_MODULE_WARNING_MSG = "note resty.openssl.auxiliary.nginx is using plain FFI " ..
+ "and it's only intended to be used in development, " ..
+ "consider using lua-resty-openssl.aux-module in production."
+
+ local function get_ngx_ssl_from_req()
+ if not NO_C_MODULE_WARNING_MSG_SHOWN then
+ ngx.log(ngx.WARN, NO_C_MODULE_WARNING_MSG)
+ NO_C_MODULE_WARNING_MSG_SHOWN = true
+ end
+
+ local c = get_request()
+ if ngx.config.subsystem == "stream" then
+ c = ffi.cast("ngx_stream_lua_request_s*", c)
+ else -- http
+ c = ffi.cast("ngx_http_request_s*", c)
+ end
+
+ local ngx_ssl = c.connection.ssl
+ if ngx_ssl == nil then
+ return nil, "c.connection.ssl is nil"
+ end
+ return ngx_ssl
+ end
+
+ get_req_ssl = function()
+ local ssl, err = get_ngx_ssl_from_req()
+ if err then
+ return nil, err
+ end
+
+ return ssl.connection
+ end
+
+ get_req_ssl_ctx = function()
+ local ssl, err = get_ngx_ssl_from_req()
+ if err then
+ return nil, err
+ end
+
+ return ssl.session_ctx
+ end
+
+ ffi.cdef[[
+ typedef struct ngx_http_lua_socket_tcp_upstream_s
+ ngx_http_lua_socket_tcp_upstream_t;
+
+ typedef struct {
+ ngx_connection_s *connection;
+ // trimmed
+ } ngx_peer_connection_s;
+
+ typedef
+ int (*ngx_http_lua_socket_tcp_retval_handler_masked)(void *r,
+ void *u, void *L);
+
+ typedef void (*ngx_http_lua_socket_tcp_upstream_handler_pt_masked)
+ (void *r, void *u);
+
+
+ typedef
+ int (*ngx_stream_lua_socket_tcp_retval_handler)(void *r,
+ void *u, void *L);
+
+ typedef void (*ngx_stream_lua_socket_tcp_upstream_handler_pt)
+ (void *r, void *u);
+
+ typedef struct {
+ ngx_stream_lua_socket_tcp_retval_handler read_prepare_retvals;
+ ngx_stream_lua_socket_tcp_retval_handler write_prepare_retvals;
+ ngx_stream_lua_socket_tcp_upstream_handler_pt read_event_handler;
+ ngx_stream_lua_socket_tcp_upstream_handler_pt write_event_handler;
+
+ void *socket_pool;
+
+ void *conf;
+ void *cleanup;
+ void *request;
+
+ ngx_peer_connection_s peer;
+ // trimmed
+ } ngx_stream_lua_socket_tcp_upstream_s;
+ ]]
+
+ local ngx_lua_version = ngx.config and
+ ngx.config.ngx_lua_version and
+ ngx.config.ngx_lua_version
+
+ if ngx_lua_version >= 10019 and ngx_lua_version <= 10021 then
+ -- https://github.com/openresty/lua-nginx-module/blob/master/src/ngx_http_lua_socket_tcp.h
+ ffi.cdef[[
+ typedef struct {
+ ngx_http_lua_socket_tcp_retval_handler_masked read_prepare_retvals;
+ ngx_http_lua_socket_tcp_retval_handler_masked write_prepare_retvals;
+ ngx_http_lua_socket_tcp_upstream_handler_pt_masked read_event_handler;
+ ngx_http_lua_socket_tcp_upstream_handler_pt_masked write_event_handler;
+
+ void *udata_queue; // 0.10.19
+
+ void *socket_pool;
+
+ void *conf;
+ void *cleanup;
+ void *request;
+ ngx_peer_connection_s peer;
+ // trimmed
+ } ngx_http_lua_socket_tcp_upstream_s;
+ ]]
+ elseif ngx_lua_version < 10019 then
+ -- the struct doesn't seem to get changed a long time since birth
+ ffi.cdef[[
+ typedef struct {
+ ngx_http_lua_socket_tcp_retval_handler_masked read_prepare_retvals;
+ ngx_http_lua_socket_tcp_retval_handler_masked write_prepare_retvals;
+ ngx_http_lua_socket_tcp_upstream_handler_pt_masked read_event_handler;
+ ngx_http_lua_socket_tcp_upstream_handler_pt_masked write_event_handler;
+
+ void *socket_pool;
+
+ void *conf;
+ void *cleanup;
+ void *request;
+ ngx_peer_connection_s peer;
+ // trimmed
+ } ngx_http_lua_socket_tcp_upstream_s;
+ ]]
+ else
+ error("resty.openssl.auxiliary.nginx doesn't support lua-nginx-module version " .. (ngx_lua_version or "nil"), 2)
+ end
+
+ local function get_ngx_ssl_from_socket_ctx(sock)
+ if not NO_C_MODULE_WARNING_MSG_SHOWN then
+ ngx.log(ngx.WARN, NO_C_MODULE_WARNING_MSG)
+ NO_C_MODULE_WARNING_MSG_SHOWN = true
+ end
+
+ local u = sock[SOCKET_CTX_INDEX]
+ if u == nil then
+ return nil, "lua_socket_tcp_upstream_t not found"
+ end
+
+ if ngx.config.subsystem == "stream" then
+ u = ffi.cast("ngx_stream_lua_socket_tcp_upstream_s*", u)
+ else -- http
+ u = ffi.cast("ngx_http_lua_socket_tcp_upstream_s*", u)
+ end
+
+ local p = u.peer
+ if p == nil then
+ return nil, "u.peer is nil"
+ end
+
+ local uc = p.connection
+ if uc == nil then
+ return nil, "u.peer.connection is nil"
+ end
+
+ local ngx_ssl = uc.ssl
+ if ngx_ssl == nil then
+ return nil, "u.peer.connection.ssl is nil"
+ end
+ return ngx_ssl
+ end
+
+ get_socket_ssl = function(sock)
+ local ssl, err = get_ngx_ssl_from_socket_ctx(sock)
+ if err then
+ return nil, err
+ end
+
+ return ssl.connection
+ end
+
+ get_socket_ssl_ctx = function(sock)
+ local ssl, err = get_ngx_ssl_from_socket_ctx(sock)
+ if err then
+ return nil, err
+ end
+
+ return ssl.session_ctx
+ end
+
+end
+
+
+return {
+ get_req_ssl = get_req_ssl,
+ get_req_ssl_ctx = get_req_ssl_ctx,
+ get_socket_ssl = get_socket_ssl,
+ get_socket_ssl_ctx = get_socket_ssl_ctx,
+}