96 lines
3.7 KiB
Lua
96 lines
3.7 KiB
Lua
-- test normalization of the 'sslparams' table passed to copas.wrap()/copas.handler()
|
|
--
|
|
-- Covers the fix for https://github.com/lunarmodules/copas/issues/210:
|
|
-- * an empty (or otherwise malformed) sslparams table used to silently
|
|
-- disable TLS -- identical to passing nil -- even though the doc-comment
|
|
-- claimed it enabled TLS "with defaults". No such defaults exist (a
|
|
-- certificate is mandatory), so normalize_sslt() now only recognizes the
|
|
-- current {wrap=..., sni=...} shape by the presence of those two keys;
|
|
-- anything else (an empty table, a garbage-key table, or the legacy flat
|
|
-- luasec-context table) is passed straight through as 'wrap' parameters,
|
|
-- which LuaSec itself validates and errors on when actually used for a
|
|
-- handshake. This never fails open into silent plaintext.
|
|
-- Also checks the other supported shapes still normalize as before: no
|
|
-- params at all, the legacy flat luasec-context table, and the current
|
|
-- {wrap=..., sni=...} table.
|
|
|
|
local copas = require("copas")
|
|
local socket = require("socket")
|
|
|
|
local failures = 0
|
|
|
|
local function check(cond, msg)
|
|
if cond then
|
|
print("OK: "..msg)
|
|
else
|
|
print("FAILED: "..msg)
|
|
failures = failures + 1
|
|
end
|
|
end
|
|
|
|
-- no ssl params at all: TLS fully disabled, no error
|
|
do
|
|
local skt = copas.wrap(socket.tcp())
|
|
check(skt.ssl_params.wrap == false, "nil sslparams: wrap is false")
|
|
check(skt.ssl_params.sni == false, "nil sslparams: sni is false")
|
|
end
|
|
|
|
-- empty table: has neither 'wrap' nor 'sni' keys, so it is treated as a
|
|
-- (malformed) flat luasec-context table rather than silently disabling TLS.
|
|
-- It must never normalize to wrap==false, and using it for a handshake must
|
|
-- error rather than silently proceed unencrypted.
|
|
do
|
|
local sslt = {}
|
|
local skt = copas.wrap(socket.tcp(), sslt)
|
|
check(skt.ssl_params.wrap == sslt, "empty sslparams table: wrap is the table itself, not false")
|
|
check(skt.ssl_params.sni == false, "empty sslparams table: sni is false")
|
|
|
|
local ok, err = pcall(skt.dohandshake, skt)
|
|
check(not ok, "empty sslparams table: handshake throws instead of silently succeeding")
|
|
check(tostring(err):match("create") ~= nil,
|
|
"empty sslparams table: LuaSec's own error surfaces, got: "..tostring(err))
|
|
end
|
|
|
|
-- table with unrelated/misspelled keys: same as the empty-table case, this
|
|
-- must not be mistaken for the current {wrap=..., sni=...} format either.
|
|
do
|
|
local sslt = { just_some_key = true }
|
|
local skt = copas.wrap(socket.tcp(), sslt)
|
|
check(skt.ssl_params.wrap == sslt, "garbage-key sslparams table: wrap is the table itself, not false")
|
|
check(skt.ssl_params.sni == false, "garbage-key sslparams table: sni is false")
|
|
|
|
local ok, err = pcall(skt.dohandshake, skt)
|
|
check(not ok, "garbage-key sslparams table: handshake throws instead of silently succeeding")
|
|
check(tostring(err):match("create") ~= nil,
|
|
"garbage-key sslparams table: LuaSec's own error surfaces, got: "..tostring(err))
|
|
end
|
|
|
|
-- legacy flat table (luasec context params directly, no wrap/sni keys)
|
|
do
|
|
local sslt = {
|
|
mode = "client",
|
|
protocol = "any",
|
|
}
|
|
local skt = copas.wrap(socket.tcp(), sslt)
|
|
check(skt.ssl_params.wrap == sslt, "legacy sslparams: wrap is the sslparams table itself")
|
|
check(skt.ssl_params.sni == false, "legacy sslparams: sni is false")
|
|
end
|
|
|
|
-- current-style table with both wrap and sni set
|
|
do
|
|
local sslt = {
|
|
wrap = { mode = "client", protocol = "any" },
|
|
sni = { names = "myhost.com", strict = true },
|
|
}
|
|
local skt = copas.wrap(socket.tcp(), sslt)
|
|
check(skt.ssl_params.wrap == sslt.wrap, "current sslparams: wrap matches provided table")
|
|
check(skt.ssl_params.sni == sslt.sni, "current sslparams: sni matches provided table")
|
|
end
|
|
|
|
if failures > 0 then
|
|
print(failures.." check(s) failed")
|
|
os.exit(1)
|
|
end
|
|
|
|
print("all checks passed")
|
|
os.exit(0)
|