Comparison

plugins/mod_dialback.lua @ 4567:24617f360200

mod_dialback: import util.hashes and functionality once in s2smanager.
author Florian Zeitz <florob@babelmonkeys.de>
date Fri, 24 Feb 2012 15:20:03 +0000
parent 4316:2478698bdc52
child 4579:5650c290fe8e
comparison
equal deleted inserted replaced
4566:afd09bfa0884 4567:24617f360200
4 -- 4 --
5 -- This project is MIT/X11 licensed. Please see the 5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information. 6 -- COPYING file in the source package for more information.
7 -- 7 --
8 8
9 local format = string.format;
9 10
10 local hosts = _G.hosts; 11 local hosts = _G.hosts;
11 local send_s2s = require "core.s2smanager".send_to_host; 12 local send_s2s = require "core.s2smanager".send_to_host;
12 local s2s_make_authenticated = require "core.s2smanager".make_authenticated; 13 local s2s_make_authenticated = require "core.s2smanager".make_authenticated;
13 local s2s_initiate_dialback = require "core.s2smanager".initiate_dialback;
14 local s2s_verify_dialback = require "core.s2smanager".verify_dialback;
15 14
16 local log = module._log; 15 local log = module._log;
17 16
18 local st = require "util.stanza"; 17 local st = require "util.stanza";
18 local sha256_hash = require "util.hashes".sha256;
19 19
20 local xmlns_stream = "http://etherx.jabber.org/streams"; 20 local xmlns_stream = "http://etherx.jabber.org/streams";
21 local xmlns_dialback = "jabber:server:dialback"; 21 local xmlns_dialback = "jabber:server:dialback";
22 22
23 local dialback_requests = setmetatable({}, { __mode = 'v' }); 23 local dialback_requests = setmetatable({}, { __mode = 'v' });
24
25 function generate_dialback(id, to, from)
26 return sha256_hash(id..to..from..hosts[from].dialback_secret, true);
27 end
28
29 function initiate_dialback(session)
30 -- generate dialback key
31 session.dialback_key = generate_dialback(session.streamid, session.to_host, session.from_host);
32 session.sends2s(format("<db:result from='%s' to='%s'>%s</db:result>", session.from_host, session.to_host, session.dialback_key));
33 session.log("info", "sent dialback key on outgoing s2s stream");
34 end
35
36 function verify_dialback(id, to, from, key)
37 return key == generate_dialback(id, to, from);
38 end
24 39
25 module:hook("stanza/jabber:server:dialback:verify", function(event) 40 module:hook("stanza/jabber:server:dialback:verify", function(event)
26 local origin, stanza = event.origin, event.stanza; 41 local origin, stanza = event.origin, event.stanza;
27 42
28 if origin.type == "s2sin_unauthed" or origin.type == "s2sin" then 43 if origin.type == "s2sin_unauthed" or origin.type == "s2sin" then
30 origin.log("debug", "verifying that dialback key is ours..."); 45 origin.log("debug", "verifying that dialback key is ours...");
31 local attr = stanza.attr; 46 local attr = stanza.attr;
32 -- COMPAT: Grr, ejabberd breaks this one too?? it is black and white in XEP-220 example 34 47 -- COMPAT: Grr, ejabberd breaks this one too?? it is black and white in XEP-220 example 34
33 --if attr.from ~= origin.to_host then error("invalid-from"); end 48 --if attr.from ~= origin.to_host then error("invalid-from"); end
34 local type; 49 local type;
35 if s2s_verify_dialback(attr.id, attr.from, attr.to, stanza[1]) then 50 if verify_dialback(attr.id, attr.from, attr.to, stanza[1]) then
36 type = "valid" 51 type = "valid"
37 else 52 else
38 type = "invalid" 53 type = "invalid"
39 origin.log("warn", "Asked to verify a dialback key that was incorrect. An imposter is claiming to be %s?", attr.to); 54 origin.log("warn", "Asked to verify a dialback key that was incorrect. An imposter is claiming to be %s?", attr.to);
40 end 55 end
70 -- Just used for friendlier logging 85 -- Just used for friendlier logging
71 origin.to_host = attr.to; 86 origin.to_host = attr.to;
72 end 87 end
73 88
74 origin.log("debug", "asking %s if key %s belongs to them", attr.from, stanza[1]); 89 origin.log("debug", "asking %s if key %s belongs to them", attr.from, stanza[1]);
75 send_s2s(attr.to, attr.from, 90 --send_s2s(attr.to, attr.from,
76 st.stanza("db:verify", { from = attr.to, to = attr.from, id = origin.streamid }):text(stanza[1])); 91 origin.send(st.stanza("db:verify", { from = attr.to, to = attr.from, id = origin.streamid }):text(stanza[1]));
77 return true; 92 return true;
78 end 93 end
79 end); 94 end);
80 95
81 module:hook("stanza/jabber:server:dialback:verify", function(event) 96 module:hook("stanza/jabber:server:dialback:verify", function(event)
82 local origin, stanza = event.origin, event.stanza; 97 local origin, stanza = event.origin, event.stanza;
83 98
84 if origin.type == "s2sout_unauthed" or origin.type == "s2sout" then 99 if origin.type == "s2sout_unauthed" or origin.type == "s2sout" then
85 local attr = stanza.attr; 100 local attr = stanza.attr;
86 local dialback_verifying = dialback_requests[attr.from.."/"..(attr.id or "")]; 101 local dialback_verifying = dialback_requests[attr.from.."/"..(attr.id or "")];
102 module:log("debug", tostring(dialback_verifying).." "..attr.from.." "..origin.to_host);
87 if dialback_verifying and attr.from == origin.to_host then 103 if dialback_verifying and attr.from == origin.to_host then
88 local valid; 104 local valid;
89 if attr.type == "valid" then 105 if attr.type == "valid" then
90 s2s_make_authenticated(dialback_verifying, attr.from); 106 s2s_make_authenticated(dialback_verifying, attr.from);
91 valid = "valid"; 107 valid = "valid";
132 end); 148 end);
133 149
134 module:hook_stanza("urn:ietf:params:xml:ns:xmpp-sasl", "failure", function (origin, stanza) 150 module:hook_stanza("urn:ietf:params:xml:ns:xmpp-sasl", "failure", function (origin, stanza)
135 if origin.external_auth == "failed" then 151 if origin.external_auth == "failed" then
136 module:log("debug", "SASL EXTERNAL failed, falling back to dialback"); 152 module:log("debug", "SASL EXTERNAL failed, falling back to dialback");
137 s2s_initiate_dialback(origin); 153 initiate_dialback(origin);
138 return true; 154 return true;
139 end 155 end
140 end, 100); 156 end, 100);
141 157
142 module:hook_stanza(xmlns_stream, "features", function (origin, stanza) 158 module:hook_stanza(xmlns_stream, "features", function (origin, stanza)
143 if not origin.external_auth or origin.external_auth == "failed" then 159 if not origin.external_auth or origin.external_auth == "failed" then
144 s2s_initiate_dialback(origin); 160 initiate_dialback(origin);
145 return true; 161 return true;
146 end 162 end
147 end, 100); 163 end, 100);
148 164
149 -- Offer dialback to incoming hosts 165 -- Offer dialback to incoming hosts