IMPORTANT: due to a drive failure, as of 13-Mar-2021, the Mercurial repository had to be re-mirrored, which changed every commit SHA. The old SHAs and trees are backed up in the vault branches. Please migrate to the new branches as soon as you can.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
prosody/plugins/mod_dialback.lua

127 lines
4.5 KiB

-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local hosts = _G.hosts;
local send_s2s = require "core.s2smanager".send_to_host;
local s2s_make_authenticated = require "core.s2smanager".make_authenticated;
local s2s_initiate_dialback = require "core.s2smanager".initiate_dialback;
local s2s_verify_dialback = require "core.s2smanager".verify_dialback;
local s2s_destroy_session = require "core.s2smanager".destroy_session;
local log = module._log;
local st = require "util.stanza";
local xmlns_stream = "http://etherx.jabber.org/streams";
local xmlns_dialback = "jabber:server:dialback";
local dialback_requests = setmetatable({}, { __mode = 'v' });
module:add_handler({"s2sin_unauthed", "s2sin"}, "verify", xmlns_dialback,
function (origin, stanza)
-- We are being asked to verify the key, to ensure it was generated by us
origin.log("debug", "verifying that dialback key is ours...");
local attr = stanza.attr;
-- COMPAT: Grr, ejabberd breaks this one too?? it is black and white in XEP-220 example 34
--if attr.from ~= origin.to_host then error("invalid-from"); end
local type;
if s2s_verify_dialback(attr.id, attr.from, attr.to, stanza[1]) then
type = "valid"
else
type = "invalid"
origin.log("warn", "Asked to verify a dialback key that was incorrect. An imposter is claiming to be %s?", attr.to);
end
origin.log("debug", "verified dialback key... it is %s", type);
origin.sends2s(st.stanza("db:verify", { from = attr.to, to = attr.from, id = attr.id, type = type }):text(stanza[1]));
end);
module:add_handler({ "s2sin_unauthed", "s2sin" }, "result", xmlns_dialback,
function (origin, stanza)
-- he wants to be identified through dialback
-- We need to check the key with the Authoritative server
local attr = stanza.attr;
origin.hosts[attr.from] = { dialback_key = stanza[1] };
if not hosts[attr.to] then
-- Not a host that we serve
origin.log("info", "%s tried to connect to %s, which we don't serve", attr.from, attr.to);
origin:close("host-unknown");
return;
end
dialback_requests[attr.from] = origin;
if not origin.from_host then
-- Just used for friendlier logging
origin.from_host = attr.from;
end
if not origin.to_host then
-- Just used for friendlier logging
origin.to_host = attr.to;
end
origin.log("debug", "asking %s if key %s belongs to them", attr.from, stanza[1]);
send_s2s(attr.to, attr.from,
st.stanza("db:verify", { from = attr.to, to = attr.from, id = origin.streamid }):text(stanza[1]));
end);
module:add_handler({ "s2sout_unauthed", "s2sout" }, "verify", xmlns_dialback,
function (origin, stanza)
local attr = stanza.attr;
local dialback_verifying = dialback_requests[attr.from];
if dialback_verifying then
local valid;
if attr.type == "valid" then
s2s_make_authenticated(dialback_verifying, attr.from);
valid = "valid";
else
-- Warn the original connection that is was not verified successfully
log("warn", "authoritative server for "..(attr.from or "(unknown)").." denied the key");
valid = "invalid";
end
if not dialback_verifying.sends2s then
log("warn", "Incoming s2s session %s was closed in the meantime, so we can't notify it of the db result", tostring(dialback_verifying):match("%w+$"));
else
dialback_verifying.sends2s(
st.stanza("db:result", { from = attr.to, to = attr.from, id = attr.id, type = valid })
:text(dialback_verifying.hosts[attr.from].dialback_key));
end
dialback_requests[attr.from] = nil;
end
end);
module:add_handler({ "s2sout_unauthed", "s2sout" }, "result", xmlns_dialback,
function (origin, stanza)
-- Remote server is telling us whether we passed dialback
local attr = stanza.attr;
if not hosts[attr.to] then
origin:close("host-unknown");
return;
elseif hosts[attr.to].s2sout[attr.from] ~= origin then
-- This isn't right
origin:close("invalid-id");
return;
end
if stanza.attr.type == "valid" then
s2s_make_authenticated(origin, attr.from);
else
s2s_destroy_session(origin)
end
end);
module:hook_stanza(xmlns_stream, "features", function (origin, stanza)
s2s_initiate_dialback(origin);
return true;
end, 100);
-- Offer dialback to incoming hosts
module:hook("s2s-stream-features", function (data)
data.features:tag("dialback", { xmlns='urn:xmpp:features:dialback' }):tag("optional"):up():up();
end);