Skip to content

Commit ec6bd55

Browse files
author
mengxiangwei
committed
feat: add server random and master key fetch api
1 parent 5a8c479 commit ec6bd55

File tree

4 files changed

+314
-1
lines changed

4 files changed

+314
-1
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ install:
7474
- git clone https://github.com/openresty/openresty.git ../openresty
7575
- git clone https://github.com/openresty/openresty-devel-utils.git
7676
- git clone https://github.com/simpl/ngx_devel_kit.git ../ndk-nginx-module
77-
- git clone https://github.com/openresty/lua-nginx-module.git ../lua-nginx-module
77+
- git clone https://github.com/theweakgod/lua-nginx-module.git ../lua-nginx-module # TODO: revert to openresty/lua-nginx-module once the companion lua-nginx-module PR is merged
7878
- git clone https://github.com/openresty/no-pool-nginx.git ../no-pool-nginx
7979
- git clone https://github.com/openresty/echo-nginx-module.git ../echo-nginx-module
8080
- git clone https://github.com/openresty/lua-resty-lrucache.git

lib/ngx/ssl.lua

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ local ngx_lua_ffi_free_cert
4141
local ngx_lua_ffi_free_priv_key
4242
local ngx_lua_ffi_ssl_verify_client
4343
local ngx_lua_ffi_ssl_client_random
44+
local ngx_lua_ffi_ssl_server_random
45+
local ngx_lua_ffi_ssl_session_master_key
4446
local ngx_lua_ffi_ssl_export_keying_material
4547
local ngx_lua_ffi_ssl_export_keying_material_early
4648
local ngx_lua_ffi_get_req_ssl_pointer
@@ -117,6 +119,12 @@ if subsystem == 'http' then
117119
int ngx_http_lua_ffi_ssl_client_random(ngx_http_request_t *r,
118120
const unsigned char *out, size_t *outlen, char **err);
119121

