diff options
Diffstat (limited to 'core/certmanager.lua')
-rw-r--r-- | core/certmanager.lua | 118 |
1 files changed, 40 insertions, 78 deletions
diff --git a/core/certmanager.lua b/core/certmanager.lua index 6a46588c..9e0ace6a 100644 --- a/core/certmanager.lua +++ b/core/certmanager.lua @@ -6,15 +6,13 @@ -- COPYING file in the source package for more information. -- -local ssl = require "ssl"; -local configmanager = require "core.configmanager"; -local log = require "util.logger".init("certmanager"); -local ssl_context = ssl.context or require "ssl.context"; -local ssl_newcontext = ssl.newcontext; -local new_config = require"util.sslconfig".new; +local configmanager = require "prosody.core.configmanager"; +local log = require "prosody.util.logger".init("certmanager"); +local new_config = require"prosody.net.server".tls_builder; +local tls = require "prosody.net.tls_luasec"; local stat = require "lfs".attributes; -local x509 = require "util.x509"; +local x509 = require "prosody.util.x509"; local lfs = require "lfs"; local tonumber, tostring = tonumber, tostring; @@ -28,33 +26,10 @@ local next = next; local pcall = pcall; local prosody = prosody; -local pathutil = require"util.paths"; +local pathutil = require"prosody.util.paths"; local resolve_path = pathutil.resolve_relative_path; local config_path = prosody.paths.config or "."; -local function test_option(option) - return not not ssl_newcontext({mode="server",protocol="sslv23",options={ option }}); -end - -local luasec_major, luasec_minor = ssl._VERSION:match("^(%d+)%.(%d+)"); -local luasec_version = tonumber(luasec_major) * 100 + tonumber(luasec_minor); -local luasec_has = ssl.config or { - algorithms = { - ec = luasec_version >= 5; - }; - capabilities = { - curves_list = luasec_version >= 7; - }; - options = { - cipher_server_preference = test_option("cipher_server_preference"); - no_ticket = test_option("no_ticket"); - no_compression = test_option("no_compression"); - single_dh_use = test_option("single_dh_use"); - single_ecdh_use = test_option("single_ecdh_use"); - no_renegotiation = test_option("no_renegotiation"); - }; -}; - local _ENV = nil; -- luacheck: std none @@ -122,7 +97,7 @@ local function index_certs(dir, files_by_name, depth_limit) local firstline = f:read(); if firstline == "-----BEGIN CERTIFICATE-----" and lfs.attributes(find_matching_key(full), "mode") == "file" then f:seek("set") - local cert = ssl.loadcertificate(f:read("*a")) + local cert = tls.load_certificate(f:read("*a")) -- TODO if more than one cert is found for a name, the most recently -- issued one should be used. -- for now, just filter out expired certs @@ -207,18 +182,18 @@ local core_defaults = { protocol = "tlsv1+"; verify = "none"; options = { - cipher_server_preference = luasec_has.options.cipher_server_preference; - no_ticket = luasec_has.options.no_ticket; - no_compression = luasec_has.options.no_compression and configmanager.get("*", "ssl_compression") ~= true; - single_dh_use = luasec_has.options.single_dh_use; - single_ecdh_use = luasec_has.options.single_ecdh_use; - no_renegotiation = luasec_has.options.no_renegotiation; + cipher_server_preference = tls.features.options.cipher_server_preference; + no_ticket = tls.features.options.no_ticket; + no_compression = tls.features.options.no_compression and configmanager.get("*", "ssl_compression") ~= true; + single_dh_use = tls.features.options.single_dh_use; + single_ecdh_use = tls.features.options.single_ecdh_use; + no_renegotiation = tls.features.options.no_renegotiation; }; verifyext = { "lsec_continue", -- Continue past certificate verification errors "lsec_ignore_purpose", -- Validate client certificates as if they were server certificates }; - curve = luasec_has.algorithms.ec and not luasec_has.capabilities.curves_list and "secp384r1"; + curve = tls.features.algorithms.ec and not tls.features.capabilities.curves_list and "secp384r1"; curveslist = { "X25519", "P-384", @@ -235,9 +210,21 @@ local core_defaults = { "!3DES", -- 3DES - slow and of questionable security "!aNULL", -- Ciphers that does not authenticate the connection }; - dane = luasec_has.capabilities.dane and configmanager.get("*", "use_dane") and { "no_ee_namechecks" }; + dane = tls.features.capabilities.dane and configmanager.get("*", "use_dane") and { "no_ee_namechecks" }; } +-- https://datatracker.ietf.org/doc/html/rfc7919#appendix-A.1 +local ffdhe2048 = [[ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz ++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a +87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 +YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi +7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD +ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== +-----END DH PARAMETERS----- +]] + local mozilla_ssl_configs = { -- https://wiki.mozilla.org/Security/Server_Side_TLS -- Version 5.7 as of 2023-07-09 @@ -250,7 +237,7 @@ local mozilla_ssl_configs = { }; intermediate = { protocol = "tlsv1_2+"; - dhparam = nil; -- ffdhe2048.txt + dhparam = ffdhe2048; options = { cipher_server_preference = false }; ciphers = { "ECDHE-ECDSA-AES128-GCM-SHA256"; @@ -304,9 +291,9 @@ local mozilla_ssl_configs = { }; -if luasec_has.curves then +if tls.features.curves then for i = #core_defaults.curveslist, 1, -1 do - if not luasec_has.curves[ core_defaults.curveslist[i] ] then + if not tls.features.curves[ core_defaults.curveslist[i] ] then t_remove(core_defaults.curveslist, i); end end @@ -314,10 +301,6 @@ else core_defaults.curveslist = nil; end -local path_options = { -- These we pass through resolve_path() - key = true, certificate = true, cafile = true, capath = true, dhparam = true -} - local function create_context(host, mode, ...) local cfg = new_config(); cfg:apply(core_defaults); @@ -351,39 +334,12 @@ local function create_context(host, mode, ...) if mode == "server" then if not user_ssl_config.certificate then - log("info", "No certificate present in SSL/TLS configuration for %s. SNI will be required.", host); + log("debug", "No certificate present in SSL/TLS configuration for %s. SNI will be required.", host); end if user_ssl_config.certificate and not user_ssl_config.key then return nil, "No key present in SSL/TLS configuration for "..host; end end - for option in pairs(path_options) do - if type(user_ssl_config[option]) == "string" then - user_ssl_config[option] = resolve_path(config_path, user_ssl_config[option]); - else - user_ssl_config[option] = nil; - end - end - - -- LuaSec expects dhparam to be a callback that takes two arguments. - -- We ignore those because it is mostly used for having a separate - -- set of params for EXPORT ciphers, which we don't have by default. - if type(user_ssl_config.dhparam) == "string" then - local f, err = io_open(user_ssl_config.dhparam); - if not f then return nil, "Could not open DH parameters: "..err end - local dhparam = f:read("*a"); - f:close(); - user_ssl_config.dhparam = function() return dhparam; end - end - - local ctx, err = ssl_newcontext(user_ssl_config); - - -- COMPAT Older LuaSec ignores the cipher list from the config, so we have to take care - -- of it ourselves (W/A for #x) - if ctx and user_ssl_config.ciphers then - local success; - success, err = ssl_context.setcipher(ctx, user_ssl_config.ciphers); - if not success then ctx = nil; end - end + local ctx, err = cfg:build(); if not ctx then err = err or "invalid ssl config" @@ -422,10 +378,16 @@ end local function reload_ssl_config() global_ssl_config = configmanager.get("*", "ssl"); global_certificates = configmanager.get("*", "certificates") or "certs"; - if luasec_has.options.no_compression then + if tls.features.options.no_compression then core_defaults.options.no_compression = configmanager.get("*", "ssl_compression") ~= true; end - core_defaults.dane = configmanager.get("*", "use_dane") or false; + if not configmanager.get("*", "use_dane") then + core_defaults.dane = false; + elseif tls.features.capabilities.dane then + core_defaults.dane = { "no_ee_namechecks" }; + else + core_defaults.dane = true; + end cert_index = index_certs(resolve_path(config_path, global_certificates)); end |