Skip to content

Commit 0a39402

Browse files
authored
feat: init tlshandshake patch (#1)
1 parent 142c88c commit 0a39402

File tree

4 files changed

+1011
-0
lines changed

4 files changed

+1011
-0
lines changed
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
diff --git Makefile Makefile
2+
index 3caabe2..6361a23 100644
3+
--- Makefile
4+
+++ Makefile
5+
@@ -12,10 +12,12 @@ all: ;
6+
7+
install: all
8+
$(INSTALL) -d $(DESTDIR)$(LUA_LIB_DIR)/resty/core/
9+
+ $(INSTALL) -d $(DESTDIR)$(LUA_LIB_DIR)/resty/core/socket
10+
$(INSTALL) -d $(DESTDIR)$(LUA_LIB_DIR)/ngx/
11+
$(INSTALL) -d $(DESTDIR)$(LUA_LIB_DIR)/ngx/ssl
12+
$(INSTALL) lib/resty/*.lua $(DESTDIR)$(LUA_LIB_DIR)/resty/
13+
$(INSTALL) lib/resty/core/*.lua $(DESTDIR)$(LUA_LIB_DIR)/resty/core/
14+
+ $(INSTALL) lib/resty/core/socket/*.lua $(DESTDIR)$(LUA_LIB_DIR)/resty/core/socket
15+
$(INSTALL) lib/ngx/*.lua $(DESTDIR)$(LUA_LIB_DIR)/ngx/
16+
$(INSTALL) lib/ngx/ssl/*.lua $(DESTDIR)$(LUA_LIB_DIR)/ngx/ssl/
17+
18+
diff --git lib/resty/core/socket/tcp.lua lib/resty/core/socket/tcp.lua
19+
new file mode 100644
20+
index 0000000..30302f0
21+
--- /dev/null
22+
+++ lib/resty/core/socket/tcp.lua
23+
@@ -0,0 +1,236 @@
24+
+-- Copyright (C) by OpenResty Inc.
25+
+
26+
+
27+
+local base = require "resty.core.base"
28+
+local ffi = require "ffi"
29+
+local ssl = require "ngx.ssl"
30+
+
31+
+
32+
+local C = ffi.C
33+
+local ffi_str = ffi.string
34+
+local ffi_gc = ffi.gc
35+
+local FFI_ERROR = base.FFI_ERROR
36+
+local FFI_DONE = base.FFI_DONE
37+
+local FFI_OK = base.FFI_OK
38+
+local FFI_AGAIN = base.FFI_AGAIN
39+
+local FFI_NO_REQ_CTX = base.FFI_NO_REQ_CTX
40+
+local get_request = base.get_request
41+
+local new_tab = base.new_tab
42+
+local clear_tab = base.clear_tab
43+
+local error = error
44+
+local assert = assert
45+
+local type = type
46+
+local pcall = pcall
47+
+local select = select
48+
+local co_yield = coroutine._yield
49+
+local io_open = io.open
50+
+
51+
+
52+
+ffi.cdef[[
53+
+typedef struct ngx_http_lua_socket_tcp_upstream_s
54+
+ ngx_http_lua_socket_tcp_upstream_t;
55+
+
56+
+int ngx_http_lua_ffi_socket_tcp_tlshandshake(ngx_http_request_t *r,
57+
+ ngx_http_lua_socket_tcp_upstream_t *u, void *sess,
58+
+ int enable_session_reuse, ngx_str_t *server_name, int verify,
59+
+ int ocsp_status_req, void *chain, void *pkey, char **errmsg);
60+
+
61+
+int ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(ngx_http_request_t *r,
62+
+ ngx_http_lua_socket_tcp_upstream_t *u, void **sess, char **errmsg,
63+
+ int *openssl_error_code);
64+
+
65+
+void ngx_http_lua_ffi_tls_free_session(void *sess);
66+
+]]
67+
+
68+
+
69+
+local SOCKET_CTX_INDEX = 1
70+
+
71+
+
72+
+local errmsg = base.get_errmsg_ptr()
73+
+local session_ptr = ffi.new("void *[1]")
74+
+local server_name_str = ffi.new("ngx_str_t[1]")
75+
+local openssl_error_code = ffi.new("int[1]")
76+
+local cached_options = new_tab(0, 4)
77+
+
78+
+
79+
+local function read_file(path)
80+
+ local f, err = io_open(path)
81+
+ if not f then
82+
+ return nil, err
83+
+ end
84+
+
85+
+ local txt, err = f:read("*a")
86+
+ f:close()
87+
+ if not txt then
88+
+ return nil, err
89+
+ end
90+
+
91+
+ return txt
92+
+end
93+
+
94+
+
95+
+local function tlshandshake(self, options)
96+
+ if not options then
97+
+ clear_tab(cached_options)
98+
+ options = cached_options
99+
+
100+
+ elseif type(options) ~= "table" then
101+
+ error("bad options arg: table expected", 2)
102+
+ end
103+
+
104+
+ local r = get_request()
105+
+ if not r then
106+
+ error("no request found", 2)
107+
+ end
108+
+
109+
+ local reused_session = options.reused_session
110+
+ session_ptr[0] = type(reused_session) == "cdata" and reused_session or nil
111+
+
112+
+ if options.server_name then
113+
+ server_name_str[0].data = options.server_name
114+
+ server_name_str[0].len = #options.server_name
115+
+
116+
+ else
117+
+ server_name_str[0].data = nil
118+
+ server_name_str[0].len = 0
119+
+ end
120+
+
121+
+ local client_cert, client_pkey
122+
+
123+
+ local client_cert_path = options.client_cert_path
124+
+ local client_pkey_path = options.client_priv_key_path
125+
+ if client_cert_path then
126+
+ if not client_pkey_path then
127+
+ error("client certificate supplied without corresponding " ..
128+
+ "private key", 2)
129+
+ end
130+
+
131+
+ if type(client_cert_path) ~= "string" then
132+
+ error("bad client_cert option type", 2)
133+
+ end
134+
+
135+
+ if type(client_pkey_path) ~= "string" then
136+
+ error("bad client_priv_key option type", 2)
137+
+ end
138+
+
139+
+ local txt, err = read_file(client_cert_path)
140+
+ if not txt then
141+
+ return nil, err
142+
+ end
143+
+
144+
+ local cert, err = ssl.parse_pem_cert(txt)
145+
+ if not cert then
146+
+ return nil, err
147+
+ end
148+
+
149+
+ client_cert = cert
150+
+
151+
+ local txt, err = read_file(client_pkey_path)
152+
+ if not txt then
153+
+ return nil, err
154+
+ end
155+
+
156+
+ local pkey, err = ssl.parse_pem_priv_key(txt)
157+
+ if not pkey then
158+
+ return nil, err
159+
+ end
160+
+
161+
+ client_pkey = pkey
162+
+ end
163+
+
164+
+ local u = self[SOCKET_CTX_INDEX]
165+
+
166+
+ local rc = C.ngx_http_lua_ffi_socket_tcp_tlshandshake(r, u,
167+
+ session_ptr[0],
168+
+ reused_session ~= false,
169+
+ server_name_str,
170+
+ options.verify and 1 or 0,
171+
+ options.ocsp_status_req and 1 or 0,
172+
+ client_cert, client_pkey, errmsg)
173+
+
174+
+ if rc == FFI_NO_REQ_CTX then
175+
+ error("no request ctx found", 2)
176+
+ end
177+
+
178+
+ while true do
179+
+ if rc == FFI_ERROR then
180+
+ if openssl_error_code[0] ~= 0 then
181+
+ return nil, openssl_error_code[0] .. ": " .. ffi_str(errmsg[0])
182+
+ end
183+
+
184+
+ return nil, ffi_str(errmsg[0])
185+
+ end
186+
+
187+
+ if rc == FFI_DONE then
188+
+ return reused_session
189+
+ end
190+
+
191+
+ if rc == FFI_OK then
192+
+ if reused_session == false then
193+
+ return true
194+
+ end
195+
+
196+
+ rc = C.ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(r, u,
197+
+ session_ptr, errmsg, openssl_error_code)
198+
+
199+
+ assert(rc == FFI_OK)
200+
+
201+
+ if session_ptr[0] == nil then
202+
+ return nil
203+
+ end
204+
+
205+
+ return ffi_gc(session_ptr[0], C.ngx_http_lua_ffi_tls_free_session)
206+
+ end
207+
+
208+
+ assert(rc == FFI_AGAIN)
209+
+
210+
+ co_yield()
211+
+
212+
+ rc = C.ngx_http_lua_ffi_socket_tcp_get_tlshandshake_result(r, u,
213+
+ session_ptr, errmsg, openssl_error_code)
214+
+ end
215+
+end
216+
+
217+
+
218+
+local function sslhandshake(self, reused_session, server_name, ssl_verify,
219+
+ send_status_req, ...)
220+
+
221+
+ local n = select("#", ...)
222+
+ if not self or n > 1 then
223+
+ error("ngx.socket sslhandshake: expecting 1 ~ 5 arguments " ..
224+
+ "(including the object), but seen " .. (self and 5 + n or 0))
225+
+ end
226+
+
227+
+ cached_options.reused_session = reused_session
228+
+ cached_options.server_name = server_name
229+
+ cached_options.verify = ssl_verify
230+
+ cached_options.ocsp_status_req = send_status_req
231+
+
232+
+ local res, err = tlshandshake(self, cached_options)
233+
+
234+
+ clear_tab(cached_options)
235+
+
236+
+ return res, err
237+
+end
238+
+
239+
+
240+
+do
241+
+ local old_socket_tcp = ngx.socket.tcp
242+
+
243+
+ function ngx.socket.tcp()
244+
+ local ok, sock = pcall(old_socket_tcp)
245+
+ if not ok then
246+
+ error(sock, 2)
247+
+ end
248+
+
249+
+ sock.tlshandshake = tlshandshake
250+
+ sock.sslhandshake = sslhandshake
251+
+
252+
+ return sock
253+
+ end
254+
+end
255+
+
256+
+
257+
+return {
258+
+ version = base.version
259+
+}

0 commit comments

Comments
 (0)