# HG changeset patch # User Jonas Schäfer # Date 1648890933 -7200 # Node ID 2ee27587fec7465d86275759d652529a4d2f71ac # Parent 7e9ebdc75ce4245b5aa8c5c90648dacce8f478e6 net: refactor sslconfig to not depend on LuaSec This now requires that the network backend exposes a tls_builder function, which essentially wraps the former util.sslconfig.new() function, passing a factory to create the eventual SSL context. That allows a net.server backend to pick whatever it likes as SSL context factory, as long as it understands the config table passed by the SSL config builder. Heck, a backend could even mock and replace the entire SSL config builder API. diff -r 7e9ebdc75ce4 -r 2ee27587fec7 core/certmanager.lua --- a/core/certmanager.lua Wed Apr 27 17:44:14 2022 +0200 +++ b/core/certmanager.lua Sat Apr 02 11:15:33 2022 +0200 @@ -10,7 +10,7 @@ local configmanager = require "core.configmanager"; local log = require "util.logger".init("certmanager"); local ssl_newcontext = ssl.newcontext; -local new_config = require"util.sslconfig".new; +local new_config = require"net.server".tls_builder; local stat = require "lfs".attributes; local x509 = require "util.x509"; diff -r 7e9ebdc75ce4 -r 2ee27587fec7 net/server.lua --- a/net/server.lua Wed Apr 27 17:44:14 2022 +0200 +++ b/net/server.lua Sat Apr 02 11:15:33 2022 +0200 @@ -118,6 +118,13 @@ prosody.events.add_handler("config-reloaded", load_config); end +local tls_builder = server.tls_builder; +-- resolving the basedir here avoids util.sslconfig depending on +-- prosody.paths.config +function server.tls_builder() + return tls_builder(prosody.paths.config or "") +end + -- require "net.server" shall now forever return this, -- ie. server_select or server_event as chosen above. return server; diff -r 7e9ebdc75ce4 -r 2ee27587fec7 net/server_epoll.lua --- a/net/server_epoll.lua Wed Apr 27 17:44:14 2022 +0200 +++ b/net/server_epoll.lua Sat Apr 02 11:15:33 2022 +0200 @@ -27,6 +27,8 @@ local _SOCKETINVALID = socket._SOCKETINVALID or -1; local new_id = require "util.id".short; local xpcall = require "util.xpcall".xpcall; +local sslconfig = require "util.sslconfig"; +local tls_impl = require "net.tls_luasec"; local poller = require "util.poll" local EEXIST = poller.EEXIST; @@ -1104,6 +1106,10 @@ cfg = setmetatable(newconfig, default_config); end; + tls_builder = function(basedir) + return sslconfig._new(tls_impl.new_context, basedir) + end, + -- libevent emulation event = { EV_READ = "r", EV_WRITE = "w", EV_READWRITE = "rw", EV_LEAVE = -1 }; addevent = function (fd, mode, callback) diff -r 7e9ebdc75ce4 -r 2ee27587fec7 net/server_event.lua --- a/net/server_event.lua Wed Apr 27 17:44:14 2022 +0200 +++ b/net/server_event.lua Sat Apr 02 11:15:33 2022 +0200 @@ -52,6 +52,8 @@ local levent = require "luaevent.core" local inet = require "util.net"; local inet_pton = inet.pton; +local sslconfig = require "util.sslconfig"; +local tls_impl = require "net.tls_luasec"; local socket_gettime = socket.gettime @@ -944,6 +946,10 @@ add_task = add_task, watchfd = watchfd, + tls_builder = function(basedir) + return sslconfig._new(tls_impl.new_context, basedir) + end, + __NAME = SCRIPT_NAME, __DATE = LAST_MODIFIED, __AUTHOR = SCRIPT_AUTHOR, diff -r 7e9ebdc75ce4 -r 2ee27587fec7 net/server_select.lua --- a/net/server_select.lua Wed Apr 27 17:44:14 2022 +0200 +++ b/net/server_select.lua Sat Apr 02 11:15:33 2022 +0200 @@ -52,6 +52,8 @@ local luasocket_gettime = luasocket.gettime local inet = require "util.net"; local inet_pton = inet.pton; +local sslconfig = require "util.sslconfig"; +local tls_impl = require "net.tls_luasec"; --// extern lib methods //-- @@ -1181,4 +1183,8 @@ removeserver = removeserver, get_backend = get_backend, changesettings = changesettings, + + tls_builder = function(basedir) + return sslconfig._new(tls_impl.new_context, basedir) + end, } diff -r 7e9ebdc75ce4 -r 2ee27587fec7 util/sslconfig.lua --- a/util/sslconfig.lua Wed Apr 27 17:44:14 2022 +0200 +++ b/util/sslconfig.lua Sat Apr 02 11:15:33 2022 +0200 @@ -8,12 +8,8 @@ local t_concat = table.concat; local t_insert = table.insert; local setmetatable = setmetatable; -local config_path = prosody.paths.config or "."; local resolve_path = require"util.paths".resolve_relative_path; --- TODO: use net.server directly here -local tls_impl = require"net.tls_luasec"; - local _ENV = nil; -- luacheck: std none @@ -78,9 +74,9 @@ finalisers.ciphersuites = finalisers.ciphers; -- Path expansion -function finalisers.key(path) +function finalisers.key(path, config) if type(path) == "string" then - return resolve_path(config_path, path); + return resolve_path(config._basedir, path); else return nil end @@ -110,11 +106,13 @@ -- Merge options from 'new' config into 'config' local function apply(config, new) - -- 0 == cache - rawset(config, 0, nil); + rawset(config, "_cache", nil); if type(new) == "table" then for field, value in pairs(new) do - (handlers[field] or rawset)(config, field, value); + -- exclude keys which are internal to the config builder + if field:sub(1, 1) ~= "_" then + (handlers[field] or rawset)(config, field, value); + end end end return config @@ -124,7 +122,10 @@ local function final(config) local output = { }; for field, value in pairs(config) do - output[field] = (finalisers[field] or id)(value); + -- exclude keys which are internal to the config builder + if field:sub(1, 1) ~= "_" then + output[field] = (finalisers[field] or id)(value, config); + end end -- Need to handle protocols last because it adds to the options list protocol(output); @@ -132,14 +133,14 @@ end local function build(config) - local cached = rawget(config, 0); + local cached = rawget(config, "_cache"); if cached then return cached, nil end - local ctx, err = tls_impl.new_context(config:final(), config); + local ctx, err = rawget(config, "_context_factory")(config:final(), config); if ctx then - rawset(config, 0, ctx); + rawset(config, "_cache", ctx); end return ctx, err end @@ -156,13 +157,21 @@ }; -local function new() - return setmetatable({options={}}, sslopts_mt); +-- passing basedir through everything is required to avoid sslconfig depending +-- on prosody.paths.config +local function new(context_factory, basedir) + return setmetatable({ + _context_factory = context_factory, + _basedir = basedir, + options={}, + }, sslopts_mt); end local function clone(config) local result = new(); for k, v in pairs(config) do + -- note that we *do* copy the internal keys on clone -- we have to carry + -- both the factory and the cache with us rawset(result, k, v); end return result @@ -173,5 +182,5 @@ return { apply = apply; final = final; - new = new; + _new = new; };