diff --git a/lib/resty/core/socket.lua b/lib/resty/core/socket.lua index ac690e3d4..b8de2bfe8 100644 --- a/lib/resty/core/socket.lua +++ b/lib/resty/core/socket.lua @@ -40,6 +40,8 @@ local option_index = { local ngx_lua_ffi_socket_tcp_getoption local ngx_lua_ffi_socket_tcp_setoption local ngx_lua_ffi_socket_getfd +local ngx_lua_ffi_socket_getsslpointer +local ngx_lua_ffi_socket_getsslctx if subsystem == 'http' then ffi.cdef[[ @@ -75,11 +77,21 @@ int ngx_http_lua_socket_tcp_get_ssl_session(ngx_http_request_t *r, ngx_http_lua_socket_tcp_upstream_t *u, void **sess, char **errmsg); +int +ngx_http_lua_ffi_socket_tcp_get_ssl_pointer(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, void **pssl, + char **errmsg); +int +ngx_http_lua_ffi_socket_tcp_get_ssl_ctx(ngx_http_request_t *r, + ngx_http_lua_socket_tcp_upstream_t *u, void **pctx, + char **errmsg); ]] ngx_lua_ffi_socket_tcp_getoption = C.ngx_http_lua_ffi_socket_tcp_getoption ngx_lua_ffi_socket_tcp_setoption = C.ngx_http_lua_ffi_socket_tcp_setoption ngx_lua_ffi_socket_getfd = C.ngx_http_lua_ffi_socket_tcp_getfd +ngx_lua_ffi_socket_getsslpointer = C.ngx_http_lua_ffi_socket_tcp_get_ssl_pointer +ngx_lua_ffi_socket_getsslctx = C.ngx_http_lua_ffi_socket_tcp_get_ssl_ctx elseif subsystem == 'stream' then @@ -97,11 +109,21 @@ int ngx_stream_lua_ffi_socket_tcp_getfd(ngx_stream_lua_request_t *r, ngx_stream_lua_socket_tcp_upstream_t *u, char **errmsg); +int +ngx_stream_lua_ffi_socket_tcp_get_ssl_pointer(ngx_stream_lua_request_t *r, + ngx_stream_lua_socket_tcp_upstream_t *u, void **pssl, + char **errmsg); +int +ngx_stream_lua_ffi_socket_tcp_get_ssl_ctx(ngx_stream_lua_request_t *r, + ngx_stream_lua_socket_tcp_upstream_t *u, void **pctx, + char **errmsg); ]] ngx_lua_ffi_socket_tcp_getoption = C.ngx_stream_lua_ffi_socket_tcp_getoption ngx_lua_ffi_socket_tcp_setoption = C.ngx_stream_lua_ffi_socket_tcp_setoption ngx_lua_ffi_socket_getfd = C.ngx_stream_lua_ffi_socket_tcp_getfd +ngx_lua_ffi_socket_getsslpointer = C.ngx_stream_lua_ffi_socket_tcp_get_ssl_pointer +ngx_lua_ffi_socket_getsslctx = C.ngx_stream_lua_ffi_socket_tcp_get_ssl_ctx end @@ -215,6 +237,49 @@ local function getfd(cosocket) end +local function getsslpointer(cosocket) + if not cosocket then + error("ngx.socket getfd: expecting the cosocket object, but seen none") + end + + local r = get_request() + if not r then + error("no request found") + end + + local u = get_tcp_socket(cosocket) + local rc = ngx_lua_ffi_socket_getsslpointer(r, u, + session_ptr, errmsg) + if rc == FFI_ERROR then + return nil, ffi_str(errmsg[0]) + end + + return session_ptr[0] +end + + +local function getsslctx(cosocket) + if not cosocket then + error("ngx.socket getfd: expecting the cosocket object, but seen none") + end + + local r = get_request() + if not r then + error("no request found") + end + + local u = get_tcp_socket(cosocket) + local rc = ngx_lua_ffi_socket_getsslctx(r, u, + session_ptr, errmsg) + if rc == FFI_ERROR then + return nil, ffi_str(errmsg[0]) + end + + return session_ptr[0] +end + + + if subsystem == 'http' then local server_name_str = ffi_new("ngx_str_t[1]") local openssl_error_code = ffi_new("int[1]") @@ -358,6 +423,7 @@ local function getsslsession(cosocket) return ffi_gc(session_ptr[0], C.ngx_http_lua_ffi_ssl_free_session) end + do local method_table = registry.__tcp_cosocket_mt method_table.getoption = getoption @@ -368,6 +434,8 @@ do method_table.getoption = getoption method_table.setoption = setoption method_table.getsslsession = getsslsession + method_table.getsslpointer = getsslpointer + method_table.getsslctx = getsslctx method_table = registry.__tcp_req_cosocket_mt method_table.getfd = getfd @@ -386,6 +454,8 @@ do method_table.getoption = getoption method_table.setoption = setoption method_table.getfd = getfd + method_table.getsslpointer = getsslpointer + method_table.getsslctx = getsslctx method_table = registry.__tcp_raw_req_cosocket_mt method_table.getfd = getfd diff --git a/t/ssl.t b/t/ssl.t index 8f13a58e7..3303d6217 100644 --- a/t/ssl.t +++ b/t/ssl.t @@ -3545,3 +3545,100 @@ qr/upstream ssl state: (false|true)/ [error] [emerg] [crit] + + + +=== TEST 37: get cosocket SSL pointer +--- http_config + lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH"; + + server { + listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl; + server_name test.com; + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + server_tokens off; + location /foo { + default_type 'text/plain'; + content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)} + more_clear_headers Date; + } + } +--- config + server_tokens off; + lua_ssl_trusted_certificate ../../cert/test.crt; + + location /t { + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(3000) + + local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock") + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, "test.com", true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl handshake: ", type(sess)) + ngx.say("ssl pointer: ", type(sock:getsslpointer())) + ngx.say("ssl ctx: ", type(sock:getsslctx())) + + local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n" + local bytes, err = sock:send(req) + if not bytes then + ngx.say("failed to send http request: ", err) + return + end + + ngx.say("sent http request: ", bytes, " bytes.") + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to receive response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + } + +--- request +GET /t +--- response_body +connected: 1 +ssl handshake: cdata +ssl pointer: cdata +ssl ctx: cdata +sent http request: 56 bytes. +received: HTTP/1.1 201 Created +received: Server: nginx +received: Content-Type: text/plain +received: Content-Length: 4 +received: Connection: close +received: +received: foo +close: 1 nil +--- error_log +lua ssl server name: "test.com" +--- no_error_log +[error] +[emerg] +[crit] diff --git a/t/stream/ssl.t b/t/stream/ssl.t index 799fb1623..678e12f9e 100644 --- a/t/stream/ssl.t +++ b/t/stream/ssl.t @@ -2552,3 +2552,78 @@ qr/session reused: false/ [alert] [crit] [error] + + + +=== TEST 32: get cosocet SSL pointer +--- stream_config + lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH"; + + server { + listen 127.0.0.1:$TEST_NGINX_RAND_PORT_1 ssl; + ssl_protocols TLSv1.2; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384; + ssl_certificate ../../cert/test.crt; + ssl_certificate_key ../../cert/test.key; + + return 'it works!\n'; + } +--- stream_server_config + lua_ssl_trusted_certificate ../../cert/test.crt; + lua_ssl_protocols TLSv1.2; + lua_ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256; + + content_by_lua_block { + do + local sock = ngx.socket.tcp() + + sock:settimeout(3000) + + local ok, err = sock:connect("127.0.0.1", $TEST_NGINX_RAND_PORT_1) + if not ok then + ngx.say("failed to connect: ", err) + return + end + + ngx.say("connected: ", ok) + + local sess, err = sock:sslhandshake(nil, nil, true) + if not sess then + ngx.say("failed to do SSL handshake: ", err) + return + end + + ngx.say("ssl session: ", type(sess)) + ngx.say("ssl pointer: ", type(sock:getsslpointer())) + ngx.say("ssl ctx: ", type(sock:getsslctx())) + ngx.log(ngx.INFO, "ssl pointer: ", tostring(sock:getsslpointer())) + + while true do + local line, err = sock:receive() + if not line then + -- ngx.say("failed to receive response status line: ", err) + break + end + + ngx.say("received: ", line) + end + + local ok, err = sock:close() + ngx.say("close: ", ok, " ", err) + end -- do + -- collectgarbage() + } + +--- stream_response +connected: 1 +ssl session: userdata +ssl pointer: cdata +ssl ctx: cdata +received: it works! +close: 1 nil +--- error_log eval +qr/ssl pointer: cdata: 0x[0-9a-f]+,/ +--- no_error_log +[alert] +[crit] +[error]