about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorPaul Fariello <paul@fariello.eu>2019-03-14 22:05:47 +0220
committerPaul Fariello <paul@fariello.eu>2019-04-10 17:12:31 +0200
commita3897abba1e093aeab2b46bccded87485e518bb1 (patch)
tree59ba8739c7d43a316a75761be65cec563c5cd14f
parent33b0b4642000166ca7f8033ac5ff2e2c6e7b4671 (diff)
downloadprofani-tty-a3897abba1e093aeab2b46bccded87485e518bb1.tar.gz
Add MUC message decryption
-rw-r--r--src/omemo/omemo.c58
-rw-r--r--src/omemo/omemo.h2
-rw-r--r--src/ui/win_types.h1
-rw-r--r--src/xmpp/message.c12
-rw-r--r--src/xmpp/omemo.c9
5 files changed, 60 insertions, 22 deletions
diff --git a/src/omemo/omemo.c b/src/omemo/omemo.c
index 23892c02..62478e5d 100644
--- a/src/omemo/omemo.c
+++ b/src/omemo/omemo.c
@@ -20,6 +20,7 @@
 #include "ui/ui.h"
 #include "ui/window_list.h"
 #include "xmpp/connection.h"
+#include "xmpp/muc.h"
 #include "xmpp/omemo.h"
 #include "xmpp/xmpp.h"
 
@@ -387,7 +388,7 @@ omemo_set_device_list(const char *const from, GList * device_list)
         }
     }
 
-    free(jid);
+    jid_destroy(jid);
 }
 
 GKeyFile *
