From e9b383cdb22cbf667fc16d55351ff1d71d0e6d9f Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 30 Apr 2021 21:20:14 +0100 Subject: prosodyctl: check config: Add 'gc' to list of global options --- prosodyctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prosodyctl b/prosodyctl index 028e08d8..28e9da43 100755 --- a/prosodyctl +++ b/prosodyctl @@ -837,7 +837,7 @@ function commands.check(arg) local known_global_options = set.new({ "pidfile", "log", "plugin_paths", "prosody_user", "prosody_group", "daemonize", "umask", "prosodyctl_timeout", "use_ipv6", "use_libevent", "network_settings", - "network_backend", "http_default_host", + "network_backend", "http_default_host", "gc", "statistics_interval", "statistics", "statistics_config", }); local config = configmanager.getconfig(); -- cgit v1.2.3 From 4c7989e7e4c95ccfbdc189abc5bdea9aa9e90b02 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 7 May 2021 16:41:39 +0100 Subject: util.startup: Set more aggressive defaults for GC Testing has demonstrated that the default GC parameters are not sufficient to prevent runaway memory growth when running under Lua 5.2 and Lua 5.3. Setting the GC speed to 500 was tested on Lua versions 5.1->5.4 and did not display unbounded memory growth. --- util/startup.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/util/startup.lua b/util/startup.lua index c1f4ec8b..b3857830 100644 --- a/util/startup.lua +++ b/util/startup.lua @@ -12,7 +12,13 @@ local dependencies = require "util.dependencies"; local original_logging_config; -local default_gc_params = { mode = "incremental", threshold = 105, speed = 250 }; +local default_gc_params = { + mode = "incremental"; + -- Incremental mode defaults + threshold = 105, speed = 500; + -- Generational mode defaults + minor_threshold = 20, major_threshold = 50; +}; local short_params = { D = "daemonize", F = "no-daemonize" }; local value_params = { config = true }; -- cgit v1.2.3 From 4c4e764e23cd7d103868a73a0cdb5a7bdcaa4bea Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 7 May 2021 17:03:49 +0100 Subject: mod_c2s, mod_s2s, mod_component, mod_bosh, mod_websockets: Set default stanza size limits c2s/bosh/ws streams will default to 256KB, s2s and components to 512KB. These values are aligned with ejabberd's default settings, which should reduce issues related to inconsistent size limits between servers on the XMPP network. The previous default (10MB) is excessive for any production server, and allows significant memory usage by even unauthenticated sessions. --- plugins/mod_bosh.lua | 3 ++- plugins/mod_c2s.lua | 2 +- plugins/mod_component.lua | 3 ++- plugins/mod_s2s/mod_s2s.lua | 2 +- plugins/mod_websocket.lua | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/mod_bosh.lua b/plugins/mod_bosh.lua index 52168670..db7ae03e 100644 --- a/plugins/mod_bosh.lua +++ b/plugins/mod_bosh.lua @@ -45,6 +45,7 @@ local bosh_max_wait = module:get_option_number("bosh_max_wait", 120); local consider_bosh_secure = module:get_option_boolean("consider_bosh_secure"); local cross_domain = module:get_option("cross_domain_bosh", false); +local stanza_size_limit = module:get_option_number("c2s_stanza_size_limit", 1024*256); if cross_domain == true then cross_domain = "*"; end if type(cross_domain) == "table" then cross_domain = table.concat(cross_domain, ", "); end @@ -115,7 +116,7 @@ function handle_POST(event) local body = request.body; local context = { request = request, response = response, notopen = true }; - local stream = new_xmpp_stream(context, stream_callbacks); + local stream = new_xmpp_stream(context, stream_callbacks, stanza_size_limit); response.context = context; local headers = response.headers; diff --git a/plugins/mod_c2s.lua b/plugins/mod_c2s.lua index 8d4dcfb8..f19f9df5 100644 --- a/plugins/mod_c2s.lua +++ b/plugins/mod_c2s.lua @@ -26,7 +26,7 @@ local log = module._log; local c2s_timeout = module:get_option_number("c2s_timeout", 300); local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5); local opt_keepalives = module:get_option_boolean("c2s_tcp_keepalives", module:get_option_boolean("tcp_keepalives", true)); -local stanza_size_limit = module:get_option_number("c2s_stanza_size_limit"); -- TODO come up with a sensible default (util.xmppstream defaults to 10M) +local stanza_size_limit = module:get_option_number("c2s_stanza_size_limit", 1024*256); local measure_connections = module:measure("connections", "amount"); local measure_ipv6 = module:measure("ipv6", "amount"); diff --git a/plugins/mod_component.lua b/plugins/mod_component.lua index b41204a2..51d731c7 100644 --- a/plugins/mod_component.lua +++ b/plugins/mod_component.lua @@ -27,6 +27,7 @@ local hosts = prosody.hosts; local log = module._log; local opt_keepalives = module:get_option_boolean("component_tcp_keepalives", module:get_option_boolean("tcp_keepalives", true)); +local stanza_size_limit = module:get_option_number("component_stanza_size_limit", module:get_option_number("s2s_stanza_size_limit", 1024*512)); local sessions = module:shared("sessions"); @@ -297,7 +298,7 @@ function listener.onconnect(conn) session.log("info", "Incoming Jabber component connection"); - local stream = new_xmpp_stream(session, stream_callbacks); + local stream = new_xmpp_stream(session, stream_callbacks, stanza_size_limit); session.stream = stream; session.notopen = true; diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index 8e398f56..b2376b97 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -37,7 +37,7 @@ local secure_auth = module:get_option_boolean("s2s_secure_auth", false); -- One local secure_domains, insecure_domains = module:get_option_set("s2s_secure_domains", {})._items, module:get_option_set("s2s_insecure_domains", {})._items; local require_encryption = module:get_option_boolean("s2s_require_encryption", false); -local stanza_size_limit = module:get_option_number("s2s_stanza_size_limit"); -- TODO come up with a sensible default (util.xmppstream defaults to 10M) +local stanza_size_limit = module:get_option_number("s2s_stanza_size_limit", 1024*512); local measure_connections = module:measure("connections", "amount"); local measure_ipv6 = module:measure("ipv6", "amount"); diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index a613672b..60c76605 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -28,7 +28,7 @@ local parse_close = websocket_frames.parse_close; local t_concat = table.concat; -local stanza_size_limit = module:get_option_number("c2s_stanza_size_limit", 10 * 1024 * 1024); +local stanza_size_limit = module:get_option_number("c2s_stanza_size_limit", 1024 * 256); local frame_buffer_limit = module:get_option_number("websocket_frame_buffer_limit", 2 * stanza_size_limit); local frame_fragment_limit = module:get_option_number("websocket_frame_fragment_limit", 8); local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5); -- cgit v1.2.3 From f5460a5037f0dda1b02873ee189bf38685933529 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 10 May 2021 16:24:54 +0100 Subject: util.hashes: Add constant-time string comparison (binding to CRYPTO_memcmp) --- util-src/hashes.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/util-src/hashes.c b/util-src/hashes.c index 903ecb6e..b16eb03f 100644 --- a/util-src/hashes.c +++ b/util-src/hashes.c @@ -23,6 +23,7 @@ typedef unsigned __int32 uint32_t; #include "lua.h" #include "lauxlib.h" +#include #include #include #include @@ -189,6 +190,18 @@ static int LscramHi(lua_State *L) { return 1; } +static int Lhash_equals(lua_State *L) { + size_t len1, len2; + const char *s1 = luaL_checklstring(L, 1, &len1); + const char *s2 = luaL_checklstring(L, 2, &len2); + if(len1 == len2) { + lua_pushboolean(L, CRYPTO_memcmp(s1, s2, len1) == 0); + } else { + lua_pushboolean(L, 0); + } + return 1; +} + static const luaL_Reg Reg[] = { { "sha1", Lsha1 }, { "sha224", Lsha224 }, @@ -201,6 +214,7 @@ static const luaL_Reg Reg[] = { { "hmac_sha512", Lhmac_sha512 }, { "hmac_md5", Lhmac_md5 }, { "scram_Hi_sha1", LscramHi }, + { "equals", Lhash_equals }, { NULL, NULL } }; -- cgit v1.2.3 From 06161ab7662dace66ac7f33198d6ded5683d5abe Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 10 May 2021 16:41:56 +0100 Subject: util.set: Add is_set() to test if an object is a set --- util/set.lua | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/util/set.lua b/util/set.lua index 02fabc6a..b7345e7e 100644 --- a/util/set.lua +++ b/util/set.lua @@ -6,8 +6,8 @@ -- COPYING file in the source package for more information. -- -local ipairs, pairs, setmetatable, next, tostring = - ipairs, pairs, setmetatable, next, tostring; +local ipairs, pairs, getmetatable, setmetatable, next, tostring = + ipairs, pairs, getmetatable, setmetatable, next, tostring; local t_concat = table.concat; local _ENV = nil; @@ -31,6 +31,11 @@ function set_mt:__freeze() return a; end +local function is_set(o) + local mt = getmetatable(o); + return mt == set_mt; +end + local function new(list) local items = setmetatable({}, items_mt); local set = { _items = items }; @@ -171,6 +176,7 @@ end return { new = new; + is_set = is_set; union = union; difference = difference; intersection = intersection; -- cgit v1.2.3 From d126ee88bc666524339830b71141c92bb06cd283 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 10 May 2021 16:44:55 +0100 Subject: util.xmppstream: Reduce default xmppstream limit to 1MB --- util/xmppstream.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/xmppstream.lua b/util/xmppstream.lua index 58cbd18e..e2c24c8a 100644 --- a/util/xmppstream.lua +++ b/util/xmppstream.lua @@ -22,7 +22,7 @@ local lxp_supports_doctype = pcall(lxp.new, { StartDoctypeDecl = false }); local lxp_supports_xmldecl = pcall(lxp.new, { XmlDecl = false }); local lxp_supports_bytecount = not not lxp.new({}).getcurrentbytecount; -local default_stanza_size_limit = 1024*1024*10; -- 10MB +local default_stanza_size_limit = 1024*1024*1; -- 1MB local _ENV = nil; -- luacheck: std none -- cgit v1.2.3 From 6a54d2d2c483de3824f57fffc3ab3375fde4e21e Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 10 May 2021 16:50:24 +0100 Subject: mod_auth_internal_{plain,hashed}: Use constant-time string comparison for secrets --- plugins/mod_auth_internal_hashed.lua | 5 +++-- plugins/mod_auth_internal_plain.lua | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/mod_auth_internal_hashed.lua b/plugins/mod_auth_internal_hashed.lua index 15058098..b29a9ee8 100644 --- a/plugins/mod_auth_internal_hashed.lua +++ b/plugins/mod_auth_internal_hashed.lua @@ -16,6 +16,7 @@ local new_sasl = require "util.sasl".new; local hex = require"util.hex"; local to_hex, from_hex = hex.to, hex.from; local saslprep = require "util.encodings".stringprep.saslprep; +local secure_equals = require "util.hashes".equals; local log = module._log; local host = module.host; @@ -39,7 +40,7 @@ function provider.test_password(username, password) end if credentials.password ~= nil and string.len(credentials.password) ~= 0 then - if saslprep(credentials.password) ~= password then + if not secure_equals(saslprep(credentials.password), password) then return nil, "Auth failed. Provided password is incorrect."; end @@ -59,7 +60,7 @@ function provider.test_password(username, password) local stored_key_hex = to_hex(stored_key); local server_key_hex = to_hex(server_key); - if valid and stored_key_hex == credentials.stored_key and server_key_hex == credentials.server_key then + if valid and secure_equals(stored_key_hex, credentials.stored_key) and secure_equals(server_key_hex, credentials.server_key) then return true; else return nil, "Auth failed. Invalid username, password, or password hash information."; diff --git a/plugins/mod_auth_internal_plain.lua b/plugins/mod_auth_internal_plain.lua index 56ef52d5..8a50e820 100644 --- a/plugins/mod_auth_internal_plain.lua +++ b/plugins/mod_auth_internal_plain.lua @@ -9,6 +9,7 @@ local usermanager = require "core.usermanager"; local new_sasl = require "util.sasl".new; local saslprep = require "util.encodings".stringprep.saslprep; +local secure_equals = require "util.hashes".equals; local log = module._log; local host = module.host; @@ -26,7 +27,7 @@ function provider.test_password(username, password) return nil, "Password fails SASLprep."; end - if password == saslprep(credentials.password) then + if secure_equals(password, saslprep(credentials.password)) then return true; else return nil, "Auth failed. Invalid username or password."; -- cgit v1.2.3 From 1e42cdef094e3c34d0c3791d5d2b55d1726d8313 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 10 May 2021 17:01:38 +0100 Subject: MUC: Add support for advertising muc#roomconfig_allowinvites in room disco#info The de-facto interpretation of this (undocumented) option is to indicate to the client whether it is allowed to invite other users to the MUC. This is differs from the existing option in our config form, which only controls the behaviour of sending of invites in a members-only MUC (we always allow invites in open rooms). Conversations is one client known to use this disco#info item to determine whether it may send invites. --- plugins/muc/members_only.lib.lua | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/muc/members_only.lib.lua b/plugins/muc/members_only.lib.lua index 4194c5c7..3220225f 100644 --- a/plugins/muc/members_only.lib.lua +++ b/plugins/muc/members_only.lib.lua @@ -61,12 +61,20 @@ local function set_allow_member_invites(room, allow_member_invites) end module:hook("muc-disco#info", function(event) - event.reply:tag("feature", {var = get_members_only(event.room) and "muc_membersonly" or "muc_open"}):up(); + local members_only_room = not not get_members_only(event.room); + local members_can_invite = not not get_allow_member_invites(event.room); + event.reply:tag("feature", {var = members_only_room and "muc_membersonly" or "muc_open"}):up(); table.insert(event.form, { name = "{http://prosody.im/protocol/muc}roomconfig_allowmemberinvites"; label = "Allow members to invite new members"; type = "boolean"; - value = not not get_allow_member_invites(event.room); + value = members_can_invite; + }); + table.insert(event.form, { + name = "muc#roomconfig_allowinvites"; + label = "Allow users to invite other users"; + type = "boolean"; + value = not members_only_room or members_can_invite; }); end); -- cgit v1.2.3 From 7cb3ec61d5117fa1be7077ea9efaef4d4e52ca57 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 10 May 2021 17:02:37 +0100 Subject: util.xmppstream: Mark bytes for stream closure as handled --- util/xmppstream.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/util/xmppstream.lua b/util/xmppstream.lua index e2c24c8a..57e1def3 100644 --- a/util/xmppstream.lua +++ b/util/xmppstream.lua @@ -188,6 +188,9 @@ local function new_sax_handlers(session, stream_callbacks, cb_handleprogress) stanza = t_remove(stack); end else + if lxp_supports_bytecount then + cb_handleprogress(stanza_size); + end if cb_streamclosed then cb_streamclosed(session); end -- cgit v1.2.3 From 92cec56e9760c6dc2dc3d775e81646e9995fc6b4 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 10 May 2021 17:03:27 +0100 Subject: util.xmppstream: Allow dynamically configuring the stanza size limit for a stream This may be useful for any plugins that want to experiment with different policies for stanza size limits (e.g. unauthenticated vs authenticated streams). --- util/xmppstream.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/util/xmppstream.lua b/util/xmppstream.lua index 57e1def3..82a9820f 100644 --- a/util/xmppstream.lua +++ b/util/xmppstream.lua @@ -293,6 +293,9 @@ local function new(session, stream_callbacks, stanza_size_limit) return ok, err; end, set_session = meta.set_session; + set_stanza_size_limit = function (_, new_stanza_size_limit) + stanza_size_limit = new_stanza_size_limit; + end; }; end -- cgit v1.2.3 From a174420e52cdbc0c80680d76c750d0ac59c01870 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 26 Apr 2021 15:30:13 +0200 Subject: core.certmanager: Attempt to directly access LuaSec config table Due to a bug this field was not properly exported before See https://github.com/brunoos/luasec/issues/149 --- core/certmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/certmanager.lua b/core/certmanager.lua index 20b91318..85a24d3d 100644 --- a/core/certmanager.lua +++ b/core/certmanager.lua @@ -38,7 +38,7 @@ local config_path = prosody.paths.config or "."; local luasec_major, luasec_minor = ssl._VERSION:match("^(%d+)%.(%d+)"); local luasec_version = tonumber(luasec_major) * 100 + tonumber(luasec_minor); -local luasec_has = softreq"ssl.config" or { +local luasec_has = ssl.config or softreq"ssl.config" or { algorithms = { ec = luasec_version >= 5; }; -- cgit v1.2.3 From b369dea3d885a0a5efe882f75f5e90704cb95e87 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 26 Apr 2021 15:32:05 +0200 Subject: core.certmanager: Test for SSL options in absence of LuaSec config --- core/certmanager.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/certmanager.lua b/core/certmanager.lua index 85a24d3d..b0c7039d 100644 --- a/core/certmanager.lua +++ b/core/certmanager.lua @@ -36,6 +36,10 @@ local prosody = prosody; local resolve_path = require"util.paths".resolve_relative_path; local config_path = prosody.paths.config or "."; +local function test_option(option) + return not not ssl_newcontext({mode="server",protocol="sslv23",options={ option }}); +end + local luasec_major, luasec_minor = ssl._VERSION:match("^(%d+)%.(%d+)"); local luasec_version = tonumber(luasec_major) * 100 + tonumber(luasec_minor); local luasec_has = ssl.config or softreq"ssl.config" or { @@ -46,11 +50,11 @@ local luasec_has = ssl.config or softreq"ssl.config" or { curves_list = luasec_version >= 7; }; options = { - cipher_server_preference = luasec_version >= 2; - no_ticket = luasec_version >= 4; - no_compression = luasec_version >= 5; - single_dh_use = luasec_version >= 2; - single_ecdh_use = luasec_version >= 2; + cipher_server_preference = test_option("cipher_server_preference"); + no_ticket = test_option("no_ticket"); + no_compression = test_option("no_compression"); + single_dh_use = test_option("single_dh_use"); + single_ecdh_use = test_option("single_ecdh_use"); }; }; -- cgit v1.2.3 From 08f721a07280cf59abd167ad0fcfcb6f9bb8fb19 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 11 May 2021 14:10:26 +0100 Subject: mod_limits: Don't emit error when no burst period is configured --- plugins/mod_limits.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mod_limits.lua b/plugins/mod_limits.lua index 914d5c44..616dca1b 100644 --- a/plugins/mod_limits.lua +++ b/plugins/mod_limits.lua @@ -31,7 +31,7 @@ local function parse_burst(burst, sess_type) burst = burst:match("^(%d+) ?s$"); end local n_burst = tonumber(burst); - if not n_burst then + if burst and not n_burst then module:log("error", "Unable to parse burst for %s: %q, using default burst interval (%ds)", sess_type, tostring(burst), default_burst); end return n_burst or default_burst; -- cgit v1.2.3 From f0c2ed120130778f3a6ef59e41d1deb1667e9f3f Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 11 May 2021 14:14:15 +0100 Subject: certmanager: Disable renegotiation by default This requires LuaSec 0.7+ and OpenSSL 1.1.1+ --- core/certmanager.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/certmanager.lua b/core/certmanager.lua index b0c7039d..d8d07636 100644 --- a/core/certmanager.lua +++ b/core/certmanager.lua @@ -55,6 +55,7 @@ local luasec_has = ssl.config or softreq"ssl.config" or { no_compression = test_option("no_compression"); single_dh_use = test_option("single_dh_use"); single_ecdh_use = test_option("single_ecdh_use"); + no_renegotiation = test_option("no_renegotiation"); }; }; @@ -119,6 +120,7 @@ local core_defaults = { no_compression = luasec_has.options.no_compression and configmanager.get("*", "ssl_compression") ~= true; single_dh_use = luasec_has.options.single_dh_use; single_ecdh_use = luasec_has.options.single_ecdh_use; + no_renegotiation = luasec_has.options.no_renegotiation; }; verifyext = { "lsec_continue", "lsec_ignore_purpose" }; curve = luasec_has.algorithms.ec and not luasec_has.capabilities.curves_list and "secp384r1"; -- cgit v1.2.3 From 3fd3d2cd99284e5641084c5acb485028de535a05 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 11 May 2021 14:15:22 +0100 Subject: prosodyctl about: Report libexpat version if known --- prosodyctl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/prosodyctl b/prosodyctl index 28e9da43..8c0ce66c 100755 --- a/prosodyctl +++ b/prosodyctl @@ -413,7 +413,8 @@ function commands.about(arg) print(""); print("# Lua module versions"); local module_versions, longest_name = {}, 8; - local luaevent =dependencies.softreq"luaevent"; + local luaevent = dependencies.softreq"luaevent"; + local lxp = dependencies.softreq"lxp"; dependencies.softreq"ssl"; dependencies.softreq"DBI"; for name, module in pairs(package.loaded) do @@ -428,6 +429,9 @@ function commands.about(arg) if luaevent then module_versions["libevent"] = luaevent.core.libevent_version(); end + if lxp then + module_versions["libexpat"] = lxp._EXPAT_VERSION; + end local sorted_keys = array.collect(keys(module_versions)):sort(); for _, name in ipairs(sorted_keys) do print(name..":"..string.rep(" ", longest_name-#name), module_versions[name]); -- cgit v1.2.3 From 6d15e34180d46e5c9914be744870d14361fd010c Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 11 May 2021 14:17:12 +0100 Subject: prosody.cfg.lua.dist: Enable rate limits by default --- prosody.cfg.lua.dist | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/prosody.cfg.lua.dist b/prosody.cfg.lua.dist index f7f7b731..9ed17d56 100644 --- a/prosody.cfg.lua.dist +++ b/prosody.cfg.lua.dist @@ -51,6 +51,7 @@ modules_enabled = { "blocklist"; -- Allow users to block communications with other users "vcard4"; -- User profiles (stored in PEP) "vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard + "limits"; -- Enable bandwidth limiting for XMPP connections -- Nice to have "version"; -- Replies to server version requests @@ -71,7 +72,6 @@ modules_enabled = { --"http_files"; -- Serve static files from a directory over HTTP -- Other specific functionality - --"limits"; -- Enable bandwidth limiting for XMPP connections --"groups"; -- Shared roster support --"server_contact_info"; -- Publish contact information for this service --"announce"; -- Send announcement to all online users @@ -121,6 +121,17 @@ s2s_secure_auth = false --s2s_secure_domains = { "jabber.org" } +-- Enable rate limits for incoming client and server connections + +limits = { + c2s = { + rate = "10kb/s"; + }; + s2sin = { + rate = "30kb/s"; + }; +} + -- Select the authentication backend to use. The 'internal' providers -- use Prosody's configured data storage to store the authentication data. -- cgit v1.2.3 From 6f6c807bdf9eb25f335ace6f73243801019bbb87 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 11 May 2021 14:22:59 +0100 Subject: mod_limits: Use default limits if none configured --- plugins/mod_limits.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/mod_limits.lua b/plugins/mod_limits.lua index 616dca1b..98b52a96 100644 --- a/plugins/mod_limits.lua +++ b/plugins/mod_limits.lua @@ -39,7 +39,16 @@ end -- Process config option into limits table: -- limits = { c2s = { bytes_per_second = X, burst_seconds = Y } } -local limits = {}; +local limits = { + c2s = { + bytes_per_second = 10 * 1024; + burst_seconds = 2; + }; + s2sin = { + bytes_per_second = 30 * 1024; + burst_seconds = 2; + }; +}; for sess_type, sess_limits in pairs(limits_cfg) do limits[sess_type] = { -- cgit v1.2.3 From 0d3dc2e5223f7f63449a2c5c92b97e310377dca9 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Wed, 12 May 2021 13:59:49 +0100 Subject: mod_proxy65: Restrict access to local c2s connections by default Previously no 'proxy65_acl' option would allow unrestricted access by local or remote JIDs. --- plugins/mod_proxy65.lua | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/plugins/mod_proxy65.lua b/plugins/mod_proxy65.lua index 00833772..36614810 100644 --- a/plugins/mod_proxy65.lua +++ b/plugins/mod_proxy65.lua @@ -94,6 +94,7 @@ function module.add_host(module) local proxy_address = module:get_option_string("proxy65_address", host); local proxy_acl = module:get_option_array("proxy65_acl"); + local proxy_open_access = module:get_option_boolean("proxy65_open_access", false); -- COMPAT w/pre-0.9 where proxy65_port was specified in the components section of the config local legacy_config = module:get_option_number("proxy65_port"); @@ -110,13 +111,20 @@ function module.add_host(module) -- check ACL -- using 'while' instead of 'if' so we can break out of it - while proxy_acl and #proxy_acl > 0 do --luacheck: ignore 512 + local allow; + if proxy_acl and #proxy_acl > 0 then local jid = stanza.attr.from; - local allow; for _, acl in ipairs(proxy_acl) do - if jid_compare(jid, acl) then allow = true; break; end + if jid_compare(jid, acl) then + allow = true; + break; + end end - if allow then break; end + elseif proxy_open_access or origin.type == "c2s" then + allow = true; + end + + if not allow then module:log("warn", "Denying use of proxy for %s", tostring(stanza.attr.from)); origin.send(st.error_reply(stanza, "auth", "forbidden")); return true; -- cgit v1.2.3 From 0a3d7966232970cb9c8076d693db0a7fef69116d Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Wed, 12 May 2021 14:00:53 +0100 Subject: mod_dialback: Use constant-time comparison with hmac --- plugins/mod_dialback.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/mod_dialback.lua b/plugins/mod_dialback.lua index eddc3209..38d16b60 100644 --- a/plugins/mod_dialback.lua +++ b/plugins/mod_dialback.lua @@ -13,6 +13,7 @@ local log = module._log; local st = require "util.stanza"; local sha256_hash = require "util.hashes".sha256; local sha256_hmac = require "util.hashes".hmac_sha256; +local secure_equals = require "util.hashes".equals; local nameprep = require "util.encodings".stringprep.nameprep; local uuid_gen = require"util.uuid".generate; @@ -56,7 +57,7 @@ function initiate_dialback(session) end function verify_dialback(id, to, from, key) - return key == generate_dialback(id, to, from); + return secure_equals(key, generate_dialback(id, to, from)); end module:hook("stanza/jabber:server:dialback:verify", function(event) -- cgit v1.2.3 From 1cd5049c778cd54f88eb349411ccebd36af5ab3e Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 23 Jun 2019 16:16:26 +0200 Subject: mod_dialback: Use correct host for certificate check (fixes #1381) --- plugins/mod_dialback.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/mod_dialback.lua b/plugins/mod_dialback.lua index 38d16b60..c81484a9 100644 --- a/plugins/mod_dialback.lua +++ b/plugins/mod_dialback.lua @@ -25,8 +25,7 @@ local dialback_secret = sha256_hash(module:get_option_string("dialback_secret", local dwd = module:get_option_boolean("dialback_without_dialback", false); --- Helper to check that a session peer's certificate is valid -function check_cert_status(session) - local host = session.direction == "outgoing" and session.to_host or session.from_host +function check_cert_status(session, host) local conn = session.conn:socket() local cert if conn.getpeercertificate then -- cgit v1.2.3 From c2ce30433a9dd12436f532be4dd3b0548c2bbae3 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Wed, 12 May 2021 17:22:02 +0200 Subject: mod_dialback: Remove d-w-d feature Backs out 1d0862814bfc and 2fdd71b08126 Largely unused, undocumented and did not have enough tests to provide confidence in its correct operation. --- plugins/mod_dialback.lua | 22 ---------------------- plugins/mod_s2s/mod_s2s.lua | 2 +- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/plugins/mod_dialback.lua b/plugins/mod_dialback.lua index c81484a9..4e9f9458 100644 --- a/plugins/mod_dialback.lua +++ b/plugins/mod_dialback.lua @@ -22,19 +22,6 @@ local xmlns_stream = "http://etherx.jabber.org/streams"; local dialback_requests = setmetatable({}, { __mode = 'v' }); local dialback_secret = sha256_hash(module:get_option_string("dialback_secret", uuid_gen()), true); -local dwd = module:get_option_boolean("dialback_without_dialback", false); - ---- Helper to check that a session peer's certificate is valid -function check_cert_status(session, host) - local conn = session.conn:socket() - local cert - if conn.getpeercertificate then - cert = conn:getpeercertificate() - end - - return module:fire_event("s2s-check-certificate", { host = host, session = session, cert = cert }); -end - function module.save() return { dialback_secret = dialback_secret }; @@ -104,15 +91,6 @@ module:hook("stanza/jabber:server:dialback:result", function(event) origin:close("improper-addressing"); end - if dwd and origin.secure then - if check_cert_status(origin, from) == false then - return - elseif origin.cert_chain_status == "valid" and origin.cert_identity_status == "valid" then - origin.sends2s(st.stanza("db:result", { to = from, from = to, id = attr.id, type = "valid" })); - module:fire_event("s2s-authenticated", { session = origin, host = from }); - return true; - end - end origin.hosts[from] = { dialback_key = stanza[1] }; diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index b2376b97..c3de28db 100644 --- a/plugins/mod_s2s/mod_s2s.lua +++ b/plugins/mod_s2s/mod_s2s.lua @@ -276,7 +276,7 @@ function make_authenticated(event) end --- Helper to check that a session peer's certificate is valid -function check_cert_status(session) +local function check_cert_status(session) local host = session.direction == "outgoing" and session.to_host or session.from_host local conn = session.conn:socket() local cert -- cgit v1.2.3 -- cgit v1.2.3