Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0384.py @ 3085:c048fc192739
plugin XEP-0384: update to latest python-omemo + better trust management:
- python-omemo minimal version is now 0.11.0
- `undecided` devices are now handled, fixing the "accept all or none" issue: if a device
is `undecided`, the trust manager will be shown with the missing devices before sending
the message.
- `untrusted` devices are discarded
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 20 Dec 2019 12:28:01 +0100 |
parents | ffcdd93b61fa |
children | 518208085dfb |
comparison
equal
deleted
inserted
replaced
3084:ffcdd93b61fa | 3085:c048fc192739 |
---|---|
1 #!/usr/bin/env python3 | 1 #!/usr/bin/env python3 |
2 # -*- coding: utf-8 -*- | |
3 | 2 |
4 # SAT plugin for OMEMO encryption | 3 # SAT plugin for OMEMO encryption |
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) | 4 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) |
6 | 5 |
7 # This program is free software: you can redistribute it and/or modify | 6 # This program is free software: you can redistribute it and/or modify |
59 C.PI_MAIN: "OMEMO", | 58 C.PI_MAIN: "OMEMO", |
60 C.PI_HANDLER: "no", | 59 C.PI_HANDLER: "no", |
61 C.PI_DESCRIPTION: _("""Implementation of OMEMO"""), | 60 C.PI_DESCRIPTION: _("""Implementation of OMEMO"""), |
62 } | 61 } |
63 | 62 |
64 OMEMO_MIN_VER = (0, 10, 4) | 63 OMEMO_MIN_VER = (0, 11, 0) |
65 NS_OMEMO = "eu.siacs.conversations.axolotl" | 64 NS_OMEMO = "eu.siacs.conversations.axolotl" |
66 NS_OMEMO_DEVICES = NS_OMEMO + ".devicelist" | 65 NS_OMEMO_DEVICES = NS_OMEMO + ".devicelist" |
67 NS_OMEMO_BUNDLE = NS_OMEMO + ".bundles:{device_id}" | 66 NS_OMEMO_BUNDLE = NS_OMEMO + ".bundles:{device_id}" |
68 KEY_STATE = "STATE" | 67 KEY_STATE = "STATE" |
69 KEY_DEVICE_ID = "DEVICE_ID" | 68 KEY_DEVICE_ID = "DEVICE_ID" |
358 additional_information=additional_information, | 357 additional_information=additional_information, |
359 allow_untrusted=allow_untrusted | 358 allow_untrusted=allow_untrusted |
360 ) | 359 ) |
361 return promise2Deferred(decrypt_mess_p) | 360 return promise2Deferred(decrypt_mess_p) |
362 | 361 |
363 def trust(self, bare_jid, device, key): | 362 def setTrust(self, bare_jid, device, key, trusted): |
364 bare_jid = bare_jid.userhost() | 363 bare_jid = bare_jid.userhost() |
365 trust_p = self._session.trust( | 364 setTrust_p = self._session.setTrust( |
366 bare_jid=bare_jid, | 365 bare_jid=bare_jid, |
367 device=device, | 366 device=device, |
368 key=key) | 367 key=key, |
369 return promise2Deferred(trust_p) | 368 trusted=trusted, |
370 | 369 ) |
371 def distrust(self, bare_jid, device, key): | 370 return promise2Deferred(setTrust_p) |
372 bare_jid = bare_jid.userhost() | |
373 distrust_p = self._session.distrust( | |
374 bare_jid=bare_jid, | |
375 device=device, | |
376 key=key) | |
377 return promise2Deferred(distrust_p) | |
378 | 371 |
379 def getTrustForJID(self, bare_jid): | 372 def getTrustForJID(self, bare_jid): |
380 bare_jid = bare_jid.userhost() | 373 bare_jid = bare_jid.userhost() |
381 get_trust_p = self._session.getTrustForJID(bare_jid=bare_jid) | 374 get_trust_p = self._session.getTrustForJID(bare_jid=bare_jid) |
382 return promise2Deferred(get_trust_p) | 375 return promise2Deferred(get_trust_p) |
416 trust_id = key[6:] | 409 trust_id = key[6:] |
417 else: | 410 else: |
418 continue | 411 continue |
419 data = trust_data[trust_id] | 412 data = trust_data[trust_id] |
420 trust = C.bool(value) | 413 trust = C.bool(value) |
421 if trust: | 414 yield session.setTrust( |
422 yield session.trust(data["jid"], | 415 data["jid"], |
423 data["device"], | 416 data["device"], |
424 data["ik"]) | 417 data["ik"], |
425 else: | 418 trusted=trust, |
426 yield session.distrust(data["jid"], | 419 ) |
427 data["device"], | 420 if not trust and expect_problems is not None: |
428 data["ik"]) | 421 expect_problems.setdefault(data['jid'].userhost(), set()).add( |
429 if expect_problems is not None: | 422 data['device'] |
430 expect_problems.setdefault(data.bare_jid, set()).add(data.device) | 423 ) |
431 defer.returnValue({}) | 424 defer.returnValue({}) |
432 | 425 |
433 @defer.inlineCallbacks | 426 @defer.inlineCallbacks |
434 def getTrustUI(self, client, entity_jid=None, trust_data=None, submit_id=None): | 427 def getTrustUI(self, client, entity_jid=None, trust_data=None, submit_id=None): |
435 """Generate a XMLUI to manage trust | 428 """Generate a XMLUI to manage trust |
805 This dict will list devices where problems can be ignored | 798 This dict will list devices where problems can be ignored |
806 (those devices won't receive the encrypted data) | 799 (those devices won't receive the encrypted data) |
807 This dict is updated | 800 This dict is updated |
808 """ | 801 """ |
809 # FIXME: not all problems are handled yet | 802 # FIXME: not all problems are handled yet |
810 untrusted = {} | 803 undecided = {} |
811 missing_bundles = {} | 804 missing_bundles = {} |
805 found_bundles = None | |
812 cache = client._xep_0384_cache | 806 cache = client._xep_0384_cache |
813 for problem in problems: | 807 for problem in problems: |
814 if isinstance(problem, omemo_excpt.TrustException): | 808 if isinstance(problem, omemo_excpt.TrustException): |
815 untrusted[str(hash(problem))] = problem | 809 if problem.problem == 'undecided': |
810 undecided[str(hash(problem))] = problem | |
811 elif problem.problem == 'untrusted': | |
812 expect_problems.setdefault(problem.bare_jid, set()).add( | |
813 problem.device) | |
814 log.info(_( | |
815 "discarding untrusted device {device_id} with key {device_key} " | |
816 "for {entity}").format( | |
817 device_id=problem.device, | |
818 device_key=problem.ik.hex().upper(), | |
819 entity=problem.bare_jid, | |
820 ) | |
821 ) | |
822 else: | |
823 log.error( | |
824 f"Unexpected trust problem: {problem.problem!r} for device " | |
825 f"{problem.device} for {problem.bare_jid}, ignoring device") | |
826 expect_problems.setdefault(problem.bare_jid, set()).add( | |
827 problem.device) | |
816 elif isinstance(problem, omemo_excpt.MissingBundleException): | 828 elif isinstance(problem, omemo_excpt.MissingBundleException): |
817 pb_entity = jid.JID(problem.bare_jid) | 829 pb_entity = jid.JID(problem.bare_jid) |
818 entity_cache = cache.setdefault(pb_entity, {}) | 830 entity_cache = cache.setdefault(pb_entity, {}) |
819 entity_bundles = bundles.setdefault(pb_entity, {}) | 831 entity_bundles = bundles.setdefault(pb_entity, {}) |
820 if problem.device in entity_cache: | 832 if problem.device in entity_cache: |
828 missing_bundles.setdefault(pb_entity, set()).add( | 840 missing_bundles.setdefault(pb_entity, set()).add( |
829 problem.device) | 841 problem.device) |
830 expect_problems.setdefault(problem.bare_jid, set()).add( | 842 expect_problems.setdefault(problem.bare_jid, set()).add( |
831 problem.device) | 843 problem.device) |
832 elif isinstance(problem, omemo_excpt.NoEligibleDevicesException): | 844 elif isinstance(problem, omemo_excpt.NoEligibleDevicesException): |
833 if untrusted or found_bundles: | 845 if undecided or found_bundles: |
834 # we may have new devices after this run, so let's continue for now | 846 # we may have new devices after this run, so let's continue for now |
835 continue | 847 continue |
836 else: | 848 else: |
837 raise problem | 849 raise problem |
838 else: | 850 else: |
849 D_("You're destinee {peer} has missing encryption data on some of " | 861 D_("You're destinee {peer} has missing encryption data on some of " |
850 "his/her device(s) (bundle on device {devices}), the message won't " | 862 "his/her device(s) (bundle on device {devices}), the message won't " |
851 "be readable on this/those device.").format( | 863 "be readable on this/those device.").format( |
852 peer=peer_jid.full(), devices=", ".join(devices_s))) | 864 peer=peer_jid.full(), devices=", ".join(devices_s))) |
853 | 865 |
854 if untrusted: | 866 if undecided: |
855 trust_data = {} | 867 trust_data = {} |
856 for trust_id, data in untrusted.items(): | 868 for trust_id, data in undecided.items(): |
857 trust_data[trust_id] = { | 869 trust_data[trust_id] = { |
858 'jid': jid.JID(data.bare_jid), | 870 'jid': jid.JID(data.bare_jid), |
859 'device': data.device, | 871 'device': data.device, |
860 'ik': data.ik} | 872 'ik': data.ik} |
861 | 873 |