# HG changeset patch # User Thijs Alkemade # Date 1378465677 -7200 # Node ID 5eaecb7f680d36e9bbafd94c40d011ae61955a2d # Parent d677d1807bb065a77e12dfc96c44d8681e3bfd65 mod_watchuntrusted: New module that will warn admins about s2s connections that fail due to lack of encryption or invalid certificates. diff -r d677d1807bb0 -r 5eaecb7f680d mod_watchuntrusted/mod_watchuntrusted.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_watchuntrusted/mod_watchuntrusted.lua Fri Sep 06 13:07:57 2013 +0200 @@ -0,0 +1,56 @@ +local jid_prep = require "util.jid".prep; + +local secure_auth = module:get_option_boolean("s2s_secure_auth", false); +local secure_domains, insecure_domains = + module:get_option_set("s2s_secure_domains", {})._items, module:get_option_set("s2s_insecure_domains", {})._items; + +local untrusted_fail_watchers = module:get_option_set("untrusted_fail_watchers", module:get_option("admins", {})) / jid_prep; +local untrusted_fail_notification = module:get_option("untrusted_fail_notification", "Establishing a secure connection from $from_host to $to_host failed. Certificate hash: $sha1. $errors"); + +local st = require "util.stanza"; + +module:hook_global("s2s-check-certificate", function (event) + local session, host = event.session, event.host; + local conn = session.conn:socket(); + local local_host = session.direction == "outgoing" and session.from_host or session.to_host; + + if not (local_host == module:get_host()) then return end + + module:log("debug", "Checking certificate..."); + local must_secure = secure_auth; + + if not must_secure and secure_domains[host] then + must_secure = true; + elseif must_secure and insecure_domains[host] then + must_secure = false; + end + + if must_secure and (session.cert_chain_status ~= "valid" or session.cert_identity_status ~= "valid") then + local _, errors = conn:getpeerverification(); + local error_message = ""; + + for depth, t in pairs(errors or {}) do + if #t > 0 then + error_message = error_message .. "Error with certificate " .. (depth - 1) .. ": " .. table.concat(t, ", ") .. ". "; + end + end + + if session.cert_identity_status then + error_message = error_message .. "This certificate is " .. session.cert_identity_status .. " for " .. host .. "."; + end + + local replacements = { sha1 = event.cert and event.cert:digest("sha1"), errors = error_message }; + + local message = st.message{ type = "chat", from = local_host } + :tag("body") + :text(untrusted_fail_notification:gsub("%$([%w_]+)", function (v) + return event[v] or session and session[v] or replacements and replacements[v] or nil; + end)); + for jid in untrusted_fail_watchers do + module:log("debug", "Notifying %s", jid); + message.attr.to = jid; + module:send(message); + end + end +end, -0.5); +