| 1 | -- Prosody IM |
| 2 | -- Copyright (C) 2008-2010 Matthew Wild |
| 3 | -- Copyright (C) 2008-2010 Waqas Hussain |
| 4 | -- |
| 5 | -- This project is MIT/X11 licensed. Please see the |
| 6 | -- COPYING file in the source package for more information. |
| 7 | -- |
| 8 | |
| 9 | local configmanager = require "core.configmanager"; |
| 10 | local log = require "util.logger".init("certmanager"); |
| 11 | local ssl = ssl; |
| 12 | local ssl_newcontext = ssl and ssl.newcontext; |
| 13 | |
| 14 | local setmetatable, tostring = setmetatable, tostring; |
| 15 | |
| 16 | local prosody = prosody; |
| 17 | local resolve_path = configmanager.resolve_relative_path; |
| 18 | local config_path = prosody.paths.config; |
| 19 | |
| 20 | module "certmanager" |
| 21 | |
| 22 | -- Global SSL options if not overridden per-host |
| 23 | local default_ssl_config = configmanager.get("*", "core", "ssl"); |
| 24 | local default_capath = "/etc/ssl/certs"; |
| 25 | local default_verify = (ssl and ssl.x509 and { "peer", "client_once", "continue", "ignore_purpose" }) or "none"; |
| 26 | local default_options = { "no_sslv2" }; |
| 27 | |
| 28 | function create_context(host, mode, user_ssl_config) |
| 29 | user_ssl_config = user_ssl_config or default_ssl_config; |
| 30 | |
| 31 | if not ssl then return nil, "LuaSec (required for encryption) was not found"; end |
| 32 | if not user_ssl_config then return nil, "No SSL/TLS configuration present for "..host; end |
| 33 | |
| 34 | local ssl_config = { |
| 35 | mode = mode; |
| 36 | protocol = user_ssl_config.protocol or "sslv23"; |
| 37 | key = resolve_path(config_path, user_ssl_config.key); |
| 38 | password = user_ssl_config.password; |
| 39 | certificate = resolve_path(config_path, user_ssl_config.certificate); |
| 40 | capath = resolve_path(config_path, user_ssl_config.capath or default_capath); |
| 41 | cafile = resolve_path(config_path, user_ssl_config.cafile); |
| 42 | verify = user_ssl_config.verify or default_verify; |
| 43 | options = user_ssl_config.options or default_options; |
| 44 | ciphers = user_ssl_config.ciphers; |
| 45 | depth = user_ssl_config.depth; |
| 46 | }; |
| 47 | |
| 48 | local ctx, err = ssl_newcontext(ssl_config); |
| 49 | if not ctx then |
| 50 | err = err or "invalid ssl config" |
| 51 | local file = err:match("^error loading (.-) %("); |
| 52 | if file then |
| 53 | if file == "private key" then |
| 54 | file = ssl_config.key or "your private key"; |
| 55 | elseif file == "certificate" then |
| 56 | file = ssl_config.certificate or "your certificate file"; |
| 57 | end |
| 58 | local reason = err:match("%((.+)%)$") or "some reason"; |
| 59 | if reason == "Permission denied" then |
| 60 | reason = "Check that the permissions allow Prosody to read this file."; |
| 61 | elseif reason == "No such file or directory" then |
| 62 | reason = "Check that the path is correct, and the file exists."; |
| 63 | elseif reason == "system lib" then |
| 64 | reason = "Previous error (see logs), or other system error."; |
| 65 | elseif reason == "(null)" or not reason then |
| 66 | reason = "Check that the file exists and the permissions are correct"; |
| 67 | else |
| 68 | reason = "Reason: "..tostring(reason):lower(); |
| 69 | end |
| 70 | log("error", "SSL/TLS: Failed to load %s: %s", file, reason); |
| 71 | else |
| 72 | log("error", "SSL/TLS: Error initialising for host %s: %s", host, err ); |
| 73 | end |
| 74 | end |
| 75 | return ctx, err; |
| 76 | end |
| 77 | |
| 78 | function reload_ssl_config() |
| 79 | default_ssl_config = configmanager.get("*", "core", "ssl"); |
| 80 | end |
| 81 | |
| 82 | prosody.events.add_handler("config-reloaded", reload_ssl_config); |
| 83 | |
| 84 | return _M; |