Mercurial > prosody-hg
comparison core/certmanager.lua @ 6081:19ada596aec4
Merge 0.10->trunk
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Tue, 15 Apr 2014 20:36:39 +0200 |
| parents | b7d1607df87d |
| children | 821756a862b0 |
comparison
equal
deleted
inserted
replaced
| 6072:ce5428f6e3c3 | 6081:19ada596aec4 |
|---|---|
| 13 | 13 |
| 14 local tostring = tostring; | 14 local tostring = tostring; |
| 15 local pairs = pairs; | 15 local pairs = pairs; |
| 16 local type = type; | 16 local type = type; |
| 17 local io_open = io.open; | 17 local io_open = io.open; |
| 18 local t_concat = table.concat; | |
| 18 | 19 |
| 19 local prosody = prosody; | 20 local prosody = prosody; |
| 20 local resolve_path = configmanager.resolve_relative_path; | 21 local resolve_path = configmanager.resolve_relative_path; |
| 21 local config_path = prosody.paths.config; | 22 local config_path = prosody.paths.config; |
| 22 | 23 |
| 31 module "certmanager" | 32 module "certmanager" |
| 32 | 33 |
| 33 -- Global SSL options if not overridden per-host | 34 -- Global SSL options if not overridden per-host |
| 34 local global_ssl_config = configmanager.get("*", "ssl"); | 35 local global_ssl_config = configmanager.get("*", "ssl"); |
| 35 | 36 |
| 37 -- Built-in defaults | |
| 36 local core_defaults = { | 38 local core_defaults = { |
| 37 capath = "/etc/ssl/certs"; | 39 capath = "/etc/ssl/certs"; |
| 38 protocol = "sslv23"; | 40 protocol = "tlsv1+"; |
| 39 verify = (ssl and ssl.x509 and { "peer", "client_once", }) or "none"; | 41 verify = (ssl and ssl.x509 and { "peer", "client_once", }) or "none"; |
| 40 options = { "no_sslv2", "no_sslv3", "cipher_server_preference", luasec_has_noticket and "no_ticket" or nil }; | 42 options = { |
| 43 cipher_server_preference = true; | |
| 44 no_ticket = luasec_has_noticket; | |
| 45 no_compression = luasec_has_no_compression and configmanager.get("*", "ssl_compression") ~= true; | |
| 46 -- Has no_compression? Then it has these too... | |
| 47 single_dh_use = luasec_has_no_compression; | |
| 48 single_ecdh_use = luasec_has_no_compression; | |
| 49 }; | |
| 41 verifyext = { "lsec_continue", "lsec_ignore_purpose" }; | 50 verifyext = { "lsec_continue", "lsec_ignore_purpose" }; |
| 42 curve = "secp384r1"; | 51 curve = "secp384r1"; |
| 43 ciphers = "HIGH+kEDH:HIGH+kEECDH:HIGH:!PSK:!SRP:!3DES:!aNULL"; | 52 ciphers = "HIGH+kEDH:HIGH+kEECDH:HIGH:!PSK:!SRP:!3DES:!aNULL"; |
| 44 } | 53 } |
| 45 local path_options = { -- These we pass through resolve_path() | 54 local path_options = { -- These we pass through resolve_path() |
| 46 key = true, certificate = true, cafile = true, capath = true, dhparam = true | 55 key = true, certificate = true, cafile = true, capath = true, dhparam = true |
| 47 } | 56 } |
| 57 local set_options = { | |
| 58 options = true, verify = true, verifyext = true | |
| 59 } | |
| 48 | 60 |
| 49 if ssl and not luasec_has_verifyext and ssl.x509 then | 61 if ssl and not luasec_has_verifyext and ssl.x509 then |
| 50 -- COMPAT mw/luasec-hg | 62 -- COMPAT mw/luasec-hg |
| 51 for i=1,#core_defaults.verifyext do -- Remove lsec_ prefix | 63 for i=1,#core_defaults.verifyext do -- Remove lsec_ prefix |
| 52 core_defaults.verify[#core_defaults.verify+1] = core_defaults.verifyext[i]:sub(6); | 64 core_defaults.verify[#core_defaults.verify+1] = core_defaults.verifyext[i]:sub(6); |
| 53 end | 65 end |
| 54 end | 66 end |
| 55 | 67 |
| 56 if luasec_has_no_compression then -- Has no_compression? Then it has these too... | 68 local function merge_set(t, o) |
| 57 core_defaults.options[#core_defaults.options+1] = "single_dh_use"; | 69 if type(t) ~= "table" then t = { t } end |
| 58 core_defaults.options[#core_defaults.options+1] = "single_ecdh_use"; | 70 for k,v in pairs(t) do |
| 59 if configmanager.get("*", "ssl_compression") ~= true then | 71 if v == true or v == false then |
| 60 core_defaults.options[#core_defaults.options+1] = "no_compression"; | 72 o[k] = v; |
| 61 end | 73 else |
| 62 end | 74 o[v] = true; |
| 75 end | |
| 76 end | |
| 77 return o; | |
| 78 end | |
| 79 | |
| 80 local protocols = { "sslv2", "sslv3", "tlsv1", "tlsv1_1", "tlsv1_2" }; | |
| 81 for i = 1, #protocols do protocols[protocols[i] .. "+"] = i - 1; end | |
| 63 | 82 |
| 64 function create_context(host, mode, user_ssl_config) | 83 function create_context(host, mode, user_ssl_config) |
| 65 user_ssl_config = user_ssl_config or {} | 84 user_ssl_config = user_ssl_config or {} |
| 66 user_ssl_config.mode = mode; | 85 user_ssl_config.mode = mode; |
| 67 | 86 |
| 68 if not ssl then return nil, "LuaSec (required for encryption) was not found"; end | 87 if not ssl then return nil, "LuaSec (required for encryption) was not found"; end |
| 69 | 88 |
| 70 if global_ssl_config then | 89 if global_ssl_config then |
| 71 for option,default_value in pairs(global_ssl_config) do | 90 for option,default_value in pairs(global_ssl_config) do |
| 72 if not user_ssl_config[option] then | 91 if user_ssl_config[option] == nil then |
| 73 user_ssl_config[option] = default_value; | 92 user_ssl_config[option] = default_value; |
| 74 end | 93 end |
| 75 end | 94 end |
| 76 end | 95 end |
| 96 | |
| 77 for option,default_value in pairs(core_defaults) do | 97 for option,default_value in pairs(core_defaults) do |
| 78 if not user_ssl_config[option] then | 98 if user_ssl_config[option] == nil then |
| 79 user_ssl_config[option] = default_value; | 99 user_ssl_config[option] = default_value; |
| 80 end | 100 end |
| 81 end | 101 end |
| 82 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; | 102 |
| 103 local min_protocol = protocols[user_ssl_config.protocol]; | |
| 104 if min_protocol then | |
| 105 user_ssl_config.protocol = "sslv23"; | |
| 106 for i = min_protocol, 1, -1 do | |
| 107 user_ssl_config.options["no_"..protocols[i]] = true; | |
| 108 end | |
| 109 end | |
| 110 | |
| 111 for option in pairs(set_options) do | |
| 112 local merged = {}; | |
| 113 merge_set(core_defaults[option], merged); | |
| 114 merge_set(global_ssl_config[option], merged); | |
| 115 merge_set(user_ssl_config[option], merged); | |
| 116 local final_array = {}; | |
| 117 for opt, enable in pairs(merged) do | |
| 118 if enable then | |
| 119 final_array[#final_array+1] = opt; | |
| 120 end | |
| 121 end | |
| 122 user_ssl_config[option] = final_array; | |
| 123 end | |
| 124 | |
| 125 -- We can't read the password interactively when daemonized | |
| 126 user_ssl_config.password = user_ssl_config.password or | |
| 127 function() log("error", "Encrypted certificate for %s requires 'ssl' 'password' to be set in config", host); end; | |
| 128 | |
| 83 for option in pairs(path_options) do | 129 for option in pairs(path_options) do |
| 84 if type(user_ssl_config[option]) == "string" then | 130 if type(user_ssl_config[option]) == "string" then |
| 85 user_ssl_config[option] = resolve_path(config_path, user_ssl_config[option]); | 131 user_ssl_config[option] = resolve_path(config_path, user_ssl_config[option]); |
| 86 end | 132 end |
| 87 end | 133 end |
| 88 | 134 |
| 89 if not user_ssl_config.key then return nil, "No key present in SSL/TLS configuration for "..host; end | 135 -- Allow the cipher list to be a table |
| 90 if not user_ssl_config.certificate then return nil, "No certificate present in SSL/TLS configuration for "..host; end | 136 if type(user_ssl_config.ciphers) == "table" then |
| 137 user_ssl_config.ciphers = t_concat(user_ssl_config.ciphers, ":") | |
| 138 end | |
| 139 | |
| 140 if mode == "server" then | |
| 141 if not user_ssl_config.key then return nil, "No key present in SSL/TLS configuration for "..host; end | |
| 142 if not user_ssl_config.certificate then return nil, "No certificate present in SSL/TLS configuration for "..host; end | |
| 143 end | |
| 91 | 144 |
| 92 -- LuaSec expects dhparam to be a callback that takes two arguments. | 145 -- LuaSec expects dhparam to be a callback that takes two arguments. |
| 93 -- We ignore those because it is mostly used for having a separate | 146 -- We ignore those because it is mostly used for having a separate |
| 94 -- set of params for EXPORT ciphers, which we don't have by default. | 147 -- set of params for EXPORT ciphers, which we don't have by default. |
| 95 if type(user_ssl_config.dhparam) == "string" then | 148 if type(user_ssl_config.dhparam) == "string" then |
| 139 return ctx, err; | 192 return ctx, err; |
| 140 end | 193 end |
| 141 | 194 |
| 142 function reload_ssl_config() | 195 function reload_ssl_config() |
| 143 global_ssl_config = configmanager.get("*", "ssl"); | 196 global_ssl_config = configmanager.get("*", "ssl"); |
| 197 if luasec_has_no_compression then | |
| 198 core_defaults.options.no_compression = configmanager.get("*", "ssl_compression") ~= true; | |
| 199 end | |
| 144 end | 200 end |
| 145 | 201 |
| 146 prosody.events.add_handler("config-reloaded", reload_ssl_config); | 202 prosody.events.add_handler("config-reloaded", reload_ssl_config); |
| 147 | 203 |
| 148 return _M; | 204 return _M; |
