diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/certmanager.lua | 6 | ||||
-rw-r--r-- | core/s2smanager.lua | 45 | ||||
-rw-r--r-- | core/sessionmanager.lua | 2 |
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 |