net/tls_luasec.lua
author Jonas Schäfer <jonas@wielicki.name>
Wed, 27 Apr 2022 17:44:14 +0200
changeset 12484 7e9ebdc75ce4
child 12490 ee93df086926
permissions -rw-r--r--
net: isolate LuaSec-specifics For this, various accessor functions are now provided directly on the sockets, which reach down into the LuaSec implementation to obtain the information. While this may seem of little gain at first, it hides the implementation detail of the LuaSec+LuaSocket combination that the actual socket and the TLS layer are separate objects. The net gain here is that an alternative implementation does not have to emulate that specific implementation detail and "only" has to expose LuaSec-compatible data structures on the new functions.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12484
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
     1
-- Prosody IM
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
     2
-- Copyright (C) 2021 Prosody folks
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
     3
--
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
     4
-- This project is MIT/X11 licensed. Please see the
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
     5
-- COPYING file in the source package for more information.
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
     6
--
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
     7
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
     8
--[[
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
     9
This file provides a shim abstraction over LuaSec, consolidating some code
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    10
which was previously spread between net.server backends, portmanager and
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    11
certmanager.
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    12
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    13
The goal is to provide a more or less well-defined API on top of LuaSec which
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    14
abstracts away some of the things which are not needed and simplifies usage of
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    15
commonly used things (such as SNI contexts). Eventually, network backends
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    16
which do not rely on LuaSocket+LuaSec should be able to provide *this* API
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    17
instead of having to mimic LuaSec.
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    18
]]
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    19
local softreq = require"util.dependencies".softreq;
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    20
local ssl = softreq"ssl";
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    21
local ssl_newcontext = ssl.newcontext;
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    22
local ssl_context = ssl.context or softreq"ssl.context";
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    23
local io_open = io.open;
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    24
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    25
local context_api = {};
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    26
local context_mt = {__index = context_api};
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    27
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    28
function context_api:set_sni_host(host, cert, key)
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    29
	local ctx, err = self._builder:clone():apply({
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    30
		certificate = cert,
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    31
		key = key,
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    32
	}):build();
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    33
	if not ctx then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    34
		return false, err
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    35
	end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    36
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    37
	self._sni_contexts[host] = ctx._inner
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    38
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    39
	return true, nil
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    40
end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    41
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    42
function context_api:remove_sni_host(host)
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    43
	self._sni_contexts[host] = nil
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    44
end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    45
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    46
function context_api:wrap(sock)
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    47
	local ok, conn, err = pcall(ssl.wrap, sock, self._inner);
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    48
	if not ok then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    49
		return nil, err
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    50
	end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    51
	return conn, nil
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    52
end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    53
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    54
local function new_context(cfg, builder)
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    55
	-- LuaSec expects dhparam to be a callback that takes two arguments.
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    56
	-- We ignore those because it is mostly used for having a separate
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    57
	-- set of params for EXPORT ciphers, which we don't have by default.
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    58
	if type(cfg.dhparam) == "string" then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    59
		local f, err = io_open(cfg.dhparam);
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    60
		if not f then return nil, "Could not open DH parameters: "..err end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    61
		local dhparam = f:read("*a");
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    62
		f:close();
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    63
		cfg.dhparam = function() return dhparam; end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    64
	end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    65
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    66
	local inner, err = ssl_newcontext(cfg);
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    67
	if not inner then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    68
		return nil, err
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    69
	end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    70
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    71
	-- COMPAT Older LuaSec ignores the cipher list from the config, so we have to take care
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    72
	-- of it ourselves (W/A for #x)
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    73
	if inner and cfg.ciphers then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    74
		local success;
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    75
		success, err = ssl_context.setcipher(inner, cfg.ciphers);
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    76
		if not success then
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    77
			return nil, err
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    78
		end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    79
	end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    80
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    81
	return setmetatable({
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    82
		_inner = inner,
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    83
		_builder = builder,
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    84
		_sni_contexts = {},
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    85
	}, context_mt), nil
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    86
end
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    87
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    88
return {
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    89
	new_context = new_context,
7e9ebdc75ce4 net: isolate LuaSec-specifics
Jonas Schäfer <jonas@wielicki.name>
parents:
diff changeset
    90
};