From 899b61ad0f1995e087c6b335d64c2e2d4b7efacc Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 29 Aug 2014 02:24:49 +0200 Subject: mod_s2s_auth_certs: Warn about lack of certificate (Mostly jabberd14 not sending a client certificate) --- plugins/mod_s2s_auth_certs.lua | 61 ++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/plugins/mod_s2s_auth_certs.lua b/plugins/mod_s2s_auth_certs.lua index efc81130..dd0eb3cb 100644 --- a/plugins/mod_s2s_auth_certs.lua +++ b/plugins/mod_s2s_auth_certs.lua @@ -7,39 +7,42 @@ local log = module._log; module:hook("s2s-check-certificate", function(event) local session, host, cert = event.session, event.host, event.cert; local conn = session.conn:socket(); + local log = session.log or log; - if cert then - local log = session.log or log; - local chain_valid, errors; - if conn.getpeerverification then - chain_valid, errors = conn:getpeerverification(); - elseif conn.getpeerchainvalid then -- COMPAT mw/luasec-hg - chain_valid, errors = conn:getpeerchainvalid(); - errors = (not chain_valid) and { { errors } } or nil; - else - chain_valid, errors = false, { { "Chain verification not supported by this version of LuaSec" } }; + if not cert then + log("warn", "No certificate provided by %s", host or "unknown host"); + return; + end + + local chain_valid, errors; + if conn.getpeerverification then + chain_valid, errors = conn:getpeerverification(); + elseif conn.getpeerchainvalid then -- COMPAT mw/luasec-hg + chain_valid, errors = conn:getpeerchainvalid(); + errors = (not chain_valid) and { { errors } } or nil; + else + chain_valid, errors = false, { { "Chain verification not supported by this version of LuaSec" } }; + end + -- Is there any interest in printing out all/the number of errors here? + if not chain_valid then + log("debug", "certificate chain validation result: invalid"); + for depth, t in pairs(errors or NULL) do + log("debug", "certificate error(s) at depth %d: %s", depth-1, table.concat(t, ", ")) end - -- Is there any interest in printing out all/the number of errors here? - if not chain_valid then - log("debug", "certificate chain validation result: invalid"); - for depth, t in pairs(errors or NULL) do - log("debug", "certificate error(s) at depth %d: %s", depth-1, table.concat(t, ", ")) - end - session.cert_chain_status = "invalid"; - else - log("debug", "certificate chain validation result: valid"); - session.cert_chain_status = "valid"; + session.cert_chain_status = "invalid"; + else + log("debug", "certificate chain validation result: valid"); + session.cert_chain_status = "valid"; - -- We'll go ahead and verify the asserted identity if the - -- connecting server specified one. - if host then - if cert_verify_identity(host, "xmpp-server", cert) then - session.cert_identity_status = "valid" - else - session.cert_identity_status = "invalid" - end - log("debug", "certificate identity validation result: %s", session.cert_identity_status); + -- We'll go ahead and verify the asserted identity if the + -- connecting server specified one. + if host then + if cert_verify_identity(host, "xmpp-server", cert) then + session.cert_identity_status = "valid" + else + session.cert_identity_status = "invalid" end + log("debug", "certificate identity validation result: %s", session.cert_identity_status); end end end, 509); -- cgit v1.2.3 From 4bc9e05c119e883af72963465410c673fab815a6 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 2 Sep 2014 17:24:25 +0200 Subject: mod_s2s: Close offending s2s streams missing an 'id' attribute with a stream error instead of throwing an unhandled error --- plugins/mod_s2s/mod_s2s.lua | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 44334428..834e6a1c 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -365,8 +365,11 @@ function stream_callbacks.streamopened(session, attr) session.notopen = nil; elseif session.direction == "outgoing" then session.notopen = nil; - -- If we are just using the connection for verifying dialback keys, we won't try and auth it - if not attr.id then error("stream response did not give us a streamid!!!"); end + if not attr.id then + log("error", "Stream response did not give us a stream id!"); + session:close({ condition = "undefined-condition", text = "Missing stream ID" }); + return; + end session.streamid = attr.id; if session.secure and not session.cert_chain_status then -- cgit v1.2.3 From 257d0f104b61bac50f946c4eca9bd973110fce5d Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 29 Aug 2014 11:39:56 +0100 Subject: net.server_{select,event}: Add 'ondetach' callback for listener objects, to notify them when another listener is being assigned to a connection --- net/server_event.lua | 10 ++++++++-- net/server_select.lua | 5 +++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/net/server_event.lua b/net/server_event.lua index b05d1688..45938a13 100644 --- a/net/server_event.lua +++ b/net/server_event.lua @@ -438,8 +438,11 @@ do end function interface_mt:setlistener(listener) - self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout, self.onstatus - = listener.onconnect, listener.ondisconnect, listener.onincoming, listener.ontimeout, listener.onstatus; + self:ondetach(); -- Notify listener that it is no longer responsible for this connection + self.onconnect, self.ondisconnect, self.onincoming, + self.ontimeout, self.onstatus, self.ondetach + = listener.onconnect, listener.ondisconnect, listener.onincoming, + listener.ontimeout, listener.onstatus, listener.ondetach; end -- Stub handlers @@ -453,6 +456,8 @@ do end function interface_mt:ondrain() end + function interface_mt:ondetach() + end function interface_mt:onstatus() end end @@ -479,6 +484,7 @@ do onincoming = listener.onincoming; -- will be called when client sends data ontimeout = listener.ontimeout; -- called when fatal socket timeout occurs ondrain = listener.ondrain; -- called when writebuffer is empty + ondetach = listener.ondetach; -- called when disassociating this listener from this connection onstatus = listener.onstatus; -- called for status changes (e.g. of SSL/TLS) eventread = false, eventwrite = false, eventclose = false, eventhandshake = false, eventstarthandshake = false; -- event handler diff --git a/net/server_select.lua b/net/server_select.lua index e8964518..2b23b4f0 100644 --- a/net/server_select.lua +++ b/net/server_select.lua @@ -284,6 +284,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport local status = listeners.onstatus local disconnect = listeners.ondisconnect local drain = listeners.ondrain + local detach = listener.ondetach local bufferqueue = { } -- buffer array local bufferqueuelen = 0 -- end of buffer array @@ -313,10 +314,14 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport return disconnect end handler.setlistener = function( self, listeners ) + if detach then + detach(self) -- Notify listener that it is no longer responsible for this connection + end dispatch = listeners.onincoming disconnect = listeners.ondisconnect status = listeners.onstatus drain = listeners.ondrain + detach = listeners.ondetach end handler.getstats = function( ) return readtraffic, sendtraffic -- cgit v1.2.3 From 899b6d53ae45cae3ed7dbe9dfbca31c1ab812db3 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 29 Aug 2014 11:54:34 +0100 Subject: net.http, net.http.server, mod_c2s, mod_s2s, mod_component, mod_admin_telnet, mod_net_multiplex: Add ondetach to release connection from 'sessions' table (or equivalent) --- net/http.lua | 4 ++++ net/http/server.lua | 4 ++++ plugins/mod_admin_telnet.lua | 4 ++++ plugins/mod_c2s.lua | 4 ++++ plugins/mod_component.lua | 4 ++++ plugins/mod_net_multiplex.lua | 3 ++- plugins/mod_s2s/mod_s2s.lua | 4 ++++ 7 files changed, 26 insertions(+), 1 deletion(-) diff --git a/net/http.lua b/net/http.lua index 6ddb1900..9dde6062 100644 --- a/net/http.lua +++ b/net/http.lua @@ -72,6 +72,10 @@ function listener.ondisconnect(conn, err) requests[conn] = nil; end +function listener.ondetach(conn) + requests[conn] = nil; +end + local function request_reader(request, data, err) if not request.parser then local function error_cb(reason) diff --git a/net/http/server.lua b/net/http/server.lua index 771adf10..7937f87c 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -142,6 +142,10 @@ function listener.ondisconnect(conn) sessions[conn] = nil; end +function listener.ondetach(conn) + sessions[conn] = nil; +end + function listener.onincoming(conn, data) sessions[conn]:feed(data); end diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 671b6d89..e4b5a045 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -163,6 +163,10 @@ function console_listener.ondisconnect(conn, err) end end +function console_listener.ondetach(conn) + sessions[conn] = nil; +end + -- Console commands -- -- These are simple commands, not valid standalone in Lua diff --git a/plugins/mod_c2s.lua b/plugins/mod_c2s.lua index b6895f4b..3d6487c9 100644 --- a/plugins/mod_c2s.lua +++ b/plugins/mod_c2s.lua @@ -266,6 +266,10 @@ function listener.associate_session(conn, session) sessions[conn] = session; end +function listener.ondetach(conn) + sessions[conn] = nil; +end + module:hook("server-stopping", function(event) local reason = event.reason; for _, session in pairs(sessions) do diff --git a/plugins/mod_component.lua b/plugins/mod_component.lua index c5a1da81..7bc0f5b7 100644 --- a/plugins/mod_component.lua +++ b/plugins/mod_component.lua @@ -319,6 +319,10 @@ function listener.ondisconnect(conn, err) end end +function listener.ondetach(conn) + sessions[conn] = nil; +end + module:provides("net", { name = "component"; private = true; diff --git a/plugins/mod_net_multiplex.lua b/plugins/mod_net_multiplex.lua index d666b907..0dd3dc67 100644 --- a/plugins/mod_net_multiplex.lua +++ b/plugins/mod_net_multiplex.lua @@ -34,7 +34,6 @@ end function listener.onincoming(conn, data) if not data then return; end local buf = buffers[conn]; - buffers[conn] = nil; buf = buf and buf..data or data; for service, multiplex_pattern in pairs(available_services) do if buf:match(multiplex_pattern) then @@ -57,6 +56,8 @@ function listener.ondisconnect(conn, err) buffers[conn] = nil; -- warn if no buffer? end +listener.ondetach = listener.ondisconnect; + module:provides("net", { name = "multiplex"; config_prefix = ""; diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 834e6a1c..ee03987d 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -638,6 +638,10 @@ function listener.register_outgoing(conn, session) initialize_session(session); end +function listener.ondetach(conn) + sessions[conn] = nil; +end + function check_auth_policy(event) local host, session = event.host, event.session; local must_secure = secure_auth; -- cgit v1.2.3 From c2d718c06a1a178167ccf8c2dc4b865dc41b537e Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 1 Sep 2014 20:20:05 +0200 Subject: mod_dialback: Move d-w-d after to/from validation --- plugins/mod_dialback.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/mod_dialback.lua b/plugins/mod_dialback.lua index 2584299c..4c5e3e44 100644 --- a/plugins/mod_dialback.lua +++ b/plugins/mod_dialback.lua @@ -82,6 +82,15 @@ module:hook("stanza/jabber:server:dialback:result", function(event) local attr = stanza.attr; local to, from = nameprep(attr.to), nameprep(attr.from); + if not hosts[to] then + -- Not a host that we serve + origin.log("warn", "%s tried to connect to %s, which we don't serve", from, to); + origin:close("host-unknown"); + return true; + elseif not from then + origin:close("improper-addressing"); + end + if dwd and origin.secure then if check_cert_status(origin, from) == false then return @@ -92,15 +101,6 @@ module:hook("stanza/jabber:server:dialback:result", function(event) end end - if not hosts[to] then - -- Not a host that we serve - origin.log("warn", "%s tried to connect to %s, which we don't serve", from, to); - origin:close("host-unknown"); - return true; - elseif not from then - origin:close("improper-addressing"); - end - origin.hosts[from] = { dialback_key = stanza[1] }; dialback_requests[from.."/"..origin.streamid] = origin; -- cgit v1.2.3 From 69d97b4f7ed15249ce71a5b261bff98a008684aa Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 2 Sep 2014 17:23:44 +0100 Subject: net.server_select: 'listener'->'listeners' (fixes undefined global access) --- net/server_select.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/server_select.lua b/net/server_select.lua index 2b23b4f0..7ac41523 100644 --- a/net/server_select.lua +++ b/net/server_select.lua @@ -284,7 +284,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport local status = listeners.onstatus local disconnect = listeners.ondisconnect local drain = listeners.ondrain - local detach = listener.ondetach + local detach = listeners.ondetach local bufferqueue = { } -- buffer array local bufferqueuelen = 0 -- end of buffer array -- cgit v1.2.3 From 56b4c1c856f107e178aede2313d943022ad3c73d Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 2 Sep 2014 17:56:42 +0100 Subject: util.hex: Small util lib for converting to/from hex strings --- util/hex.lua | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 util/hex.lua diff --git a/util/hex.lua b/util/hex.lua new file mode 100644 index 00000000..72fc22bd --- /dev/null +++ b/util/hex.lua @@ -0,0 +1,19 @@ +local s_char = string.char; + +local function char_to_hex(c) + return ("%02x"):format(c:byte()) +end + +local function hex_to_char(h) + return s_char(tonumber(h, 16)); +end + +function to(s) + return s:gsub(".", char_to_hex); +end + +function from(s) + return s:gsub("..", hex_to_char); +end + +return { to = to, from = from } -- cgit v1.2.3 From 2716c4191dfe01af0f75dc7d4642f3a0e1494b31 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 2 Sep 2014 17:57:18 +0100 Subject: util.random: Generic util lib for generating strings of random bytes --- util/random.lua | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 util/random.lua diff --git a/util/random.lua b/util/random.lua new file mode 100644 index 00000000..ed5cdf4b --- /dev/null +++ b/util/random.lua @@ -0,0 +1,43 @@ +-- Prosody IM +-- Copyright (C) 2008-2014 Matthew Wild +-- Copyright (C) 2008-2014 Waqas Hussain +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + +local tostring = tostring; +local os_time = os.time; +local os_clock = os.clock; +local ceil = math.ceil; +local sha1 = require "util.hashes".sha1; + +local last_uniq_time = 0; +local function uniq_time() + local new_uniq_time = os_time(); + if last_uniq_time >= new_uniq_time then new_uniq_time = last_uniq_time + 1; end + last_uniq_time = new_uniq_time; + return new_uniq_time; +end + +local function new_random(x) + return sha1(x..os_clock()..tostring({})); +end + +local buffer = new_random(uniq_time()); + +local function seed(x) + buffer = new_random(buffer..x); +end + +local function bytes(n) + if #buffer < n then seed(uniq_time()); end + local r = buffer:sub(0, n); + buffer = buffer:sub(n+1); + return r; +end + +return { + seed = seed; + bytes = bytes; +}; -- cgit v1.2.3 From a540fdb9f448eb0990899b70e0ed8ab926e979f6 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 2 Sep 2014 17:58:12 +0100 Subject: util.uuid: Use util.hex and util.random --- util/uuid.lua | 44 +++++++++++++------------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/util/uuid.lua b/util/uuid.lua index fc487c72..e10fc0f7 100644 --- a/util/uuid.lua +++ b/util/uuid.lua @@ -6,45 +6,27 @@ -- COPYING file in the source package for more information. -- +local random = require "util.random"; +local random_bytes = random.bytes; +local hex = require "util.hex".to; +local m_ceil = math.ceil; -local m_random = math.random; -local tostring = tostring; -local os_time = os.time; -local os_clock = os.clock; -local sha1 = require "util.hashes".sha1; - -module "uuid" - -local last_uniq_time = 0; -local function uniq_time() - local new_uniq_time = os_time(); - if last_uniq_time >= new_uniq_time then new_uniq_time = last_uniq_time + 1; end - last_uniq_time = new_uniq_time; - return new_uniq_time; -end - -local function new_random(x) - return sha1(x..os_clock()..tostring({}), true); -end - -local buffer = new_random(uniq_time()); -local function _seed(x) - buffer = new_random(buffer..x); -end local function get_nibbles(n) - if #buffer < n then _seed(uniq_time()); end - local r = buffer:sub(0, n); - buffer = buffer:sub(n+1); - return r; + return hex(random_bytes(m_ceil(n/2))):sub(1, n); end + local function get_twobits() return ("%x"):format(get_nibbles(1):byte() % 4 + 8); end -function generate() +local function generate() -- generate RFC 4122 complaint UUIDs (version 4 - random) return get_nibbles(8).."-"..get_nibbles(4).."-4"..get_nibbles(3).."-"..(get_twobits())..get_nibbles(3).."-"..get_nibbles(12); end -seed = _seed; -return _M; +return { + get_nibbles=get_nibbles; + generate = generate ; + -- COMPAT + seed = random.seed; +}; -- cgit v1.2.3