@@ -515,18 +516,20 @@ omemo_start_device_session(const char *const jid, uint32_t device_id,
 
 out:
     g_list_free_full(prekeys, (GDestroyNotify)free_omemo_key);
-    free(ownjid);
+    jid_destroy(ownjid);
 }
 
 gboolean
 omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean request_receipt)
 {
     int res;
+    gboolean ret = FALSE;
     Jid *jid = jid_create(connection_get_fulljid());
+    GList *keys = NULL;
 
     GList *recipient_device_id = g_hash_table_lookup(omemo_ctx.device_list, chatwin->barejid);
     if (!recipient_device_id) {
-        return FALSE;
+        goto out;
     }
 
     GList *sender_device_id = g_hash_table_lookup(omemo_ctx.device_list, jid->barejid);
@@ -552,13 +555,12 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean
     res = aes128gcm_encrypt(ciphertext, &ciphertext_len, tag, &tag_len, (const unsigned char * const)message, strlen(message), iv, key);
     if (res != 0) {
         log_error("OMEMO: cannot encrypt message");
-        return FALSE;
+        goto out;
     }
 
     memcpy(key_tag, key, AES128_GCM_KEY_LENGTH);
     memcpy(key_tag + AES128_GCM_KEY_LENGTH, tag, AES128_GCM_TAG_LENGTH);
 
-    GList *keys = NULL;
     GList *device_ids_iter;
     for (device_ids_iter = recipient_device_id; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) {
         int res;
@@ -623,7 +625,10 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean
     char *id = message_send_chat_omemo(chatwin->barejid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt);
     chat_log_omemo_msg_out(chatwin->barejid, message);
     chatwin_outgoing_msg(chatwin, message, id, PROF_MSG_OMEMO, request_receipt);
+    ret = TRUE;
 
+out:
+    jid_destroy(jid);
     free(id);
     g_list_free_full(keys, free);
     free(ciphertext);
@@ -632,14 +637,22 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean
     gcry_free(tag);
     gcry_free(key_tag);
 
-    return TRUE;
+    return ret;
 }
 
 char *
-omemo_on_message_recv(const char *const from, uint32_t sid,
+omemo_on_message_recv(const char *const from_jid, uint32_t sid,
     const unsigned char *const iv, size_t iv_len, GList *keys,
-    const unsigned char *const payload, size_t payload_len)
+    const unsigned char *const payload, size_t payload_len, gboolean muc)
 {
+    unsigned char *plaintext = NULL;
+    Jid *sender;
+    Jid *from = jid_create(from_jid);
+    if (!from) {
+        log_error("Invalid jid %s", from_jid);
+        goto out;
+    }
+
     int res;
     GList *key_iter;
     omemo_key_t *key = NULL;
@@ -652,21 +665,35 @@ omemo_on_message_recv(const char *const from, uint32_t sid,
 
     if (!key) {
         log_warning("OMEMO: Received a message with no corresponding key");
-        return NULL;
+        goto out;
+    }
+
+    if (muc) {
+        GList *roster = muc_roster(from->barejid);
+        GList *iter;
+        for (iter = roster; iter != NULL; iter = iter->next) {
+            Occupant *occupant = (Occupant *)iter->data;
+            if (g_strcmp0(occupant->nick, from->resourcepart) == 0) {
+                sender = jid_create(occupant->jid);
+                break;
+            }
+        }
+    } else {
+        sender = jid_create(from->barejid);
     }
 
     session_cipher *cipher;
     signal_buffer *plaintext_key;
     signal_protocol_address address = {
-        .name = from,
-        .name_len = strlen(from),
+        .name = sender->barejid,
+        .name_len = strlen(sender->barejid),
         .device_id = sid
     };
 
     res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal);
     if (res != 0) {
         log_error("OMEMO: cannot create session cipher");
-        return NULL;
+        goto out;
     }
 
     if (key->prekey) {
@@ -687,7 +714,7 @@ omemo_on_message_recv(const char *const from, uint32_t sid,
 
         if (res == 0) {
             /* Start a new session */
-            omemo_bundle_request(from, sid, omemo_start_device_session_handle_bundle, free, strdup(from));
+            omemo_bundle_request(sender->barejid, sid, omemo_start_device_session_handle_bundle, free, strdup(sender->barejid));
         }
     } else {
         log_debug("OMEMO: decrypting message with existing session");
@@ -707,7 +734,7 @@ omemo_on_message_recv(const char *const from, uint32_t sid,
     }
 
     size_t plaintext_len = payload_len;
-    unsigned char *plaintext = malloc(plaintext_len + 1);
+    plaintext = malloc(plaintext_len + 1);
     res = aes128gcm_decrypt(plaintext, &plaintext_len, payload, payload_len, iv,
         signal_buffer_data(plaintext_key),
         signal_buffer_data(plaintext_key) + AES128_GCM_KEY_LENGTH);
@@ -720,6 +747,9 @@ omemo_on_message_recv(const char *const from, uint32_t sid,
 
     plaintext[plaintext_len] = '\0';
 
+out:
+    jid_destroy(from);
+    jid_destroy(sender);
     return (char *)plaintext;
 }
 
diff --git a/src/omemo/omemo.h b/src/omemo/omemo.h
index 7f9b7992..3cf8ea52 100644
--- a/src/omemo/omemo.h
+++ b/src/omemo/omemo.h
@@ -40,4 +40,4 @@ void omemo_start_device_session(const char *const jid, uint32_t device_id, GList
 
 gboolean omemo_loaded(void);
 gboolean omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean request_receipt);
-char * omemo_on_message_recv(const char *const from, uint32_t sid, const unsigned char *const iv, size_t iv_len, GList *keys, const unsigned char *const payload, size_t payload_len);
+char * omemo_on_message_recv(const char *const from, uint32_t sid, const unsigned char *const iv, size_t iv_len, GList *keys, const unsigned char *const payload, size_t payload_len, gboolean muc);
diff --git a/src/ui/win_types.h b/src/ui/win_types.h
index 6fe2811a..498d9bbe 100644
--- a/src/ui/win_types.h
+++ b/src/ui/win_types.h
@@ -168,6 +168,7 @@ typedef struct prof_muc_win_t {
     gboolean unread_mentions;
     gboolean unread_triggers;
     gboolean showjid;
+    gboolean is_omemo;
     unsigned long memcheck;
     char *enctext;
     char *message_char;
diff --git a/src/xmpp/message.c b/src/xmpp/message.c
index 53190998..8fbaedd9 100644
--- a/src/xmpp/message.c
+++ b/src/xmpp/message.c
@@ -723,10 +723,16 @@ _handle_groupchat(xmpp_stanza_t *const stanza)
         return;
     }
 
-    message = xmpp_message_get_body(stanza);
+#ifdef HAVE_OMEMO
+    message = omemo_receive_message(stanza);
+#endif
+
     if (!message) {
-        jid_destroy(jid);
-        return;
+        message = xmpp_message_get_body(stanza);
+        if (!message) {
+            jid_destroy(jid);
+            return;
+        }
     }
 
     // determine if the notifications happened whilst offline
diff --git a/src/xmpp/omemo.c b/src/xmpp/omemo.c
index 0c033921..16610cb5 100644
--- a/src/xmpp/omemo.c
+++ b/src/xmpp/omemo.c
@@ -197,6 +197,8 @@ omemo_start_device_session_handle_bundle(xmpp_stanza_t *const stanza, void *cons
 char *
 omemo_receive_message(xmpp_stanza_t *const stanza)
 {
+    const char *type = xmpp_stanza_get_type(stanza);
+
     xmpp_stanza_t *encrypted = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_OMEMO);
     if (!encrypted) {
         return NULL;
@@ -264,11 +266,10 @@ skip:
     }
 
     const char *from = xmpp_stanza_get_from(stanza);
-    Jid *jid = jid_create(from);
-
-    char *plaintext = omemo_on_message_recv(jid->barejid, sid, iv_raw, iv_len, keys, payload_raw, payload_len);
 
-    jid_destroy(jid);
+    char *plaintext = omemo_on_message_recv(from, sid, iv_raw, iv_len,
+        keys, payload_raw, payload_len,
+        g_strcmp0(type, STANZA_TYPE_GROUPCHAT) == 0);
 
     return plaintext;
 }