aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/certmanager.lua6
-rw-r--r--core/s2smanager.lua45
-rw-r--r--core/sessionmanager.lua2
3 files changed, 46 insertions, 7 deletions
diff --git a/core/certmanager.lua b/core/certmanager.lua
index 7f1ca42e..0dc0bfd4 100644
--- a/core/certmanager.lua
+++ b/core/certmanager.lua
@@ -22,6 +22,8 @@ module "certmanager"
-- Global SSL options if not overridden per-host
local default_ssl_config = configmanager.get("*", "core", "ssl");
local default_capath = "/etc/ssl/certs";
+local default_verify = (ssl and ssl.x509 and { "peer", "client_once", "continue", "ignore_purpose" }) or "none";
+local default_options = { "no_sslv2" };
function create_context(host, mode, user_ssl_config)
user_ssl_config = user_ssl_config or default_ssl_config;
@@ -37,8 +39,8 @@ function create_context(host, mode, user_ssl_config)
certificate = resolve_path(config_path, user_ssl_config.certificate);
capath = resolve_path(config_path, user_ssl_config.capath or default_capath);
cafile = resolve_path(config_path, user_ssl_config.cafile);
- verify = user_ssl_config.verify or "none";
- options = user_ssl_config.options or "no_sslv2";
+ verify = user_ssl_config.verify or default_verify;
+ options = user_ssl_config.options or default_options;
ciphers = user_ssl_config.ciphers;
depth = user_ssl_config.depth;
};
diff --git a/core/s2smanager.lua b/core/s2smanager.lua
index fd9a72d0..c87540e4 100644
--- a/core/s2smanager.lua
+++ b/core/s2smanager.lua
@@ -27,6 +27,7 @@ local modulemanager = require "core.modulemanager";
local st = require "stanza";
local stanza = st.stanza;
local nameprep = require "util.encodings".stringprep.nameprep;
+local cert_verify_identity = require "util.x509".verify_identity;
local fire_event = prosody.events.fire_event;
local uuid_gen = require "util.uuid".generate;
@@ -392,23 +393,54 @@ function session_open_stream(session, from, to)
from=from, to=to, version='1.0', ["xml:lang"]='en'}):top_tag());
end
+local function check_cert_status(session)
+ local conn = session.conn:socket()
+ local cert
+ if conn.getpeercertificate then
+ cert = conn:getpeercertificate()
+ end
+
+ if cert then
+ local chain_valid, err = conn:getpeerchainvalid()
+ if not chain_valid then
+ session.cert_chain_status = "invalid";
+ (session.log or log)("debug", "certificate chain validation result: %s", err);
+ else
+ session.cert_chain_status = "valid";
+
+ local host = session.direction == "incoming" and session.from_host or session.to_host
+
+ -- We'll go ahead and verify the asserted identity if the
+ -- connecting server specified one.
+ if host then
+ if cert_verify_identity(host, "xmpp-server", cert) then
+ session.cert_identity_status = "valid"
+ else
+ session.cert_identity_status = "invalid"
+ end
+ end
+ end
+ end
+end
+
function streamopened(session, attr)
local send = session.sends2s;
-- TODO: #29: SASL/TLS on s2s streams
session.version = tonumber(attr.version) or 0;
+ -- TODO: Rename session.secure to session.encrypted
if session.secure == false then
session.secure = true;
end
-
+
if session.direction == "incoming" then
-- Send a reply stream header
session.to_host = attr.to and nameprep(attr.to);
session.from_host = attr.from and nameprep(attr.from);
session.streamid = uuid_gen();
- (session.log or log)("debug", "incoming s2s received <stream:stream>");
+ (session.log or log)("debug", "Incoming s2s received <stream:stream>");
if session.to_host then
if not hosts[session.to_host] then
-- Attempting to connect to a host we don't serve
@@ -426,6 +458,9 @@ function streamopened(session, attr)
return;
end
end
+
+ if session.secure and not session.cert_chain_status then check_cert_status(session); end
+
send("<?xml version='1.0'?>");
send(stanza("stream:stream", { xmlns='jabber:server', ["xmlns:db"]='jabber:server:dialback',
["xmlns:stream"]='http://etherx.jabber.org/streams', id=session.streamid, from=session.to_host, to=session.from_host, version=(session.version > 0 and "1.0" or nil) }):top_tag());
@@ -445,7 +480,9 @@ function streamopened(session, attr)
-- If we are just using the connection for verifying dialback keys, we won't try and auth it
if not attr.id then error("stream response did not give us a streamid!!!"); end
session.streamid = attr.id;
-
+
+ if session.secure and not session.cert_chain_status then check_cert_status(session); end
+
-- Send unauthed buffer
-- (stanzas which are fine to send before dialback)
-- Note that this is *not* the stanza queue (which
@@ -588,7 +625,7 @@ end
function destroy_session(session, reason)
if session.destroyed then return; end
- (session.log or log)("debug", "Destroying "..tostring(session.direction).." session "..tostring(session.from_host).."->"..tostring(session.to_host));
+ (session.log or log)("debug", "Destroying "..tostring(session.direction).." session "..tostring(session.from_host).."->"..tostring(session.to_host)..(reason and (": "..reason) or ""));
if session.direction == "outgoing" then
hosts[session.from_host].s2sout[session.to_host] = nil;
diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua
index 426763f5..e9f81d82 100644
--- a/core/sessionmanager.lua
+++ b/core/sessionmanager.lua
@@ -103,7 +103,7 @@ function retire_session(session)
end
function destroy_session(session, err)
- (session.log or log)("info", "Destroying session for %s (%s@%s)", session.full_jid or "(unknown)", session.username or "(unknown)", session.host or "(unknown)");
+ (session.log or log)("info", "Destroying session for %s (%s@%s)%s", session.full_jid or "(unknown)", session.username or "(unknown)", session.host or "(unknown)", err and (": "..err) or "");
if session.destroyed then return; end
-- Remove session/resource from user's session list