comparison sat/plugins/plugin_xep_0384.py @ 3240:d85b68e44297

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
author Goffi <goffi@goffi.org>
date Mon, 30 Mar 2020 19:59:17 +0200
parents b0c57c9a4bd8
children be6d91572633
comparison
equal deleted inserted replaced
3239:4396bf14f5fc 3240:d85b68e44297
140 """ 140 """
141 deferred.addCallback(partial(callback, True)) 141 deferred.addCallback(partial(callback, True))
142 deferred.addErrback(partial(callback, False)) 142 deferred.addErrback(partial(callback, False))
143 143
144 def _checkJid(self, bare_jid): 144 def _checkJid(self, bare_jid):
145 """Check if jid is know, and store it if not 145 """Check if jid is known, and store it if not
146 146
147 @param bare_jid(unicode): bare jid to check 147 @param bare_jid(unicode): bare jid to check
148 @return (D): Deferred fired when jid is stored 148 @return (D): Deferred fired when jid is stored
149 """ 149 """
150 if bare_jid in self.all_jids: 150 if bare_jid in self.all_jids:
327 get_devices_p = self._session.getDevices(bare_jid=bare_jid) 327 get_devices_p = self._session.getDevices(bare_jid=bare_jid)
328 return promise2Deferred(get_devices_p) 328 return promise2Deferred(get_devices_p)
329 329
330 def buildSession(self, bare_jid, device, bundle): 330 def buildSession(self, bare_jid, device, bundle):
331 bare_jid = bare_jid.userhost() 331 bare_jid = bare_jid.userhost()
332 build_session_p = self._session.buildSession(bare_jid, device, bundle) 332 build_session_p = self._session.buildSession(bare_jid, int(device), bundle)
333 return promise2Deferred(build_session_p) 333 return promise2Deferred(build_session_p)
334 334
335 def deleteSession(self, bare_jid, device): 335 def deleteSession(self, bare_jid, device):
336 bare_jid = bare_jid.userhost() 336 bare_jid = bare_jid.userhost()
337 delete_session_p = self._session.deleteSession(bare_jid=bare_jid, device=device) 337 delete_session_p = self._session.deleteSession(
338 bare_jid=bare_jid, device=int(device))
338 return promise2Deferred(delete_session_p) 339 return promise2Deferred(delete_session_p)
339 340
340 def encryptMessage(self, bare_jids, message, bundles=None, expect_problems=None): 341 def encryptMessage(self, bare_jids, message, bundles=None, expect_problems=None):
341 """Encrypt a message 342 """Encrypt a message
342 343
354 plaintext=message.encode(), 355 plaintext=message.encode(),
355 bundles=bundles, 356 bundles=bundles,
356 expect_problems=expect_problems) 357 expect_problems=expect_problems)
357 return promise2Deferred(encrypt_mess_p) 358 return promise2Deferred(encrypt_mess_p)
358 359
360 def encryptRatchetForwardingMessage(
361 self, bare_jids, bundles=None, expect_problems=None):
362 bare_jids = [e.userhost() for e in bare_jids]
363 if bundles is not None:
364 bundles = {e.userhost(): v for e, v in bundles.items()}
365 encrypt_ratchet_fwd_p = self._session.encryptRatchetForwardingMessage(
366 bare_jids=bare_jids,
367 bundles=bundles,
368 expect_problems=expect_problems)
369 return promise2Deferred(encrypt_ratchet_fwd_p)
370
359 def decryptMessage(self, bare_jid, device, iv, message, is_pre_key_message, 371 def decryptMessage(self, bare_jid, device, iv, message, is_pre_key_message,
360 ciphertext, additional_information=None, allow_untrusted=False): 372 ciphertext, additional_information=None, allow_untrusted=False):
361 bare_jid = bare_jid.userhost() 373 bare_jid = bare_jid.userhost()
362 decrypt_mess_p = self._session.decryptMessage( 374 decrypt_mess_p = self._session.decryptMessage(
363 bare_jid=bare_jid, 375 bare_jid=bare_jid,
364 device=device, 376 device=int(device),
365 iv=iv, 377 iv=iv,
366 message=message, 378 message=message,
367 is_pre_key_message=is_pre_key_message, 379 is_pre_key_message=is_pre_key_message,
368 ciphertext=ciphertext, 380 ciphertext=ciphertext,
369 additional_information=additional_information, 381 additional_information=additional_information,
370 allow_untrusted=allow_untrusted 382 allow_untrusted=allow_untrusted
371 ) 383 )
372 return promise2Deferred(decrypt_mess_p) 384 return promise2Deferred(decrypt_mess_p)
373 385
386 def decryptRatchetForwardingMessage(
387 self, bare_jid, device, iv, message, is_pre_key_message,
388 additional_information=None, allow_untrusted=False):
389 bare_jid = bare_jid.userhost()
390 decrypt_ratchet_fwd_p = self._session.decryptRatchetForwardingMessage(
391 bare_jid=bare_jid,
392 device=int(device),
393 iv=iv,
394 message=message,
395 is_pre_key_message=is_pre_key_message,
396 additional_information=additional_information,
397 allow_untrusted=allow_untrusted
398 )
399 return promise2Deferred(decrypt_ratchet_fwd_p)
400
374 def setTrust(self, bare_jid, device, key, trusted): 401 def setTrust(self, bare_jid, device, key, trusted):
375 bare_jid = bare_jid.userhost() 402 bare_jid = bare_jid.userhost()
376 setTrust_p = self._session.setTrust( 403 setTrust_p = self._session.setTrust(
377 bare_jid=bare_jid, 404 bare_jid=bare_jid,
378 device=device, 405 device=int(device),
379 key=key, 406 key=key,
380 trusted=trusted, 407 trusted=trusted,
381 ) 408 )
382 return promise2Deferred(setTrust_p) 409 return promise2Deferred(setTrust_p)
383 410
384 def resetTrust(self, bare_jid, device): 411 def resetTrust(self, bare_jid, device):
385 bare_jid = bare_jid.userhost() 412 bare_jid = bare_jid.userhost()
386 resetTrust_p = self._session.resetTrust( 413 resetTrust_p = self._session.resetTrust(
387 bare_jid=bare_jid, 414 bare_jid=bare_jid,
388 device=device, 415 device=int(device),
389 ) 416 )
390 return promise2Deferred(resetTrust_p) 417 return promise2Deferred(resetTrust_p)
391 418
392 def getTrustForJID(self, bare_jid): 419 def getTrustForJID(self, bare_jid):
393 bare_jid = bare_jid.userhost() 420 bare_jid = bare_jid.userhost()
672 xmlui.addEmpty() 699 xmlui.addEmpty()
673 xmlui.addEmpty() 700 xmlui.addEmpty()
674 701
675 return xmlui 702 return xmlui
676 703
677 @defer.inlineCallbacks 704 async def profileConnected(self, client):
678 def profileConnected(self, client):
679 if self._m is not None: 705 if self._m is not None:
680 # we keep plain text message for MUC messages we send 706 # we keep plain text message for MUC messages we send
681 # as we can't encrypt for our own device 707 # as we can't encrypt for our own device
682 client._xep_0384_muc_cache = {} 708 client._xep_0384_muc_cache = {}
683 # and we keep them only for some time, in case something goes wrong 709 # and we keep them only for some time, in case something goes wrong
689 client._xep_0384_ready = defer.Deferred() 715 client._xep_0384_ready = defer.Deferred()
690 # we first need to get devices ids (including our own) 716 # we first need to get devices ids (including our own)
691 persistent_dict = persistent.LazyPersistentBinaryDict("XEP-0384", client.profile) 717 persistent_dict = persistent.LazyPersistentBinaryDict("XEP-0384", client.profile)
692 client._xep_0384_data = persistent_dict 718 client._xep_0384_data = persistent_dict
693 # all known devices of profile 719 # all known devices of profile
694 devices = yield self.getDevices(client) 720 devices = await self.getDevices(client)
695 # and our own device id 721 # and our own device id
696 device_id = yield persistent_dict.get(KEY_DEVICE_ID) 722 device_id = await persistent_dict.get(KEY_DEVICE_ID)
697 if device_id is None: 723 if device_id is None:
698 log.info(_("We have no identity for this device yet, let's generate one")) 724 log.info(_("We have no identity for this device yet, let's generate one"))
699 # we have a new device, we create device_id 725 # we have a new device, we create device_id
700 device_id = random.randint(1, 2**31-1) 726 device_id = random.randint(1, 2**31-1)
701 # we check that it's really unique 727 # we check that it's really unique
707 log.debug(f"our OMEMO device id is {device_id}") 733 log.debug(f"our OMEMO device id is {device_id}")
708 734
709 if device_id not in devices: 735 if device_id not in devices:
710 log.debug(f"our device id ({device_id}) is not in the list, adding it") 736 log.debug(f"our device id ({device_id}) is not in the list, adding it")
711 devices.add(device_id) 737 devices.add(device_id)
712 yield defer.ensureDeferred(self.setDevices(client, devices)) 738 await defer.ensureDeferred(self.setDevices(client, devices))
713 739
714 all_jids = yield persistent_dict.get(KEY_ALL_JIDS, set()) 740 all_jids = await persistent_dict.get(KEY_ALL_JIDS, set())
715 741
716 omemo_storage = OmemoStorage(client, device_id, all_jids) 742 omemo_storage = OmemoStorage(client, device_id, all_jids)
717 omemo_session = yield OmemoSession.create(client, omemo_storage, device_id) 743 omemo_session = await OmemoSession.create(client, omemo_storage, device_id)
718 client._xep_0384_cache = {} 744 client._xep_0384_cache = {}
719 client._xep_0384_session = omemo_session 745 client._xep_0384_session = omemo_session
720 client._xep_0384_device_id = device_id 746 client._xep_0384_device_id = device_id
721 yield omemo_session.newDeviceList(client.jid, devices) 747 await omemo_session.newDeviceList(client.jid, devices)
722 if omemo_session.republish_bundle: 748 if omemo_session.republish_bundle:
723 log.info(_("Saving public bundle for this device ({device_id})").format( 749 log.info(_("Saving public bundle for this device ({device_id})").format(
724 device_id=device_id)) 750 device_id=device_id))
725 yield defer.ensureDeferred( 751 await defer.ensureDeferred(
726 self.setBundle(client, omemo_session.public_bundle, device_id) 752 self.setBundle(client, omemo_session.public_bundle, device_id)
727 ) 753 )
728 client._xep_0384_ready.callback(None) 754 client._xep_0384_ready.callback(None)
729 del client._xep_0384_ready 755 del client._xep_0384_ready
756
730 757
731 ## XMPP PEP nodes manipulation 758 ## XMPP PEP nodes manipulation
732 759
733 # devices 760 # devices
734 761
1124 msg = _("Too many iterations in encryption loop") 1151 msg = _("Too many iterations in encryption loop")
1125 log.error(msg) 1152 log.error(msg)
1126 raise exceptions.InternalError(msg) 1153 raise exceptions.InternalError(msg)
1127 # encryptMessage may fail, in case of e.g. trust issue or missing bundle 1154 # encryptMessage may fail, in case of e.g. trust issue or missing bundle
1128 try: 1155 try:
1129 encrypted = await omemo_session.encryptMessage( 1156 if not message:
1130 entity_bare_jids, 1157 encrypted = await omemo_session.encryptRatchetForwardingMessage(
1131 message, 1158 entity_bare_jids,
1132 bundles, 1159 bundles,
1133 expect_problems = expect_problems) 1160 expect_problems = expect_problems)
1161 else:
1162 encrypted = await omemo_session.encryptMessage(
1163 entity_bare_jids,
1164 message,
1165 bundles,
1166 expect_problems = expect_problems)
1134 except omemo_excpt.EncryptionProblemsException as e: 1167 except omemo_excpt.EncryptionProblemsException as e:
1135 # we know the problem to solve, we can try to fix them 1168 # we know the problem to solve, we can try to fix them
1136 await self.handleProblems( 1169 await self.handleProblems(
1137 client, 1170 client,
1138 feedback_jid=feedback_jid, 1171 feedback_jid=feedback_jid,
1273 "bare_jid": from_jid.userhostJID(), 1306 "bare_jid": from_jid.userhostJID(),
1274 "device": s_device_id, 1307 "device": s_device_id,
1275 "iv": base64.b64decode(bytes(iv_elt)), 1308 "iv": base64.b64decode(bytes(iv_elt)),
1276 "message": base64.b64decode(bytes(key_elt)), 1309 "message": base64.b64decode(bytes(key_elt)),
1277 "is_pre_key_message": is_pre_key, 1310 "is_pre_key_message": is_pre_key,
1278 "ciphertext": base64.b64decode(bytes(payload_elt))
1279 if payload_elt is not None else None,
1280 "additional_information": additional_information, 1311 "additional_information": additional_information,
1281 } 1312 }
1282 1313
1283 try: 1314 try:
1284 try: 1315 if payload_elt is None:
1285 plaintext = yield omemo_session.decryptMessage(**kwargs) 1316 omemo_session.decryptRatchetForwardingMessage(**kwargs)
1286 except omemo_excpt.TrustException: 1317 plaintext = None
1287 post_treat.addCallback(client.encryption.markAsUntrusted)
1288 kwargs['allow_untrusted'] = True
1289 plaintext = yield omemo_session.decryptMessage(**kwargs)
1290 else: 1318 else:
1291 post_treat.addCallback(client.encryption.markAsTrusted) 1319 kwargs["ciphertext"] = base64.b64decode(bytes(payload_elt))
1292 plaintext = plaintext.decode() 1320 try:
1321 plaintext = yield omemo_session.decryptMessage(**kwargs)
1322 except omemo_excpt.TrustException:
1323 post_treat.addCallback(client.encryption.markAsUntrusted)
1324 kwargs['allow_untrusted'] = True
1325 plaintext = yield omemo_session.decryptMessage(**kwargs)
1326 else:
1327 post_treat.addCallback(client.encryption.markAsTrusted)
1328 plaintext = plaintext.decode()
1293 except Exception as e: 1329 except Exception as e:
1294 log.warning(_("Can't decrypt message: {reason}\n{xml}").format( 1330 log.warning(_("Can't decrypt message: {reason}\n{xml}").format(
1295 reason=e, xml=message_elt.toXml())) 1331 reason=e, xml=message_elt.toXml()))
1296 user_msg = (D_( 1332 user_msg = (D_(
1297 "An OMEMO message from {sender} can't be decrypted: {reason}") 1333 "An OMEMO message from {sender} can't be decrypted: {reason}")