mirror of
https://github.com/profanity-im/profanity.git
synced 2024-11-03 19:37:16 -05:00
Add support for sending encrypted message in MUC
This commit is contained in:
parent
f7ce1607f9
commit
a9d55dec92
@ -218,7 +218,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
|
||||
#ifndef HAVE_LIBGPGME
|
||||
#ifdef HAVE_OMEMO
|
||||
if (chatwin->is_omemo) {
|
||||
omemo_on_message_send(chatwin, plugin_msg, request_receipt);
|
||||
omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE);
|
||||
} else {
|
||||
char *id = message_send_chat(chatwin->barejid, plugin_msg, oob_url, request_receipt);
|
||||
chat_log_msg_out(chatwin->barejid, plugin_msg);
|
||||
@ -238,7 +238,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
|
||||
#ifndef HAVE_LIBGPGME
|
||||
#ifdef HAVE_OMEMO
|
||||
if (chatwin->is_omemo) {
|
||||
omemo_on_message_send(chatwin, plugin_msg, request_receipt);
|
||||
omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE);
|
||||
} else {
|
||||
gboolean handled = otr_on_message_send(chatwin, plugin_msg, request_receipt);
|
||||
if (!handled) {
|
||||
@ -261,7 +261,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
|
||||
#ifdef HAVE_LIBGPGME
|
||||
#ifdef HAVE_OMEMO
|
||||
if (chatwin->is_omemo) {
|
||||
omemo_on_message_send(chatwin, plugin_msg, request_receipt);
|
||||
omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE);
|
||||
} else if (chatwin->pgp_send) {
|
||||
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt);
|
||||
chat_log_pgp_msg_out(chatwin->barejid, plugin_msg);
|
||||
@ -286,7 +286,7 @@ cl_ev_send_msg(ProfChatWin *chatwin, const char *const msg, const char *const oo
|
||||
#ifdef HAVE_LIBGPGME
|
||||
#ifdef HAVE_OMEMO
|
||||
if (chatwin->is_omemo) {
|
||||
omemo_on_message_send(chatwin, plugin_msg, request_receipt);
|
||||
omemo_on_message_send((ProfWin *)chatwin, plugin_msg, request_receipt, FALSE);
|
||||
} else if (chatwin->pgp_send) {
|
||||
char *id = message_send_chat_pgp(chatwin->barejid, plugin_msg, request_receipt);
|
||||
chat_log_pgp_msg_out(chatwin->barejid, plugin_msg);
|
||||
@ -334,10 +334,25 @@ cl_ev_send_muc_msg(ProfMucWin *mucwin, const char *const msg, const char *const
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_OMEMO
|
||||
if (mucwin->is_omemo) {
|
||||
omemo_on_message_send((ProfWin *)mucwin, plugin_msg, FALSE, TRUE);
|
||||
} else {
|
||||
message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url);
|
||||
}
|
||||
|
||||
plugins_post_room_message_send(mucwin->roomjid, plugin_msg);
|
||||
free(plugin_msg);
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_OMEMO
|
||||
message_send_groupchat(mucwin->roomjid, plugin_msg, oob_url);
|
||||
|
||||
plugins_post_room_message_send(mucwin->roomjid, plugin_msg);
|
||||
free(plugin_msg);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <glib.h>
|
||||
#include <pthread.h>
|
||||
@ -168,6 +169,7 @@ omemo_init(void)
|
||||
void
|
||||
omemo_on_connect(ProfAccount *account)
|
||||
{
|
||||
GError *error = NULL;
|
||||
char *omemodir = files_get_data_path(DIR_OMEMO);
|
||||
GString *basedir = g_string_new(omemodir);
|
||||
free(omemodir);
|
||||
@ -194,18 +196,26 @@ omemo_on_connect(ProfAccount *account)
|
||||
}
|
||||
}
|
||||
|
||||
omemo_devicelist_subscribe();
|
||||
|
||||
omemo_ctx.identity_keyfile = g_key_file_new();
|
||||
if (g_key_file_load_from_file(omemo_ctx.identity_keyfile, omemo_ctx.identity_filename->str, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
|
||||
omemo_ctx.sessions_keyfile = g_key_file_new();
|
||||
|
||||
if (g_key_file_load_from_file(omemo_ctx.identity_keyfile, omemo_ctx.identity_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) {
|
||||
load_identity();
|
||||
omemo_generate_short_term_crypto_materials(account);
|
||||
} else if (error->code != G_FILE_ERROR_NOENT) {
|
||||
log_warning("OMEMO: error loading identity from: %s, %s", omemo_ctx.identity_filename->str, error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
omemo_ctx.sessions_keyfile = g_key_file_new();
|
||||
if (g_key_file_load_from_file(omemo_ctx.sessions_keyfile, omemo_ctx.sessions_filename->str, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
|
||||
error = NULL;
|
||||
if (g_key_file_load_from_file(omemo_ctx.sessions_keyfile, omemo_ctx.sessions_filename->str, G_KEY_FILE_KEEP_COMMENTS, &error)) {
|
||||
load_sessions();
|
||||
} else if (error->code != G_FILE_ERROR_NOENT) {
|
||||
log_warning("OMEMO: error loading sessions from: %s, %s", omemo_ctx.sessions_filename->str, error->message);
|
||||
}
|
||||
|
||||
omemo_devicelist_subscribe();
|
||||
}
|
||||
|
||||
void
|
||||
@ -533,22 +543,15 @@ out:
|
||||
}
|
||||
|
||||
gboolean
|
||||
omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean request_receipt)
|
||||
omemo_on_message_send(ProfWin *win, const char *const message, gboolean request_receipt, gboolean muc)
|
||||
{
|
||||
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) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
GList *sender_device_id = g_hash_table_lookup(omemo_ctx.device_list, jid->barejid);
|
||||
|
||||
/* TODO generate fresh AES-GCM materials */
|
||||
/* TODO encrypt message */
|
||||
unsigned char *key;
|
||||
unsigned char *iv;
|
||||
unsigned char *ciphertext;
|
||||
@ -574,37 +577,72 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean
|
||||
memcpy(key_tag, key, AES128_GCM_KEY_LENGTH);
|
||||
memcpy(key_tag + AES128_GCM_KEY_LENGTH, tag, AES128_GCM_TAG_LENGTH);
|
||||
|
||||
GList *device_ids_iter;
|
||||
for (device_ids_iter = recipient_device_id; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) {
|
||||
int res;
|
||||
ciphertext_message *ciphertext;
|
||||
session_cipher *cipher;
|
||||
signal_protocol_address address = {
|
||||
.name = chatwin->barejid,
|
||||
.name_len = strlen(chatwin->barejid),
|
||||
.device_id = GPOINTER_TO_INT(device_ids_iter->data)
|
||||
};
|
||||
|
||||
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);
|
||||
continue;
|
||||
GList *recipients = NULL;
|
||||
if (muc) {
|
||||
ProfMucWin *mucwin = (ProfMucWin *)win;
|
||||
assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
|
||||
GList *roster = muc_roster(mucwin->roomjid);
|
||||
GList *iter;
|
||||
for (iter = roster; iter != NULL; iter = iter->next) {
|
||||
Occupant *occupant = (Occupant *)iter->data;
|
||||
Jid *jid = jid_create(occupant->jid);
|
||||
if (!jid->barejid) {
|
||||
log_warning("OMEMO: missing barejid for MUC %s occupant %s", mucwin->roomjid, occupant->nick);
|
||||
} else {
|
||||
recipients = g_list_append(recipients, strdup(jid->barejid));
|
||||
}
|
||||
jid_destroy(jid);
|
||||
}
|
||||
|
||||
res = session_cipher_encrypt(cipher, key_tag, AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH, &ciphertext);
|
||||
if (res != 0) {
|
||||
log_error("OMEMO: cannot encrypt key for %s device id %d", address.name, address.device_id);
|
||||
continue;
|
||||
}
|
||||
signal_buffer *buffer = ciphertext_message_get_serialized(ciphertext);
|
||||
omemo_key_t *key = malloc(sizeof(omemo_key_t));
|
||||
key->data = signal_buffer_data(buffer);
|
||||
key->length = signal_buffer_len(buffer);
|
||||
key->device_id = GPOINTER_TO_INT(device_ids_iter->data);
|
||||
key->prekey = ciphertext_message_get_type(ciphertext) == CIPHERTEXT_PREKEY_TYPE;
|
||||
keys = g_list_append(keys, key);
|
||||
} else {
|
||||
ProfChatWin *chatwin = (ProfChatWin *)win;
|
||||
assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
|
||||
recipients = g_list_append(recipients, strdup(chatwin->barejid));
|
||||
}
|
||||
|
||||
GList *device_ids_iter;
|
||||
|
||||
GList *recipients_iter;
|
||||
for (recipients_iter = recipients; recipients_iter != NULL; recipients_iter = recipients_iter->next) {
|
||||
GList *recipient_device_id = NULL;
|
||||
recipient_device_id = g_hash_table_lookup(omemo_ctx.device_list, recipients_iter->data);
|
||||
if (!recipient_device_id) {
|
||||
log_warning("OMEMO: cannot find device ids for %s", recipients_iter->data);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (device_ids_iter = recipient_device_id; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) {
|
||||
int res;
|
||||
ciphertext_message *ciphertext;
|
||||
session_cipher *cipher;
|
||||
signal_protocol_address address = {
|
||||
.name = recipients_iter->data,
|
||||
.name_len = strlen(recipients_iter->data),
|
||||
.device_id = GPOINTER_TO_INT(device_ids_iter->data)
|
||||
};
|
||||
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
res = session_cipher_encrypt(cipher, key_tag, AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH, &ciphertext);
|
||||
if (res != 0) {
|
||||
log_error("OMEMO: cannot encrypt key for %s device id %d", address.name, address.device_id);
|
||||
continue;
|
||||
}
|
||||
signal_buffer *buffer = ciphertext_message_get_serialized(ciphertext);
|
||||
omemo_key_t *key = malloc(sizeof(omemo_key_t));
|
||||
key->data = signal_buffer_data(buffer);
|
||||
key->length = signal_buffer_len(buffer);
|
||||
key->device_id = GPOINTER_TO_INT(device_ids_iter->data);
|
||||
key->prekey = ciphertext_message_get_type(ciphertext) == CIPHERTEXT_PREKEY_TYPE;
|
||||
keys = g_list_append(keys, key);
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free_full(recipients, free);
|
||||
|
||||
for (device_ids_iter = sender_device_id; device_ids_iter != NULL; device_ids_iter = device_ids_iter->next) {
|
||||
int res;
|
||||
ciphertext_message *ciphertext;
|
||||
@ -635,14 +673,23 @@ omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean
|
||||
keys = g_list_append(keys, key);
|
||||
}
|
||||
|
||||
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);
|
||||
if (muc) {
|
||||
ProfMucWin *mucwin = (ProfMucWin *)win;
|
||||
assert(mucwin->memcheck == PROFMUCWIN_MEMCHECK);
|
||||
char *id = message_send_chat_omemo(mucwin->roomjid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, TRUE);
|
||||
free(id);
|
||||
} else {
|
||||
ProfChatWin *chatwin = (ProfChatWin *)win;
|
||||
assert(chatwin->memcheck == PROFCHATWIN_MEMCHECK);
|
||||
char *id = message_send_chat_omemo(chatwin->barejid, omemo_ctx.device_id, keys, iv, AES128_GCM_IV_LENGTH, ciphertext, ciphertext_len, request_receipt, FALSE);
|
||||
chat_log_omemo_msg_out(chatwin->barejid, message);
|
||||
chatwin_outgoing_msg(chatwin, message, id, PROF_MSG_OMEMO, request_receipt);
|
||||
free(id);
|
||||
}
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
jid_destroy(jid);
|
||||
free(id);
|
||||
g_list_free_full(keys, free);
|
||||
free(ciphertext);
|
||||
gcry_free(key);
|
||||
@ -659,7 +706,7 @@ omemo_on_message_recv(const char *const from_jid, uint32_t sid,
|
||||
const unsigned char *const payload, size_t payload_len, gboolean muc)
|
||||
{
|
||||
unsigned char *plaintext = NULL;
|
||||
Jid *sender;
|
||||
Jid *sender = NULL;
|
||||
Jid *from = jid_create(from_jid);
|
||||
if (!from) {
|
||||
log_error("Invalid jid %s", from_jid);
|
||||
|
@ -40,5 +40,5 @@ void omemo_start_muc_sessions(const char *const roomjid);
|
||||
void omemo_start_device_session(const char *const jid, uint32_t device_id, GList *prekeys, uint32_t signed_prekey_id, const unsigned char *const signed_prekey, size_t signed_prekey_len, const unsigned char *const signature, size_t signature_len, const unsigned char *const identity_key, size_t identity_key_len);
|
||||
|
||||
gboolean omemo_loaded(void);
|
||||
gboolean omemo_on_message_send(ProfChatWin *chatwin, const char *const message, gboolean request_receipt);
|
||||
gboolean omemo_on_message_send(ProfWin *win, const char *const message, gboolean request_receipt, gboolean muc);
|
||||
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);
|
||||
|
@ -318,13 +318,19 @@ char*
|
||||
message_send_chat_omemo(const char *const jid, uint32_t sid, GList *keys,
|
||||
const unsigned char *const iv, size_t iv_len,
|
||||
const unsigned char *const ciphertext, size_t ciphertext_len,
|
||||
gboolean request_receipt)
|
||||
gboolean request_receipt, gboolean muc)
|
||||
{
|
||||
char *state = chat_session_get_state(jid);
|
||||
xmpp_ctx_t * const ctx = connection_get_ctx();
|
||||
char *id = connection_create_stanza_id("msg");
|
||||
|
||||
xmpp_stanza_t *message = xmpp_message_new(ctx, STANZA_TYPE_CHAT, jid, id);
|
||||
char *id;
|
||||
xmpp_stanza_t *message;
|
||||
if (muc) {
|
||||
id = connection_create_stanza_id("muc");
|
||||
message = xmpp_message_new(ctx, STANZA_TYPE_GROUPCHAT, jid, id);
|
||||
} else {
|
||||
id = connection_create_stanza_id("msg");
|
||||
message = xmpp_message_new(ctx, STANZA_TYPE_CHAT, jid, id);
|
||||
}
|
||||
|
||||
xmpp_stanza_t *encrypted = xmpp_stanza_new(ctx);
|
||||
xmpp_stanza_set_name(encrypted, "encrypted");
|
||||
|
@ -140,7 +140,7 @@ char* message_send_chat(const char *const barejid, const char *const msg, const
|
||||
gboolean request_receipt);
|
||||
char* message_send_chat_otr(const char *const barejid, const char *const msg, gboolean request_receipt);
|
||||
char* message_send_chat_pgp(const char *const barejid, const char *const msg, gboolean request_receipt);
|
||||
char* message_send_chat_omemo(const char *const jid, uint32_t sid, GList *keys, const unsigned char *const iv, size_t iv_len, const unsigned char *const ciphertext, size_t ciphertext_len, gboolean request_receipt);
|
||||
char* message_send_chat_omemo(const char *const jid, uint32_t sid, GList *keys, const unsigned char *const iv, size_t iv_len, const unsigned char *const ciphertext, size_t ciphertext_len, gboolean request_receipt, gboolean muc);
|
||||
void message_send_private(const char *const fulljid, const char *const msg, const char *const oob_url);
|
||||
void message_send_groupchat(const char *const roomjid, const char *const msg, const char *const oob_url);
|
||||
void message_send_groupchat_subject(const char *const roomjid, const char *const subject);
|
||||
|
Loading…
Reference in New Issue
Block a user