# HG changeset patch # User Matthew Wild # Date 1587646398 -3600 # Node ID d0e6d5bc7ea217e16d2e152cb7c8303f5118421e # Parent 9dec7cddb40b5900a221122ea49bfa5461847f30# Parent 930f38939f1e2fc8983e83a2449f71830adcb0b5 Merge with upstream trunk diff -r 9dec7cddb40b -r d0e6d5bc7ea2 doc/doap.xml --- a/doc/doap.xml Thu Apr 23 13:52:19 2020 +0100 +++ b/doc/doap.xml Thu Apr 23 13:53:18 2020 +0100 @@ -431,6 +431,14 @@ + + 1.2 + 0.12 + mod_csi_simple + + + + 0.12.1 complete diff -r 9dec7cddb40b -r d0e6d5bc7ea2 plugins/mod_csi_simple.lua --- a/plugins/mod_csi_simple.lua Thu Apr 23 13:52:19 2020 +0100 +++ b/plugins/mod_csi_simple.lua Thu Apr 23 13:53:18 2020 +0100 @@ -48,6 +48,9 @@ if stanza:get_child("encryption", "urn:xmpp:eme:0") then return true; end + if stanza:get_child("x", "jabber:x:conference") or stanza:find("{http://jabber.org/protocol/muc#user}x/invite") then + return true; + end for important in important_payloads do if stanza:find(important) then return true; diff -r 9dec7cddb40b -r d0e6d5bc7ea2 plugins/mod_lastactivity.lua --- a/plugins/mod_lastactivity.lua Thu Apr 23 13:52:19 2020 +0100 +++ b/plugins/mod_lastactivity.lua Thu Apr 23 13:53:18 2020 +0100 @@ -30,7 +30,7 @@ if not stanza.attr.to or is_contact_subscribed(username, module.host, jid_bare(stanza.attr.from)) then local seconds, text = "0", ""; if map[username] then - seconds = tostring(os.difftime(os.time(), map[username].t)); + seconds = string.format("%d", os.difftime(os.time(), map[username].t)); text = map[username].s; end origin.send(st.reply(stanza):tag('query', {xmlns='jabber:iq:last', seconds=seconds}):text(text)); diff -r 9dec7cddb40b -r d0e6d5bc7ea2 plugins/mod_mam/mod_mam.lua --- a/plugins/mod_mam/mod_mam.lua Thu Apr 23 13:52:19 2020 +0100 +++ b/plugins/mod_mam/mod_mam.lua Thu Apr 23 13:53:18 2020 +0100 @@ -263,11 +263,65 @@ return stanza; end +local function should_store(stanza) --> boolean, reason: string + local st_type = stanza.attr.type or "normal"; + -- FIXME pass direction of stanza and use that along with bare/full JID addressing + -- for more accurate MUC / type=groupchat check + + if st_type == "headline" then + -- Headline messages are ephemeral by definition + return false, "headline"; + end + if st_type == "error" then + return true, "bounce"; + end + if st_type == "groupchat" then + -- MUC messages always go to the full JID, usually archived by the MUC + return false, "groupchat"; + end + if stanza:get_child("no-store", "urn:xmpp:hints") + or stanza:get_child("no-permanent-store", "urn:xmpp:hints") then + -- XXX Experimental XEP + return false, "hint"; + end + if stanza:get_child("store", "urn:xmpp:hints") then + return true, "hint"; + end + if stanza:get_child("body") then + return true, "body"; + end + if stanza:get_child("subject") then + -- XXX Who would send a message with a subject but without a body? + return true, "subject"; + end + if stanza:get_child("encryption", "urn:xmpp:eme:0") then + -- Since we can't know what an encrypted message contains, we assume it's important + -- XXX Experimental XEP + return true, "encrypted"; + end + if stanza:get_child(nil, "urn:xmpp:receipts") then + -- If it's important enough to ask for a receipt then it's important enough to archive + -- and the same applies to the receipt + return true, "receipt"; + end + if stanza:get_child(nil, "urn:xmpp:chat-markers:0") then + -- XXX Experimental XEP + return true, "marker"; + end + if stanza:get_child("x", "jabber:x:conference") + or stanza:find("{http://jabber.org/protocol/muc#user}x/invite") then + return true, "invite"; + end + + -- The IM-NG thing to do here would be to return `not st_to_full` + -- One day ... + return false, "default"; +end + -- Handle messages local function message_handler(event, c2s) local origin, stanza = event.origin, event.stanza; local log = c2s and origin.log or module._log; - local orig_type = stanza.attr.type or "normal"; local orig_from = stanza.attr.from; local orig_to = stanza.attr.to or orig_from; -- Stanza without 'to' are treated as if it was to their own bare jid @@ -280,21 +334,12 @@ -- Filter out that claim to be from us event.stanza = strip_stanza_id(stanza, store_user); - -- We store chat messages or normal messages that have a body - if not(orig_type == "chat" or (orig_type == "normal" and stanza:get_child("body")) ) then - log("debug", "Not archiving stanza: %s (type)", stanza:top_tag()); + local should, why = should_store(stanza); + if not should then + log("debug", "Not archiving stanza: %s (%s)", stanza:top_tag(), why); return; end - -- or if hints suggest we shouldn't - if not stanza:get_child("store", "urn:xmpp:hints") then -- No hint telling us we should store - if stanza:get_child("no-permanent-store", "urn:xmpp:hints") - or stanza:get_child("no-store", "urn:xmpp:hints") then -- Hint telling us we should NOT store - log("debug", "Not archiving stanza: %s (hint)", stanza:top_tag()); - return; - end - end - local clone_for_storage; if not strip_tags:empty() then clone_for_storage = st.clone(stanza); @@ -315,7 +360,7 @@ -- Check with the users preferences if shall_store(store_user, with) then - log("debug", "Archiving stanza: %s", stanza:top_tag()); + log("debug", "Archiving stanza: %s (%s)", stanza:top_tag(), why); -- And stash it local time = time_now(); diff -r 9dec7cddb40b -r d0e6d5bc7ea2 plugins/mod_uptime.lua --- a/plugins/mod_uptime.lua Thu Apr 23 13:52:19 2020 +0100 +++ b/plugins/mod_uptime.lua Thu Apr 23 13:53:18 2020 +0100 @@ -16,7 +16,7 @@ module:hook("iq-get/host/jabber:iq:last:query", function(event) local origin, stanza = event.origin, event.stanza; - origin.send(st.reply(stanza):tag("query", {xmlns = "jabber:iq:last", seconds = tostring(os.difftime(os.time(), start_time))})); + origin.send(st.reply(stanza):tag("query", {xmlns = "jabber:iq:last", seconds = tostring(("%d"):format(os.difftime(os.time(), start_time)))})); return true; end); diff -r 9dec7cddb40b -r d0e6d5bc7ea2 spec/scansion/lastactivity.scs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spec/scansion/lastactivity.scs Thu Apr 23 13:53:18 2020 +0100 @@ -0,0 +1,45 @@ +# XEP-0012: Last Activity / mod_lastactivity + +[Client] Romeo + jid: romeo@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + + Hello + + +Romeo receives: + + Hello + + +Romeo sends: + + Goodbye + + +Romeo receives: + + Goodbye + + +# mod_lastlog saves time + status message from the last unavailable presence + +Romeo sends: + + + + +Romeo receives: + + Goodbye + + +Romeo disconnects + +# recording ended on 2020-04-20T14:39:47Z diff -r 9dec7cddb40b -r d0e6d5bc7ea2 spec/scansion/prosody.cfg.lua --- a/spec/scansion/prosody.cfg.lua Thu Apr 23 13:52:19 2020 +0100 +++ b/spec/scansion/prosody.cfg.lua Thu Apr 23 13:53:18 2020 +0100 @@ -1,5 +1,16 @@ --luacheck: ignore +-- Mock time functions to simplify tests +function _G.os.time() + return 1219439344; +end +package.preload["util.time"] = function () + return { + now = function () return 1219439344.1; end; + monotonic = function () return 0.1; end; + } +end + admins = { "admin@localhost" } use_libevent = true @@ -48,6 +59,7 @@ --"motd"; -- Send a message to users when they log in --"legacyauth"; -- Legacy authentication. Only used by some old clients and bots. --"proxy65"; -- Enables a file transfer proxy service which clients behind NAT can use + "lastactivity"; -- Useful for testing --"scansion_record"; -- Records things that happen in scansion test case format @@ -84,6 +96,8 @@ VirtualHost "localhost" +hide_os_type = true -- absense tested for in version.scs + Component "conference.localhost" "muc" storage = "memory" diff -r 9dec7cddb40b -r d0e6d5bc7ea2 spec/scansion/uptime.scs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spec/scansion/uptime.scs Thu Apr 23 13:53:18 2020 +0100 @@ -0,0 +1,21 @@ +# XEP-0012: Last Activity / mod_uptime + +[Client] Romeo + jid: romeo@localhost + password: password + +----- + +Romeo connects + +Romeo sends: + + + + +Romeo receives: + + + + +Romeo disconnects diff -r 9dec7cddb40b -r d0e6d5bc7ea2 spec/scansion/version.scs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spec/scansion/version.scs Thu Apr 23 13:53:18 2020 +0100 @@ -0,0 +1,27 @@ +# XEP-0092: Software Version / mod_version + +[Client] Romeo + password: password + jid: romeo@localhost/dfaZpuxV + +----- + +Romeo connects + +Romeo sends: + + + + +# Version string would vary so we can't do an exact match atm +# Inclusion of is disabled in the config, it should be absent +Romeo receives: + + + Prosody + + + + + +Romeo disconnects diff -r 9dec7cddb40b -r d0e6d5bc7ea2 spec/util_hashes_spec.lua --- a/spec/util_hashes_spec.lua Thu Apr 23 13:52:19 2020 +0100 +++ b/spec/util_hashes_spec.lua Thu Apr 23 13:53:18 2020 +0100 @@ -4,34 +4,52 @@ -- Also see spec for util.hmac where HMAC test cases reside -describe("PBKDF2-SHA1", function () +describe("PBKDF2-HMAC-SHA1", function () it("test vector 1", function () local P = "password" local S = "salt" local c = 1 local DK = "0c60c80f961f0e71f3a9b524af6012062fe037a6"; - assert.equal(DK, hex.to(hashes.scram_Hi_sha1(P, S, c))); + assert.equal(DK, hex.to(hashes.pbkdf2_hmac_sha1(P, S, c))); end); it("test vector 2", function () local P = "password" local S = "salt" local c = 2 local DK = "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"; - assert.equal(DK, hex.to(hashes.scram_Hi_sha1(P, S, c))); + assert.equal(DK, hex.to(hashes.pbkdf2_hmac_sha1(P, S, c))); end); it("test vector 3", function () local P = "password" local S = "salt" local c = 4096 local DK = "4b007901b765489abead49d926f721d065a429c1"; - assert.equal(DK, hex.to(hashes.scram_Hi_sha1(P, S, c))); + assert.equal(DK, hex.to(hashes.pbkdf2_hmac_sha1(P, S, c))); end); it("test vector 4 #SLOW", function () local P = "password" local S = "salt" local c = 16777216 local DK = "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984"; - assert.equal(DK, hex.to(hashes.scram_Hi_sha1(P, S, c))); + assert.equal(DK, hex.to(hashes.pbkdf2_hmac_sha1(P, S, c))); end); end); +describe("PBKDF2-HMAC-SHA256", function () + it("test vector 1", function () + local P = "password"; + local S = "salt"; + local c = 1 + local DK = "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b"; + assert.equal(DK, hex.to(hashes.pbkdf2_hmac_sha256(P, S, c))); + end); + it("test vector 2", function () + local P = "password"; + local S = "salt"; + local c = 2 + local DK = "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43"; + assert.equal(DK, hex.to(hashes.pbkdf2_hmac_sha256(P, S, c))); + end); +end); + + diff -r 9dec7cddb40b -r d0e6d5bc7ea2 util-src/hashes.c --- a/util-src/hashes.c Thu Apr 23 13:52:19 2020 +0100 +++ b/util-src/hashes.c Thu Apr 23 13:53:18 2020 +0100 @@ -129,7 +129,7 @@ return luaL_error(L, "PKCS5_PBKDF2_HMAC() failed"); } - lua_pushlstring(L, (char *)out, SHA_DIGEST_LENGTH); + lua_pushlstring(L, (char *)out, SHA256_DIGEST_LENGTH); return 1; }