From 2f8902e0d6b7010a4e2fbb917df6ad515e1d5b0f Mon Sep 17 00:00:00 2001 From: Goffi Date: Mon, 23 Mar 2020 17:52:18 +0100 Subject: [PATCH] core (memory/encryption): automatic start encryption if peer send encrypted message: If peer sends encrypted message and we have no encryption activated, we automatically start encryption to avoid sending plain text message when answering. markAsEncrypted now needs the encryption algorithm namespace as mandatory argument. --- sat/memory/encryption.py | 21 ++++++++++++++++++--- sat/plugins/plugin_sec_otr.py | 2 +- sat/plugins/plugin_xep_0384.py | 2 +- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/sat/memory/encryption.py b/sat/memory/encryption.py index 16852123..284f401b 100644 --- a/sat/memory/encryption.py +++ b/sat/memory/encryption.py @@ -442,23 +442,38 @@ class EncryptionHandler: to_jid = mess_data['to'] encryption = self._sessions.get(to_jid.userhostJID()) if encryption is not None: - if mess_data["type"] == "groupchat" and encryption['plugin'].directed: + plugin = encryption['plugin'] + if mess_data["type"] == "groupchat" and plugin.directed: raise exceptions.InternalError( f"encryption flag must not be set for groupchat if encryption algorithm " f"({encryption['plugin'].name}) is directed!") mess_data[C.MESS_KEY_ENCRYPTION] = encryption - self.markAsEncrypted(mess_data) + self.markAsEncrypted(mess_data, plugin.namespace) ## Misc ## - def markAsEncrypted(self, mess_data): + def markAsEncrypted(self, mess_data, namespace): """Helper method to mark a message as having been e2e encrypted. This should be used in the post_treat workflow of messageReceived trigger of the plugin @param mess_data(dict): message data as used in post treat workflow + @param namespace(str): namespace of the algorithm used for encrypting the message """ mess_data['extra'][C.MESS_KEY_ENCRYPTED] = True + from_bare_jid = mess_data['from'].userhostJID() + if from_bare_jid != self.client.jid.userhostJID(): + session = self.getSession(from_bare_jid) + if session is None: + # if we are currently unencrypted, we start a session automatically + # to avoid sending unencrypted messages in an encrypted context + log.info(_( + "Starting e2e session with {peer_jid} as we receive encrypted " + "messages") + .format(peer_jid=from_bare_jid) + ) + defer.ensureDeferred(self.start(from_bare_jid, namespace)) + return mess_data def isEncryptionRequested(self, mess_data, namespace=None): diff --git a/sat/plugins/plugin_sec_otr.py b/sat/plugins/plugin_sec_otr.py index 201b6a4a..cd115e84 100644 --- a/sat/plugins/plugin_sec_otr.py +++ b/sat/plugins/plugin_sec_otr.py @@ -698,7 +698,7 @@ class OTR(object): exceptions.CancelError("Cancelled by OTR") ) # no message at all (no history, no signal) - client.encryption.markAsEncrypted(data) + client.encryption.markAsEncrypted(data, namespace=NS_OTR) trusted = otrctx.isTrusted() if trusted: diff --git a/sat/plugins/plugin_xep_0384.py b/sat/plugins/plugin_xep_0384.py index f929750e..020c9faa 100644 --- a/sat/plugins/plugin_xep_0384.py +++ b/sat/plugins/plugin_xep_0384.py @@ -1162,7 +1162,7 @@ class OMEMO: message_elt.children.remove(encrypted_elt) if plaintext: message_elt.addElement("body", content=plaintext) - post_treat.addCallback(client.encryption.markAsEncrypted) + post_treat.addCallback(client.encryption.markAsEncrypted, namespace=NS_OMEMO) defer.returnValue(True) def getJIDsForRoom(self, client, room_jid):