# HG changeset patch # User Goffi # Date 1585591157 -7200 # Node ID d85b68e44297965a08ace8b56dc7a4cd72095295 # Parent 4396bf14f5fc9ff35abf15ca66bcd00235dab17c plugin XEP-0384: fixed /omemo_reset + device ID type: - the workflow done with /omemo_reset is now using the right methods (encryptRatchetForwardingMessage and decryptRatchetForwardingMessage) - fixed type error with device when calling python-omemo methods: a mix of str and int was leading to two caches being created, and random bugs diff -r 4396bf14f5fc -r d85b68e44297 sat/plugins/plugin_xep_0384.py --- a/sat/plugins/plugin_xep_0384.py Mon Mar 30 19:59:14 2020 +0200 +++ b/sat/plugins/plugin_xep_0384.py Mon Mar 30 19:59:17 2020 +0200 @@ -142,7 +142,7 @@ deferred.addErrback(partial(callback, False)) def _checkJid(self, bare_jid): - """Check if jid is know, and store it if not + """Check if jid is known, and store it if not @param bare_jid(unicode): bare jid to check @return (D): Deferred fired when jid is stored @@ -329,12 +329,13 @@ def buildSession(self, bare_jid, device, bundle): bare_jid = bare_jid.userhost() - build_session_p = self._session.buildSession(bare_jid, device, bundle) + build_session_p = self._session.buildSession(bare_jid, int(device), bundle) return promise2Deferred(build_session_p) def deleteSession(self, bare_jid, device): bare_jid = bare_jid.userhost() - delete_session_p = self._session.deleteSession(bare_jid=bare_jid, device=device) + delete_session_p = self._session.deleteSession( + bare_jid=bare_jid, device=int(device)) return promise2Deferred(delete_session_p) def encryptMessage(self, bare_jids, message, bundles=None, expect_problems=None): @@ -356,12 +357,23 @@ expect_problems=expect_problems) return promise2Deferred(encrypt_mess_p) + def encryptRatchetForwardingMessage( + self, bare_jids, bundles=None, expect_problems=None): + bare_jids = [e.userhost() for e in bare_jids] + if bundles is not None: + bundles = {e.userhost(): v for e, v in bundles.items()} + encrypt_ratchet_fwd_p = self._session.encryptRatchetForwardingMessage( + bare_jids=bare_jids, + bundles=bundles, + expect_problems=expect_problems) + return promise2Deferred(encrypt_ratchet_fwd_p) + def decryptMessage(self, bare_jid, device, iv, message, is_pre_key_message, ciphertext, additional_information=None, allow_untrusted=False): bare_jid = bare_jid.userhost() decrypt_mess_p = self._session.decryptMessage( bare_jid=bare_jid, - device=device, + device=int(device), iv=iv, message=message, is_pre_key_message=is_pre_key_message, @@ -371,11 +383,26 @@ ) return promise2Deferred(decrypt_mess_p) + def decryptRatchetForwardingMessage( + self, bare_jid, device, iv, message, is_pre_key_message, + additional_information=None, allow_untrusted=False): + bare_jid = bare_jid.userhost() + decrypt_ratchet_fwd_p = self._session.decryptRatchetForwardingMessage( + bare_jid=bare_jid, + device=int(device), + iv=iv, + message=message, + is_pre_key_message=is_pre_key_message, + additional_information=additional_information, + allow_untrusted=allow_untrusted + ) + return promise2Deferred(decrypt_ratchet_fwd_p) + def setTrust(self, bare_jid, device, key, trusted): bare_jid = bare_jid.userhost() setTrust_p = self._session.setTrust( bare_jid=bare_jid, - device=device, + device=int(device), key=key, trusted=trusted, ) @@ -385,7 +412,7 @@ bare_jid = bare_jid.userhost() resetTrust_p = self._session.resetTrust( bare_jid=bare_jid, - device=device, + device=int(device), ) return promise2Deferred(resetTrust_p) @@ -674,8 +701,7 @@ return xmlui - @defer.inlineCallbacks - def profileConnected(self, client): + async def profileConnected(self, client): if self._m is not None: # we keep plain text message for MUC messages we send # as we can't encrypt for our own device @@ -691,9 +717,9 @@ persistent_dict = persistent.LazyPersistentBinaryDict("XEP-0384", client.profile) client._xep_0384_data = persistent_dict # all known devices of profile - devices = yield self.getDevices(client) + devices = await self.getDevices(client) # and our own device id - device_id = yield persistent_dict.get(KEY_DEVICE_ID) + device_id = await persistent_dict.get(KEY_DEVICE_ID) if device_id is None: log.info(_("We have no identity for this device yet, let's generate one")) # we have a new device, we create device_id @@ -709,25 +735,26 @@ if device_id not in devices: log.debug(f"our device id ({device_id}) is not in the list, adding it") devices.add(device_id) - yield defer.ensureDeferred(self.setDevices(client, devices)) + await defer.ensureDeferred(self.setDevices(client, devices)) - all_jids = yield persistent_dict.get(KEY_ALL_JIDS, set()) + all_jids = await persistent_dict.get(KEY_ALL_JIDS, set()) omemo_storage = OmemoStorage(client, device_id, all_jids) - omemo_session = yield OmemoSession.create(client, omemo_storage, device_id) + omemo_session = await OmemoSession.create(client, omemo_storage, device_id) client._xep_0384_cache = {} client._xep_0384_session = omemo_session client._xep_0384_device_id = device_id - yield omemo_session.newDeviceList(client.jid, devices) + await omemo_session.newDeviceList(client.jid, devices) if omemo_session.republish_bundle: log.info(_("Saving public bundle for this device ({device_id})").format( device_id=device_id)) - yield defer.ensureDeferred( + await defer.ensureDeferred( self.setBundle(client, omemo_session.public_bundle, device_id) ) client._xep_0384_ready.callback(None) del client._xep_0384_ready + ## XMPP PEP nodes manipulation # devices @@ -1126,11 +1153,17 @@ raise exceptions.InternalError(msg) # encryptMessage may fail, in case of e.g. trust issue or missing bundle try: - encrypted = await omemo_session.encryptMessage( - entity_bare_jids, - message, - bundles, - expect_problems = expect_problems) + if not message: + encrypted = await omemo_session.encryptRatchetForwardingMessage( + entity_bare_jids, + bundles, + expect_problems = expect_problems) + else: + encrypted = await omemo_session.encryptMessage( + entity_bare_jids, + message, + bundles, + expect_problems = expect_problems) except omemo_excpt.EncryptionProblemsException as e: # we know the problem to solve, we can try to fix them await self.handleProblems( @@ -1275,21 +1308,24 @@ "iv": base64.b64decode(bytes(iv_elt)), "message": base64.b64decode(bytes(key_elt)), "is_pre_key_message": is_pre_key, - "ciphertext": base64.b64decode(bytes(payload_elt)) - if payload_elt is not None else None, "additional_information": additional_information, } try: - try: - plaintext = yield omemo_session.decryptMessage(**kwargs) - except omemo_excpt.TrustException: - post_treat.addCallback(client.encryption.markAsUntrusted) - kwargs['allow_untrusted'] = True - plaintext = yield omemo_session.decryptMessage(**kwargs) + if payload_elt is None: + omemo_session.decryptRatchetForwardingMessage(**kwargs) + plaintext = None else: - post_treat.addCallback(client.encryption.markAsTrusted) - plaintext = plaintext.decode() + kwargs["ciphertext"] = base64.b64decode(bytes(payload_elt)) + try: + plaintext = yield omemo_session.decryptMessage(**kwargs) + except omemo_excpt.TrustException: + post_treat.addCallback(client.encryption.markAsUntrusted) + kwargs['allow_untrusted'] = True + plaintext = yield omemo_session.decryptMessage(**kwargs) + else: + post_treat.addCallback(client.encryption.markAsTrusted) + plaintext = plaintext.decode() except Exception as e: log.warning(_("Can't decrypt message: {reason}\n{xml}").format( reason=e, xml=message_elt.toXml()))