Software /
code /
prosody
Comparison
plugins/mod_s2s/mod_s2s.lua @ 5364:61cf6b84ae81
Merge 0.9->trunk
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Fri, 22 Mar 2013 14:22:46 +0000 |
parent | 5363:f29c26da7ecc |
child | 5365:cd480ea490f1 |
comparison
equal
deleted
inserted
replaced
5356:97197ca60cb2 | 5364:61cf6b84ae81 |
---|---|
22 local nameprep = require "util.encodings".stringprep.nameprep; | 22 local nameprep = require "util.encodings".stringprep.nameprep; |
23 local new_xmpp_stream = require "util.xmppstream".new; | 23 local new_xmpp_stream = require "util.xmppstream".new; |
24 local s2s_new_incoming = require "core.s2smanager".new_incoming; | 24 local s2s_new_incoming = require "core.s2smanager".new_incoming; |
25 local s2s_new_outgoing = require "core.s2smanager".new_outgoing; | 25 local s2s_new_outgoing = require "core.s2smanager".new_outgoing; |
26 local s2s_destroy_session = require "core.s2smanager".destroy_session; | 26 local s2s_destroy_session = require "core.s2smanager".destroy_session; |
27 local s2s_mark_connected = require "core.s2smanager".mark_connected; | |
28 local uuid_gen = require "util.uuid".generate; | 27 local uuid_gen = require "util.uuid".generate; |
29 local cert_verify_identity = require "util.x509".verify_identity; | 28 local cert_verify_identity = require "util.x509".verify_identity; |
29 local fire_global_event = prosody.events.fire_event; | |
30 | 30 |
31 local s2sout = module:require("s2sout"); | 31 local s2sout = module:require("s2sout"); |
32 | 32 |
33 local connect_timeout = module:get_option_number("s2s_timeout", 90); | 33 local connect_timeout = module:get_option_number("s2s_timeout", 90); |
34 local stream_close_timeout = module:get_option_number("s2s_close_timeout", 5); | 34 local stream_close_timeout = module:get_option_number("s2s_close_timeout", 5); |
35 | |
36 local secure_auth = module:get_option_boolean("s2s_secure_auth", false); -- One day... | |
37 local secure_domains, insecure_domains = | |
38 module:get_option_set("s2s_secure_domains", {})._items, module:get_option_set("s2s_insecure_domains", {})._items; | |
39 local require_encryption = module:get_option_boolean("s2s_require_encryption", secure_auth); | |
35 | 40 |
36 local sessions = module:shared("sessions"); | 41 local sessions = module:shared("sessions"); |
37 | 42 |
38 local log = module._log; | 43 local log = module._log; |
39 | 44 |
130 module:log("warn", "The 'disallow_s2s' config option is deprecated, please see http://prosody.im/doc/s2s#disabling"); | 135 module:log("warn", "The 'disallow_s2s' config option is deprecated, please see http://prosody.im/doc/s2s#disabling"); |
131 return nil, "This host has disallow_s2s set"; | 136 return nil, "This host has disallow_s2s set"; |
132 end | 137 end |
133 module:hook("route/remote", route_to_existing_session, 200); | 138 module:hook("route/remote", route_to_existing_session, 200); |
134 module:hook("route/remote", route_to_new_session, 100); | 139 module:hook("route/remote", route_to_new_session, 100); |
140 module:hook("s2s-authenticated", make_authenticated, -1); | |
141 end | |
142 | |
143 -- Stream is authorised, and ready for normal stanzas | |
144 function mark_connected(session) | |
145 local sendq, send = session.sendq, session.sends2s; | |
146 | |
147 local from, to = session.from_host, session.to_host; | |
148 | |
149 session.log("info", "%s s2s connection %s->%s complete", session.direction, from, to); | |
150 | |
151 local event_data = { session = session }; | |
152 if session.type == "s2sout" then | |
153 fire_global_event("s2sout-established", event_data); | |
154 hosts[from].events.fire_event("s2sout-established", event_data); | |
155 else | |
156 local host_session = hosts[to]; | |
157 session.send = function(stanza) | |
158 return host_session.events.fire_event("route/remote", { from_host = to, to_host = from, stanza = stanza }); | |
159 end; | |
160 | |
161 fire_global_event("s2sin-established", event_data); | |
162 hosts[to].events.fire_event("s2sin-established", event_data); | |
163 end | |
164 | |
165 if session.direction == "outgoing" then | |
166 if sendq then | |
167 session.log("debug", "sending %d queued stanzas across new outgoing connection to %s", #sendq, session.to_host); | |
168 for i, data in ipairs(sendq) do | |
169 send(data[1]); | |
170 sendq[i] = nil; | |
171 end | |
172 session.sendq = nil; | |
173 end | |
174 | |
175 session.ip_hosts = nil; | |
176 session.srv_hosts = nil; | |
177 end | |
178 end | |
179 | |
180 function make_authenticated(event) | |
181 local session, host = event.session, event.host; | |
182 if not session.secure then | |
183 if require_encryption or secure_auth or secure_domains[host] then | |
184 session:close({ | |
185 condition = "policy-violation", | |
186 text = "Encrypted server-to-server communication is required but was not " | |
187 ..((session.direction == "outgoing" and "offered") or "used") | |
188 }); | |
189 end | |
190 end | |
191 if session.type == "s2sout_unauthed" then | |
192 session.type = "s2sout"; | |
193 elseif session.type == "s2sin_unauthed" then | |
194 session.type = "s2sin"; | |
195 if host then | |
196 if not session.hosts[host] then session.hosts[host] = {}; end | |
197 session.hosts[host].authed = true; | |
198 end | |
199 elseif session.type == "s2sin" and host then | |
200 if not session.hosts[host] then session.hosts[host] = {}; end | |
201 session.hosts[host].authed = true; | |
202 else | |
203 return false; | |
204 end | |
205 session.log("debug", "connection %s->%s is now authenticated for %s", session.from_host, session.to_host, host); | |
206 | |
207 mark_connected(session); | |
208 | |
209 return true; | |
135 end | 210 end |
136 | 211 |
137 --- Helper to check that a session peer's certificate is valid | 212 --- Helper to check that a session peer's certificate is valid |
138 local function check_cert_status(session) | 213 local function check_cert_status(session) |
139 local host = session.direction == "incoming" and session.from_host or session.to_host | 214 local host = session.direction == "incoming" and session.from_host or session.to_host |
165 session.cert_identity_status = "invalid" | 240 session.cert_identity_status = "invalid" |
166 end | 241 end |
167 end | 242 end |
168 end | 243 end |
169 end | 244 end |
170 module:fire_event("s2s-check-certificate", { host = host, session = session, cert = cert }); | 245 return module:fire_event("s2s-check-certificate", { host = host, session = session, cert = cert }); |
171 end | 246 end |
172 | 247 |
173 --- XMPP stream event handlers | 248 --- XMPP stream event handlers |
174 | 249 |
175 local stream_callbacks = { default_ns = "jabber:server", handlestanza = core_process_stanza }; | 250 local stream_callbacks = { default_ns = "jabber:server", handlestanza = core_process_stanza }; |
244 }); | 319 }); |
245 return; | 320 return; |
246 end | 321 end |
247 end | 322 end |
248 | 323 |
249 if session.secure and not session.cert_chain_status then check_cert_status(session); end | 324 if session.secure and not session.cert_chain_status then |
325 if check_cert_status(session) == false then | |
326 return; | |
327 end | |
328 end | |
250 | 329 |
251 session:open_stream() | 330 session:open_stream() |
252 if session.version >= 1.0 then | 331 if session.version >= 1.0 then |
253 local features = st.stanza("stream:features"); | 332 local features = st.stanza("stream:features"); |
254 | 333 |
264 elseif session.direction == "outgoing" then | 343 elseif session.direction == "outgoing" then |
265 -- If we are just using the connection for verifying dialback keys, we won't try and auth it | 344 -- If we are just using the connection for verifying dialback keys, we won't try and auth it |
266 if not attr.id then error("stream response did not give us a streamid!!!"); end | 345 if not attr.id then error("stream response did not give us a streamid!!!"); end |
267 session.streamid = attr.id; | 346 session.streamid = attr.id; |
268 | 347 |
269 if session.secure and not session.cert_chain_status then check_cert_status(session); end | 348 if session.secure and not session.cert_chain_status then |
349 if check_cert_status(session) == false then | |
350 return; | |
351 end | |
352 end | |
270 | 353 |
271 -- Send unauthed buffer | 354 -- Send unauthed buffer |
272 -- (stanzas which are fine to send before dialback) | 355 -- (stanzas which are fine to send before dialback) |
273 -- Note that this is *not* the stanza queue (which | 356 -- Note that this is *not* the stanza queue (which |
274 -- we can only send if auth succeeds) :) | 357 -- we can only send if auth succeeds) :) |
285 -- If server is pre-1.0, don't wait for features, just do dialback | 368 -- If server is pre-1.0, don't wait for features, just do dialback |
286 if session.version < 1.0 then | 369 if session.version < 1.0 then |
287 if not session.dialback_verifying then | 370 if not session.dialback_verifying then |
288 hosts[session.from_host].events.fire_event("s2sout-authenticate-legacy", { origin = session }); | 371 hosts[session.from_host].events.fire_event("s2sout-authenticate-legacy", { origin = session }); |
289 else | 372 else |
290 s2s_mark_connected(session); | 373 mark_connected(session); |
291 end | 374 end |
292 end | 375 end |
293 end | 376 end |
294 session.notopen = nil; | 377 session.notopen = nil; |
295 end | 378 end |
524 session.direction = "outgoing"; | 607 session.direction = "outgoing"; |
525 sessions[conn] = session; | 608 sessions[conn] = session; |
526 initialize_session(session); | 609 initialize_session(session); |
527 end | 610 end |
528 | 611 |
612 function check_auth_policy(event) | |
613 local host, session = event.host, event.session; | |
614 | |
615 if not secure_auth and secure_domains[host] then | |
616 secure_auth = true; | |
617 elseif secure_auth and insecure_domains[host] then | |
618 secure_auth = false; | |
619 end | |
620 | |
621 if secure_auth and not session.cert_identity_status then | |
622 module:log("warn", "Forbidding insecure connection to/from %s", host); | |
623 session:close(false); | |
624 return false; | |
625 end | |
626 end | |
627 | |
628 module:hook("s2s-check-certificate", check_auth_policy, -1); | |
629 | |
529 s2sout.set_listener(listener); | 630 s2sout.set_listener(listener); |
530 | 631 |
531 module:hook("server-stopping", function(event) | 632 module:hook("server-stopping", function(event) |
532 local reason = event.reason; | 633 local reason = event.reason; |
533 for _, session in pairs(sessions) do | 634 for _, session in pairs(sessions) do |