Follow normal workflow for OMEMO message reception
We try to decrypt all messages, if it's successful we use sv_ev_incoming_message even for OMEMO messages. We pass an OMEMO boolean to let UI be aware that message were encrypted.
This commit is contained in:
@@ -442,7 +442,7 @@ _sv_ev_incoming_plain(ProfChatWin *chatwin, gboolean new_win, char *barejid, cha
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sv_ev_incoming_message(char *barejid, char *resource, char *message, char *pgp_message, GDateTime *timestamp)
|
sv_ev_incoming_message(char *barejid, char *resource, char *message, char *pgp_message, GDateTime *timestamp, gboolean omemo)
|
||||||
{
|
{
|
||||||
gboolean new_win = FALSE;
|
gboolean new_win = FALSE;
|
||||||
ProfChatWin *chatwin = wins_get_chat(barejid);
|
ProfChatWin *chatwin = wins_get_chat(barejid);
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ void sv_ev_room_history(const char *const room_jid, const char *const nick,
|
|||||||
GDateTime *timestamp, const char *const message);
|
GDateTime *timestamp, const char *const message);
|
||||||
void sv_ev_room_message(const char *const room_jid, const char *const nick,
|
void sv_ev_room_message(const char *const room_jid, const char *const nick,
|
||||||
const char *const message);
|
const char *const message);
|
||||||
void sv_ev_incoming_message(char *barejid, char *resource, char *message, char *pgp_message, GDateTime *timestamp);
|
void sv_ev_incoming_message(char *barejid, char *resource, char *message, char *pgp_message, GDateTime *timestamp, gboolean omemo);
|
||||||
void sv_ev_incoming_private_message(const char *const fulljid, char *message);
|
void sv_ev_incoming_private_message(const char *const fulljid, char *message);
|
||||||
void sv_ev_delayed_private_message(const char *const fulljid, char *message, GDateTime *timestamp);
|
void sv_ev_delayed_private_message(const char *const fulljid, char *message, GDateTime *timestamp);
|
||||||
void sv_ev_typing(char *barejid, char *resource);
|
void sv_ev_typing(char *barejid, char *resource);
|
||||||
|
|||||||
@@ -473,7 +473,7 @@ api_settings_int_set(const char *const group, const char *const key, int value)
|
|||||||
void
|
void
|
||||||
api_incoming_message(const char *const barejid, const char *const resource, const char *const message)
|
api_incoming_message(const char *const barejid, const char *const resource, const char *const message)
|
||||||
{
|
{
|
||||||
sv_ev_incoming_message((char*)barejid, (char*)resource, (char*)message, NULL, NULL);
|
sv_ev_incoming_message((char*)barejid, (char*)resource, (char*)message, NULL, NULL, FALSE);
|
||||||
|
|
||||||
// TODO handle all states
|
// TODO handle all states
|
||||||
sv_ev_activity((char*)barejid, (char*)resource, FALSE);
|
sv_ev_activity((char*)barejid, (char*)resource, FALSE);
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
#include "xmpp/xmpp.h"
|
#include "xmpp/xmpp.h"
|
||||||
|
|
||||||
#ifdef HAVE_OMEMO
|
#ifdef HAVE_OMEMO
|
||||||
|
#include "xmpp/omemo.h"
|
||||||
#include "omemo/omemo.h"
|
#include "omemo/omemo.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -82,7 +83,6 @@ static void _handle_conference(xmpp_stanza_t *const stanza);
|
|||||||
static void _handle_captcha(xmpp_stanza_t *const stanza);
|
static void _handle_captcha(xmpp_stanza_t *const stanza);
|
||||||
static void _handle_receipt_received(xmpp_stanza_t *const stanza);
|
static void _handle_receipt_received(xmpp_stanza_t *const stanza);
|
||||||
static void _handle_chat(xmpp_stanza_t *const stanza);
|
static void _handle_chat(xmpp_stanza_t *const stanza);
|
||||||
static void _handle_omemo(xmpp_stanza_t *const stanza);
|
|
||||||
|
|
||||||
static void _send_message_stanza(xmpp_stanza_t *const stanza);
|
static void _send_message_stanza(xmpp_stanza_t *const stanza);
|
||||||
|
|
||||||
@@ -150,13 +150,6 @@ _message_handler(xmpp_conn_t *const conn, xmpp_stanza_t *const stanza, void *con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_OMEMO
|
|
||||||
xmpp_stanza_t *omemo = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_OMEMO);
|
|
||||||
if (omemo) {
|
|
||||||
_handle_omemo(stanza);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_handle_chat(stanza);
|
_handle_chat(stanza);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -327,7 +320,7 @@ message_send_chat_omemo(const char *const jid, uint32_t sid, GList *keys,
|
|||||||
const unsigned char *const ciphertext, size_t ciphertext_len,
|
const unsigned char *const ciphertext, size_t ciphertext_len,
|
||||||
gboolean request_receipt)
|
gboolean request_receipt)
|
||||||
{
|
{
|
||||||
char *state = chat_session_get_state(barejid);
|
char *state = chat_session_get_state(jid);
|
||||||
xmpp_ctx_t * const ctx = connection_get_ctx();
|
xmpp_ctx_t * const ctx = connection_get_ctx();
|
||||||
char *id = connection_create_stanza_id("msg");
|
char *id = connection_create_stanza_id("msg");
|
||||||
|
|
||||||
@@ -932,6 +925,7 @@ _handle_carbons(xmpp_stanza_t *const stanza)
|
|||||||
static void
|
static void
|
||||||
_handle_chat(xmpp_stanza_t *const stanza)
|
_handle_chat(xmpp_stanza_t *const stanza)
|
||||||
{
|
{
|
||||||
|
char *message = NULL;
|
||||||
// ignore if type not chat or absent
|
// ignore if type not chat or absent
|
||||||
const char *type = xmpp_stanza_get_type(stanza);
|
const char *type = xmpp_stanza_get_type(stanza);
|
||||||
if (!(g_strcmp0(type, "chat") == 0 || type == NULL)) {
|
if (!(g_strcmp0(type, "chat") == 0 || type == NULL)) {
|
||||||
@@ -944,11 +938,17 @@ _handle_chat(xmpp_stanza_t *const stanza)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check omemo encryption
|
||||||
|
gboolean omemo = FALSE;
|
||||||
|
#ifdef HAVE_OMEMO
|
||||||
|
message = omemo_receive_message(stanza);
|
||||||
|
omemo = message != NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
// ignore handled namespaces
|
// ignore handled namespaces
|
||||||
xmpp_stanza_t *conf = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE);
|
xmpp_stanza_t *conf = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CONFERENCE);
|
||||||
xmpp_stanza_t *captcha = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CAPTCHA);
|
xmpp_stanza_t *captcha = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_CAPTCHA);
|
||||||
xmpp_stanza_t *omemo = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_OMEMO);
|
if (conf || captcha) {
|
||||||
if (conf || captcha || omemo) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -974,19 +974,24 @@ _handle_chat(xmpp_stanza_t *const stanza)
|
|||||||
// standard chat message, use jid without resource
|
// standard chat message, use jid without resource
|
||||||
xmpp_ctx_t *ctx = connection_get_ctx();
|
xmpp_ctx_t *ctx = connection_get_ctx();
|
||||||
GDateTime *timestamp = stanza_get_delay(stanza);
|
GDateTime *timestamp = stanza_get_delay(stanza);
|
||||||
if (body) {
|
if (!message && body) {
|
||||||
char *message = xmpp_stanza_get_text(body);
|
message = xmpp_stanza_get_text(body);
|
||||||
if (message) {
|
}
|
||||||
char *enc_message = NULL;
|
|
||||||
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_ENCRYPTED);
|
|
||||||
if (x) {
|
|
||||||
enc_message = xmpp_stanza_get_text(x);
|
|
||||||
}
|
|
||||||
sv_ev_incoming_message(jid->barejid, jid->resourcepart, message, enc_message, timestamp);
|
|
||||||
xmpp_free(ctx, enc_message);
|
|
||||||
|
|
||||||
_receipt_request_handler(stanza);
|
if (message) {
|
||||||
|
char *enc_message = NULL;
|
||||||
|
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_ENCRYPTED);
|
||||||
|
if (x) {
|
||||||
|
enc_message = xmpp_stanza_get_text(x);
|
||||||
|
}
|
||||||
|
sv_ev_incoming_message(jid->barejid, jid->resourcepart, message, enc_message, timestamp, omemo);
|
||||||
|
xmpp_free(ctx, enc_message);
|
||||||
|
|
||||||
|
_receipt_request_handler(stanza);
|
||||||
|
|
||||||
|
if (omemo) {
|
||||||
|
free(message);
|
||||||
|
} else {
|
||||||
xmpp_free(ctx, message);
|
xmpp_free(ctx, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1016,100 +1021,6 @@ _handle_chat(xmpp_stanza_t *const stanza)
|
|||||||
jid_destroy(jid);
|
jid_destroy(jid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
_handle_omemo(xmpp_stanza_t *const stanza)
|
|
||||||
{
|
|
||||||
xmpp_stanza_t *encrypted = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_OMEMO);
|
|
||||||
if (!encrypted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
xmpp_stanza_t *header = xmpp_stanza_get_child_by_name(encrypted, "header");
|
|
||||||
if (!header) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *sid_text = xmpp_stanza_get_attribute(header, "sid");
|
|
||||||
if (!sid_text) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint32_t sid = strtoul(sid_text, NULL, 10);
|
|
||||||
|
|
||||||
xmpp_stanza_t *iv = xmpp_stanza_get_child_by_name(header, "iv");
|
|
||||||
if (!iv) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const char *iv_text = xmpp_stanza_get_text(iv);
|
|
||||||
if (!iv_text) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
size_t iv_len;
|
|
||||||
const unsigned char *iv_raw = g_base64_decode(iv_text, &iv_len);
|
|
||||||
|
|
||||||
xmpp_stanza_t *payload = xmpp_stanza_get_child_by_name(encrypted, "payload");
|
|
||||||
if (!payload) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const char *payload_text = xmpp_stanza_get_text(payload);
|
|
||||||
if (!payload_text) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
size_t payload_len;
|
|
||||||
const unsigned char *payload_raw = g_base64_decode(payload_text, &payload_len);
|
|
||||||
|
|
||||||
GList *keys = NULL;
|
|
||||||
xmpp_stanza_t *key_stanza;
|
|
||||||
for (key_stanza = xmpp_stanza_get_children(header); key_stanza != NULL; key_stanza = xmpp_stanza_get_next(key_stanza)) {
|
|
||||||
if (g_strcmp0(xmpp_stanza_get_name(key_stanza), "key") != 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
omemo_key_t *key = malloc(sizeof(omemo_key_t));
|
|
||||||
const char *key_text = xmpp_stanza_get_text(key_stanza);
|
|
||||||
if (!key_text) {
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char *rid_text = xmpp_stanza_get_attribute(key_stanza, "rid");
|
|
||||||
key->device_id = strtoul(rid_text, NULL, 10);
|
|
||||||
if (!key->device_id) {
|
|
||||||
goto skip;
|
|
||||||
}
|
|
||||||
key->data = g_base64_decode(key_text, &key->length);
|
|
||||||
key->prekey = g_strcmp0(xmpp_stanza_get_attribute(key_stanza, "prekey"), "true") == 0;
|
|
||||||
keys = g_list_append(keys, key);
|
|
||||||
continue;
|
|
||||||
|
|
||||||
skip:
|
|
||||||
free(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *from = xmpp_stanza_get_from(stanza);
|
|
||||||
Jid *jid = jid_create(from);
|
|
||||||
GDateTime *timestamp = stanza_get_delay(stanza);
|
|
||||||
|
|
||||||
char *plaintext = omemo_on_message_recv(jid->barejid, sid, iv_raw, iv_len, keys, payload_raw, payload_len);
|
|
||||||
if (!plaintext) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean new_win = FALSE;
|
|
||||||
ProfChatWin *chatwin = wins_get_chat(jid->barejid);
|
|
||||||
if (!chatwin) {
|
|
||||||
ProfWin *window = wins_new_chat(jid->barejid);
|
|
||||||
chatwin = (ProfChatWin*)window;
|
|
||||||
new_win = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
chat_log_omemo_msg_in(jid->barejid, plaintext, timestamp);
|
|
||||||
chatwin_incoming_msg(chatwin, jid->resourcepart, plaintext, timestamp, new_win, PROF_MSG_OMEMO);
|
|
||||||
|
|
||||||
out:
|
|
||||||
jid_destroy(jid);
|
|
||||||
if (timestamp) g_date_time_unref(timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_send_message_stanza(xmpp_stanza_t *const stanza)
|
_send_message_stanza(xmpp_stanza_t *const stanza)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -191,6 +191,85 @@ omemo_start_device_session_handle_bundle(xmpp_stanza_t *const stanza, void *cons
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
omemo_receive_message(xmpp_stanza_t *const stanza)
|
||||||
|
{
|
||||||
|
xmpp_stanza_t *encrypted = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_OMEMO);
|
||||||
|
if (!encrypted) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmpp_stanza_t *header = xmpp_stanza_get_child_by_name(encrypted, "header");
|
||||||
|
if (!header) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *sid_text = xmpp_stanza_get_attribute(header, "sid");
|
||||||
|
if (!sid_text) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
uint32_t sid = strtoul(sid_text, NULL, 10);
|
||||||
|
|
||||||
|
xmpp_stanza_t *iv = xmpp_stanza_get_child_by_name(header, "iv");
|
||||||
|
if (!iv) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const char *iv_text = xmpp_stanza_get_text(iv);
|
||||||
|
if (!iv_text) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
size_t iv_len;
|
||||||
|
const unsigned char *iv_raw = g_base64_decode(iv_text, &iv_len);
|
||||||
|
|
||||||
|
xmpp_stanza_t *payload = xmpp_stanza_get_child_by_name(encrypted, "payload");
|
||||||
|
if (!payload) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const char *payload_text = xmpp_stanza_get_text(payload);
|
||||||
|
if (!payload_text) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
size_t payload_len;
|
||||||
|
const unsigned char *payload_raw = g_base64_decode(payload_text, &payload_len);
|
||||||
|
|
||||||
|
GList *keys = NULL;
|
||||||
|
xmpp_stanza_t *key_stanza;
|
||||||
|
for (key_stanza = xmpp_stanza_get_children(header); key_stanza != NULL; key_stanza = xmpp_stanza_get_next(key_stanza)) {
|
||||||
|
if (g_strcmp0(xmpp_stanza_get_name(key_stanza), "key") != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
omemo_key_t *key = malloc(sizeof(omemo_key_t));
|
||||||
|
const char *key_text = xmpp_stanza_get_text(key_stanza);
|
||||||
|
if (!key_text) {
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *rid_text = xmpp_stanza_get_attribute(key_stanza, "rid");
|
||||||
|
key->device_id = strtoul(rid_text, NULL, 10);
|
||||||
|
if (!key->device_id) {
|
||||||
|
goto skip;
|
||||||
|
}
|
||||||
|
key->data = g_base64_decode(key_text, &key->length);
|
||||||
|
key->prekey = g_strcmp0(xmpp_stanza_get_attribute(key_stanza, "prekey"), "true") == 0;
|
||||||
|
keys = g_list_append(keys, key);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
skip:
|
||||||
|
free(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_omemo_receive_devicelist(xmpp_stanza_t *const stanza, void *const userdata)
|
_omemo_receive_devicelist(xmpp_stanza_t *const stanza, void *const userdata)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,3 +8,4 @@ void omemo_devicelist_request(const char * const jid);
|
|||||||
void omemo_bundle_publish(void);
|
void omemo_bundle_publish(void);
|
||||||
void omemo_bundle_request(const char * const jid, uint32_t device_id, ProfIqCallback func, ProfIqFreeCallback free_func, void *userdata);
|
void omemo_bundle_request(const char * const jid, uint32_t device_id, ProfIqCallback func, ProfIqFreeCallback free_func, void *userdata);
|
||||||
int omemo_start_device_session_handle_bundle(xmpp_stanza_t *const stanza, void *const userdata);
|
int omemo_start_device_session_handle_bundle(xmpp_stanza_t *const stanza, void *const userdata);
|
||||||
|
char * omemo_receive_message(xmpp_stanza_t *const stanza);
|
||||||
|
|||||||
Reference in New Issue
Block a user