From 4d9fdf2b0fd2213a17bf6bc223617561cea66902 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 23 Apr 2019 19:13:50 +0200 Subject: mod_tls: Log debug message for each kind of TLS context created Creating TLS contexts triggers a lot of messages from certmanager that don't really describe their purpose. This is meant to provide hints about that. --- plugins/mod_tls.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_tls.lua b/plugins/mod_tls.lua index 029ddd1d..eb208e28 100644 --- a/plugins/mod_tls.lua +++ b/plugins/mod_tls.lua @@ -52,12 +52,15 @@ function module.load() local parent_s2s = rawgetopt(parent, "s2s_ssl") or NULL; local host_s2s = rawgetopt(modhost, "s2s_ssl") or parent_s2s; + module:log("debug", "Creating context for c2s"); ssl_ctx_c2s, err, ssl_cfg_c2s = create_context(host.host, "server", host_c2s, host_ssl, global_c2s); -- for incoming client connections if not ssl_ctx_c2s then module:log("error", "Error creating context for c2s: %s", err); end + module:log("debug", "Creating context for s2sout"); ssl_ctx_s2sout, err, ssl_cfg_s2sout = create_context(host.host, "client", host_s2s, host_ssl, global_s2s); -- for outgoing server connections if not ssl_ctx_s2sout then module:log("error", "Error creating contexts for s2sout: %s", err); end + module:log("debug", "Creating context for s2sin"); ssl_ctx_s2sin, err, ssl_cfg_s2sin = create_context(host.host, "server", host_s2s, host_ssl, global_s2s); -- for incoming server connections if not ssl_ctx_s2sin then module:log("error", "Error creating contexts for s2sin: %s", err); end end -- cgit v1.2.3 From 1045642fa450a0dd46009a39c6a1fa4b949e9888 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 13 May 2019 14:47:41 +0200 Subject: mod_storage_sql: Move code out of if-else chain --- plugins/mod_storage_sql.lua | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 56cef569..dbf5e2da 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -390,6 +390,14 @@ function archive_store:delete(username, query) else args[#args+1] = query.truncate; local unlimited = "ALL"; + sql_query = [[ + DELETE FROM "prosodyarchive" + WHERE "sort_id" IN ( + SELECT "sort_id" FROM "prosodyarchive" + WHERE %s + ORDER BY "sort_id" %s + LIMIT %s OFFSET ? + );]]; if engine.params.driver == "SQLite3" then sql_query = [[ DELETE FROM "prosodyarchive" @@ -407,15 +415,6 @@ function archive_store:delete(username, query) LIMIT %s OFFSET ? ) AS limiter on result.sort_id = limiter.sort_id;]]; unlimited = "18446744073709551615"; - else - sql_query = [[ - DELETE FROM "prosodyarchive" - WHERE "sort_id" IN ( - SELECT "sort_id" FROM "prosodyarchive" - WHERE %s - ORDER BY "sort_id" %s - LIMIT %s OFFSET ? - );]]; end sql_query = string.format(sql_query, t_concat(where, " AND "), query.reverse and "ASC" or "DESC", unlimited); -- cgit v1.2.3 From 9838f3732d53e1e3d34cd57a25a030f61005cb53 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 13 May 2019 14:39:38 +0200 Subject: mod_storage_sql: Handle SQLite DELETE with LIMIT being optional (fixes #1359) --- plugins/mod_storage_sql.lua | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index dbf5e2da..a449091e 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -399,12 +399,14 @@ function archive_store:delete(username, query) LIMIT %s OFFSET ? );]]; if engine.params.driver == "SQLite3" then - sql_query = [[ - DELETE FROM "prosodyarchive" - WHERE %s - ORDER BY "sort_id" %s - LIMIT %s OFFSET ?; - ]]; + if engine._have_delete_limit then + sql_query = [[ + DELETE FROM "prosodyarchive" + WHERE %s + ORDER BY "sort_id" %s + LIMIT %s OFFSET ?; + ]]; + end unlimited = "-1"; elseif engine.params.driver == "MySQL" then sql_query = [[ @@ -620,6 +622,13 @@ function module.load() module:log("error", "Old database format detected. Please run: prosodyctl mod_%s upgrade", module.name); return false, "database upgrade needed"; end + if engine.params.driver == "SQLite3" then + for row in engine:select("PRAGMA compile_options") do + if row[1] == "ENABLE_UPDATE_DELETE_LIMIT" then + engine._have_delete_limit = true; + end + end + end end end); engines[sql.db2uri(params)] = engine; -- cgit v1.2.3 From c85ae3be7853cde7e08c2afad290770994f4c851 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 18 May 2019 17:45:20 +0200 Subject: mod_c2s: Associate connection with session last (fixes #1313) This way, any fatal error in the callback will not leave a half-established session. --- plugins/mod_c2s.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_c2s.lua b/plugins/mod_c2s.lua index 8e31a968..15d3a9be 100644 --- a/plugins/mod_c2s.lua +++ b/plugins/mod_c2s.lua @@ -239,7 +239,6 @@ end --- Port listener function listener.onconnect(conn) local session = sm_new_session(conn); - sessions[conn] = session; session.log("info", "Client connected"); @@ -300,6 +299,8 @@ function listener.onconnect(conn) end session.dispatch_stanza = stream_callbacks.handlestanza; + + sessions[conn] = session; end function listener.onincoming(conn, data) -- cgit v1.2.3 From 05f81e425ccb058a8a944bfbe3eb604cb5d5e96b Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 27 May 2019 12:05:35 +0200 Subject: mod_announce: Check for admin on current virtualhost instead of global (fixes #1365) (thanks yc) --- plugins/mod_announce.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_announce.lua b/plugins/mod_announce.lua index 14bb9f3d..970a273a 100644 --- a/plugins/mod_announce.lua +++ b/plugins/mod_announce.lua @@ -44,7 +44,7 @@ function handle_announcement(event) return; -- Not an announcement end - if not is_admin(stanza.attr.from) then + if not is_admin(stanza.attr.from, host) then -- Not an admin? Not allowed! module:log("warn", "Non-admin '%s' tried to send server announcement", stanza.attr.from); return; -- cgit v1.2.3 From 837334916e773f4e69812057db281e0e2c549129 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 27 May 2019 19:00:32 +0200 Subject: mod_mam: Cache last date that archive owner has messages to reduce writes (fixes #1368) --- plugins/mod_mam/mod_mam.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index a8c2689d..8900a2be 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -348,8 +348,14 @@ if cleanup_after ~= "never" then -- messages, we collect the union of sets of users from dates that fall -- outside the cleanup range. + local last_date = require "util.cache".new(module:get_option_number("archive_cleanup_date_cache_size", 1000)); function schedule_cleanup(username, date) - cleanup_map:set(date or datestamp(), username, true); + date = date or datestamp(); + if last_date:get(username) == date then return end + local ok = cleanup_map:set(date, username, true); + if ok then + last_date:set(username, date); + end end cleanup_runner = require "util.async".runner(function () -- cgit v1.2.3 From e96902f6b477fe31d599ae9abf50e9baf0489d50 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 27 May 2019 19:00:34 +0200 Subject: mod_muc_mam: Cache last date that archive owner has messages to reduce writes (fixes #1368) --- plugins/mod_muc_mam.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index 1fbc8b2a..a2e3f81b 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -422,8 +422,14 @@ if cleanup_after ~= "never" then -- messages, we collect the union of sets of rooms from dates that fall -- outside the cleanup range. + local last_date = require "util.cache".new(module:get_option_number("muc_log_cleanup_date_cache_size", 1000)); function schedule_cleanup(roomname, date) - cleanup_map:set(date or datestamp(), roomname, true); + date = date or datestamp(); + if last_date:get(roomname) == date then return end + local ok = cleanup_map:set(date, roomname, true); + if ok then + last_date:set(roomname, date); + end end cleanup_runner = require "util.async".runner(function () -- cgit v1.2.3 From 3b49129ad4f9266b525df1ff73baf7c6a58a1b58 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 30 May 2019 15:16:56 +0200 Subject: mod_pep: Handle presence based subscription outside of util.pubsub (fixes #1372) Subscriptions were updated for each incoming presence stanza from contacts. Each subscription change triggered a configuration save, which would filter out the presence based subscriptions and usually end up replacing the existing data with identical data. With many subscribed nodes this adds up to a fair bit of IO bound work that is avoided by keeping them separate. --- plugins/mod_pep.lua | 54 +++++++++++++++++------------------------------------ 1 file changed, 17 insertions(+), 37 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_pep.lua b/plugins/mod_pep.lua index 7a4aac2b..f60f84c9 100644 --- a/plugins/mod_pep.lua +++ b/plugins/mod_pep.lua @@ -90,21 +90,6 @@ local function nodestore(username) return data, err; end function store:set(node, data) - if data then - -- Save the data without subscriptions - local subscribers = {}; - for jid, sub in pairs(data.subscribers) do - if type(sub) ~= "table" or not sub.presence then - subscribers[jid] = sub; - end - end - data = { - name = data.name; - config = data.config; - affiliations = data.affiliations; - subscribers = subscribers; - }; - end return node_config:set(username, node, data); end function store:users() @@ -151,7 +136,23 @@ local function get_broadcaster(username) end message:add_child(item); end + + local broadcast_to = {}; for jid in pairs(jids) do + broadcast_to[jid] = true; + end + + local service_recipients = recipients[username]; + if service_recipients then + local service = services[username]; + for recipient, nodes in pairs(service_recipients) do + if nodes:contains(node) and service:may(node, recipient, "subscribe") then + broadcast_to[recipient] = true; + end + end + end + + for jid in pairs(broadcast_to) do module:log("debug", "Sending notification to %s from %s: %s", jid, user_bare, tostring(item)); message.attr.to = jid; module:send(message); @@ -160,20 +161,6 @@ local function get_broadcaster(username) return simple_broadcast; end -local function on_node_creation(event) - local service = event.service; - local node = event.node; - local username = service.config.pep_username; - - local service_recipients = recipients[username]; - if not service_recipients then return; end - - for recipient, nodes in pairs(service_recipients) do - if nodes:contains(node) then - service:add_subscription(node, recipient, recipient, { presence = true }); - end - end -end function get_pep_service(username) module:log("debug", "get_pep_service(%q)", username); @@ -233,10 +220,6 @@ function get_pep_service(username) return service; end -module:hook("item-added/pep-service", function (event) - local service = event.item.service; - module:hook_object_event(service.events, "node-created", on_node_creation); -end); function handle_pubsub_iq(event) local origin, stanza = event.origin, event.stanza; @@ -303,12 +286,9 @@ local function update_subscriptions(recipient, service_name, nodes) end local service = get_pep_service(service_name); - for node in current - nodes do - service:remove_subscription(node, recipient, recipient); - end for node in nodes - current do - if service:add_subscription(node, recipient, recipient, { presence = true }) then + if service:may(node, recipient, "subscribe") then resend_last_item(recipient, node, service); end end -- cgit v1.2.3 From a4764762b3dad679f40dadd6eb2eb31ea1d5cace Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 10 Jun 2019 12:58:00 +0200 Subject: mod_pep: Revert 045209b41b3a, caused a regression Adding in all presence based subscriptions in the broadcaster caused resend_last_item() to unintentionally send out more notifications than it should have. --- plugins/mod_pep.lua | 54 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 17 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_pep.lua b/plugins/mod_pep.lua index f60f84c9..7a4aac2b 100644 --- a/plugins/mod_pep.lua +++ b/plugins/mod_pep.lua @@ -90,6 +90,21 @@ local function nodestore(username) return data, err; end function store:set(node, data) + if data then + -- Save the data without subscriptions + local subscribers = {}; + for jid, sub in pairs(data.subscribers) do + if type(sub) ~= "table" or not sub.presence then + subscribers[jid] = sub; + end + end + data = { + name = data.name; + config = data.config; + affiliations = data.affiliations; + subscribers = subscribers; + }; + end return node_config:set(username, node, data); end function store:users() @@ -136,23 +151,7 @@ local function get_broadcaster(username) end message:add_child(item); end - - local broadcast_to = {}; for jid in pairs(jids) do - broadcast_to[jid] = true; - end - - local service_recipients = recipients[username]; - if service_recipients then - local service = services[username]; - for recipient, nodes in pairs(service_recipients) do - if nodes:contains(node) and service:may(node, recipient, "subscribe") then - broadcast_to[recipient] = true; - end - end - end - - for jid in pairs(broadcast_to) do module:log("debug", "Sending notification to %s from %s: %s", jid, user_bare, tostring(item)); message.attr.to = jid; module:send(message); @@ -161,6 +160,20 @@ local function get_broadcaster(username) return simple_broadcast; end +local function on_node_creation(event) + local service = event.service; + local node = event.node; + local username = service.config.pep_username; + + local service_recipients = recipients[username]; + if not service_recipients then return; end + + for recipient, nodes in pairs(service_recipients) do + if nodes:contains(node) then + service:add_subscription(node, recipient, recipient, { presence = true }); + end + end +end function get_pep_service(username) module:log("debug", "get_pep_service(%q)", username); @@ -220,6 +233,10 @@ function get_pep_service(username) return service; end +module:hook("item-added/pep-service", function (event) + local service = event.item.service; + module:hook_object_event(service.events, "node-created", on_node_creation); +end); function handle_pubsub_iq(event) local origin, stanza = event.origin, event.stanza; @@ -286,9 +303,12 @@ local function update_subscriptions(recipient, service_name, nodes) end local service = get_pep_service(service_name); + for node in current - nodes do + service:remove_subscription(node, recipient, recipient); + end for node in nodes - current do - if service:may(node, recipient, "subscribe") then + if service:add_subscription(node, recipient, recipient, { presence = true }) then resend_last_item(recipient, node, service); end end -- cgit v1.2.3 From c6ad506b85a5740f55c9b12896f92ee15e74abce Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 20 Jun 2019 21:20:00 +0200 Subject: mod_blocklist: Trigger resend of presence when unblocking a contact (fixes #1380) --- plugins/mod_blocklist.lua | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_blocklist.lua b/plugins/mod_blocklist.lua index 8aca7332..ee48ffad 100644 --- a/plugins/mod_blocklist.lua +++ b/plugins/mod_blocklist.lua @@ -128,6 +128,7 @@ local function edit_blocklist(event) -- > only if the contact is allowed to receive presence notifications [...] -- So contacts we need to do that for are added to the set below. local send_unavailable = is_blocking and {}; + local send_available = not is_blocking and {}; -- Because blocking someone currently also blocks the ability to reject -- subscription requests, we'll preemptively reject such @@ -147,6 +148,8 @@ local function edit_blocklist(event) elseif is_contact_pending_in(username, module.host, jid) then remove_pending[jid] = true; end + elseif is_contact_subscribed(username, module.host, jid) then + send_available[jid] = true; end end @@ -203,6 +206,11 @@ local function edit_blocklist(event) save_roster(username, module.host, roster); -- Not much we can do about save failing here end + else + local user_bare = username .. "@" .. module.host; + for jid in pairs(send_available) do + module:send(st.presence({ type = "probe", to = user_bare, from = jid })); + end end local blocklist_push = st.iq({ type = "set", id = "blocklist-push" }) -- cgit v1.2.3 From 022198143dcc0d586030d183ac8ca3368ff6172b Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 20 Jul 2019 04:19:58 +0200 Subject: mod_websocket: Clone stanza before mutating (fixes #1398) Checking for `stanza.attr.xmlns == nil` to determine if the stanza object is an actual stanza (``, `` or `` in the `jabber:client` or `jabbber:server` namespace) or some other stream element. Since this mutation is not reverted, it may leak to other places and cause them to mistreat stanzas as stream elements. Especially in cases like MUC where a single stanza is broadcast to many recipients. --- plugins/mod_websocket.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index b4aba338..686a8981 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -285,6 +285,7 @@ function handle_request(event) end); add_filter(session, "stanzas/out", function(stanza) + stanza = st.clone(stanza); local attr = stanza.attr; attr.xmlns = attr.xmlns or xmlns_client; if stanza.name:find("^stream:") then -- cgit v1.2.3 From 12431d51d7746c4c1a70fccb2a6ec081b13d1b93 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 30 Jul 2019 08:01:22 +0200 Subject: MUC: Advertise XEP-0410 support Unsure if the feature was in the XEP at the time of 7c1cdf5f9f83 --- plugins/muc/muc.lib.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index 9648ea78..a942182d 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -358,6 +358,7 @@ end module:hook("muc-disco#info", function(event) event.reply:tag("feature", {var = "http://jabber.org/protocol/muc"}):up(); event.reply:tag("feature", {var = "http://jabber.org/protocol/muc#stable_id"}):up(); + event.reply:tag("feature", {var = "http://jabber.org/protocol/muc#self-ping-optimization"}):up(); end); module:hook("muc-disco#info", function(event) table.insert(event.form, { name = "muc#roominfo_occupants", label = "Number of occupants" }); -- cgit v1.2.3 From 8a309e53bd73871538ad27a873dd6740168ad4ce Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 31 Aug 2019 16:08:45 +0200 Subject: MUC: Fix delay@from to be room JID (fixes #1416) --- plugins/muc/history.lib.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/muc/history.lib.lua b/plugins/muc/history.lib.lua index 445aacb9..0d69c97d 100644 --- a/plugins/muc/history.lib.lua +++ b/plugins/muc/history.lib.lua @@ -178,10 +178,10 @@ module:hook("muc-add-history", function(event) local ts = gettime(); local stamp = datetime.datetime(ts); stanza:tag("delay", { -- XEP-0203 - xmlns = "urn:xmpp:delay", from = module.host, stamp = stamp + xmlns = "urn:xmpp:delay", from = room.jid, stamp = stamp }):up(); stanza:tag("x", { -- XEP-0091 (deprecated) - xmlns = "jabber:x:delay", from = module.host, stamp = datetime.legacy() + xmlns = "jabber:x:delay", from = room.jid, stamp = datetime.legacy() }):up(); local entry = { stanza = stanza, timestamp = ts }; table.insert(history, entry); -- cgit v1.2.3 From 70427ffd2b92953d4868ed9fd97ea1bf0480c492 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 21 Sep 2019 15:20:50 +0200 Subject: mod_vcard_legacy: Advertise lack of avatar correctly (fixes #1431) (thanks lovetox) --- plugins/mod_vcard_legacy.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_vcard_legacy.lua b/plugins/mod_vcard_legacy.lua index ab2c4490..6229b931 100644 --- a/plugins/mod_vcard_legacy.lua +++ b/plugins/mod_vcard_legacy.lua @@ -301,10 +301,10 @@ local function inject_xep153(event) local pep_service = mod_pep.get_pep_service(username); stanza:remove_children("x", "vcard-temp:x:update"); - local x_update = st.stanza("x", { xmlns = "vcard-temp:x:update" }); + local x_update = st.stanza("x", { xmlns = "vcard-temp:x:update" }):tag("photo"); local ok, avatar_hash = pep_service:get_last_item("urn:xmpp:avatar:metadata", true); if ok and avatar_hash then - x_update:text_tag("photo", avatar_hash); + x_update:text(avatar_hash); end stanza:add_direct_child(x_update); end -- cgit v1.2.3 From ae7a763b275c6306e6c6dcb19e624c1255158d8e Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 21 Sep 2019 16:29:16 +0200 Subject: mod_vcard_legacy: Don't owerwrite empty photo elements (fixes #1432) --- plugins/mod_vcard_legacy.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_vcard_legacy.lua b/plugins/mod_vcard_legacy.lua index 6229b931..5e75947a 100644 --- a/plugins/mod_vcard_legacy.lua +++ b/plugins/mod_vcard_legacy.lua @@ -300,13 +300,19 @@ local function inject_xep153(event) if stanza.attr.type then return end local pep_service = mod_pep.get_pep_service(username); - stanza:remove_children("x", "vcard-temp:x:update"); - local x_update = st.stanza("x", { xmlns = "vcard-temp:x:update" }):tag("photo"); + local x_update = stanza:get_child("x", "vcard-temp:x:update"); + if not x_update then + x_update = st.stanza("x", { xmlns = "vcard-temp:x:update" }):tag("photo"); + stanza:add_direct_child(x_update); + elseif x_update:get_child("photo") then + return; -- XEP implies that these should be left alone + else + x_update:tag("photo"); + end local ok, avatar_hash = pep_service:get_last_item("urn:xmpp:avatar:metadata", true); if ok and avatar_hash then x_update:text(avatar_hash); end - stanza:add_direct_child(x_update); end module:hook("pre-presence/full", inject_xep153, 1); -- cgit v1.2.3 From dfa96d659ccfe41766f37767faef45fc5a8ae60e Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 29 Sep 2019 20:48:00 +0200 Subject: MUC: Strip tags with MUC-related namespaces from private messages (fixes #1427) Prevents duplication since it adds another <{muc#user}x> here --- plugins/muc/muc.lib.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index a942182d..cf9b46f7 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -779,6 +779,7 @@ function room_mt:handle_message_to_occupant(origin, stanza) return true; end log("debug", "%s sent private message stanza to %s (%s)", from, to, o_data.jid); + stanza = muc_util.filter_muc_x(st.clone(stanza)); stanza:tag("x", { xmlns = "http://jabber.org/protocol/muc#user" }):up(); stanza.attr.from = current_nick; self:route_to_occupant(o_data, stanza) -- cgit v1.2.3 From 811c707639eba97d17d90e45606454fad75e5c32 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 3 Oct 2019 16:38:15 +0100 Subject: mod_mam: Add flag to session when it performs a MAM query --- plugins/mod_mam/mod_mam.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index 8900a2be..b500770f 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -90,6 +90,8 @@ module:hook("iq-set/self/"..xmlns_mam..":query", function(event) local query = stanza.tags[1]; local qid = query.attr.queryid; + origin.mam_requested = true; + get_prefs(origin.username, true); -- Search query parameters -- cgit v1.2.3 From 86b23ae5f736829e3c86fa47c1c1047c49b449e6 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 20 Oct 2019 01:20:11 +0200 Subject: MUC: Don't advertise registration feature on host JID (fixes #1451) There is currently no mention in XEP-0045 of how or where to advertise support for registration. Advertising on the host JID may be confusable with service-wide registration, as implemented in ejabberd. A common and sensible pattern in XMPP is that a feature is advertised on the JID where the service is available. --- plugins/muc/register.lib.lua | 2 -- 1 file changed, 2 deletions(-) (limited to 'plugins') diff --git a/plugins/muc/register.lib.lua b/plugins/muc/register.lib.lua index 21cb3f2f..95ed1a84 100644 --- a/plugins/muc/register.lib.lua +++ b/plugins/muc/register.lib.lua @@ -48,8 +48,6 @@ module:hook("muc-set-affiliation", function (event) event.room._reserved_nicks = nil; end); -module:add_feature("jabber:iq:register"); - module:hook("muc-disco#info", function (event) event.reply:tag("feature", { var = "jabber:iq:register" }):up(); end); -- cgit v1.2.3 From 17e77058d6d3a1e936f8d108a70dde4b3dd296a2 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 23 Nov 2019 01:05:28 +0100 Subject: MUC: Keep role across nickname change (fixes #1466) --- plugins/muc/muc.lib.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins') diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index cf9b46f7..639ecc38 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -524,6 +524,9 @@ function room_mt:handle_normal_presence(origin, stanza) log("debug", "no occupant found for %s; creating new occupant object for %s", dest_jid, real_jid); is_first_dest_session = true; dest_occupant = self:new_occupant(bare_jid, dest_jid); + if orig_occupant then + dest_occupant.role = orig_occupant.role; + end else is_first_dest_session = false; end -- cgit v1.2.3 From dfdc2502ee41533db43d1aa4d0bc38bc44973ac1 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 10 Jun 2019 13:57:09 +0200 Subject: mod_pep: Handle presence subscriptions in filter (fixes #1372) Take two on 045209b41b3a --- plugins/mod_pep.lua | 51 +++++++++++++++++---------------------------------- 1 file changed, 17 insertions(+), 34 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_pep.lua b/plugins/mod_pep.lua index 7a4aac2b..12be41a2 100644 --- a/plugins/mod_pep.lua +++ b/plugins/mod_pep.lua @@ -90,21 +90,6 @@ local function nodestore(username) return data, err; end function store:set(node, data) - if data then - -- Save the data without subscriptions - local subscribers = {}; - for jid, sub in pairs(data.subscribers) do - if type(sub) ~= "table" or not sub.presence then - subscribers[jid] = sub; - end - end - data = { - name = data.name; - config = data.config; - affiliations = data.affiliations; - subscribers = subscribers; - }; - end return node_config:set(username, node, data); end function store:users() @@ -160,18 +145,23 @@ local function get_broadcaster(username) return simple_broadcast; end -local function on_node_creation(event) - local service = event.service; - local node = event.node; - local username = service.config.pep_username; - - local service_recipients = recipients[username]; - if not service_recipients then return; end +local function get_subscriber_filter(username) + return function (jids, node) + local broadcast_to = {}; + for jid, opts in pairs(jids) do + broadcast_to[jid] = opts; + end - for recipient, nodes in pairs(service_recipients) do - if nodes:contains(node) then - service:add_subscription(node, recipient, recipient, { presence = true }); + local service_recipients = recipients[username]; + if service_recipients then + local service = services[username]; + for recipient, nodes in pairs(service_recipients) do + if nodes:contains(node) and service:may(node, recipient, "subscribe") then + broadcast_to[recipient] = true; + end + end end + return broadcast_to; end end @@ -196,6 +186,7 @@ function get_pep_service(username) nodestore = nodestore(username); itemstore = simple_itemstore(username); broadcaster = get_broadcaster(username); + subscriber_filter = get_subscriber_filter(username); itemcheck = is_item_stanza; get_affiliation = function (jid) if jid_bare(jid) == user_bare then @@ -233,11 +224,6 @@ function get_pep_service(username) return service; end -module:hook("item-added/pep-service", function (event) - local service = event.item.service; - module:hook_object_event(service.events, "node-created", on_node_creation); -end); - function handle_pubsub_iq(event) local origin, stanza = event.origin, event.stanza; local service_name = origin.username; @@ -303,12 +289,9 @@ local function update_subscriptions(recipient, service_name, nodes) end local service = get_pep_service(service_name); - for node in current - nodes do - service:remove_subscription(node, recipient, recipient); - end for node in nodes - current do - if service:add_subscription(node, recipient, recipient, { presence = true }) then + if service:may(node, recipient, "subscribe") then resend_last_item(recipient, node, service); end end -- cgit v1.2.3 From 34b067a5ad009f0efb5bd2c6bb036f4689fe801f Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 23 Dec 2019 22:42:39 +0100 Subject: mod_auth_internal_hashed: Pass on errors from password hash function (fixes #1477) --- plugins/mod_auth_internal_hashed.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_auth_internal_hashed.lua b/plugins/mod_auth_internal_hashed.lua index 35764afb..083f648b 100644 --- a/plugins/mod_auth_internal_hashed.lua +++ b/plugins/mod_auth_internal_hashed.lua @@ -68,6 +68,9 @@ function provider.set_password(username, password) account.salt = generate_uuid(); account.iteration_count = max(account.iteration_count or 0, default_iteration_count); local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, account.salt, account.iteration_count); + if not valid then + return valid, stored_key; + end local stored_key_hex = to_hex(stored_key); local server_key_hex = to_hex(server_key); @@ -99,6 +102,9 @@ function provider.create_user(username, password) end local salt = generate_uuid(); local valid, stored_key, server_key = getAuthenticationDatabaseSHA1(password, salt, default_iteration_count); + if not valid then + return valid, stored_key; + end local stored_key_hex = to_hex(stored_key); local server_key_hex = to_hex(server_key); return accounts:set(username, { -- cgit v1.2.3 From 83455007ac12820c87bdb637b45ab1b5c45aa1f0 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 23 Dec 2019 23:18:39 +0100 Subject: mod_mam: Log error when unable to store stanza (fix #1478) Unclear what else to do here. Caught by luacheck --- plugins/mod_mam/mod_mam.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index b500770f..2443270f 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -305,6 +305,8 @@ local function message_handler(event, c2s) event.stanza = clone_for_other_handlers; schedule_cleanup(store_user); module:fire_event("archive-message-added", { origin = origin, stanza = clone_for_storage, for_user = store_user, id = id }); + else + log("error", "Could not archive stanza: %s", err); end else log("debug", "Not archiving stanza: %s (prefs)", stanza:top_tag()); -- cgit v1.2.3 From 6e8878ea74d4b1fca57da6806d530030b345426a Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 24 Dec 2019 00:27:41 +0100 Subject: mod_mam: Log error when unable to delete old messages (fix #1479) [luacheck] --- plugins/mod_mam/mod_mam.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index 2443270f..df5d925a 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -387,6 +387,8 @@ if cleanup_after ~= "never" then if ok then num_users = num_users + 1; sum = sum + (tonumber(ok) or 0); + else + module:log("error", "Could not delete messages for user '%s': %s", user, err); end end module:log("info", "Deleted %d expired messages for %d users", sum, num_users); -- cgit v1.2.3 From 9401b471251fa39b1f127a9a25881a86e9fad776 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 24 Dec 2019 00:27:44 +0100 Subject: mod_mam: Schedule cleanup again if unable to delete messages --- plugins/mod_mam/mod_mam.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index df5d925a..fd319486 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -388,6 +388,7 @@ if cleanup_after ~= "never" then num_users = num_users + 1; sum = sum + (tonumber(ok) or 0); else + cleanup_map:set(cut_off, user, true); module:log("error", "Could not delete messages for user '%s': %s", user, err); end end -- cgit v1.2.3 From 791fa6db10bfed7fb1c3aa5cf0cafa8298ea2e3c Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 23 Dec 2019 23:32:49 +0100 Subject: mod_muc_mam: Log error when unable to store stanza (fix #1480) [luacheck] --- plugins/mod_muc_mam.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index a2e3f81b..37e41157 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -357,6 +357,8 @@ local function save_to_history(self, stanza) if id then schedule_cleanup(room_node); stanza:add_direct_child(st.stanza("stanza-id", { xmlns = xmlns_st_id, by = self.jid, id = id })); + else + module:log("error", "Could not archive stanza: %s", err); end end -- cgit v1.2.3 From 26e530afc0ac4935ef0117a2bd5257693f9fdc93 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 24 Dec 2019 00:26:37 +0100 Subject: mod_muc_mam: Log error when unable to delete old messages (fix #1481) [luacheck] --- plugins/mod_muc_mam.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index 37e41157..c6104757 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -459,6 +459,8 @@ if cleanup_after ~= "never" then if ok then num_rooms = num_rooms + 1; sum = sum + (tonumber(ok) or 0); + else + module:log("error", "Could not delete messages for room '%s': %s", room, err); end end module:log("info", "Deleted %d expired messages for %d rooms", sum, num_rooms); -- cgit v1.2.3 From b22125f0645b3281d99843dcdb7b44e92b9167cd Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 24 Dec 2019 00:26:40 +0100 Subject: mod_muc_mam: Schedule cleanup again on failure --- plugins/mod_muc_mam.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index c6104757..a9287224 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -460,6 +460,7 @@ if cleanup_after ~= "never" then num_rooms = num_rooms + 1; sum = sum + (tonumber(ok) or 0); else + cleanup_map:set(cut_off, room, true); module:log("error", "Could not delete messages for room '%s': %s", room, err); end end -- cgit v1.2.3 From d04e48f29f39957392861c2132c4727e6cea9e45 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 24 Dec 2019 01:00:35 +0100 Subject: mod_muc_mam: Fix rebase mistake [luacheck] The 'err' was there in trunk --- plugins/mod_muc_mam.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index a9287224..2ce5e1b5 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -352,7 +352,7 @@ local function save_to_history(self, stanza) end -- And stash it - local id = archive:append(room_node, nil, stored_stanza, time_now(), with); + local id, err = archive:append(room_node, nil, stored_stanza, time_now(), with); if id then schedule_cleanup(room_node); -- cgit v1.2.3 From c2267c12ea1c41d430eb5b29645399b7f883db1c Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 24 Dec 2019 01:01:05 +0100 Subject: mod_mam: Fix rebase mistake [luacheck] The 'err' was there in trunk --- plugins/mod_mam/mod_mam.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index fd319486..295d90e1 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -297,7 +297,7 @@ local function message_handler(event, c2s) log("debug", "Archiving stanza: %s", stanza:top_tag()); -- And stash it - local ok = archive:append(store_user, nil, clone_for_storage, time_now(), with); + local ok, err = archive:append(store_user, nil, clone_for_storage, time_now(), with); if ok then local clone_for_other_handlers = st.clone(stanza); local id = ok; -- cgit v1.2.3 From 954b42849d39da059603d00d1ee8851d25894636 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 2 Jan 2020 10:49:37 +0100 Subject: mod_websocket: Clear mask bit when reflecting ping frames (fixes #1484) --- plugins/mod_websocket.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index 686a8981..6625c676 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -236,6 +236,7 @@ function handle_request(event) return; elseif opcode == 0x9 then -- Ping frame frame.opcode = 0xA; + frame.MASK = false; -- Clients send masked frames, servers don't, see #1484 conn:write(build_frame(frame)); return ""; elseif opcode == 0xA then -- Pong frame, MAY be sent unsolicited, eg as keepalive -- cgit v1.2.3 From 37ba5f795f519c55a28ae6b2a7a8cb239d097545 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 19 Jan 2020 15:28:09 +0000 Subject: mod_posix: Support for command-line flags to override 'daemonize' config option -D / --daemonize -F / --no-daemonize --- plugins/mod_posix.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_posix.lua b/plugins/mod_posix.lua index 23df4d23..fe826c22 100644 --- a/plugins/mod_posix.lua +++ b/plugins/mod_posix.lua @@ -126,7 +126,12 @@ function syslog_sink_maker(config) -- luacheck: ignore 212/config end require "core.loggingmanager".register_sink_type("syslog", syslog_sink_maker); -local daemonize = module:get_option("daemonize", prosody.installed); +local daemonize = prosody.opts.daemonize; + +if daemonize == nil then + -- Fall back to config file if not specified on command-line + daemonize = module:get_option("daemonize", prosody.installed); +end local function remove_log_sinks() local lm = require "core.loggingmanager"; -- cgit v1.2.3 From 70e9ff3887f78b7ce8ea5487c5c7b9bdc128a7d9 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 24 Jan 2020 16:21:30 +0000 Subject: mod_websocket: Fire event on session creation (thanks Aaron van Meerten) --- plugins/mod_websocket.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index 6625c676..177259e6 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -305,6 +305,8 @@ function handle_request(event) response.headers.sec_webSocket_accept = base64(sha1(request.headers.sec_websocket_key .. "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")); response.headers.sec_webSocket_protocol = "xmpp"; + module:fire_event("websocket-session", { session = session, request = request }); + session.log("debug", "Sending WebSocket handshake"); return ""; -- cgit v1.2.3 From c17d65758ed1b357c1b3cf2a8e4af773f301c2cd Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 24 Jan 2020 23:27:49 +0100 Subject: mod_admin_telnet: Create a DNS resolver per console session (fixes #1492) This is now the common pattern, eg see mod_s2s. --- plugins/mod_admin_telnet.lua | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 1cbe27a4..59eca28b 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -1074,36 +1074,49 @@ end def_env.dns = {}; local adns = require"net.adns"; -local dns = require"net.dns"; + +local function get_resolver(session) + local resolver = session.dns_resolver; + if not resolver then + resolver = adns.resolver(); + session.dns_resolver = resolver; + end + return resolver; +end function def_env.dns:lookup(name, typ, class) + local resolver = get_resolver(self.session); local ret = "Query sent"; local print = self.session.print; local function handler(...) ret = "Got response"; print(...); end - adns.lookup(handler, name, typ, class); + resolver:lookup(handler, name, typ, class); return true, ret; end function def_env.dns:addnameserver(...) - dns._resolver:addnameserver(...) + local resolver = get_resolver(self.session); + resolver._resolver:addnameserver(...) return true end function def_env.dns:setnameserver(...) - dns._resolver:setnameserver(...) + local resolver = get_resolver(self.session); + resolver._resolver:setnameserver(...) return true end function def_env.dns:purge() - dns.purge() + local resolver = get_resolver(self.session); + resolver._resolver:purge() return true end function def_env.dns:cache() - return true, "Cache:\n"..tostring(dns.cache()) + local resolver = get_resolver(self.session); + return true, "Cache:\n"..tostring(resolver._resolver.cache) end def_env.http = {}; -- cgit v1.2.3 From 239bd598467f2e4b2768a71a2b2fe708f34181a3 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 13 Feb 2020 14:27:12 +0000 Subject: mod_muc: Allow control over the server-admins-are-room-owners feature (see #1174) --- plugins/muc/mod_muc.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/muc/mod_muc.lua b/plugins/muc/mod_muc.lua index 954bae92..b9c7c859 100644 --- a/plugins/muc/mod_muc.lua +++ b/plugins/muc/mod_muc.lua @@ -104,7 +104,8 @@ local function is_admin(jid) return um_is_admin(jid, module.host); end -do -- Monkey patch to make server admins room owners +if module:get_option_boolean("component_admins_as_room_owners", true) then + -- Monkey patch to make server admins room owners local _get_affiliation = room_mt.get_affiliation; function room_mt:get_affiliation(jid) if is_admin(jid) then return "owner"; end -- cgit v1.2.3 From a8812b45ad23d58ba7a9da7d3b341d46bb006df4 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 21 Feb 2020 23:00:44 +0100 Subject: mod_storage_sql: Fix check for deletion limits (fixes #1494) The check was only performed if sql_manage_tables was set to true (the default) It should always be performed --- plugins/mod_storage_sql.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index a449091e..a9298138 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -622,15 +622,15 @@ function module.load() module:log("error", "Old database format detected. Please run: prosodyctl mod_%s upgrade", module.name); return false, "database upgrade needed"; end - if engine.params.driver == "SQLite3" then - for row in engine:select("PRAGMA compile_options") do - if row[1] == "ENABLE_UPDATE_DELETE_LIMIT" then - engine._have_delete_limit = true; - end - end - end end end); + if engine.params.driver == "SQLite3" then + for row in engine:select("PRAGMA compile_options") do + if row[1] == "ENABLE_UPDATE_DELETE_LIMIT" then + engine._have_delete_limit = true; + end + end + end engines[sql.db2uri(params)] = engine; end -- cgit v1.2.3 From e69d6a21b3a1e0af470eb7a88239b20d463e123c Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 22 Feb 2020 16:23:43 +0100 Subject: mod_storage_sql: Move update limit check back one step, fixes traceback 0c00274528a4 moved it one step too far, so the check was performed before connecting to the database instead of after. --- plugins/mod_storage_sql.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index a9298138..73207073 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -623,14 +623,14 @@ function module.load() return false, "database upgrade needed"; end end - end); - if engine.params.driver == "SQLite3" then - for row in engine:select("PRAGMA compile_options") do - if row[1] == "ENABLE_UPDATE_DELETE_LIMIT" then - engine._have_delete_limit = true; + if engine.params.driver == "SQLite3" then + for row in engine:select("PRAGMA compile_options") do + if row[1] == "ENABLE_UPDATE_DELETE_LIMIT" then + engine._have_delete_limit = true; + end end end - end + end); engines[sql.db2uri(params)] = engine; end -- cgit v1.2.3 From ea1ca4fd42978b1606f64dd3d32818f3ee8166a6 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 27 Feb 2020 19:42:51 +0100 Subject: mod_muc_mam: Fix traceback saving message from non-occupant (fixes #1497) Caused by a plugin sending a message from the room itself. --- plugins/mod_muc_mam.lua | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index 2ce5e1b5..f7ea3136 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -335,11 +335,14 @@ local function save_to_history(self, stanza) if stanza.name == "message" and self:get_whois() == "anyone" then stored_stanza = st.clone(stanza); stored_stanza.attr.to = nil; - local actor = jid_bare(self._occupants[stanza.attr.from].jid); - local affiliation = self:get_affiliation(actor) or "none"; - local role = self:get_role(actor) or self:get_default_role(affiliation); - stored_stanza:add_direct_child(st.stanza("x", { xmlns = xmlns_muc_user }) - :tag("item", { affiliation = affiliation; role = role; jid = actor })); + local occupant = self._occupants[stanza.attr.from]; + if occupant then + local actor = jid_bare(occupant.jid); + local affiliation = self:get_affiliation(actor) or "none"; + local role = self:get_role(actor) or self:get_default_role(affiliation); + stored_stanza:add_direct_child(st.stanza("x", { xmlns = xmlns_muc_user }) + :tag("item", { affiliation = affiliation; role = role; jid = actor })); + end end -- Policy check -- cgit v1.2.3 From 3ab4eb0e103c29ab4e0f82ba6c28002052e5a0b8 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 27 Feb 2020 20:01:54 +0100 Subject: mod_pubsub, mod_pep: Ensure correct number of children of (fixes #1496) --- plugins/mod_pep.lua | 2 +- plugins/mod_pubsub/mod_pubsub.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_pep.lua b/plugins/mod_pep.lua index 12be41a2..f8047a92 100644 --- a/plugins/mod_pep.lua +++ b/plugins/mod_pep.lua @@ -51,7 +51,7 @@ function module.restore(data) end function is_item_stanza(item) - return st.is_stanza(item) and item.attr.xmlns == xmlns_pubsub and item.name == "item"; + return st.is_stanza(item) and item.attr.xmlns == xmlns_pubsub and item.name == "item" and #item.tags == 1; end function check_node_config(node, actor, new_config) -- luacheck: ignore 212/node 212/actor diff --git a/plugins/mod_pubsub/mod_pubsub.lua b/plugins/mod_pubsub/mod_pubsub.lua index 855c5fd2..4276bc5e 100644 --- a/plugins/mod_pubsub/mod_pubsub.lua +++ b/plugins/mod_pubsub/mod_pubsub.lua @@ -112,7 +112,7 @@ function check_node_config(node, actor, new_config) -- luacheck: ignore 212/acto end function is_item_stanza(item) - return st.is_stanza(item) and item.attr.xmlns == xmlns_pubsub and item.name == "item"; + return st.is_stanza(item) and item.attr.xmlns == xmlns_pubsub and item.name == "item" and #item.tags == 1; end module:hook("pubsub-summary/http://www.w3.org/2005/Atom", function (event) -- cgit v1.2.3 From 02b23bdc6699dfcd5f14de1933a171b6415a64a5 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Wed, 11 Mar 2020 21:15:01 +0100 Subject: mod_mam,mod_muc_mam: Allow other work to be performed during archive cleanup (fixes #1504) This lets Prosody handle socket related work between each step in the cleanup in order to prevent the server from being completely blocked during this. An async storage backend would not need this but those are currently rare. --- plugins/mod_mam/mod_mam.lua | 6 +++++- plugins/mod_muc_mam.lua | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua index 295d90e1..e7d89a95 100644 --- a/plugins/mod_mam/mod_mam.lua +++ b/plugins/mod_mam/mod_mam.lua @@ -362,7 +362,8 @@ if cleanup_after ~= "never" then end end - cleanup_runner = require "util.async".runner(function () + local async = require "util.async"; + cleanup_runner = async.runner(function () local users = {}; local cut_off = datestamp(os.time() - cleanup_after); for date in cleanup_storage:users() do @@ -391,6 +392,9 @@ if cleanup_after ~= "never" then cleanup_map:set(cut_off, user, true); module:log("error", "Could not delete messages for user '%s': %s", user, err); end + local wait, done = async.waiter(); + module:add_timer(0.01, done); + wait(); end module:log("info", "Deleted %d expired messages for %d users", sum, num_users); end); diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index f7ea3136..5a01324d 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -437,7 +437,8 @@ if cleanup_after ~= "never" then end end - cleanup_runner = require "util.async".runner(function () + local async = require "util.async"; + cleanup_runner = async.runner(function () local rooms = {}; local cut_off = datestamp(os.time() - cleanup_after); for date in cleanup_storage:users() do @@ -466,6 +467,9 @@ if cleanup_after ~= "never" then cleanup_map:set(cut_off, room, true); module:log("error", "Could not delete messages for room '%s': %s", room, err); end + local wait, done = async.waiter(); + module:add_timer(0.01, done); + wait(); end module:log("info", "Deleted %d expired messages for %d rooms", sum, num_rooms); end); -- cgit v1.2.3 From e50a3fac0be9cee64746f88dda46989ec87e8e29 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 12 Mar 2020 20:32:07 +0000 Subject: MUC: Persist affiliation_data in new MUC format! --- plugins/muc/muc.lib.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index 639ecc38..bc370da5 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -1449,6 +1449,7 @@ function room_mt:freeze(live) frozen = { _jid = self.jid; _data = self._data; + _affiliation_data = self._affiliation_data; }; for user, affiliation in pairs(self._affiliations) do frozen[user] = affiliation; -- cgit v1.2.3 From af11cae5114d8237c8f17be3a89482bc70cf42b8 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 22 Mar 2020 17:35:26 +0100 Subject: mod_admin_telnet: Handle unavailable cipher info (fixes #1510) The LuaSec :info() method gathers info using the OpenSSL function SSL_get_current_cipher(). Documentation for this function states that it may return NULL if no session has been established (yet). If so, the LuaSec functions wrapping this return nil, triggering a nil-indexing error in mod_admin_telnet. --- plugins/mod_admin_telnet.lua | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_admin_telnet.lua b/plugins/mod_admin_telnet.lua index 59eca28b..b0e349da 100644 --- a/plugins/mod_admin_telnet.lua +++ b/plugins/mod_admin_telnet.lua @@ -528,11 +528,14 @@ local function tls_info(session, line) common_info(session, line); if session.secure then local sock = session.conn and session.conn.socket and session.conn:socket(); - if sock and sock.info then - local info = sock:info(); - line[#line+1] = ("(%s with %s)"):format(info.protocol, info.cipher); - else - line[#line+1] = "(cipher info unavailable)"; + if sock then + local info = sock.info and sock:info(); + if info then + line[#line+1] = ("(%s with %s)"):format(info.protocol, info.cipher); + else + -- TLS session might not be ready yet + line[#line+1] = "(cipher info unavailable)"; + end end else line[#line+1] = "(insecure)"; -- cgit v1.2.3 From 51f4e1c896e2135b3164847c37d8d2410a9127a4 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 22 Mar 2020 21:05:59 +0100 Subject: mod_storage_sql: Add index covering sort_id to improve performance (fixes #1505) --- plugins/mod_storage_sql.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/mod_storage_sql.lua b/plugins/mod_storage_sql.lua index 73207073..5b1c3603 100644 --- a/plugins/mod_storage_sql.lua +++ b/plugins/mod_storage_sql.lua @@ -500,6 +500,7 @@ local function create_table(engine) -- luacheck: ignore 431/engine Index { name="prosodyarchive_index", unique = engine.params.driver ~= "MySQL", "host", "user", "store", "key" }; Index { name="prosodyarchive_with_when", "host", "user", "store", "with", "when" }; Index { name="prosodyarchive_when", "host", "user", "store", "when" }; + Index { name="prosodyarchive_sort", "host", "user", "store", "sort_id" }; }; engine:transaction(function() ProsodyArchiveTable:create(engine); -- cgit v1.2.3 From 1ee06a447b217fd288654e65236bd81b65a640f5 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sun, 29 Sep 2019 15:05:17 +0200 Subject: mod_register_ibr: Add FORM_TYPE as required by XEP-0077 (fixes #1511) Backport of f90abf142d53 from trunk --- plugins/mod_register_ibr.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_register_ibr.lua b/plugins/mod_register_ibr.lua index bbe7581d..e04e6ecd 100644 --- a/plugins/mod_register_ibr.lua +++ b/plugins/mod_register_ibr.lua @@ -25,6 +25,7 @@ end); local account_details = module:open_store("account_details"); local field_map = { + FORM_TYPE = { name = "FORM_TYPE", type = "hidden", value = "jabber:iq:register" }; username = { name = "username", type = "text-single", label = "Username", required = true }; password = { name = "password", type = "text-private", label = "Password", required = true }; nick = { name = "nick", type = "text-single", label = "Nickname" }; @@ -50,6 +51,7 @@ local registration_form = dataform_new{ title = title; instructions = instructions; + field_map.FORM_TYPE; field_map.username; field_map.password; }; -- cgit v1.2.3 From b60c0cb4354cbbf4904ed9c774d9522f8d628085 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 3 Apr 2020 22:35:47 +0200 Subject: mod_vcard4: Report correct error condition (fixes #1521) On error, the second return value is the error condition, not the third. --- plugins/mod_vcard4.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_vcard4.lua b/plugins/mod_vcard4.lua index 378c0602..04dbca9e 100644 --- a/plugins/mod_vcard4.lua +++ b/plugins/mod_vcard4.lua @@ -14,9 +14,9 @@ module:hook("iq-get/bare/urn:ietf:params:xml:ns:vcard-4.0:vcard", function (even local ok, id, item = pep_service:get_last_item("urn:xmpp:vcard4", stanza.attr.from); if ok and item then origin.send(st.reply(stanza):add_child(item.tags[1])); - elseif item == "item-not-found" or not id then + elseif id == "item-not-found" or not id then origin.send(st.error_reply(stanza, "cancel", "item-not-found")); - elseif item == "forbidden" then + elseif id == "forbidden" then origin.send(st.error_reply(stanza, "auth", "forbidden")); else origin.send(st.error_reply(stanza, "modify", "undefined-condition")); -- cgit v1.2.3 From 5e262dfdf6bdc94ac8a1b49c8c73124a90c6d1df Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 23 Apr 2020 13:16:25 +0100 Subject: MUC: Always include 'affiliation'/'role' attributes, defaulting to 'none' if nil --- plugins/muc/muc.lib.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua index bc370da5..93334b88 100644 --- a/plugins/muc/muc.lib.lua +++ b/plugins/muc/muc.lib.lua @@ -143,7 +143,7 @@ end -- actor is the attribute table local function add_item(x, affiliation, role, jid, nick, actor_nick, actor_jid, reason) - x:tag("item", {affiliation = affiliation; role = role; jid = jid; nick = nick;}) + x:tag("item", {affiliation = affiliation or "none"; role = role; jid = jid; nick = nick;}) if actor_nick or actor_jid then x:tag("actor", {nick = actor_nick; jid = actor_jid;}):up() end -- cgit v1.2.3 From 2d57486958db8f1d07b7afd19340ece0a1a8714d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 25 Apr 2020 20:55:00 +0200 Subject: mod_http_files: Avoid using inode in etag, fix #1498 --- plugins/mod_http_files.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_http_files.lua b/plugins/mod_http_files.lua index 1dae0d6d..a8398c01 100644 --- a/plugins/mod_http_files.lua +++ b/plugins/mod_http_files.lua @@ -112,7 +112,7 @@ function serve(opts) local last_modified = os_date('!%a, %d %b %Y %H:%M:%S GMT', attr.modification); response_headers.last_modified = last_modified; - local etag = ('"%02x-%x-%x-%x"'):format(attr.dev or 0, attr.ino or 0, attr.size or 0, attr.modification or 0); + local etag = ('"%x-%x-%x"'):format(attr.change or 0, attr.size or 0, attr.modification or 0); response_headers.etag = etag; local if_none_match = request_headers.if_none_match -- cgit v1.2.3 From 75c5a894fc8949106b13a01918a25bd8dc5c82c3 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 26 Apr 2020 20:39:39 +0200 Subject: mod_carbons: Fix handling of incoming MUC PMs #1540 27f5db07bec9 fixed this wrong. The code is supposed to check if the stanza is NOT sent to your bare JID. A MUC PM is always sent to your full JID. Hopefully nobody sends MUC invites to full JIDs, because those would be skipped by this as well. --- plugins/mod_carbons.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_carbons.lua b/plugins/mod_carbons.lua index 1dcd4a07..79d3e737 100644 --- a/plugins/mod_carbons.lua +++ b/plugins/mod_carbons.lua @@ -69,7 +69,7 @@ local function message_handler(event, c2s) elseif stanza:get_child("no-copy", "urn:xmpp:hints") then module:log("debug", "Message has no-copy hint, ignoring"); return - elseif not c2s and bare_jid == orig_from and stanza:get_child("x", "http://jabber.org/protocol/muc#user") then + elseif not c2s and bare_jid ~= orig_to and stanza:get_child("x", "http://jabber.org/protocol/muc#user") then module:log("debug", "MUC PM, ignoring"); return end -- cgit v1.2.3 From 8882e11c711176dbe1fd1133e5d8111eb5f06ef3 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 26 Apr 2020 20:58:51 +0200 Subject: mod_tls: Log when certificates are (re)loaded Meant to reduce user confusion over what's reloaded and not. --- plugins/mod_tls.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_tls.lua b/plugins/mod_tls.lua index eb208e28..8c0c4e20 100644 --- a/plugins/mod_tls.lua +++ b/plugins/mod_tls.lua @@ -36,7 +36,7 @@ local host = hosts[module.host]; local ssl_ctx_c2s, ssl_ctx_s2sout, ssl_ctx_s2sin; local ssl_cfg_c2s, ssl_cfg_s2sout, ssl_cfg_s2sin; -function module.load() +function module.load(reload) local NULL, err = {}; local modhost = module.host; local parent = modhost:match("%.(.*)$"); @@ -63,6 +63,12 @@ function module.load() module:log("debug", "Creating context for s2sin"); ssl_ctx_s2sin, err, ssl_cfg_s2sin = create_context(host.host, "server", host_s2s, host_ssl, global_s2s); -- for incoming server connections if not ssl_ctx_s2sin then module:log("error", "Error creating contexts for s2sin: %s", err); end + + if reload then + module:log("info", "Certificates reloaded"); + else + module:log("info", "Certificates loaded"); + end end module:hook_global("config-reloaded", module.load); -- cgit v1.2.3 From ee464bb36d566f5f47e0ab3d3ba562f227fb47bd Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Wed, 29 Apr 2020 18:04:05 +0200 Subject: mod_muc_mam: Fix stanza id filter event name, fixes #1546 Nice typo --- plugins/mod_muc_mam.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index 5a01324d..8216e2e6 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -309,7 +309,7 @@ module:hook("muc-get-history", function (event) return true; end, 1); -module:hook("muc-broadcast-messages", function (event) +module:hook("muc-broadcast-message", function (event) local room, stanza = event.room, event.stanza; -- Filter out that claim to be from us -- cgit v1.2.3 From b199403ab512344f8f05ceef1a8bd20c399da5b8 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 8 May 2020 22:39:01 +0200 Subject: mod_muc_mam: Fix missing advertising of XEP-0359, fixes #1547 --- plugins/mod_muc_mam.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index 8216e2e6..88018f72 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -395,6 +395,7 @@ module:add_feature(xmlns_mam); module:hook("muc-disco#info", function(event) event.reply:tag("feature", {var=xmlns_mam}):up(); + event.reply:tag("feature", {var=xmlns_st_id}):up(); end); -- Cleanup -- cgit v1.2.3 From 3e5bae8965ab0c707919cd1012881f0fa188a6d1 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 8 May 2020 23:47:48 +0200 Subject: mod_csi_simple: Consider XEP-0353: Jingle Message Initiation important Improves experience with VoIP calls initiated via JMI Closes #1548 --- plugins/mod_csi_simple.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_csi_simple.lua b/plugins/mod_csi_simple.lua index da2dd953..7fb6b41f 100644 --- a/plugins/mod_csi_simple.lua +++ b/plugins/mod_csi_simple.lua @@ -79,6 +79,9 @@ module:hook("csi-is-stanza-important", function (event) if stanza:get_child("encryption", "urn:xmpp:eme:0") then return true; end + if stanza:get_child(nil, "urn:xmpp:jingle-message:0") then + return true; + end return false; end return true; -- cgit v1.2.3 From 3e4cbaf0f918f0c392518c055aef2593a6b9b1ed Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 11 May 2020 21:14:02 +0200 Subject: mod_muc_mam: Remove spoofed archive IDs before archiving, fix #1552 The stanza-id added during archiving looks exactly like what should be stripped, so the stripping must happen before archiving. Getting priorities right is hard! Also no test coverage yet. --- plugins/mod_muc_mam.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index 88018f72..711bf163 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -324,7 +324,7 @@ module:hook("muc-broadcast-message", function (event) return tag; end); -end, 0); +end, 1); -- Handle messages local function save_to_history(self, stanza) -- cgit v1.2.3 From 984bf1c1bfc83537db694e0a340e5f44772ee6ba Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 15 May 2020 21:22:35 +0200 Subject: mod_storage_internal: Fix error in time limited queries on items without 'when' field, fixes #1557 --- plugins/mod_storage_internal.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_storage_internal.lua b/plugins/mod_storage_internal.lua index 42b451bd..0becfc8f 100644 --- a/plugins/mod_storage_internal.lua +++ b/plugins/mod_storage_internal.lua @@ -104,12 +104,14 @@ function archive:find(username, query) end if query.start then items:filter(function (item) - return item.when >= query.start; + local when = item.when or datetime.parse(item.attr.stamp); + return when >= query.start; end); end if query["end"] then items:filter(function (item) - return item.when <= query["end"]; + local when = item.when or datetime.parse(item.attr.stamp); + return when <= query["end"]; end); end count = #items; -- cgit v1.2.3 From 5a0f5d2de06dfec97d1f736286a8f6be1625dece Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 23 May 2020 14:17:04 +0200 Subject: mod_auth_internal_*: Apply saslprep to passwords Related to #1560 --- plugins/mod_auth_insecure.lua | 5 +++++ plugins/mod_auth_internal_hashed.lua | 7 ++++++- plugins/mod_auth_internal_plain.lua | 15 ++++++++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_auth_insecure.lua b/plugins/mod_auth_insecure.lua index 9e23c29f..dc5ee616 100644 --- a/plugins/mod_auth_insecure.lua +++ b/plugins/mod_auth_insecure.lua @@ -9,6 +9,7 @@ local datamanager = require "util.datamanager"; local new_sasl = require "util.sasl".new; +local saslprep = require "util.encodings".stringprep.saslprep; local host = module.host; local provider = { name = "insecure" }; @@ -21,6 +22,10 @@ end function provider.set_password(username, password) local account = datamanager.load(username, host, "accounts"); + password = saslprep(password); + if not password then + return nil, "Password fails SASLprep."; + end if account then account.password = password; return datamanager.store(username, host, "accounts", account); diff --git a/plugins/mod_auth_internal_hashed.lua b/plugins/mod_auth_internal_hashed.lua index 083f648b..15058098 100644 --- a/plugins/mod_auth_internal_hashed.lua +++ b/plugins/mod_auth_internal_hashed.lua @@ -15,6 +15,7 @@ local generate_uuid = require "util.uuid".generate; 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 log = module._log; local host = module.host; @@ -32,9 +33,13 @@ local provider = {}; function provider.test_password(username, password) log("debug", "test password for user '%s'", username); local credentials = accounts:get(username) or {}; + password = saslprep(password); + if not password then + return nil, "Password fails SASLprep."; + end if credentials.password ~= nil and string.len(credentials.password) ~= 0 then - if credentials.password ~= password then + if saslprep(credentials.password) ~= password then return nil, "Auth failed. Provided password is incorrect."; end diff --git a/plugins/mod_auth_internal_plain.lua b/plugins/mod_auth_internal_plain.lua index 276efb64..56ef52d5 100644 --- a/plugins/mod_auth_internal_plain.lua +++ b/plugins/mod_auth_internal_plain.lua @@ -8,6 +8,7 @@ local usermanager = require "core.usermanager"; local new_sasl = require "util.sasl".new; +local saslprep = require "util.encodings".stringprep.saslprep; local log = module._log; local host = module.host; @@ -20,8 +21,12 @@ local provider = {}; function provider.test_password(username, password) log("debug", "test password for user '%s'", username); local credentials = accounts:get(username) or {}; + password = saslprep(password); + if not password then + return nil, "Password fails SASLprep."; + end - if password == credentials.password then + if password == saslprep(credentials.password) then return true; else return nil, "Auth failed. Invalid username or password."; @@ -35,6 +40,10 @@ end function provider.set_password(username, password) log("debug", "set_password for username '%s'", username); + password = saslprep(password); + if not password then + return nil, "Password fails SASLprep."; + end local account = accounts:get(username); if account then account.password = password; @@ -57,6 +66,10 @@ function provider.users() end function provider.create_user(username, password) + password = saslprep(password); + if not password then + return nil, "Password fails SASLprep."; + end return accounts:set(username, {password = password}); end -- cgit v1.2.3 From 396ae378944abc3981024617ae87605974364335 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 21 Jun 2020 19:20:54 +0200 Subject: mod_muc_mam: Don't strip MUC tags, fix #1567 --- plugins/mod_muc_mam.lua | 3 --- 1 file changed, 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_muc_mam.lua b/plugins/mod_muc_mam.lua index 711bf163..f0417889 100644 --- a/plugins/mod_muc_mam.lua +++ b/plugins/mod_muc_mam.lua @@ -318,9 +318,6 @@ module:hook("muc-broadcast-message", function (event) and jid_prep(tag.attr.by) == room.jid then return nil; end - if tag.name == "x" and tag.attr.xmlns == xmlns_muc_user then - return nil; - end return tag; end); -- cgit v1.2.3 From d0178fb089d0c757051959114b10e67820dfd981 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 1 Aug 2020 12:58:37 +0200 Subject: mod_s2s: Escape invalid XML in loggin (same way as mod_c2s) fix #1574 --- plugins/mod_s2s/mod_s2s.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_s2s/mod_s2s.lua b/plugins/mod_s2s/mod_s2s.lua index aae37b7f..3f56b953 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: %s", tostring(err), #data, data:sub(1, 300):gsub("[\r\n]+", " "):gsub("[%z\1-\31]", "_")); session:close("not-well-formed"); end end -- cgit v1.2.3 From d8be48981f7e64f984c05f88ecf381da831f7232 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 17 Sep 2020 13:04:46 +0100 Subject: mod_websocket: Switch partial frame buffering to util.dbuffer This improves performance and enforces stanza size limits earlier in the pipeline. --- plugins/mod_websocket.lua | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index 177259e6..ad94486b 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -18,6 +18,7 @@ local contains_token = require "util.http".contains_token; local portmanager = require "core.portmanager"; local sm_destroy_session = require"core.sessionmanager".destroy_session; local log = module._log; +local dbuffer = require "util.dbuffer"; local websocket_frames = require"net.websocket.frames"; local parse_frame = websocket_frames.parse; @@ -27,6 +28,8 @@ 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 frame_fragment_limit = module:get_option_number("websocket_frame_fragment_limit", 8); local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5); local consider_websocket_secure = module:get_option_boolean("consider_websocket_secure"); local cross_domain = module:get_option_set("cross_domain_websocket", {}); @@ -269,14 +272,16 @@ function handle_request(event) session.open_stream = session_open_stream; session.close = session_close; - local frameBuffer = ""; + -- max frame header is 22 bytes + local frameBuffer = dbuffer.new(stanza_size_limit + 22, frame_fragment_limit); add_filter(session, "bytes/in", function(data) + frameBuffer:write(data); + local cache = {}; - frameBuffer = frameBuffer .. data; local frame, length = parse_frame(frameBuffer); while frame do - frameBuffer = frameBuffer:sub(length + 1); + frameBuffer:discard(length); local result = handle_frame(frame); if not result then return; end cache[#cache+1] = filter_open_close(result); -- cgit v1.2.3 From 7f839ba44930e5384a2c170e136ef837c7b54cd2 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 17 Sep 2020 16:41:48 +0100 Subject: mod_websocket: handle full frame buffer and raise stream error --- plugins/mod_websocket.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index ad94486b..d3b035db 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -275,7 +275,11 @@ function handle_request(event) -- max frame header is 22 bytes local frameBuffer = dbuffer.new(stanza_size_limit + 22, frame_fragment_limit); add_filter(session, "bytes/in", function(data) - frameBuffer:write(data); + if not frameBuffer:write(data) then + session.log("warn", "websocket frame buffer full - terminating session"); + session:close({ condition = "resource-constraint", text = "frame buffer exceeded" }); + return; + end local cache = {}; local frame, length = parse_frame(frameBuffer); -- cgit v1.2.3 From 2eee29ff1eec57e9204f2487b0349abb80e9c9f0 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 17 Sep 2020 16:42:14 +0100 Subject: mod_websocket: Add separate limit for frame buffer size --- plugins/mod_websocket.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index d3b035db..53a1d452 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -29,6 +29,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 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); local consider_websocket_secure = module:get_option_boolean("consider_websocket_secure"); @@ -272,8 +273,7 @@ function handle_request(event) session.open_stream = session_open_stream; session.close = session_close; - -- max frame header is 22 bytes - local frameBuffer = dbuffer.new(stanza_size_limit + 22, frame_fragment_limit); + local frameBuffer = dbuffer.new(frame_buffer_limit, frame_fragment_limit); add_filter(session, "bytes/in", function(data) if not frameBuffer:write(data) then session.log("warn", "websocket frame buffer full - terminating session"); -- cgit v1.2.3 From 68898a08805177d6e2ad52c88580893eed506d66 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 17 Sep 2020 16:42:36 +0100 Subject: mod_websocket: Enforce stanza size limit and close stream --- plugins/mod_websocket.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'plugins') diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index 53a1d452..0bd001f4 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -285,6 +285,10 @@ function handle_request(event) local frame, length = parse_frame(frameBuffer); while frame do + if length > stanza_size_limit then + session:close({ condition = "policy-violation", text = "stanza too large" }); + return; + end frameBuffer:discard(length); local result = handle_frame(frame); if not result then return; end -- cgit v1.2.3 From fb2a77467f01351f3b88d45b436fd7420eba90dc Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 28 Sep 2020 16:36:12 +0100 Subject: mod_websocket: Continue to process data already in the buffer after an error occurs Previously any error, or even a normal websocket close frame, would return early, leaving potentially entire frames in the buffer unprocessed and then discarded. This change stops processing new data, but returns an existing processed data up to the point of the error/close. --- plugins/mod_websocket.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index 0bd001f4..ecc12a45 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -291,7 +291,7 @@ function handle_request(event) end frameBuffer:discard(length); local result = handle_frame(frame); - if not result then return; end + if not result then break; end cache[#cache+1] = filter_open_close(result); frame, length = parse_frame(frameBuffer); end -- cgit v1.2.3 From 2546c272bc9f683885d2b4943e70e21696a4c762 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 29 Sep 2020 15:18:32 +0100 Subject: mod_websocket: Refactor frame validity checking, also check partially-received frames against constraints --- plugins/mod_websocket.lua | 172 +++++++++++++++++++++++++--------------------- 1 file changed, 95 insertions(+), 77 deletions(-) (limited to 'plugins') diff --git a/plugins/mod_websocket.lua b/plugins/mod_websocket.lua index ecc12a45..a613672b 100644 --- a/plugins/mod_websocket.lua +++ b/plugins/mod_websocket.lua @@ -142,6 +142,65 @@ local function filter_open_close(data) return data; end + +local function validate_frame(frame, max_length) + local opcode, length = frame.opcode, frame.length; + + if max_length and length > max_length then + return false, 1009, "Payload too large"; + end + + -- Error cases + if frame.RSV1 or frame.RSV2 or frame.RSV3 then -- Reserved bits non zero + return false, 1002, "Reserved bits not zero"; + end + + if opcode == 0x8 and frame.data then -- close frame + if length == 1 then + return false, 1002, "Close frame with payload, but too short for status code"; + elseif length >= 2 then + local status_code = parse_close(frame.data) + if status_code < 1000 then + return false, 1002, "Closed with invalid status code"; + elseif ((status_code > 1003 and status_code < 1007) or status_code > 1011) and status_code < 3000 then + return false, 1002, "Closed with reserved status code"; + end + end + end + + if opcode >= 0x8 then + if length > 125 then -- Control frame with too much payload + return false, 1002, "Payload too large"; + end + + if not frame.FIN then -- Fragmented control frame + return false, 1002, "Fragmented control frame"; + end + end + + if (opcode > 0x2 and opcode < 0x8) or (opcode > 0xA) then + return false, 1002, "Reserved opcode"; + end + + -- Check opcode + if opcode == 0x2 then -- Binary frame + return false, 1003, "Only text frames are supported, RFC 7395 3.2"; + elseif opcode == 0x8 then -- Close request + return false, 1000, "Goodbye"; + end + + -- Other (XMPP-specific) validity checks + if not frame.FIN then + return false, 1003, "Continuation frames are not supported, RFC 7395 3.3.3"; + end + if opcode == 0x01 and frame.data and frame.data:byte(1, 1) ~= 60 then + return false, 1007, "Invalid payload start character, RFC 7395 3.3.3"; + end + + return true; +end + + function handle_request(event) local request, response = event.request, event.response; local conn = response.conn; @@ -172,90 +231,40 @@ function handle_request(event) conn:close(); end - local dataBuffer; - local function handle_frame(frame) - local opcode = frame.opcode; - local length = frame.length; - module:log("debug", "Websocket received frame: opcode=%0x, %i bytes", frame.opcode, #frame.data); - - -- Error cases - if frame.RSV1 or frame.RSV2 or frame.RSV3 then -- Reserved bits non zero - websocket_close(1002, "Reserved bits not zero"); - return false; - end - - if opcode == 0x8 then -- close frame - if length == 1 then - websocket_close(1002, "Close frame with payload, but too short for status code"); - return false; - elseif length >= 2 then - local status_code = parse_close(frame.data) - if status_code < 1000 then - websocket_close(1002, "Closed with invalid status code"); - return false; - elseif ((status_code > 1003 and status_code < 1007) or status_code > 1011) and status_code < 3000 then - websocket_close(1002, "Closed with reserved status code"); - return false; - end - end - end - - if opcode >= 0x8 then - if length > 125 then -- Control frame with too much payload - websocket_close(1002, "Payload too large"); - return false; - end - - if not frame.FIN then -- Fragmented control frame - websocket_close(1002, "Fragmented control frame"); - return false; - end - end - - if (opcode > 0x2 and opcode < 0x8) or (opcode > 0xA) then - websocket_close(1002, "Reserved opcode"); - return false; + local function websocket_handle_error(session, code, message) + if code == 1009 then -- stanza size limit exceeded + -- we close the session, rather than the connection, + -- otherwise a resuming client will simply resend the + -- offending stanza + session:close({ condition = "policy-violation", text = "stanza too large" }); + else + websocket_close(code, message); end + end - if opcode == 0x0 and not dataBuffer then - websocket_close(1002, "Unexpected continuation frame"); - return false; - end + local function handle_frame(frame) + module:log("debug", "Websocket received frame: opcode=%0x, %i bytes", frame.opcode, #frame.data); - if (opcode == 0x1 or opcode == 0x2) and dataBuffer then - websocket_close(1002, "Continuation frame expected"); - return false; + -- Check frame makes sense + local frame_ok, err_status, err_text = validate_frame(frame, stanza_size_limit); + if not frame_ok then + return frame_ok, err_status, err_text; end - -- Valid cases - if opcode == 0x0 then -- Continuation frame - dataBuffer[#dataBuffer+1] = frame.data; - elseif opcode == 0x1 then -- Text frame - dataBuffer = {frame.data}; - elseif opcode == 0x2 then -- Binary frame - websocket_close(1003, "Only text frames are supported"); - return; - elseif opcode == 0x8 then -- Close request - websocket_close(1000, "Goodbye"); - return; - elseif opcode == 0x9 then -- Ping frame + local opcode = frame.opcode; + if opcode == 0x9 then -- Ping frame frame.opcode = 0xA; frame.MASK = false; -- Clients send masked frames, servers don't, see #1484 conn:write(build_frame(frame)); return ""; elseif opcode == 0xA then -- Pong frame, MAY be sent unsolicited, eg as keepalive return ""; - else + elseif opcode ~= 0x1 then -- Not text frame (which is all we support) log("warn", "Received frame with unsupported opcode %i", opcode); return ""; end - if frame.FIN then - local data = t_concat(dataBuffer, ""); - dataBuffer = nil; - return data; - end - return ""; + return frame.data; end conn:setlistener(c2s_listener); @@ -282,19 +291,28 @@ function handle_request(event) end local cache = {}; - local frame, length = parse_frame(frameBuffer); + local frame, length, partial = parse_frame(frameBuffer); while frame do - if length > stanza_size_limit then - session:close({ condition = "policy-violation", text = "stanza too large" }); - return; - end frameBuffer:discard(length); - local result = handle_frame(frame); - if not result then break; end + local result, err_status, err_text = handle_frame(frame); + if not result then + websocket_handle_error(session, err_status, err_text); + break; + end cache[#cache+1] = filter_open_close(result); - frame, length = parse_frame(frameBuffer); + frame, length, partial = parse_frame(frameBuffer); end + + if partial then + -- The header of the next frame is already in the buffer, run + -- some early validation here + local frame_ok, err_status, err_text = validate_frame(partial, stanza_size_limit); + if not frame_ok then + websocket_handle_error(session, err_status, err_text); + end + end + return t_concat(cache, ""); end); -- cgit v1.2.3