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
This commit is contained in:
Goffi 2020-03-30 19:59:17 +02:00
commit bd94d2620d

View file

@ -142,7 +142,7 @@ class OmemoStorage(omemo.Storage):
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 @@ class OmemoSession:
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 @@ class OmemoSession:
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 @@ class OmemoSession:
)
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 @@ class OmemoSession:
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 @@ class OMEMO:
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 @@ class OMEMO:
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 @@ class OMEMO:
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 @@ class OMEMO:
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 @@ class OMEMO:
"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()))