Software /
code /
prosody
Comparison
core/certmanager.lua @ 5684:5554029d759b
certmanager: Overhaul of how ssl configs are built.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 13 Jun 2013 17:44:42 +0200 |
parent | 5679:51f7de1b6bb5 |
child | 5746:3137751751b4 |
comparison
equal
deleted
inserted
replaced
5683:624b874059bf | 5684:5554029d759b |
---|---|
10 local log = require "util.logger".init("certmanager"); | 10 local log = require "util.logger".init("certmanager"); |
11 local ssl = ssl; | 11 local ssl = ssl; |
12 local ssl_newcontext = ssl and ssl.newcontext; | 12 local ssl_newcontext = ssl and ssl.newcontext; |
13 | 13 |
14 local tostring = tostring; | 14 local tostring = tostring; |
15 local pairs = pairs; | |
15 | 16 |
16 local prosody = prosody; | 17 local prosody = prosody; |
17 local resolve_path = configmanager.resolve_relative_path; | 18 local resolve_path = configmanager.resolve_relative_path; |
18 local config_path = prosody.paths.config; | 19 local config_path = prosody.paths.config; |
19 | 20 |
26 end | 27 end |
27 | 28 |
28 module "certmanager" | 29 module "certmanager" |
29 | 30 |
30 -- Global SSL options if not overridden per-host | 31 -- Global SSL options if not overridden per-host |
31 local default_ssl_config = configmanager.get("*", "ssl"); | 32 local global_ssl_config = configmanager.get("*", "ssl"); |
32 local default_capath = "/etc/ssl/certs"; | 33 |
33 local default_verify = (ssl and ssl.x509 and { "peer", "client_once", }) or "none"; | 34 local core_defaults = { |
34 local default_options = { "no_sslv2", luasec_has_noticket and "no_ticket" or nil }; | 35 capath = "/etc/ssl/certs"; |
35 local default_verifyext = { "lsec_continue", "lsec_ignore_purpose" }; | 36 protocol = "sslv23"; |
37 verify = (ssl and ssl.x509 and { "peer", "client_once", }) or "none"; | |
38 options = { "no_sslv2", luasec_has_noticket and "no_ticket" or nil }; | |
39 verifyext = { "lsec_continue", "lsec_ignore_purpose" }; | |
40 curve = "secp384r1"; | |
41 } | |
42 local path_options = { -- These we pass through resolve_path() | |
43 key = true, certificate = true, cafile = true, capath = true | |
44 } | |
36 | 45 |
37 if ssl and not luasec_has_verifyext and ssl.x509 then | 46 if ssl and not luasec_has_verifyext and ssl.x509 then |
38 -- COMPAT mw/luasec-hg | 47 -- COMPAT mw/luasec-hg |
39 for i=1,#default_verifyext do -- Remove lsec_ prefix | 48 for i=1,#core_defaults.verifyext do -- Remove lsec_ prefix |
40 default_verify[#default_verify+1] = default_verifyext[i]:sub(6); | 49 core_defaults.verify[#core_defaults.verify+1] = core_defaults.verifyext[i]:sub(6); |
41 end | 50 end |
42 end | 51 end |
52 | |
43 if luasec_has_no_compression and configmanager.get("*", "ssl_compression") ~= true then | 53 if luasec_has_no_compression and configmanager.get("*", "ssl_compression") ~= true then |
44 default_options[#default_options+1] = "no_compression"; | 54 core_defaults.options[#core_defaults.options+1] = "no_compression"; |
45 end | |
46 | |
47 if luasec_has_no_compression then -- Has no_compression? Then it has these too... | |
48 default_options[#default_options+1] = "single_dh_use"; | |
49 default_options[#default_options+1] = "single_ecdh_use"; | |
50 end | 55 end |
51 | 56 |
52 function create_context(host, mode, user_ssl_config) | 57 function create_context(host, mode, user_ssl_config) |
53 user_ssl_config = user_ssl_config or default_ssl_config; | 58 user_ssl_config = user_ssl_config or {} |
59 user_ssl_config.mode = mode; | |
54 | 60 |
55 if not ssl then return nil, "LuaSec (required for encryption) was not found"; end | 61 if not ssl then return nil, "LuaSec (required for encryption) was not found"; end |
56 if not user_ssl_config then return nil, "No SSL/TLS configuration present for "..host; end | 62 |
63 if global_ssl_config then | |
64 for option,default_value in pairs(global_ssl_config) do | |
65 if not user_ssl_config[option] then | |
66 user_ssl_config[option] = default_value; | |
67 end | |
68 end | |
69 end | |
70 for option,default_value in pairs(core_defaults) do | |
71 if not user_ssl_config[option] then | |
72 user_ssl_config[option] = default_value; | |
73 end | |
74 end | |
75 user_ssl_config.password = user_ssl_config.password or function() log("error", "Encrypted certificate for %s requires 'ssl' 'password' to be set in config", host); end; | |
76 for option in pairs(path_options) do | |
77 user_ssl_config[option] = user_ssl_config[option] and resolve_path(config_path, user_ssl_config[option]); | |
78 end | |
79 | |
57 if not user_ssl_config.key then return nil, "No key present in SSL/TLS configuration for "..host; end | 80 if not user_ssl_config.key then return nil, "No key present in SSL/TLS configuration for "..host; end |
58 if not user_ssl_config.certificate then return nil, "No certificate present in SSL/TLS configuration for "..host; end | 81 if not user_ssl_config.certificate then return nil, "No certificate present in SSL/TLS configuration for "..host; end |
59 | |
60 local ssl_config = { | |
61 mode = mode; | |
62 protocol = user_ssl_config.protocol or "sslv23"; | |
63 key = resolve_path(config_path, user_ssl_config.key); | |
64 password = user_ssl_config.password or function() log("error", "Encrypted certificate for %s requires 'ssl' 'password' to be set in config", host); end; | |
65 certificate = resolve_path(config_path, user_ssl_config.certificate); | |
66 capath = resolve_path(config_path, user_ssl_config.capath or default_capath); | |
67 cafile = resolve_path(config_path, user_ssl_config.cafile); | |
68 verify = user_ssl_config.verify or default_verify; | |
69 verifyext = user_ssl_config.verifyext or default_verifyext; | |
70 options = user_ssl_config.options or default_options; | |
71 depth = user_ssl_config.depth; | |
72 curve = user_ssl_config.curve or "secp384r1"; | |
73 dhparam = user_ssl_config.dhparam; | |
74 }; | |
75 | 82 |
76 local ctx, err = ssl_newcontext(ssl_config); | 83 local ctx, err = ssl_newcontext(user_ssl_config); |
77 | 84 |
78 -- LuaSec ignores the cipher list from the config, so we have to take care | 85 -- COMPAT Older LuaSec ignores the cipher list from the config, so we have to take care |
79 -- of it ourselves (W/A for #x) | 86 -- of it ourselves (W/A for #x) |
80 if ctx and user_ssl_config.ciphers then | 87 if ctx and user_ssl_config.ciphers then |
81 local success; | 88 local success; |
82 success, err = ssl.context.setcipher(ctx, user_ssl_config.ciphers); | 89 success, err = ssl.context.setcipher(ctx, user_ssl_config.ciphers); |
83 if not success then ctx = nil; end | 90 if not success then ctx = nil; end |
86 if not ctx then | 93 if not ctx then |
87 err = err or "invalid ssl config" | 94 err = err or "invalid ssl config" |
88 local file = err:match("^error loading (.-) %("); | 95 local file = err:match("^error loading (.-) %("); |
89 if file then | 96 if file then |
90 if file == "private key" then | 97 if file == "private key" then |
91 file = ssl_config.key or "your private key"; | 98 file = user_ssl_config.key or "your private key"; |
92 elseif file == "certificate" then | 99 elseif file == "certificate" then |
93 file = ssl_config.certificate or "your certificate file"; | 100 file = user_ssl_config.certificate or "your certificate file"; |
94 end | 101 end |
95 local reason = err:match("%((.+)%)$") or "some reason"; | 102 local reason = err:match("%((.+)%)$") or "some reason"; |
96 if reason == "Permission denied" then | 103 if reason == "Permission denied" then |
97 reason = "Check that the permissions allow Prosody to read this file."; | 104 reason = "Check that the permissions allow Prosody to read this file."; |
98 elseif reason == "No such file or directory" then | 105 elseif reason == "No such file or directory" then |
111 end | 118 end |
112 return ctx, err; | 119 return ctx, err; |
113 end | 120 end |
114 | 121 |
115 function reload_ssl_config() | 122 function reload_ssl_config() |
116 default_ssl_config = configmanager.get("*", "ssl"); | 123 global_ssl_config = configmanager.get("*", "ssl"); |
117 end | 124 end |
118 | 125 |
119 prosody.events.add_handler("config-reloaded", reload_ssl_config); | 126 prosody.events.add_handler("config-reloaded", reload_ssl_config); |
120 | 127 |
121 return _M; | 128 return _M; |