Explorar o código

OMEMO: ensure reflected encrypted MUC messages are identified

JC Brand %!s(int64=4) %!d(string=hai) anos
pai
achega
0a82a177c4

+ 1 - 1
src/components/message-history.js

@@ -18,7 +18,7 @@ const tpl_message = (o) => html`
         ?editable=${o.editable}
         ?has_mentions=${o.has_mentions}
         ?is_delayed=${o.is_delayed}
-        ?is_encrypted=${o.is_encrypted}
+        ?is_encrypted=${!!o.is_encrypted}
         ?is_first_unread=${o.is_first_unread}
         ?is_me_message=${o.is_me_message}
         ?is_only_emojis=${o.is_only_emojis}

+ 1 - 1
src/components/message.js

@@ -161,7 +161,7 @@ export default class Message extends CustomElement {
             this.message_type !== 'info' &&
             prev_model.get('type') !== 'info' &&
             date.isBefore(dayjs(prev_model.get('time')).add(10, 'minutes')) &&
-            this.is_encrypted === prev_model.get('is_encrypted');
+            !!this.is_encrypted === !!prev_model.get('is_encrypted');
     }
 
     getExtraMessageClasses () {

+ 4 - 4
src/converse-omemo.js

@@ -187,9 +187,9 @@ async function decryptWhisperMessage (attrs) {
 function addKeysToMessageStanza (stanza, dicts, iv) {
     for (const i in dicts) {
         if (Object.prototype.hasOwnProperty.call(dicts, i)) {
-            const payload = dicts[i].payload,
-                    device = dicts[i].device,
-                    prekey = 3 == parseInt(payload.type, 10);
+            const payload = dicts[i].payload;
+            const device = dicts[i].device;
+            const prekey = 3 == parseInt(payload.type, 10);
 
             stanza.c('key', {'rid': device.get('id') }).t(btoa(payload.body));
             if (prekey) {
@@ -1206,7 +1206,7 @@ converse.plugins.add('converse-omemo', {
         });
 
         function parseEncryptedMessage (stanza, attrs) {
-            if (attrs.is_encrypted) {
+            if (attrs.is_encrypted && attrs.encrypted.key) {
                 // https://xmpp.org/extensions/xep-0384.html#usecases-receiving
                 if (attrs.encrypted.prekey === true) {
                     return decryptPrekeyWhisperMessage(attrs);

+ 1 - 1
src/headless/converse-core.js

@@ -466,7 +466,7 @@ export const api = _converse.api = {
      * @method _converse.api.hook
      * @param {string} name - The hook name
      * @param {...any} context - The context to which the hook applies (could be for example, a {@link _converse.ChatBox)).
-     * @param {...any} data - The data structure to be intercepted and * modified by the hook listeners.
+     * @param {...any} data - The data structure to be intercepted and modified by the hook listeners.
      */
     hook (name, context, data) {
         const events = _converse._events[name] || [];

+ 15 - 0
src/headless/converse-muc.js

@@ -1930,6 +1930,21 @@ converse.plugins.add('converse-muc', {
                 return false;
             },
 
+            getMessageBodyQueryAttrs (attrs) {
+                if (attrs.message && attrs.msgid) {
+                    const query = {
+                        'from': attrs.from,
+                        'msgid': attrs.msgid
+                    }
+                    if (!attrs.is_encrypted) {
+                        // We can't match the message if it's a reflected
+                        // encrypted MUC message
+                        query['message'] =  attrs.message;
+                    }
+                    return query;
+                }
+            },
+
             /**
              * Queue an incoming message stanza meant for this {@link _converse.Chatroom} for processing.
              * @async

+ 14 - 15
src/headless/utils/stanza.js

@@ -50,25 +50,24 @@ function getCorrectionAttributes (stanza, original_stanza) {
 
 function getEncryptionAttributes (stanza, _converse) {
     const encrypted = sizzle(`encrypted[xmlns="${Strophe.NS.OMEMO}"]`, stanza).pop();
+    const attrs = { 'is_encrypted': !!encrypted };
     if (!encrypted || !_converse.config.get('trusted')) {
-        return {};
+        return attrs;
     }
+    const header = encrypted.querySelector('header');
+    attrs['encrypted'] = {'device_id': header.getAttribute('sid')};
+
     const device_id = _converse.omemo_store?.get('device_id');
     const key = device_id && sizzle(`key[rid="${device_id}"]`, encrypted).pop();
     if (key) {
-        const header = encrypted.querySelector('header');
-        return {
-            'is_encrypted': true,
-            'encrypted': {
-                'device_id': header.getAttribute('sid'),
-                'iv': header.querySelector('iv').textContent,
-                'key': key.textContent,
-                'payload': encrypted.querySelector('payload')?.textContent || null,
-                'prekey': ['true', '1'].includes(key.getAttribute('prekey'))
-            }
-        }
+        Object.assign(attrs.encrypted, {
+            'iv': header.querySelector('iv').textContent,
+            'key': key.textContent,
+            'payload': encrypted.querySelector('payload')?.textContent || null,
+            'prekey': ['true', '1'].includes(key.getAttribute('prekey'))
+        });
     }
-    return {};
+    return attrs;
 }
 
 
@@ -537,7 +536,7 @@ const st = {
          * *Hook* which allows plugins to add additional parsing
          * @event _converse#parseMessage
          */
-        return api.hook('parseMessage', _converse, attrs);
+        return api.hook('parseMessage', stanza, attrs);
     },
 
     /**
@@ -685,7 +684,7 @@ const st = {
          * *Hook* which allows plugins to add additional parsing
          * @event _converse#parseMUCMessage
          */
-        return api.hook('parseMUCMessage', chatbox, attrs);
+        return api.hook('parseMUCMessage', stanza, attrs);
     },
 
     /**