Mercurial > prosody-hg
comparison core/certmanager.lua @ 14219:7f4fcbb1bbe4 13.0
certmanager: Drop embedded Mozilla TLSRef data in favour of util.tlsref
This adds a 'tls_profile_version' configuration option. If unspecified, it
will use the default profile version from util.tlsref. If specified, it must
be either a valid version (known to util.tlsref) or the value "latest".
This allows admins to pin to specific versions, go with the default (for the
best balance between security/stability) or always use the latest available
profiles.
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Fri, 12 Jun 2026 13:04:23 +0100 |
| parents | 4aed38a1c971 |
| children | 565debd9c37a |
comparison
equal
deleted
inserted
replaced
| 14218:926f25af2ffe | 14219:7f4fcbb1bbe4 |
|---|---|
| 9 local configmanager = require "prosody.core.configmanager"; | 9 local configmanager = require "prosody.core.configmanager"; |
| 10 local log = require "prosody.util.logger".init("certmanager"); | 10 local log = require "prosody.util.logger".init("certmanager"); |
| 11 local new_config = require"prosody.net.server".tls_builder; | 11 local new_config = require"prosody.net.server".tls_builder; |
| 12 local tls = require "prosody.net.tls_luasec"; | 12 local tls = require "prosody.net.tls_luasec"; |
| 13 local stat = require "lfs".attributes; | 13 local stat = require "lfs".attributes; |
| 14 | |
| 15 local tlsref = require "prosody.util.tlsref"; | |
| 14 | 16 |
| 15 local x509 = require "prosody.util.x509"; | 17 local x509 = require "prosody.util.x509"; |
| 16 local lfs = require "lfs"; | 18 local lfs = require "lfs"; |
| 17 | 19 |
| 18 local tonumber, tostring = tonumber, tostring; | 20 local tonumber, tostring = tonumber, tostring; |
| 214 "!aNULL", -- Ciphers that does not authenticate the connection | 216 "!aNULL", -- Ciphers that does not authenticate the connection |
| 215 }; | 217 }; |
| 216 dane = tls.features.capabilities.dane and configmanager.get("*", "use_dane") and { "no_ee_namechecks" }; | 218 dane = tls.features.capabilities.dane and configmanager.get("*", "use_dane") and { "no_ee_namechecks" }; |
| 217 } | 219 } |
| 218 | 220 |
| 219 -- https://datatracker.ietf.org/doc/html/rfc7919#appendix-A.1 | |
| 220 local ffdhe2048 = [[ | |
| 221 -----BEGIN DH PARAMETERS----- | |
| 222 MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz | |
| 223 +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a | |
| 224 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 | |
| 225 YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi | |
| 226 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD | |
| 227 ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== | |
| 228 -----END DH PARAMETERS----- | |
| 229 ]] | |
| 230 | |
| 231 local mozilla_ssl_configs = { | |
| 232 -- https://wiki.mozilla.org/Security/Server_Side_TLS | |
| 233 -- Version 5.7 as of 2023-07-09 | |
| 234 modern = { | |
| 235 protocol = "tlsv1_3"; | |
| 236 options = { cipher_server_preference = false }; | |
| 237 ciphers = "DEFAULT"; -- TLS 1.3 uses 'ciphersuites' rather than these | |
| 238 curveslist = { "X25519"; "prime256v1"; "secp384r1" }; | |
| 239 ciphersuites = { "TLS_AES_128_GCM_SHA256"; "TLS_AES_256_GCM_SHA384"; "TLS_CHACHA20_POLY1305_SHA256" }; | |
| 240 }; | |
| 241 intermediate = { | |
| 242 protocol = "tlsv1_2+"; | |
| 243 dhparam = ffdhe2048; | |
| 244 options = { cipher_server_preference = false }; | |
| 245 ciphers = { | |
| 246 "ECDHE-ECDSA-AES128-GCM-SHA256"; | |
| 247 "ECDHE-RSA-AES128-GCM-SHA256"; | |
| 248 "ECDHE-ECDSA-AES256-GCM-SHA384"; | |
| 249 "ECDHE-RSA-AES256-GCM-SHA384"; | |
| 250 "ECDHE-ECDSA-CHACHA20-POLY1305"; | |
| 251 "ECDHE-RSA-CHACHA20-POLY1305"; | |
| 252 "DHE-RSA-AES128-GCM-SHA256"; | |
| 253 "DHE-RSA-AES256-GCM-SHA384"; | |
| 254 "DHE-RSA-CHACHA20-POLY1305"; | |
| 255 }; | |
| 256 curveslist = { "X25519"; "prime256v1"; "secp384r1" }; | |
| 257 ciphersuites = { "TLS_AES_128_GCM_SHA256"; "TLS_AES_256_GCM_SHA384"; "TLS_CHACHA20_POLY1305_SHA256" }; | |
| 258 }; | |
| 259 old = { | |
| 260 protocol = "tlsv1+"; | |
| 261 dhparam = nil; -- openssl dhparam 1024 | |
| 262 options = { cipher_server_preference = true }; | |
| 263 ciphers = { | |
| 264 "ECDHE-ECDSA-AES128-GCM-SHA256"; | |
| 265 "ECDHE-RSA-AES128-GCM-SHA256"; | |
| 266 "ECDHE-ECDSA-AES256-GCM-SHA384"; | |
| 267 "ECDHE-RSA-AES256-GCM-SHA384"; | |
| 268 "ECDHE-ECDSA-CHACHA20-POLY1305"; | |
| 269 "ECDHE-RSA-CHACHA20-POLY1305"; | |
| 270 "DHE-RSA-AES128-GCM-SHA256"; | |
| 271 "DHE-RSA-AES256-GCM-SHA384"; | |
| 272 "DHE-RSA-CHACHA20-POLY1305"; | |
| 273 "ECDHE-ECDSA-AES128-SHA256"; | |
| 274 "ECDHE-RSA-AES128-SHA256"; | |
| 275 "ECDHE-ECDSA-AES128-SHA"; | |
| 276 "ECDHE-RSA-AES128-SHA"; | |
| 277 "ECDHE-ECDSA-AES256-SHA384"; | |
| 278 "ECDHE-RSA-AES256-SHA384"; | |
| 279 "ECDHE-ECDSA-AES256-SHA"; | |
| 280 "ECDHE-RSA-AES256-SHA"; | |
| 281 "DHE-RSA-AES128-SHA256"; | |
| 282 "DHE-RSA-AES256-SHA256"; | |
| 283 "AES128-GCM-SHA256"; | |
| 284 "AES256-GCM-SHA384"; | |
| 285 "AES128-SHA256"; | |
| 286 "AES256-SHA256"; | |
| 287 "AES128-SHA"; | |
| 288 "AES256-SHA"; | |
| 289 "DES-CBC3-SHA"; | |
| 290 }; | |
| 291 curveslist = { "X25519"; "prime256v1"; "secp384r1" }; | |
| 292 ciphersuites = { "TLS_AES_128_GCM_SHA256"; "TLS_AES_256_GCM_SHA384"; "TLS_CHACHA20_POLY1305_SHA256" }; | |
| 293 }; | |
| 294 }; | |
| 295 | |
| 296 | |
| 297 if tls.features.curves then | 221 if tls.features.curves then |
| 298 for i = #core_defaults.curveslist, 1, -1 do | 222 for i = #core_defaults.curveslist, 1, -1 do |
| 299 if not tls.features.curves[ core_defaults.curveslist[i] ] then | 223 if not tls.features.curves[ core_defaults.curveslist[i] ] then |
| 300 t_remove(core_defaults.curveslist, i); | 224 t_remove(core_defaults.curveslist, i); |
| 301 end | 225 end |
| 319 cfg:apply({ | 243 cfg:apply({ |
| 320 mode = mode, | 244 mode = mode, |
| 321 -- We can't read the password interactively when daemonized | 245 -- We can't read the password interactively when daemonized |
| 322 password = function() log("error", "Encrypted certificate for %s requires 'ssl' 'password' to be set in config", host); end; | 246 password = function() log("error", "Encrypted certificate for %s requires 'ssl' 'password' to be set in config", host); end; |
| 323 }); | 247 }); |
| 324 local profile = configmanager.get("*", "tls_profile") or "intermediate"; | 248 local profile_version = configmanager.get("*", "tls_profile_version"); |
| 325 if mozilla_ssl_configs[profile] then | 249 local profile_name = configmanager.get("*", "tls_profile"); |
| 326 cfg:apply(mozilla_ssl_configs[profile]); | 250 |
| 327 elseif profile ~= "legacy" then | 251 if profile_name ~= "legacy" then |
| 328 log("error", "Invalid value for 'tls_profile': expected one of \"modern\", \"intermediate\" (default), \"old\" or \"legacy\" but got %q", profile); | 252 local tls_profile, tls_profile_err = tlsref.get_profile(profile_version, profile_name); |
| 329 return nil, "Invalid configuration, 'tls_profile' had an unknown value."; | 253 if not tls_profile then |
| 254 if tls_profile_err == "unknown-version" then | |
| 255 log( | |
| 256 "error", | |
| 257 "Invalid value %q for 'tls_profile_version': expected one of: \"%s\" or \"latest\"", | |
| 258 profile_version, | |
| 259 tlsref.get_valid_versions():concat("\", \"") | |
| 260 ); | |
| 261 return nil, "Invalid configuration, 'tls_profile_version' had an unknown value."; | |
| 262 elseif tls_profile_err == "unknown-profile" then | |
| 263 log( | |
| 264 "error", | |
| 265 "Invalid value %q for 'tls_profile': expected one of \"%s\" or \"legacy\" (default: %q)", | |
| 266 profile_name, | |
| 267 tlsref.get_valid_profile_names(profile_version):concat("\", \""), | |
| 268 tlsref.get_default_profile_name(profile_version) | |
| 269 ); | |
| 270 return nil, "Invalid configuration, 'tls_profile' had an unknown value."; | |
| 271 end | |
| 272 else | |
| 273 cfg:apply(tls_profile); | |
| 274 end | |
| 330 end | 275 end |
| 331 cfg:apply(global_ssl_config); | 276 cfg:apply(global_ssl_config); |
| 332 | 277 |
| 333 for i = select('#', ...), 1, -1 do | 278 for i = select('#', ...), 1, -1 do |
| 334 cfg:apply(select(i, ...)); | 279 cfg:apply(select(i, ...)); |
