about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorMaximilian Wuttke <mwuttke97@posteo.de>2021-03-29 21:53:51 +0200
committerMaximilian Wuttke <mwuttke97@posteo.de>2021-04-08 00:29:58 +0200
commite8664e27303e6028bc335e33172d84025ff3fa30 (patch)
treee1c999de8bac1f82b593a80377f06d987ad1615a
parent9e0d0ed46664bcfe9bc3197be2d794fc1c7a5142 (diff)
downloadprofani-tty-e8664e27303e6028bc335e33172d84025ff3fa30.tar.gz
OMEMO: Fail if message keys couldn't be encrypted for any recipient device
If the message (key) can't be encrypted for any device, sending the
message is refused and an informative error message is presented to the
user.

Also, don't encrypt for the same device, since the OMEMO XEP disallows
this.
-rw-r--r--src/command/cmd_funcs.c15
-rw-r--r--src/omemo/omemo.c20
2 files changed, 27 insertions, 8 deletions
diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c
index b140de53..90c41dfd 100644
--- a/src/command/cmd_funcs.c
+++ b/src/command/cmd_funcs.c
@@ -2151,22 +2151,21 @@ cmd_msg(ProfWin* window, const char* const command, gchar** args)
 
         ProfChatWin* chatwin = wins_get_chat(barejid);
         if (!chatwin) {
-            // NOTE: This will also start the new OMEMO session
-            // and send a MAM request.
+            // NOTE: This will also start the new OMEMO session and send a MAM request.
             chatwin = chatwin_new(barejid);
         }
         ui_focus_win((ProfWin*)chatwin);
 
         if (msg) {
-            // FIXME [OMEMO] We can't be sure whether the
-            // bundles have already been receieved. Thus, it is
-            // possible (and probable) that the recipent can't
-            // encrypt the message.
+            // NOTE: In case the message is OMEMO encrypted, we can't be sure
+            // whether the key bundles of the recipient have already been
+            // received. In the case that *no* bundles have been received yet,
+            // the message won't be sent, and an error is shown to the user.
+            // Other cases are not handled here.
             cl_ev_send_msg(chatwin, msg, NULL);
         } else {
 #ifdef HAVE_LIBOTR
-            // Start the OTR session after this (i.e. the
-            // first) message was sent
+            // Start the OTR session after this (i.e. the first) message was sent
             if (otr_is_secure(barejid)) {
                 chatwin_otr_secured(chatwin, otr_is_trusted(barejid));
             }
diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c
index a552cd57..495842bf 100644
--- a/src/omemo/omemo.c
+++ b/src/omemo/omemo.c
@@ -705,6 +705,7 @@ omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_
     memcpy(key_tag, key, AES128_GCM_KEY_LENGTH);
     memcpy(key_tag + AES128_GCM_KEY_LENGTH, tag, AES128_GCM_TAG_LENGTH);
 
+    // List of barejids of the recipients of this message
     GList* recipients = NULL;
     if (muc) {
         ProfMucWin* mucwin = (ProfMucWin*)win;
@@ -727,6 +728,7 @@ omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_
 
     omemo_ctx.identity_key_store.recv = false;
 
+    // Encrypt keys for the recipients
     GList* recipients_iter;
     for (recipients_iter = recipients; recipients_iter != NULL; recipients_iter = recipients_iter->next) {
         GList* recipient_device_id = NULL;
@@ -772,6 +774,17 @@ omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_
 
     g_list_free_full(recipients, free);
 
+    // Don't send the message if no key could be encrypted.
+    // (Since none of the recipients would be able to read the message.)
+    if (keys == NULL) {
+        win_println(win, THEME_ERROR, "!", "This message cannot be decrypted for any recipient.\n"
+                "You should trust your recipients' device fingerprint(s) using \"/omemo fingerprint trust FINGERPRINT\".\n"
+                "It could also be that the key bundle of the recipient(s) have not been received. "
+                "In this case, you could try \"omemo end\", \"omemo start\", and send the message again.");
+        goto out;
+    }
+
+    // Encrypt keys for the sender
     if (!muc) {
         GList* sender_device_id = g_hash_table_lookup(omemo_ctx.device_list, jid->barejid);
         for (device_ids_iter = sender_device_id; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) {
@@ -784,6 +797,12 @@ omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_
                 .device_id = GPOINTER_TO_INT(device_ids_iter->data)
             };
 
+            // Don't encrypt for this device (according to
+            // <https://xmpp.org/extensions/xep-0384.html#encrypt>).
+            if (address.device_id == omemo_ctx.device_id) {
+                continue;
+            }
+
             res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal);
             if (res != 0) {
                 log_error("[OMEMO] cannot create cipher for %s device id %d", address.name, address.device_id);
@@ -808,6 +827,7 @@ omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_
         }
     }
 
+    // Send the message
     if (muc) {
         ProfMucWin* mucwin = (ProfMucWin*)win;
         assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);