changeset 3231:e756e0eb1be4

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.
author Goffi <goffi@goffi.org>
date Mon, 23 Mar 2020 17:52:18 +0100
parents 109d94c62b95
children f3c99e96ac03
files sat/memory/encryption.py sat/plugins/plugin_sec_otr.py sat/plugins/plugin_xep_0384.py
diffstat 3 files changed, 20 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/sat/memory/encryption.py	Mon Mar 23 16:55:15 2020 +0100
+++ b/sat/memory/encryption.py	Mon Mar 23 17:52:18 2020 +0100
@@ -442,23 +442,38 @@
         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):
--- a/sat/plugins/plugin_sec_otr.py	Mon Mar 23 16:55:15 2020 +0100
+++ b/sat/plugins/plugin_sec_otr.py	Mon Mar 23 17:52:18 2020 +0100
@@ -698,7 +698,7 @@
                     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:
--- a/sat/plugins/plugin_xep_0384.py	Mon Mar 23 16:55:15 2020 +0100
+++ b/sat/plugins/plugin_xep_0384.py	Mon Mar 23 17:52:18 2020 +0100
@@ -1162,7 +1162,7 @@
         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):