core/certmanager.lua

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;