comparison sat/plugins/plugin_xep_0380.py @ 3028:ab2696e34d29

Python 3 port: /!\ this is a huge commit /!\ starting from this commit, SàT is needs Python 3.6+ /!\ SàT maybe be instable or some feature may not work anymore, this will improve with time This patch port backend, bridge and frontends to Python 3. Roughly this has been done this way: - 2to3 tools has been applied (with python 3.7) - all references to python2 have been replaced with python3 (notably shebangs) - fixed files not handled by 2to3 (notably the shell script) - several manual fixes - fixed issues reported by Python 3 that where not handled in Python 2 - replaced "async" with "async_" when needed (it's a reserved word from Python 3.7) - replaced zope's "implements" with @implementer decorator - temporary hack to handle data pickled in database, as str or bytes may be returned, to be checked later - fixed hash comparison for password - removed some code which is not needed anymore with Python 3 - deactivated some code which needs to be checked (notably certificate validation) - tested with jp, fixed reported issues until some basic commands worked - ported Primitivus (after porting dependencies like urwid satext) - more manual fixes
author Goffi <goffi@goffi.org>
date Tue, 13 Aug 2019 19:08:41 +0200
parents 607cfc79e40f
children 9d0df638c8b4
comparison
equal deleted inserted replaced
3027:ff5bcb12ae60 3028:ab2696e34d29
1 #!/usr/bin/env python2 1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 3
4 # SAT plugin for Explicit Message Encryption 4 # SAT plugin for Explicit Message Encryption
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org)
6 6
23 from twisted.words.protocols.jabber import jid 23 from twisted.words.protocols.jabber import jid
24 24
25 log = getLogger(__name__) 25 log = getLogger(__name__)
26 26
27 PLUGIN_INFO = { 27 PLUGIN_INFO = {
28 C.PI_NAME: u"Explicit Message Encryption", 28 C.PI_NAME: "Explicit Message Encryption",
29 C.PI_IMPORT_NAME: u"XEP-0380", 29 C.PI_IMPORT_NAME: "XEP-0380",
30 C.PI_TYPE: u"SEC", 30 C.PI_TYPE: "SEC",
31 C.PI_PROTOCOLS: [u"XEP-0380"], 31 C.PI_PROTOCOLS: ["XEP-0380"],
32 C.PI_DEPENDENCIES: [], 32 C.PI_DEPENDENCIES: [],
33 C.PI_MAIN: u"XEP_0380", 33 C.PI_MAIN: "XEP_0380",
34 C.PI_HANDLER: u"no", 34 C.PI_HANDLER: "no",
35 C.PI_DESCRIPTION: _(u"""Implementation of Explicit Message Encryption"""), 35 C.PI_DESCRIPTION: _("""Implementation of Explicit Message Encryption"""),
36 } 36 }
37 37
38 NS_EME = u"urn:xmpp:eme:0" 38 NS_EME = "urn:xmpp:eme:0"
39 KNOWN_NAMESPACES = { 39 KNOWN_NAMESPACES = {
40 u"urn:xmpp:otr:0": u"OTR", 40 "urn:xmpp:otr:0": "OTR",
41 u"jabber:x:encrypted": u"Legacy OpenPGP", 41 "jabber:x:encrypted": "Legacy OpenPGP",
42 u"urn:xmpp:openpgp:0": u"OpenPGP for XMPP", 42 "urn:xmpp:openpgp:0": "OpenPGP for XMPP",
43 } 43 }
44 44
45 45
46 class XEP_0380(object): 46 class XEP_0380(object):
47 47
48 def __init__(self, host): 48 def __init__(self, host):
49 self.host = host 49 self.host = host
50 host.trigger.add("sendMessage", self._sendMessageTrigger) 50 host.trigger.add("sendMessage", self._sendMessageTrigger)
51 host.trigger.add("MessageReceived", self._MessageReceivedTrigger, priority=100) 51 host.trigger.add("MessageReceived", self._MessageReceivedTrigger, priority=100)
52 host.registerNamespace(u"eme", NS_EME) 52 host.registerNamespace("eme", NS_EME)
53 53
54 def _addEMEElement(self, mess_data, namespace, name): 54 def _addEMEElement(self, mess_data, namespace, name):
55 message_elt = mess_data[u'xml'] 55 message_elt = mess_data['xml']
56 encryption_elt = message_elt.addElement((NS_EME, u'encryption')) 56 encryption_elt = message_elt.addElement((NS_EME, 'encryption'))
57 encryption_elt[u'namespace'] = namespace 57 encryption_elt['namespace'] = namespace
58 if name is not None: 58 if name is not None:
59 encryption_elt[u'name'] = name 59 encryption_elt['name'] = name
60 return mess_data 60 return mess_data
61 61
62 def _sendMessageTrigger(self, client, mess_data, __, post_xml_treatments): 62 def _sendMessageTrigger(self, client, mess_data, __, post_xml_treatments):
63 encryption = mess_data.get(C.MESS_KEY_ENCRYPTION) 63 encryption = mess_data.get(C.MESS_KEY_ENCRYPTION)
64 if encryption is not None: 64 if encryption is not None:
65 namespace = encryption['plugin'].namespace 65 namespace = encryption['plugin'].namespace
66 if namespace not in KNOWN_NAMESPACES: 66 if namespace not in KNOWN_NAMESPACES:
67 name = encryption[u'plugin'].name 67 name = encryption['plugin'].name
68 else: 68 else:
69 name = None 69 name = None
70 post_xml_treatments.addCallback( 70 post_xml_treatments.addCallback(
71 self._addEMEElement, namespace=namespace, name=name) 71 self._addEMEElement, namespace=namespace, name=name)
72 return True 72 return True
73 73
74 def _MessageReceivedTrigger(self, client, message_elt, post_treat): 74 def _MessageReceivedTrigger(self, client, message_elt, post_treat):
75 try: 75 try:
76 encryption_elt = next(message_elt.elements(NS_EME, u'encryption')) 76 encryption_elt = next(message_elt.elements(NS_EME, 'encryption'))
77 except StopIteration: 77 except StopIteration:
78 return True 78 return True
79 79
80 namespace = encryption_elt['namespace'] 80 namespace = encryption_elt['namespace']
81 if namespace in client.encryption.getNamespaces(): 81 if namespace in client.encryption.getNamespaces():
82 # message is encrypted and we can decrypt it 82 # message is encrypted and we can decrypt it
83 return True 83 return True
84 84
85 name = KNOWN_NAMESPACES.get(namespace, encryption_elt.getAttribute(u"name")) 85 name = KNOWN_NAMESPACES.get(namespace, encryption_elt.getAttribute("name"))
86 86
87 # at this point, message is encrypted but we know that we can't decrypt it, 87 # at this point, message is encrypted but we know that we can't decrypt it,
88 # we need to notify the user 88 # we need to notify the user
89 sender_s = message_elt[u'from'] 89 sender_s = message_elt['from']
90 to_jid = jid.JID(message_elt[u'from']) 90 to_jid = jid.JID(message_elt['from'])
91 algorithm = u"{} [{}]".format(name, namespace) if name else namespace 91 algorithm = "{} [{}]".format(name, namespace) if name else namespace
92 log.warning( 92 log.warning(
93 _(u"Message from {sender} is encrypted with {algorithm} and we can't " 93 _("Message from {sender} is encrypted with {algorithm} and we can't "
94 u"decrypt it.".format(sender=message_elt['from'], algorithm=algorithm))) 94 "decrypt it.".format(sender=message_elt['from'], algorithm=algorithm)))
95 95
96 user_msg = D_( 96 user_msg = D_(
97 u"User {sender} sent you an encrypted message (encrypted with {algorithm}), " 97 "User {sender} sent you an encrypted message (encrypted with {algorithm}), "
98 u"and we can't decrypt it.").format(sender=sender_s, algorithm=algorithm) 98 "and we can't decrypt it.").format(sender=sender_s, algorithm=algorithm)
99 99
100 extra = {C.MESS_EXTRA_INFO: C.EXTRA_INFO_DECR_ERR} 100 extra = {C.MESS_EXTRA_INFO: C.EXTRA_INFO_DECR_ERR}
101 client.feedback(to_jid, user_msg, extra) 101 client.feedback(to_jid, user_msg, extra)
102 return False 102 return False