From cf984835d120a714e2ed4337f8522e935cf85498 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 15 Jan 2019 20:08:30 +0100 Subject: mod_c2s, mod_s2s, mod_component: Log invalid XML escaped (fixes #734) See 6ed0d6224d64 --- plugins/mod_s2s/mod_s2s.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index aae37b7f..79308847 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -595,8 +595,7 @@ local function initialize_session(session) if data then local ok, err = stream:feed(data); if ok then return; end - log("warn", "Received invalid XML: %s", data); - log("warn", "Problem was: %s", err); + log("debug", "Received invalid XML (%s) %d bytes: %q", tostring(err), #data, data:sub(1, 300)); session:close("not-well-formed"); end end -- cgit v1.2.3 From 9f65ce71893ef10485442ee209472a38865da081 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 10 Mar 2019 19:58:28 +0100 Subject: core.certmanager: Do not ask for client certificates by default Since it's mostly only mod_s2s that needs to request client certificates it makes some sense to have mod_s2s ask for this, instead of having eg mod_http ask to disable it. --- plugins/mod_s2s/mod_s2s.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 79308847..b0d551fe 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -738,6 +738,9 @@ module:provides("net", { listener = listener; default_port = 5269; encryption = "starttls"; + ssl_config = { + verify = { "peer", "client_once", }; + }; multiplex = { pattern = "^<.*:stream.*%sxmlns%s*=%s*(['\"])jabber:server%1.*>"; }; -- cgit v1.2.3 From b246b00f85b1973058f8b607190a72168380dbc3 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 11 Mar 2019 13:07:59 +0100 Subject: mod_tls: Restore querying for certificates on s2s The 'ssl_config' setting in the mod_s2s network service is not used. Only direct TLS ports use this currently. --- plugins/mod_s2s/mod_s2s.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index b0d551fe..f0fdc5fb 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -738,7 +738,7 @@ module:provides("net", { listener = listener; default_port = 5269; encryption = "starttls"; - ssl_config = { + ssl_config = { -- FIXME This is not used atm, see mod_tls verify = { "peer", "client_once", }; }; multiplex = { -- cgit v1.2.3 From 755b5076441531a8c8b6f2b2ab831800768402ef Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 19 Mar 2019 09:08:33 +0000 Subject: mod_s2s: Set warning status if not listening on any ports --- plugins/mod_s2s/s2sout.lib.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/s2sout.lib.lua b/plugins/mod_s2s/s2sout.lib.lua index 5f765da8..34e322d2 100644 --- a/plugins/mod_s2s/s2sout.lib.lua +++ b/plugins/mod_s2s/s2sout.lib.lua @@ -318,7 +318,7 @@ module:hook_global("service-added", function (event) local s2s_sources = portmanager.get_active_services():get("s2s"); if not s2s_sources then - module:log("warn", "s2s not listening on any ports, outgoing connections may fail"); + module:log_status("warn", "s2s not listening on any ports, outgoing connections may fail"); return; end for source, _ in pairs(s2s_sources) do -- cgit v1.2.3 From 40b1e3e0ed1223517f29bcf136fc08a6f33b17f2 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 30 Jul 2019 02:29:36 +0200 Subject: plugins: Remove tostring call from logging Taken care of by loggingmanager now Mass-rewrite using lua pattern like `tostring%b()` --- plugins/mod_s2s/mod_s2s.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index f0fdc5fb..dd19f350 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -127,7 +127,7 @@ function route_to_existing_session(event) elseif host.type == "local" or host.type == "component" then log("error", "Trying to send a stanza to ourselves??") log("error", "Traceback: %s", traceback()); - log("error", "Stanza: %s", tostring(stanza)); + log("error", "Stanza: %s", stanza); return false; else -- FIXME @@ -151,7 +151,7 @@ function route_to_new_session(event) -- Store in buffer host_session.bounce_sendq = bounce_sendq; host_session.sendq = { {tostring(stanza), stanza.attr.type ~= "error" and stanza.attr.type ~= "result" and st.reply(stanza)} }; - log("debug", "stanza [%s] queued until connection complete", tostring(stanza.name)); + log("debug", "stanza [%s] queued until connection complete", stanza.name); s2sout.initiate_connection(host_session); if (not host_session.connecting) and (not host_session.conn) then log("warn", "Connection to %s failed already, destroying session...", to_host); @@ -595,7 +595,7 @@ local function initialize_session(session) if data then local ok, err = stream:feed(data); if ok then return; end - log("debug", "Received invalid XML (%s) %d bytes: %q", tostring(err), #data, data:sub(1, 300)); + log("debug", "Received invalid XML (%s) %d bytes: %q", err, #data, data:sub(1, 300)); session:close("not-well-formed"); end end -- cgit v1.2.3 From 45a8e8ea7f8f4342a2ca2f8c0ea7d2bbb6591f8d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 1 Aug 2019 05:25:34 +0200 Subject: mod_s2s: Distinguish between high and low level errors in bounces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `remote-server-not-found` is reported for problems occurring without a reply `` having been opened, e.g. DNS records were not found or no TCP stream could be established to a functioning XMPP entity. `remote-server-timeout` is reported for problems that occurring after a stream has been opened, such as configuration problems, inability to perform TLS or unsuccessful certificate validation. Related: #770 --- plugins/mod_s2s/mod_s2s.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index dd19f350..012c5341 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -77,12 +77,19 @@ local function bounce_sendq(session, reason) (session.log or log)("error", "Attempting to close the dummy origin of s2s error replies, please report this! Traceback: %s", traceback()); end; }; + -- FIXME Allow for more specific error conditions + -- TODO use util.error ? + local error_type = "cancel"; + local condition = "remote-server-not-found"; + if session.had_stream then -- set when a stream is opened by the remote + error_type, condition = "wait", "remote-server-timeout"; + end for i, data in ipairs(sendq) do local reply = data[2]; if reply and not(reply.attr.xmlns) and bouncy_stanzas[reply.name] then reply.attr.type = "error"; - reply:tag("error", {type = "cancel", by = session.from_host}) - :tag("remote-server-not-found", {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"}):up(); + reply:tag("error", {type = error_type, by = session.from_host}) + :tag(condition, {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"}):up(); if reason then reply:tag("text", {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"}) :text("Server-to-server connection failed: "..reason):up(); @@ -301,6 +308,7 @@ end function stream_callbacks._streamopened(session, attr) session.version = tonumber(attr.version) or 0; + session.had_stream = true; -- Had a stream opened at least once -- TODO: Rename session.secure to session.encrypted if session.secure == false then -- cgit v1.2.3 From c788104e048f868c0448df797d2020fba1fa0934 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 10 Nov 2018 13:37:32 +0100 Subject: mod_s2s: Use net.connect instead of s2sout.lib for outgoing s2s connections --- plugins/mod_s2s/mod_s2s.lua | 38 +++-- plugins/mod_s2s/s2sout.lib.lua | 349 ----------------------------------------- 2 files changed, 23 insertions(+), 364 deletions(-) delete mode 100644 plugins/mod_s2s/s2sout.lib.lua (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 012c5341..ea19f7ad 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -27,8 +27,8 @@ local s2s_destroy_session = require "core.s2smanager".destroy_session; local uuid_gen = require "util.uuid".generate; local fire_global_event = prosody.events.fire_event; local runner = require "util.async".runner; - -local s2sout = module:require("s2sout"); +local connect = require "net.connect".connect; +local service = require "net.resolvers.service"; local connect_timeout = module:get_option_number("s2s_timeout", 90); local stream_close_timeout = module:get_option_number("s2s_close_timeout", 5); @@ -45,6 +45,8 @@ local sessions = module:shared("sessions"); local runner_callbacks = {}; +local listener = {}; + local log = module._log; module:hook("stats-update", function () @@ -154,17 +156,13 @@ function route_to_new_session(event) local from_host, to_host, stanza = event.from_host, event.to_host, event.stanza; log("debug", "opening a new outgoing connection for this stanza"); local host_session = s2s_new_outgoing(from_host, to_host); + host_session.version = 1; -- Store in buffer host_session.bounce_sendq = bounce_sendq; host_session.sendq = { {tostring(stanza), stanza.attr.type ~= "error" and stanza.attr.type ~= "result" and st.reply(stanza)} }; log("debug", "stanza [%s] queued until connection complete", stanza.name); - s2sout.initiate_connection(host_session); - if (not host_session.connecting) and (not host_session.conn) then - log("warn", "Connection to %s failed already, destroying session...", to_host); - s2s_destroy_session(host_session, "Connection failed"); - return false; - end + connect(service.new(to_host, "xmpp-server", "tcp", { default_port = 5269 }), listener, nil, { session = host_session }); return true; end @@ -479,8 +477,6 @@ function stream_callbacks.error(session, error, data) end end -local listener = {}; - --- Session methods local stream_xmlns_attr = {xmlns='urn:ietf:params:xml:ns:xmpp-streams'}; local function session_close(session, reason, remote_reason) @@ -679,11 +675,16 @@ function listener.ondisconnect(conn, err) local session = sessions[conn]; if session then sessions[conn] = nil; + (session.log or log)("debug", "s2s disconnected: %s->%s (%s)", session.from_host, session.to_host, err or "connection closed"); + s2s_destroy_session(session, err); + end +end + +function listener.onfail(data, err) + local session = data and data.session; + if session then if err and session.direction == "outgoing" and session.notopen then (session.log or log)("debug", "s2s connection attempt failed: %s", err); - if s2sout.attempt_connection(session, err) then - return; -- Session lives for now - end end (session.log or log)("debug", "s2s disconnected: %s->%s (%s)", session.from_host, session.to_host, err or "connection closed"); s2s_destroy_session(session, err); @@ -707,6 +708,15 @@ function listener.ondetach(conn) sessions[conn] = nil; end +function listener.onattach(conn, data) + local session = data and data.session; + if session then + session.conn = conn; + sessions[conn] = session; + initialize_session(session); + end +end + function check_auth_policy(event) local host, session = event.host, event.session; local must_secure = secure_auth; @@ -730,8 +740,6 @@ end module:hook("s2s-check-certificate", check_auth_policy, -1); -s2sout.set_listener(listener); - module:hook("server-stopping", function(event) local reason = event.reason; for _, session in pairs(sessions) do diff --git a/plugins/mod_s2s/s2sout.lib.lua b/plugins/mod_s2s/s2sout.lib.lua deleted file mode 100644 index 34e322d2..00000000 --- a/plugins/mod_s2s/s2sout.lib.lua +++ /dev/null @@ -1,349 +0,0 @@ --- 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. --- - ---- Module containing all the logic for connecting to a remote server - --- luacheck: ignore 432/err - -local portmanager = require "core.portmanager"; -local wrapclient = require "net.server".wrapclient; -local initialize_filters = require "util.filters".initialize; -local idna_to_ascii = require "util.encodings".idna.to_ascii; -local new_ip = require "util.ip".new_ip; -local rfc6724_dest = require "util.rfc6724".destination; -local socket = require "socket"; -local adns = require "net.adns"; -local t_insert, t_sort, ipairs = table.insert, table.sort, ipairs; -local local_addresses = require "util.net".local_addresses; - -local s2s_destroy_session = require "core.s2smanager".destroy_session; - -local default_mode = module:get_option("network_default_read_size", 4096); - -local log = module._log; - -local sources = {}; -local has_ipv4, has_ipv6; - -local dns_timeout = module:get_option_number("dns_timeout", 15); -local resolvers = module:get_option_set("s2s_dns_resolvers") - -local s2sout = {}; - -local s2s_listener; - - -function s2sout.set_listener(listener) - s2s_listener = listener; -end - -local function compare_srv_priorities(a,b) - return a.priority < b.priority or (a.priority == b.priority and a.weight > b.weight); -end - -function s2sout.initiate_connection(host_session) - local log = host_session.log or log; - - initialize_filters(host_session); - host_session.version = 1; - - host_session.resolver = adns.resolver(); - host_session.resolver._resolver:settimeout(dns_timeout); - if resolvers then - for resolver in resolvers do - host_session.resolver._resolver:addnameserver(resolver); - end - end - - -- Kick the connection attempting machine into life - if not s2sout.attempt_connection(host_session) then - -- Intentionally not returning here, the - -- session is needed, connected or not - s2s_destroy_session(host_session); - end - - if not host_session.sends2s then - -- A sends2s which buffers data (until the stream is opened) - -- note that data in this buffer will be sent before the stream is authed - -- and will not be ack'd in any way, successful or otherwise - local buffer; - function host_session.sends2s(data) - if not buffer then - buffer = {}; - host_session.send_buffer = buffer; - end - log("debug", "Buffering data on unconnected s2sout to %s", host_session.to_host); - buffer[#buffer+1] = data; - log("debug", "Buffered item %d: %s", #buffer, data); - end - end -end - -function s2sout.attempt_connection(host_session, err) - local to_host = host_session.to_host; - local connect_host, connect_port = to_host and idna_to_ascii(to_host), 5269; - local log = host_session.log or log; - - if not connect_host then - return false; - end - - if not err then -- This is our first attempt - log("debug", "First attempt to connect to %s, starting with SRV lookup...", to_host); - host_session.connecting = true; - host_session.resolver:lookup(function (answer) - local srv_hosts = { answer = answer }; - host_session.srv_hosts = srv_hosts; - host_session.srv_choice = 0; - host_session.connecting = nil; - if answer and #answer > 0 then - log("debug", "%s has SRV records, handling...", to_host); - for _, record in ipairs(answer) do - t_insert(srv_hosts, record.srv); - end - if #srv_hosts == 1 and srv_hosts[1].target == "." then - log("debug", "%s does not provide a XMPP service", to_host); - s2s_destroy_session(host_session, err); -- Nothing to see here - return; - end - t_sort(srv_hosts, compare_srv_priorities); - - local srv_choice = srv_hosts[1]; - host_session.srv_choice = 1; - if srv_choice then - connect_host, connect_port = srv_choice.target or to_host, srv_choice.port or connect_port; - log("debug", "Best record found, will connect to %s:%d", connect_host, connect_port); - end - else - log("debug", "%s has no SRV records, falling back to A/AAAA", to_host); - end - -- Try with SRV, or just the plain hostname if no SRV - local ok, err = s2sout.try_connect(host_session, connect_host, connect_port); - if not ok then - if not s2sout.attempt_connection(host_session, err) then - -- No more attempts will be made - s2s_destroy_session(host_session, err); - end - end - end, "_xmpp-server._tcp."..connect_host..".", "SRV"); - - return true; -- Attempt in progress - elseif host_session.ip_hosts then - return s2sout.try_connect(host_session, connect_host, connect_port, err); - elseif host_session.srv_hosts and #host_session.srv_hosts > host_session.srv_choice then -- Not our first attempt, and we also have SRV - host_session.srv_choice = host_session.srv_choice + 1; - local srv_choice = host_session.srv_hosts[host_session.srv_choice]; - connect_host, connect_port = srv_choice.target or to_host, srv_choice.port or connect_port; - host_session.log("info", "Connection failed (%s). Attempt #%d: This time to %s:%d", err, host_session.srv_choice, connect_host, connect_port); - else - host_session.log("info", "Failed in all attempts to connect to %s", host_session.to_host); - -- We're out of options - return false; - end - - if not (connect_host and connect_port) then - -- Likely we couldn't resolve DNS - log("warn", "Hmm, we're without a host (%s) and port (%s) to connect to for %s, giving up :(", connect_host, connect_port, to_host); - return false; - end - - return s2sout.try_connect(host_session, connect_host, connect_port); -end - -function s2sout.try_next_ip(host_session) - host_session.connecting = nil; - host_session.ip_choice = host_session.ip_choice + 1; - local ip = host_session.ip_hosts[host_session.ip_choice]; - local ok, err= s2sout.make_connect(host_session, ip.ip, ip.port); - if not ok then - if not s2sout.attempt_connection(host_session, err or "closed") then - err = err and (": "..err) or ""; - s2s_destroy_session(host_session, "Connection failed"..err); - end - end -end - -function s2sout.try_connect(host_session, connect_host, connect_port, err) - host_session.connecting = true; - local log = host_session.log or log; - - if not err then - local IPs = {}; - host_session.ip_hosts = IPs; - -- luacheck: ignore 231/handle4 231/handle6 - local handle4, handle6; - local have_other_result = not(has_ipv4) or not(has_ipv6) or false; - - if has_ipv4 then - handle4 = host_session.resolver:lookup(function (reply, err) - handle4 = nil; - - if reply and reply[#reply] and reply[#reply].a then - for _, ip in ipairs(reply) do - log("debug", "DNS reply for %s gives us %s", connect_host, ip.a); - IPs[#IPs+1] = new_ip(ip.a, "IPv4"); - end - elseif err then - log("debug", "Error in DNS lookup: %s", err); - end - - if have_other_result then - if #IPs > 0 then - rfc6724_dest(host_session.ip_hosts, sources); - for i = 1, #IPs do - IPs[i] = {ip = IPs[i], port = connect_port}; - end - host_session.ip_choice = 0; - s2sout.try_next_ip(host_session); - else - log("debug", "DNS lookup failed to get a response for %s", connect_host); - host_session.ip_hosts = nil; - if not s2sout.attempt_connection(host_session, "name resolution failed") then -- Retry if we can - log("debug", "No other records to try for %s - destroying", host_session.to_host); - err = err and (": "..err) or ""; - s2s_destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't - end - end - else - have_other_result = true; - end - end, connect_host, "A", "IN"); - else - have_other_result = true; - end - - if has_ipv6 then - handle6 = host_session.resolver:lookup(function (reply, err) - handle6 = nil; - - if reply and reply[#reply] and reply[#reply].aaaa then - for _, ip in ipairs(reply) do - log("debug", "DNS reply for %s gives us %s", connect_host, ip.aaaa); - IPs[#IPs+1] = new_ip(ip.aaaa, "IPv6"); - end - elseif err then - log("debug", "Error in DNS lookup: %s", err); - end - - if have_other_result then - if #IPs > 0 then - rfc6724_dest(host_session.ip_hosts, sources); - for i = 1, #IPs do - IPs[i] = {ip = IPs[i], port = connect_port}; - end - host_session.ip_choice = 0; - s2sout.try_next_ip(host_session); - else - log("debug", "DNS lookup failed to get a response for %s", connect_host); - host_session.ip_hosts = nil; - if not s2sout.attempt_connection(host_session, "name resolution failed") then -- Retry if we can - log("debug", "No other records to try for %s - destroying", host_session.to_host); - err = err and (": "..err) or ""; - s2s_destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't - end - end - else - have_other_result = true; - end - end, connect_host, "AAAA", "IN"); - else - have_other_result = true; - end - return true; - elseif host_session.ip_hosts and #host_session.ip_hosts > host_session.ip_choice then -- Not our first attempt, and we also have IPs left to try - s2sout.try_next_ip(host_session); - else - log("debug", "Out of IP addresses, trying next SRV record (if any)"); - host_session.ip_hosts = nil; - if not s2sout.attempt_connection(host_session, "out of IP addresses") then -- Retry if we can - log("debug", "No other records to try for %s - destroying", host_session.to_host); - err = err and (": "..err) or ""; - s2s_destroy_session(host_session, "Connecting failed"..err); -- End of the line, we can't - return false; - end - end - - return true; -end - -function s2sout.make_connect(host_session, connect_host, connect_port) - local log = host_session.log or log; - log("debug", "Beginning new connection attempt to %s ([%s]:%d)", host_session.to_host, connect_host.addr, connect_port); - - -- Reset secure flag in case this is another - -- connection attempt after a failed STARTTLS - host_session.secure = nil; - host_session.encrypted = nil; - - local conn, handler; - local proto = connect_host.proto; - if proto == "IPv4" then - conn, handler = socket.tcp(); - elseif proto == "IPv6" and socket.tcp6 then - conn, handler = socket.tcp6(); - else - handler = "Unsupported protocol: "..tostring(proto); - end - - if not conn then - log("warn", "Failed to create outgoing connection, system error: %s", handler); - return false, handler; - end - - conn:settimeout(0); - local success, err = conn:connect(connect_host.addr, connect_port); - if not success and err ~= "timeout" then - log("warn", "s2s connect() to %s (%s:%d) failed: %s", host_session.to_host, connect_host.addr, connect_port, err); - return false, err; - end - - conn = wrapclient(conn, connect_host.addr, connect_port, s2s_listener, default_mode); - host_session.conn = conn; - - -- Register this outgoing connection so that xmppserver_listener knows about it - -- otherwise it will assume it is a new incoming connection - s2s_listener.register_outgoing(conn, host_session); - - log("debug", "Connection attempt in progress..."); - return true; -end - -module:hook_global("service-added", function (event) - if event.name ~= "s2s" then return end - - local s2s_sources = portmanager.get_active_services():get("s2s"); - if not s2s_sources then - module:log_status("warn", "s2s not listening on any ports, outgoing connections may fail"); - return; - end - for source, _ in pairs(s2s_sources) do - if source == "*" or source == "0.0.0.0" then - for _, addr in ipairs(local_addresses("ipv4", true)) do - sources[#sources + 1] = new_ip(addr, "IPv4"); - end - elseif source == "::" then - for _, addr in ipairs(local_addresses("ipv6", true)) do - sources[#sources + 1] = new_ip(addr, "IPv6"); - end - else - sources[#sources + 1] = new_ip(source, (source:find(":") and "IPv6") or "IPv4"); - end - end - for i = 1,#sources do - if sources[i].proto == "IPv6" then - has_ipv6 = true; - elseif sources[i].proto == "IPv4" then - has_ipv4 = true; - end - end - if not (has_ipv4 or has_ipv6) then - module:log("warn", "No local IPv4 or IPv6 addresses detected, outgoing connections may fail"); - end -end); - -return s2sout; -- cgit v1.2.3 From b16782257d441196d7fbab2823ba8fa878c4c056 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 25 Aug 2019 23:12:55 +0200 Subject: Remove COMPAT with temporary luasec fork The changes in the temporary fork were merged into mainline luasec ca 2013 and included in the 0.5 release in 2014. --- plugins/mod_s2s/mod_s2s.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index ea19f7ad..5a0d2a49 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -320,7 +320,6 @@ function stream_callbacks._streamopened(session, attr) session.compressed = info.compression; else (session.log or log)("info", "Stream encrypted"); - session.compressed = sock.compression and sock:compression(); --COMPAT mw/luasec-hg end end -- cgit v1.2.3 From 42861396cd1eeb5a880691e9ee00a75836b2fddb Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 7 Sep 2019 19:00:37 +0200 Subject: mod_s2s: Remove obsolete cleanup code These were added by s2sout.lib --- plugins/mod_s2s/mod_s2s.lua | 7 ------- 1 file changed, 7 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 5a0d2a49..6c4d92ae 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -228,13 +228,6 @@ function mark_connected(session) end session.sendq = nil; end - - if session.resolver then - session.resolver._resolver:closeall() - end - session.resolver = nil; - session.ip_hosts = nil; - session.srv_hosts = nil; end end -- cgit v1.2.3 From 5c27fe4b793490d6ec80cdbdcc5063ae3b660766 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 7 Sep 2019 17:44:57 +0200 Subject: mod_s2s: Handle authentication of s2sin and s2sout the same way --- plugins/mod_s2s/mod_s2s.lua | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 6c4d92ae..d8e631b9 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -249,15 +249,13 @@ function make_authenticated(event) session.type = "s2sout"; elseif session.type == "s2sin_unauthed" then session.type = "s2sin"; - if host then - if not session.hosts[host] then session.hosts[host] = {}; end - session.hosts[host].authed = true; - end - elseif session.type == "s2sin" and host then + elseif session.type ~= "s2sin" and session.type ~= "s2sout" then + return false; + end + + if session.incoming and host then if not session.hosts[host] then session.hosts[host] = {}; end session.hosts[host].authed = true; - else - return false; end session.log("debug", "connection %s->%s is now authenticated for %s", session.from_host, session.to_host, host); -- cgit v1.2.3 From f6ba50139a104e69aad9378756b927ccc7b2e661 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 7 Sep 2019 18:32:29 +0200 Subject: mod_s2s: Add function to send replies on s2sout connections that support incoming traffic --- plugins/mod_s2s/mod_s2s.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index d8e631b9..5114b1ce 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -208,6 +208,13 @@ function mark_connected(session) if session.type == "s2sout" then fire_global_event("s2sout-established", event_data); hosts[from].events.fire_event("s2sout-established", event_data); + + if session.incoming then + session.send = function(stanza) + return hosts[from].events.fire_event("route/remote", { from_host = from, to_host = to, stanza = stanza }); + end; + end + else local host_session = hosts[to]; session.send = function(stanza) -- cgit v1.2.3 From 4eda545430dc80353a1b168828990e22c73e7a41 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 7 Sep 2019 18:33:16 +0200 Subject: mod_s2s: Insert s2sin into outgoing routing table when bidirectional --- plugins/mod_s2s/mod_s2s.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 5114b1ce..673c93a2 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -216,6 +216,10 @@ function mark_connected(session) end else + if session.outgoing and not hosts[to].s2sout[from] then + session.log("debug", "Setting up to handle route from %s to %s", to, from); + hosts[to].s2sout[from] = session; -- luacheck: ignore 122 + end local host_session = hosts[to]; session.send = function(stanza) return host_session.events.fire_event("route/remote", { from_host = to, to_host = from, stanza = stanza }); -- cgit v1.2.3 From 55efbf445b422313e209e02bae07db8b35826a62 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 7 Sep 2019 18:54:59 +0200 Subject: mod_s2s: Remove warning about hostname mismatch It triggers on bidi-related routing where this to/from is flipped. Removing since I don't think we have ever seen this potential bug. --- plugins/mod_s2s/mod_s2s.lua | 5 ----- 1 file changed, 5 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 673c93a2..41b1875b 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -139,11 +139,6 @@ function route_to_existing_session(event) log("error", "Stanza: %s", stanza); return false; else - -- FIXME - if host.from_host ~= from_host then - log("error", "WARNING! This might, possibly, be a bug, but it might not..."); - log("error", "We are going to send from %s instead of %s", host.from_host, from_host); - end if host.sends2s(stanza) then return true; end -- cgit v1.2.3 From 5460dfed75e36009063b3f0af2b3f9fd0f920837 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 6 Oct 2019 21:14:53 +0200 Subject: mod_s2s: Close with a stream error in case neither SASL or Dialback are available This both tells the remote server and users who sent any queued stanzas why it failed. --- plugins/mod_s2s/mod_s2s.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 41b1875b..b9c13ef2 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -184,7 +184,10 @@ function module.add_host(module) return true; elseif not session.dialback_verifying then session.log("warn", "No SASL EXTERNAL offer and Dialback doesn't seem to be enabled, giving up"); - session:close(); + session:close({ + condition = "unsupported-feature", + text = "No viable authentication method offered", + }); return false; end end, -1); -- cgit v1.2.3 From b24814cbe469216a4321635a48e3f9077d313f49 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 2 Nov 2019 15:43:17 +0100 Subject: mod_s2s: Only nameprep stream to/from addresses if they are present Prevents traceback from nameprep(nil) --- plugins/mod_s2s/mod_s2s.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index b9c13ef2..42998c30 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -327,7 +327,9 @@ function stream_callbacks._streamopened(session, attr) -- Send a reply stream header -- Validate to/from - local to, from = nameprep(attr.to), nameprep(attr.from); + local to, from = attr.to, attr.from; + if to then to = nameprep(attr.to); end + if from then from = nameprep(attr.from); end if not to and attr.to then -- COMPAT: Some servers do not reliably set 'to' (especially on stream restarts) session:close({ condition = "improper-addressing", text = "Invalid 'to' address" }); return; -- cgit v1.2.3 From 6666a4c8147fd5ba7e58fdc0fef64e8c0ff83be3 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 8 Nov 2019 23:03:47 +0100 Subject: mod_s2s: Allow passing bounce reason as an util.error object (see #770) This argument is currently unused in s2smanager. --- plugins/mod_s2s/mod_s2s.lua | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 42998c30..9db13cb7 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -29,6 +29,7 @@ local fire_global_event = prosody.events.fire_event; local runner = require "util.async".runner; local connect = require "net.connect".connect; local service = require "net.resolvers.service"; +local errors = require "util.error"; local connect_timeout = module:get_option_number("s2s_timeout", 90); local stream_close_timeout = module:get_option_number("s2s_close_timeout", 5); @@ -83,18 +84,24 @@ local function bounce_sendq(session, reason) -- TODO use util.error ? local error_type = "cancel"; local condition = "remote-server-not-found"; + local reason_text; if session.had_stream then -- set when a stream is opened by the remote error_type, condition = "wait", "remote-server-timeout"; end + if errors.is_err(reason) then + error_type, condition, reason_text = reason.type, reason.condition, reason.text; + elseif type(reason) == "string" then + reason_text = reason; + end for i, data in ipairs(sendq) do local reply = data[2]; if reply and not(reply.attr.xmlns) and bouncy_stanzas[reply.name] then reply.attr.type = "error"; reply:tag("error", {type = error_type, by = session.from_host}) :tag(condition, {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"}):up(); - if reason then + if reason_text then reply:tag("text", {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"}) - :text("Server-to-server connection failed: "..reason):up(); + :text("Server-to-server connection failed: "..reason_text):up(); end core_process_stanza(dummy, reply); end -- cgit v1.2.3 From 4216970602aaf459c0f3b0f408eae7d6239f6861 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 18 Nov 2019 20:37:40 +0100 Subject: mod_s2s: Wait for remote to close any connection allowing incoming stanzas Ie both s2sin and bidi-enabled s2sout. --- plugins/mod_s2s/mod_s2s.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 9db13cb7..7ee88f3e 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -533,7 +533,7 @@ local function session_close(session, reason, remote_reason) -- Authenticated incoming stream may still be sending us stanzas, so wait for from remote local conn = session.conn; - if reason == nil and not session.notopen and session.type == "s2sin" then + if reason == nil and not session.notopen and session.incoming then add_task(stream_close_timeout, function () if not session.destroyed then session.log("warn", "Failed to receive a stream close response, closing connection anyway..."); -- cgit v1.2.3 From 3aee8e24a6873fce6b7ab30f5b87d17089e0d5a6 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 23 Nov 2019 01:29:03 +0100 Subject: s2s: Allow passing a custom error for bouncing queued stanzas (#770) Since stream errors and stanza errors are different --- plugins/mod_s2s/mod_s2s.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 7ee88f3e..6bb444f5 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -487,7 +487,7 @@ end --- Session methods local stream_xmlns_attr = {xmlns='urn:ietf:params:xml:ns:xmpp-streams'}; -local function session_close(session, reason, remote_reason) +local function session_close(session, reason, remote_reason, bounce_reason) local log = session.log or log; if session.conn then if session.notopen then @@ -537,12 +537,12 @@ local function session_close(session, reason, remote_reason) add_task(stream_close_timeout, function () if not session.destroyed then session.log("warn", "Failed to receive a stream close response, closing connection anyway..."); - s2s_destroy_session(session, reason); + s2s_destroy_session(session, reason, bounce_reason); conn:close(); end end); else - s2s_destroy_session(session, reason); + s2s_destroy_session(session, reason, bounce_reason); conn:close(); -- Close immediately, as this is an outgoing connection or is not authed end end -- cgit v1.2.3 From 55c130d1e410cdab6e35312f848d4f4a33682699 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 23 Nov 2019 01:32:53 +0100 Subject: mod_s2s: Add error text for error replies on some s2s failures (#770) --- plugins/mod_s2s/mod_s2s.lua | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 6bb444f5..e7ed8797 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -194,7 +194,7 @@ function module.add_host(module) session:close({ condition = "unsupported-feature", text = "No viable authentication method offered", - }); + }, nil, "No viable authentication method offered by remote server"); return false; end end, -1); @@ -255,7 +255,7 @@ function make_authenticated(event) condition = "policy-violation", text = "Encrypted server-to-server communication is required but was not " ..((session.direction == "outgoing" and "offered") or "used") - }); + }, nil, "Could not establish encrypted connection to remote server"); end end if hosts[host] then @@ -608,7 +608,7 @@ local function initialize_session(session) local ok, err = stream:feed(data); if ok then return; end log("debug", "Received invalid XML (%s) %d bytes: %q", err, #data, data:sub(1, 300)); - session:close("not-well-formed"); + session:close("not-well-formed", nil, "Received invalid XML from remote server"); end end @@ -738,9 +738,10 @@ function check_auth_policy(event) if must_secure and (session.cert_chain_status ~= "valid" or session.cert_identity_status ~= "valid") then module:log("warn", "Forbidding insecure connection to/from %s", host or session.ip or "(unknown host)"); if session.direction == "incoming" then - session:close({ condition = "not-authorized", text = "Your server's certificate is invalid, expired, or not trusted by "..session.to_host }); + session:close({ condition = "not-authorized", text = "Your server's certificate is invalid, expired, or not trusted by "..session.to_host }, + nil, "Remote server's certificate is invalid, expired, or not trusted"); else -- Close outgoing connections without warning - session:close(false); + session:close(false, nil, "Remote server's certificate is invalid, expired, or not trusted"); end return false; end -- cgit v1.2.3 From 2934eccd99592b9f1b500e9dea0eeea49b0ffbde Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Wed, 27 Nov 2019 23:26:59 +0100 Subject: mod_s2s: Improve error in bounces due to cert validation problems --- plugins/mod_s2s/mod_s2s.lua | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index e7ed8797..4d79a825 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -30,6 +30,7 @@ local runner = require "util.async".runner; local connect = require "net.connect".connect; local service = require "net.resolvers.service"; local errors = require "util.error"; +local set = require "util.set"; local connect_timeout = module:get_option_number("s2s_timeout", 90); local stream_close_timeout = module:get_option_number("s2s_close_timeout", 5); @@ -725,6 +726,25 @@ function listener.onattach(conn, data) end end +-- Complete the sentence "Your certificate " with what's wrong +local function friendly_cert_error(session) --> string + if session.cert_chain_status == "invalid" then + if session.cert_chain_errors then + local cert_errors = set.new(session.cert_chain_errors[1]); + if cert_errors:contains("certificate has expired") then + return "has expired"; + elseif cert_errors:contains("self signed certificate") then + return "is self-signed"; + end + end + return "is not trusted"; -- for some other reason + elseif session.cert_identity_status == "invalid" then + return "is not valid for this name"; + end + -- this should normally be unreachable except if no s2s auth module was loaded + return "could not be validated"; +end + function check_auth_policy(event) local host, session = event.host, event.session; local must_secure = secure_auth; @@ -737,11 +757,12 @@ function check_auth_policy(event) if must_secure and (session.cert_chain_status ~= "valid" or session.cert_identity_status ~= "valid") then module:log("warn", "Forbidding insecure connection to/from %s", host or session.ip or "(unknown host)"); + local reason = friendly_cert_error(session); if session.direction == "incoming" then - session:close({ condition = "not-authorized", text = "Your server's certificate is invalid, expired, or not trusted by "..session.to_host }, - nil, "Remote server's certificate is invalid, expired, or not trusted"); + session:close({ condition = "not-authorized", text = "Your server's certificate "..reason }, + nil, "Remote server's certificate "..reason); else -- Close outgoing connections without warning - session:close(false, nil, "Remote server's certificate is invalid, expired, or not trusted"); + session:close(false, nil, "Remote server's certificate "..reason); end return false; end -- cgit v1.2.3 From 976a86ee4645baf3e4ef8e0f8e6066fc62e8f379 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 28 Nov 2019 17:32:15 +0100 Subject: mod_s2s: Send stream errors for cert problems on outgoing connections Rationale in comment. --- plugins/mod_s2s/mod_s2s.lua | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 4d79a825..6419ea67 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -758,12 +758,13 @@ function check_auth_policy(event) if must_secure and (session.cert_chain_status ~= "valid" or session.cert_identity_status ~= "valid") then module:log("warn", "Forbidding insecure connection to/from %s", host or session.ip or "(unknown host)"); local reason = friendly_cert_error(session); - if session.direction == "incoming" then - session:close({ condition = "not-authorized", text = "Your server's certificate "..reason }, - nil, "Remote server's certificate "..reason); - else -- Close outgoing connections without warning - session:close(false, nil, "Remote server's certificate "..reason); - end + -- XEP-0178 recommends closing outgoing connections without warning + -- but does not give a rationale for this. + -- In practice most cases are configuration mistakes or forgotten + -- certificate renewals. We think it's better to let the other party + -- know about the problem so that they can fix it. + session:close({ condition = "not-authorized", text = "Your server's certificate "..reason }, + nil, "Remote server's certificate "..reason); return false; end end -- cgit v1.2.3 From 61228e919ce13247321c04b6b32020d2652d58ba Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 28 Nov 2019 18:30:30 +0100 Subject: mod_s2s: Abort outgoing connections earlier when TLS requirement isn't satisfied This ensures the closure reason is accurate and not reported as an authentication or other problem --- plugins/mod_s2s/mod_s2s.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 6419ea67..0fd022cd 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -190,6 +190,13 @@ function module.add_host(module) -- so the stream is ready for stanzas. RFC 6120 Section 4.3 mark_connected(session); return true; + elseif require_encryption and not session.secure then + session.log("warn", "Encrypted server-to-server communication is required but was not offered by %s", session.to_host); + session:close({ + condition = "policy-violation", + text = "Encrypted server-to-server communication is required but was not offered", + }, nil, "Could not establish encrypted connection to remote server"); + return false; elseif not session.dialback_verifying then session.log("warn", "No SASL EXTERNAL offer and Dialback doesn't seem to be enabled, giving up"); session:close({ -- cgit v1.2.3 From 35d07425e3e09a6d6ec4ca997271bf39f59f15f6 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 29 Nov 2019 18:15:23 +0100 Subject: mod_s2s: Prevent unhandled stanza handler from complaining about stream features on aborted connections I have no idea why I wrote return false in e5945fb5b71f --- plugins/mod_s2s/mod_s2s.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 0fd022cd..7cd90a84 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -196,14 +196,14 @@ function module.add_host(module) condition = "policy-violation", text = "Encrypted server-to-server communication is required but was not offered", }, nil, "Could not establish encrypted connection to remote server"); - return false; + return true; elseif not session.dialback_verifying then session.log("warn", "No SASL EXTERNAL offer and Dialback doesn't seem to be enabled, giving up"); session:close({ condition = "unsupported-feature", text = "No viable authentication method offered", }, nil, "No viable authentication method offered by remote server"); - return false; + return true; end end, -1); end -- cgit v1.2.3 From 0fdb85997abd2be59252595b1fec9e46389da586 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 29 Nov 2019 23:27:51 +0100 Subject: mod_net_multiplex: Add support for using ALPN Potentially a bit more efficient since it can jump to the selected protocol on connect instead of waiting for some data to look at. Adds a 'protocol' field to net providers for this purpose. --- plugins/mod_s2s/mod_s2s.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 7cd90a84..7f6546e9 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -796,6 +796,7 @@ module:provides("net", { verify = { "peer", "client_once", }; }; multiplex = { + protocol = "xmpp-server"; pattern = "^<.*:stream.*%sxmlns%s*=%s*(['\"])jabber:server%1.*>"; }; }); -- cgit v1.2.3 From 39cc0ec4510c0e3d80324c7085fa1a938c1f30f8 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 30 Nov 2019 23:29:15 +0100 Subject: mod_s2s: Improve log message about forbidding insecure connections This new wording generator is nice. --- plugins/mod_s2s/mod_s2s.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 7f6546e9..7700db85 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -763,8 +763,8 @@ function check_auth_policy(event) end if must_secure and (session.cert_chain_status ~= "valid" or session.cert_identity_status ~= "valid") then - module:log("warn", "Forbidding insecure connection to/from %s", host or session.ip or "(unknown host)"); local reason = friendly_cert_error(session); + module:log("warn", "Forbidding insecure connection to/from %s because its certificate %s", host or session.ip or "(unknown host)", reason); -- XEP-0178 recommends closing outgoing connections without warning -- but does not give a rationale for this. -- In practice most cases are configuration mistakes or forgotten -- cgit v1.2.3 From 56500e6e054e18fef1ec47f53e7b58bcc0841e95 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 30 Nov 2019 23:33:39 +0100 Subject: mod_s2s: Log from session logger Helps locating all messages related to a specific session --- plugins/mod_s2s/mod_s2s.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 7700db85..d0176cea 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -764,7 +764,7 @@ function check_auth_policy(event) if must_secure and (session.cert_chain_status ~= "valid" or session.cert_identity_status ~= "valid") then local reason = friendly_cert_error(session); - module:log("warn", "Forbidding insecure connection to/from %s because its certificate %s", host or session.ip or "(unknown host)", reason); + session.log("warn", "Forbidding insecure connection to/from %s because its certificate %s", host or session.ip or "(unknown host)", reason); -- XEP-0178 recommends closing outgoing connections without warning -- but does not give a rationale for this. -- In practice most cases are configuration mistakes or forgotten -- cgit v1.2.3 From 33ba4c2dbad8a92dcd7d9a94cc32bbb82b688b93 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 1 Dec 2019 01:20:34 +0100 Subject: mod_s2s: Improve TLS handshake error messages This should make it clearer that it's about the TLS handshake. Otherwise it's something like "unsupported protocol" or "no shared ciphers" that might not be that obvious. --- plugins/mod_s2s/mod_s2s.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index d0176cea..82f6a95d 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -692,6 +692,10 @@ function listener.ondisconnect(conn, err) if session then sessions[conn] = nil; (session.log or log)("debug", "s2s disconnected: %s->%s (%s)", session.from_host, session.to_host, err or "connection closed"); + if session.secure == false and err then + -- TODO util.error-ify this + err = "Error during negotiation of encrypted connection: "..err; + end s2s_destroy_session(session, err); end end -- cgit v1.2.3 From a62ff5dc64f7034477ca073900e917ca6398c2a2 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 1 Dec 2019 12:19:36 +0100 Subject: mod_s2s: Use stanza type check instead of duck typing --- plugins/mod_s2s/mod_s2s.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 82f6a95d..64ca7709 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -521,7 +521,7 @@ local function session_close(session, reason, remote_reason, bounce_reason) log("debug", "Disconnecting %s[%s], is: %s", session.host or session.ip or "(unknown host)", session.type, stanza); session.sends2s(stanza); - elseif reason.name then -- a stanza + elseif st.is_stanza(reason) then log("debug", "Disconnecting %s->%s[%s], is: %s", session.from_host or "(unknown host)", session.to_host or "(unknown host)", session.type, reason); -- cgit v1.2.3 From 91415f5a71021cc24053de17fca1c5337ebd7249 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 1 Dec 2019 12:21:26 +0100 Subject: mod_s2s: Refactor stream error handling on close Deduplicates the 3 log calls that log the same thing but subtly differently. The first one would say "Disconnecting localhost" and the last one didn't log the IP. --- plugins/mod_s2s/mod_s2s.lua | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 64ca7709..a3eec9f9 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -507,26 +507,21 @@ local function session_close(session, reason, remote_reason, bounce_reason) end if reason then -- nil == no err, initiated by us, false == initiated by remote if type(reason) == "string" then -- assume stream error - log("debug", "Disconnecting %s[%s], is: %s", session.host or session.ip or "(unknown host)", session.type, reason); - session.sends2s(st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' })); - elseif type(reason) == "table" then - if reason.condition then - local stanza = st.stanza("stream:error"):tag(reason.condition, stream_xmlns_attr):up(); - if reason.text then - stanza:tag("text", stream_xmlns_attr):text(reason.text):up(); - end - if reason.extra then - stanza:add_child(reason.extra); - end - log("debug", "Disconnecting %s[%s], is: %s", - session.host or session.ip or "(unknown host)", session.type, stanza); - session.sends2s(stanza); - elseif st.is_stanza(reason) then - log("debug", "Disconnecting %s->%s[%s], is: %s", - session.from_host or "(unknown host)", session.to_host or "(unknown host)", - session.type, reason); - session.sends2s(reason); + reason = st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' }); + elseif type(reason) == "table" and not st.is_stanza(reason) then + local stanza = st.stanza("stream:error"):tag(reason.condition or "undefined-condition", stream_xmlns_attr):up(); + if reason.text then + stanza:tag("text", stream_xmlns_attr):text(reason.text):up(); end + if reason.extra then + stanza:add_child(reason.extra); + end + end + if st.is_stanza(reason) then + -- to and from are never unknown on outgoing connections + log("debug", "Disconnecting %s->%s[%s], is: %s", + session.from_host or "(unknown host)" or session.ip, session.to_host or "(unknown host)", session.type, reason); + session.sends2s(reason); end end -- cgit v1.2.3 From 9f46aa4d48b2d43b1529f980dda2439e865cd908 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 3 Dec 2019 17:29:43 +0100 Subject: mod_s2s: Fix mistake in 28755107c2f4 --- plugins/mod_s2s/mod_s2s.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index a3eec9f9..8663702f 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -516,6 +516,7 @@ local function session_close(session, reason, remote_reason, bounce_reason) if reason.extra then stanza:add_child(reason.extra); end + reason = stanza; end if st.is_stanza(reason) then -- to and from are never unknown on outgoing connections -- cgit v1.2.3 From 2d5eaff749da055df6a29f20a169759f0bc96479 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Wed, 4 Dec 2019 22:37:20 +0100 Subject: mod_s2s: Invert condition to return early and reduce indentation --- plugins/mod_s2s/mod_s2s.lua | 52 ++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 8663702f..e5bfbe7c 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -123,33 +123,33 @@ function route_to_existing_session(event) return false; end local host = hosts[from_host].s2sout[to_host]; - if host then - -- We have a connection to this host already - if host.type == "s2sout_unauthed" and (stanza.name ~= "db:verify" or not host.dialback_key) then - (host.log or log)("debug", "trying to send over unauthed s2sout to "..to_host); - - -- Queue stanza until we are able to send it - local queued_item = { - tostring(stanza), - stanza.attr.type ~= "error" and stanza.attr.type ~= "result" and st.reply(stanza); - }; - if host.sendq then - t_insert(host.sendq, queued_item); - else - -- luacheck: ignore 122 - host.sendq = { queued_item }; - end - host.log("debug", "stanza [%s] queued ", stanza.name); - return true; - elseif host.type == "local" or host.type == "component" then - log("error", "Trying to send a stanza to ourselves??") - log("error", "Traceback: %s", traceback()); - log("error", "Stanza: %s", stanza); - return false; + if not host then return end + + -- We have a connection to this host already + if host.type == "s2sout_unauthed" and (stanza.name ~= "db:verify" or not host.dialback_key) then + (host.log or log)("debug", "trying to send over unauthed s2sout to "..to_host); + + -- Queue stanza until we are able to send it + local queued_item = { + tostring(stanza), + stanza.attr.type ~= "error" and stanza.attr.type ~= "result" and st.reply(stanza); + }; + if host.sendq then + t_insert(host.sendq, queued_item); else - if host.sends2s(stanza) then - return true; - end + -- luacheck: ignore 122 + host.sendq = { queued_item }; + end + host.log("debug", "stanza [%s] queued ", stanza.name); + return true; + elseif host.type == "local" or host.type == "component" then + log("error", "Trying to send a stanza to ourselves??") + log("error", "Traceback: %s", traceback()); + log("error", "Stanza: %s", stanza); + return false; + else + if host.sends2s(stanza) then + return true; end end end -- cgit v1.2.3 From ffcb8303ccdc3dc6c0cceae7c7a9ba8d2de5aa65 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 10 Dec 2019 17:43:26 +0100 Subject: mod_s2s: Fix name conflict introduced in c7864f970969 --- plugins/mod_s2s/mod_s2s.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index e5bfbe7c..6912c9a4 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -506,23 +506,23 @@ local function session_close(session, reason, remote_reason, bounce_reason) end end if reason then -- nil == no err, initiated by us, false == initiated by remote + local stream_error; if type(reason) == "string" then -- assume stream error - reason = st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' }); + stream_error = st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' }); elseif type(reason) == "table" and not st.is_stanza(reason) then - local stanza = st.stanza("stream:error"):tag(reason.condition or "undefined-condition", stream_xmlns_attr):up(); + stream_error = st.stanza("stream:error"):tag(reason.condition or "undefined-condition", stream_xmlns_attr):up(); if reason.text then - stanza:tag("text", stream_xmlns_attr):text(reason.text):up(); + stream_error:tag("text", stream_xmlns_attr):text(reason.text):up(); end if reason.extra then - stanza:add_child(reason.extra); + stream_error:add_child(reason.extra); end - reason = stanza; end - if st.is_stanza(reason) then + if st.is_stanza(stream_error) then -- to and from are never unknown on outgoing connections log("debug", "Disconnecting %s->%s[%s], is: %s", session.from_host or "(unknown host)" or session.ip, session.to_host or "(unknown host)", session.type, reason); - session.sends2s(reason); + session.sends2s(stream_error); end end -- cgit v1.2.3 From ad26a3b047ab0ae2efa0d61553e32f77da2ccac4 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 17 Dec 2019 00:34:39 +0100 Subject: mod_s2s: Remove obsolete pre-connect buffer Originally added in c500d4cb7855 Dead code since the net.connect switch in 756b8821007a --- plugins/mod_s2s/mod_s2s.lua | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'plugins/mod_s2s') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 6912c9a4..00d8f5d9 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -438,20 +438,6 @@ function stream_callbacks._streamopened(session, attr) end end - -- Send unauthed buffer - -- (stanzas which are fine to send before dialback) - -- Note that this is *not* the stanza queue (which - -- we can only send if auth succeeds) :) - local send_buffer = session.send_buffer; - if send_buffer and #send_buffer > 0 then - log("debug", "Sending s2s send_buffer now..."); - for i, data in ipairs(send_buffer) do - session.sends2s(tostring(data)); - send_buffer[i] = nil; - end - end - session.send_buffer = nil; - -- If server is pre-1.0, don't wait for features, just do dialback if session.version < 1.0 then if not session.dialback_verifying then -- cgit v1.2.3