From a3897abba1e093aeab2b46bccded87485e518bb1 Mon Sep 17 00:00:00 2001 From: Paul Fariello Date: Thu, 14 Mar 2019 22:05:47 +0220 Subject: [PATCH] Add MUC message decryption --- src/omemo/omemo.c | 58 +++++++++++++++++++++++++++++++++++----------- src/omemo/omemo.h | 2 +- src/ui/win_types.h | 1 + src/xmpp/message.c | 12 +++++++--- src/xmpp/omemo.c | 9 +++---- 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; }