Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ install:
- git clone https://github.com/openresty/openresty.git ../openresty
- git clone https://github.com/openresty/openresty-devel-utils.git
- git clone https://github.com/simpl/ngx_devel_kit.git ../ndk-nginx-module
- git clone https://github.com/openresty/lua-nginx-module.git ../lua-nginx-module
- 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
- git clone https://github.com/openresty/no-pool-nginx.git ../no-pool-nginx
- git clone https://github.com/openresty/echo-nginx-module.git ../echo-nginx-module
- git clone https://github.com/openresty/lua-resty-lrucache.git
Expand Down
65 changes: 65 additions & 0 deletions lib/ngx/ssl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ 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
local ngx_lua_ffi_ssl_server_random
local ngx_lua_ffi_ssl_session_master_key
local ngx_lua_ffi_ssl_export_keying_material
local ngx_lua_ffi_ssl_export_keying_material_early
local ngx_lua_ffi_get_req_ssl_pointer
Expand Down Expand Up @@ -117,6 +119,12 @@ if subsystem == 'http' then
int ngx_http_lua_ffi_ssl_client_random(ngx_http_request_t *r,
const unsigned char *out, size_t *outlen, char **err);

int ngx_http_lua_ffi_ssl_server_random(ngx_http_request_t *r,
const unsigned char *out, size_t *outlen, char **err);

int ngx_http_lua_ffi_ssl_session_master_key(ngx_http_request_t *r,
const unsigned char *out, size_t *outlen, char **err);

int ngx_http_lua_ffi_ssl_export_keying_material(void *r,
unsigned char *out, size_t out_size,
const char *label, size_t llen,
Expand Down Expand Up @@ -154,6 +162,9 @@ if subsystem == 'http' then
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
ngx_lua_ffi_ssl_server_random = C.ngx_http_lua_ffi_ssl_server_random
ngx_lua_ffi_ssl_session_master_key =
C.ngx_http_lua_ffi_ssl_session_master_key
ngx_lua_ffi_ssl_export_keying_material =
C.ngx_http_lua_ffi_ssl_export_keying_material
ngx_lua_ffi_ssl_export_keying_material_early =
Expand Down Expand Up @@ -716,4 +727,58 @@ function _M.get_client_random(outlen)
end


function _M.get_server_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_server_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


function _M.get_session_master_key(outlen)
local r = get_request()
if not r then
error("no request found")
end

if outlen == nil then
outlen = 48
end

local out = get_string_buf(outlen)
local sizep = get_size_ptr()
sizep[0] = outlen

local rc = ngx_lua_ffi_ssl_session_master_key(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
36 changes: 36 additions & 0 deletions lib/ngx/ssl.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ Table of Contents
* [set_priv_key](#set_priv_key)
* [verify_client](#verify_client)
* [get_client_random](#get_client_random)
* [get_server_random](#get_server_random)
* [get_session_master_key](#get_session_master_key)
* [get_shared_ssl_ciphers](#get_shared_ssl_ciphers)
* [get_req_ssl_pointer](#get_req_ssl_pointer)
* [get_upstream_ssl_pointer](#get_upstream_ssl_pointer)
Expand Down Expand Up @@ -652,6 +654,40 @@ This function can be called in any context where downstream https is used, but i

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

get_server_random
-----------
**syntax:** *server_random = ssl.get_server_random(outlen?)*

**context:** *any*

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()`.

The `outlen` parameter indicates the maximum length of the server_random value returned.
If the `outlen` is zero, this function returns the total length of the server_random value.
If omitted, will use the value 32.

This function can be called in any context where downstream https is used.

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

get_session_master_key
-----------
**syntax:** *master_key = ssl.get_session_master_key(outlen?)*

**context:** *any*

Returns the master secret from the current SSL session. This wraps OpenSSL's `SSL_SESSION_get_master_key()`.

The `outlen` parameter indicates the maximum length of the master key value returned.
If the `outlen` is zero, this function returns the total length of the master key value.
If omitted, will use the value 48 (i.e. `SSL_MAX_MASTER_KEY_LENGTH`).

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.

This function can be called in any context where downstream https is used.

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

get_req_ssl_pointer
------------
**syntax:** *ssl_ptr, err = ssl.get_req_ssl_pointer()*
Expand Down
222 changes: 221 additions & 1 deletion t/ssl.t
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use t::TestCore;

repeat_each(2);

plan tests => repeat_each() * (blocks() * 6 );
plan tests => repeat_each() * (blocks() * 6);

no_long_string();
#no_diff();
Expand Down Expand Up @@ -3642,3 +3642,223 @@ lua ssl server name: "test.com"
[error]
[emerg]
[crit]



=== TEST 38: read server-random via ssl.get_server_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 server_random_len = ssl.get_server_random(0)
print("server-random length: ", server_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 server_random = ssl.get_server_random()
if server_random == init_v then
print("maybe the server 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
server-random length: 32

--- no_error_log
[error]
[alert]
[emerg]



=== TEST 39: read session master key via ssl.get_session_master_key()
--- 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_protocols TLSv1.2;
ssl_certificate_by_lua_block {
local ssl = require "ngx.ssl"
ssl.clear_certs()
ssl.set_der_cert(ssl.cert_pem_to_der(
assert(io.open("t/cert/test.crt")):read("*a")))
ssl.set_der_priv_key(ssl.priv_key_pem_to_der(
assert(io.open("t/cert/test.key")):read("*a")))
}

ssl_certificate ../../cert/test.crt;
ssl_certificate_key ../../cert/test.key;

server_tokens off;
location /foo {
default_type 'text/plain';
content_by_lua_block {
local ssl = require "ngx.ssl"
local mk_len = ssl.get_session_master_key(0)
ngx.say("master-key length: ", mk_len)

local mk = ssl.get_session_master_key()
if mk and #mk > 0 then
ngx.say("got master key of length: ",
#mk)
end
}
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
break
end

ngx.say("received: ", line)
end

local ok, err = sock:close()
ngx.say("close: ", ok, " ", err)
end -- do
}
}

--- request
GET /t
--- response_body
connected: 1
ssl handshake: cdata
sent http request: 56 bytes.
received: HTTP/1.1 200 OK
received: Server: nginx
received: Content-Type: text/plain
received: Content-Length: 51
received: Connection: close
received:
received: master-key length: 48
received: got master key of length: 48
close: 1 nil

--- error_log
lua ssl server name: "test.com"

--- no_error_log
[error]
[alert]
[emerg]
Loading