From a16f55c36c235eab357962b7026afce6c25cb1b7 Mon Sep 17 00:00:00 2001 From: Ruidong-X Date: Fri, 8 Mar 2024 15:41:40 +0800 Subject: [PATCH] feature: add ssl.get_client_random. Signed-off-by: xuruidong Co-authored-by: lijunlong --- lib/ngx/ssl.lua | 36 ++++++++++++++++ t/ssl.t | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ t/stream/ssl.t | 79 ++++++++++++++++++++++++++++++++++++ 3 files changed, 221 insertions(+) diff --git a/lib/ngx/ssl.lua b/lib/ngx/ssl.lua index 0cf038c4b..234902647 100644 --- a/lib/ngx/ssl.lua +++ b/lib/ngx/ssl.lua @@ -39,6 +39,7 @@ local ngx_lua_ffi_set_priv_key local ngx_lua_ffi_free_cert local ngx_lua_ffi_free_priv_key local ngx_lua_ffi_ssl_verify_client +local ngx_lua_ffi_ssl_client_random if subsystem == 'http' then @@ -95,6 +96,9 @@ if subsystem == 'http' then int ngx_http_lua_ffi_ssl_verify_client(void *r, void *cdata, int depth, char **err); + + int ngx_http_lua_ffi_ssl_client_random(ngx_http_request_t *r, + const unsigned char *out, size_t *outlen, char **err); ]] ngx_lua_ffi_ssl_set_der_certificate = @@ -118,6 +122,7 @@ if subsystem == 'http' then ngx_lua_ffi_free_cert = C.ngx_http_lua_ffi_free_cert ngx_lua_ffi_free_priv_key = C.ngx_http_lua_ffi_free_priv_key ngx_lua_ffi_ssl_verify_client = C.ngx_http_lua_ffi_ssl_verify_client + ngx_lua_ffi_ssl_client_random = C.ngx_http_lua_ffi_ssl_client_random elseif subsystem == 'stream' then ffi.cdef[[ @@ -174,6 +179,9 @@ elseif subsystem == 'stream' then int ngx_stream_lua_ffi_ssl_verify_client(void *r, void *cdata, int depth, char **err); + + int ngx_stream_lua_ffi_ssl_client_random(ngx_stream_lua_request_t *r, + unsigned char *out, size_t *outlen, char **err); ]] ngx_lua_ffi_ssl_set_der_certificate = @@ -197,6 +205,7 @@ elseif subsystem == 'stream' then ngx_lua_ffi_free_cert = C.ngx_stream_lua_ffi_free_cert ngx_lua_ffi_free_priv_key = C.ngx_stream_lua_ffi_free_priv_key ngx_lua_ffi_ssl_verify_client = C.ngx_stream_lua_ffi_ssl_verify_client + ngx_lua_ffi_ssl_client_random = C.ngx_stream_lua_ffi_ssl_client_random end @@ -505,4 +514,31 @@ do end +function _M.get_client_random(outlen) + local r = get_request() + if not r then + error("no request found") + end + + if outlen == nil then + outlen = 32 + end + + local out = get_string_buf(outlen) + local sizep = get_size_ptr() + sizep[0] = outlen + + local rc = ngx_lua_ffi_ssl_client_random(r, out, sizep, errmsg) + if rc == FFI_OK then + if outlen == 0 then + return tonumber(sizep[0]) + end + + return ffi_str(out, sizep[0]) + end + + return nil, ffi_str(errmsg[0]) +end + + return _M diff --git a/t/ssl.t b/t/ssl.t index 8f750ca90..f73efd08c 100644 --- a/t/ssl.t +++ b/t/ssl.t @@ -2970,3 +2970,109 @@ lua ssl server name: "test.com" [error] [alert] [emerg] + + + +=== TEST 30: read client-random via ssl.get_client_random() +--- 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_by_lua_block { + local ssl = require "ngx.ssl" + local client_random_len = ssl.get_client_random(0) + print("client-random length: ", client_random_len) + + local init_v = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + local client_random = ssl.get_client_random() + if client_random == init_v then + print("maybe the client random value is incorrect") + end + } + 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)) + + 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 +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 +client-random length: 32 + +--- no_error_log +[error] +[alert] +[emerg] diff --git a/t/stream/ssl.t b/t/stream/ssl.t index 793b804bd..eaeb434fa 100644 --- a/t/stream/ssl.t +++ b/t/stream/ssl.t @@ -2245,3 +2245,82 @@ lua ssl server name: "test.com" [error] [alert] [emerg] + + + +=== TEST 28: read client random via ssl.get_client_random() +--- stream_config + lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH"; + + server { + listen 127.0.0.1:$TEST_NGINX_RAND_PORT_1 ssl; + ssl_certificate_by_lua_block { + local ssl = require "ngx.ssl" + local client_random_len = ssl.get_client_random(0) + print("client-random length: ", client_random_len) + + local init_v = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + local client_random = ssl.get_client_random() + if client_random == init_v then + print("maybe the client random value is incorrect") + end + } + 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; + + 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 handshake: ", type(sess)) + + 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 handshake: userdata +received: it works! +close: 1 nil + +--- error_log +client-random length: 32 + +--- no_error_log +[error] +[alert] +[emerg]