122+
int ngx_http_lua_ffi_ssl_server_random(ngx_http_request_t *r,
123+
const unsigned char *out, size_t *outlen, char **err);
124+
125+
int ngx_http_lua_ffi_ssl_session_master_key(ngx_http_request_t *r,
126+
const unsigned char *out, size_t *outlen, char **err);
127+
120128
int ngx_http_lua_ffi_ssl_export_keying_material(void *r,
121129
unsigned char *out, size_t out_size,
122130
const char *label, size_t llen,
@@ -154,6 +162,8 @@ if subsystem == 'http' then
154162
ngx_lua_ffi_free_priv_key = C.ngx_http_lua_ffi_free_priv_key
155163
ngx_lua_ffi_ssl_verify_client = C.ngx_http_lua_ffi_ssl_verify_client
156164
ngx_lua_ffi_ssl_client_random = C.ngx_http_lua_ffi_ssl_client_random
165+
ngx_lua_ffi_ssl_server_random = C.ngx_http_lua_ffi_ssl_server_random
166+
ngx_lua_ffi_ssl_session_master_key = C.ngx_http_lua_ffi_ssl_session_master_key
157167
ngx_lua_ffi_ssl_export_keying_material =
158168
C.ngx_http_lua_ffi_ssl_export_keying_material
159169
ngx_lua_ffi_ssl_export_keying_material_early =
@@ -716,4 +726,58 @@ function _M.get_client_random(outlen)
716726
end
717727

718728

729+
function _M.get_server_random(outlen)
730+
local r = get_request()
731+
if not r then
732+
error("no request found")
733+
end
734+
735+
if outlen == nil then
736+
outlen = 32
737+
end
738+
739+
local out = get_string_buf(outlen)
740+
local sizep = get_size_ptr()
741+
sizep[0] = outlen
742+
743+
local rc = ngx_lua_ffi_ssl_server_random(r, out, sizep, errmsg)
744+
if rc == FFI_OK then
745+
if outlen == 0 then
746+
return tonumber(sizep[0])
747+
end
748+
749+
return ffi_str(out, sizep[0])
750+
end
751+
752+
return nil, ffi_str(errmsg[0])
753+
end
754+
755+
756+
function _M.get_session_master_key(outlen)
757+
local r = get_request()
758+
if not r then
759+
error("no request found")
760+
end
761+
762+
if outlen == nil then
763+
outlen = 48
764+
end
765+
766+
local out = get_string_buf(outlen)
767+
local sizep = get_size_ptr()
768+
sizep[0] = outlen
769+
770+
local rc = ngx_lua_ffi_ssl_session_master_key(r, out, sizep, errmsg)
771+
if rc == FFI_OK then
772+
if outlen == 0 then
773+
return tonumber(sizep[0])
774+
end
775+
776+
return ffi_str(out, sizep[0])
777+
end
778+
779+
return nil, ffi_str(errmsg[0])
780+
end
781+
782+
719783
return _M

lib/ngx/ssl.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Table of Contents
3232
* [set_priv_key](#set_priv_key)
3333
* [verify_client](#verify_client)
3434
* [get_client_random](#get_client_random)
35+
* [get_server_random](#get_server_random)
36+
* [get_session_master_key](#get_session_master_key)
3537
* [get_shared_ssl_ciphers](#get_shared_ssl_ciphers)
3638
* [get_req_ssl_pointer](#get_req_ssl_pointer)
3739
* [get_upstream_ssl_pointer](#get_upstream_ssl_pointer)
@@ -652,6 +654,40 @@ This function can be called in any context where downstream https is used, but i
652654

653655
[Back to TOC](#table-of-contents)
654656

657+
get_server_random
658+
-----------
659+
**syntax:** *server_random = ssl.get_server_random(outlen?)*
660+
661+
**context:** *any*
662+
663+
Returns the random value sent from the server to the client during the initial SSL/TLS handshake. This wraps OpenSSL's `SSL_get_server_random()`.
664+
665+
The `outlen` parameter indicates the maximum length of the server_random value returned.
666+
If the `outlen` is zero, this function returns the total length of the server_random value.
667+
If omitted, will use the value 32.
668+
669+
This function can be called in any context where downstream https is used.
670+
671+
[Back to TOC](#table-of-contents)
672+
673+
get_session_master_key
674+
-----------
675+
**syntax:** *master_key = ssl.get_session_master_key(outlen?)*
676+
677+
**context:** *any*
678+
679+
Returns the master secret from the current SSL session. This wraps OpenSSL's `SSL_SESSION_get_master_key()`.
680+
681+
The `outlen` parameter indicates the maximum length of the master key value returned.
682+
If the `outlen` is zero, this function returns the total length of the master key value.
683+
If omitted, will use the value 48 (i.e. `SSL_MAX_MASTER_KEY_LENGTH`).
684+
685+
Note that in TLS 1.3, the master secret is not used in the same way as in TLS 1.2, so this function is primarily useful for TLS 1.2 connections.
686+
687+
This function can be called in any context where downstream https is used.
688+
689+
[Back to TOC](#table-of-contents)
690+
655691
get_req_ssl_pointer
656692
------------
657693
**syntax:** *ssl_ptr, err = ssl.get_req_ssl_pointer()*

t/ssl.t

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3642,3 +3642,216 @@ lua ssl server name: "test.com"
36423642
[error]
36433643
[emerg]
36443644
[crit]
3645+
3646+
3647+
3648+
=== TEST 38: read server-random via ssl.get_server_random()
3649+
--- http_config
3650+
lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH";
3651+
3652+
server {
3653+
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
3654+
server_name test.com;
3655+
ssl_certificate_by_lua_block {
3656+
local ssl = require "ngx.ssl"
3657+
local server_random_len = ssl.get_server_random(0)
3658+
print("server-random length: ", server_random_len)
3659+
3660+
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"
3661+
local server_random = ssl.get_server_random()
3662+
if server_random == init_v then
3663+
print("maybe the server random value is incorrect")
3664+
end
3665+
}
3666+
ssl_certificate ../../cert/test.crt;
3667+
ssl_certificate_key ../../cert/test.key;
3668+
3669+
server_tokens off;
3670+
location /foo {
3671+
default_type 'text/plain';
3672+
content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)}
3673+
more_clear_headers Date;
3674+
}
3675+
}
3676+
--- config
3677+
server_tokens off;
3678+
lua_ssl_trusted_certificate ../../cert/test.crt;
3679+
3680+
location /t {
3681+
content_by_lua_block {
3682+
do
3683+
local sock = ngx.socket.tcp()
3684+
3685+
sock:settimeout(3000)
3686+
3687+
local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")
3688+
if not ok then
3689+
ngx.say("failed to connect: ", err)
3690+
return
3691+
end
3692+
3693+
ngx.say("connected: ", ok)
3694+
3695+
local sess, err = sock:sslhandshake(nil, "test.com", true)
3696+
if not sess then
3697+
ngx.say("failed to do SSL handshake: ", err)
3698+
return
3699+
end
3700+
3701+
ngx.say("ssl handshake: ", type(sess))
3702+
3703+
local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n"
3704+
local bytes, err = sock:send(req)
3705+
if not bytes then
3706+
ngx.say("failed to send http request: ", err)
3707+
return
3708+
end
3709+
3710+
ngx.say("sent http request: ", bytes, " bytes.")
3711+
3712+
while true do
3713+
local line, err = sock:receive()
3714+
if not line then
3715+
-- ngx.say("failed to receive response status line: ", err)
3716+
break
3717+
end
3718+
3719+
ngx.say("received: ", line)
3720+
end
3721+
3722+
local ok, err = sock:close()
3723+
ngx.say("close: ", ok, " ", err)
3724+
end -- do
3725+
-- collectgarbage()
3726+
}
3727+
}
3728+
3729+
--- request
3730+
GET /t
3731+
--- response_body
3732+
connected: 1
3733+
ssl handshake: cdata
3734+
sent http request: 56 bytes.
3735+
received: HTTP/1.1 201 Created
3736+
received: Server: nginx
3737+
received: Content-Type: text/plain
3738+
received: Content-Length: 4
3739+
received: Connection: close
3740+
received:
3741+
received: foo
3742+
close: 1 nil
3743+
3744+
--- error_log
3745+
server-random length: 32
3746+
3747+
--- no_error_log
3748+
[error]
3749+
[alert]
3750+
[emerg]
3751+
3752+
3753+
3754+
=== TEST 39: read session master key via ssl.get_session_master_key()
3755+
--- http_config
3756+
lua_package_path "$TEST_NGINX_LUA_PACKAGE_PATH";
3757+
3758+
server {
3759+
listen unix:$TEST_NGINX_HTML_DIR/nginx.sock ssl;
3760+
server_name test.com;
3761+
ssl_protocols TLSv1.2;
3762+
ssl_certificate_by_lua_block {
3763+
local ssl = require "ngx.ssl"
3764+
local master_key_len = ssl.get_session_master_key(0)
3765+
print("master-key length: ", master_key_len)
3766+
3767+
local master_key = ssl.get_session_master_key()
3768+
if master_key and #master_key > 0 then
3769+
print("got master key of length: ", #master_key)
3770+
end
3771+
}
3772+
ssl_certificate ../../cert/test.crt;
3773+
ssl_certificate_key ../../cert/test.key;
3774+
3775+
server_tokens off;
3776+
location /foo {
3777+
default_type 'text/plain';
3778+
content_by_lua_block {ngx.status = 201 ngx.say("foo") ngx.exit(201)}
3779+
more_clear_headers Date;
3780+
}
3781+
}
3782+
--- config
3783+
server_tokens off;
3784+
lua_ssl_trusted_certificate ../../cert/test.crt;
3785+
3786+
location /t {
3787+
content_by_lua_block {
3788+
do
3789+
local sock = ngx.socket.tcp()
3790+
3791+
sock:settimeout(3000)
3792+
3793+
local ok, err = sock:connect("unix:$TEST_NGINX_HTML_DIR/nginx.sock")
3794+
if not ok then
3795+
ngx.say("failed to connect: ", err)
3796+
return
3797+
end
3798+
3799+
ngx.say("connected: ", ok)
3800+
3801+
local sess, err = sock:sslhandshake(nil, "test.com", true)
3802+
if not sess then
3803+
ngx.say("failed to do SSL handshake: ", err)
3804+
return
3805+
end
3806+
3807+
ngx.say("ssl handshake: ", type(sess))
3808+
3809+
local req = "GET /foo HTTP/1.0\r\nHost: test.com\r\nConnection: close\r\n\r\n"
3810+
local bytes, err = sock:send(req)
3811+
if not bytes then
3812+
ngx.say("failed to send http request: ", err)
3813+
return
3814+
end
3815+
3816+
ngx.say("sent http request: ", bytes, " bytes.")
3817+
3818+
while true do
3819+
local line, err = sock:receive()
3820+
if not line then
3821+
-- ngx.say("failed to receive response status line: ", err)
3822+
break
3823+
end
3824+
3825+
ngx.say("received: ", line)
3826+
end
3827+
3828+
local ok, err = sock:close()
3829+
ngx.say("close: ", ok, " ", err)
3830+
end -- do
3831+
-- collectgarbage()
3832+
}
3833+
}
3834+
3835+
--- request
3836+
GET /t
3837+
--- response_body
3838+
connected: 1
3839+
ssl handshake: cdata
3840+
sent http request: 56 bytes.
3841+
received: HTTP/1.1 201 Created
3842+
received: Server: nginx
3843+
received: Content-Type: text/plain
3844+
received: Content-Length: 4
3845+
received: Connection: close
3846+
received:
3847+
received: foo
3848+
close: 1 nil
3849+
3850+
--- error_log
3851+
master-key length: 48
3852+
got master key of length: 48
3853+
3854+
--- no_error_log
3855+
[error]
3856+
[alert]
3857+
[emerg]

0 commit comments

Comments
 (0)