merge/upstream-full #105

Manually merged
jabber.developer merged 407 commits from merge/upstream-full into master 2026-05-26 17:54:34 +00:00
323 changed files with 11640 additions and 31005 deletions
Showing only changes of commit 4d49c2b746 - Show all commits

View File

@@ -1014,13 +1014,21 @@ out:
char*
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, gboolean muc, gboolean* trusted)
const unsigned char* const payload, size_t payload_len, gboolean muc, gboolean* trusted, omemo_error_t* error)
{
unsigned char* plaintext = NULL;
auto_jid Jid* sender = NULL;
auto_jid Jid* from = jid_create(from_jid);
if (error) {
*error = OMEMO_ERR_NONE;
}
if (!from) {
log_error("[OMEMO][RECV] Invalid jid %s", from_jid);
if (error) {
*error = OMEMO_ERR_INVALID_JID;
}
return NULL;
}
@@ -1036,6 +1044,9 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid,
if (!key) {
log_warning("[OMEMO][RECV] received a message with no corresponding key");
if (error) {
*error = OMEMO_ERR_NO_KEY;
}
return NULL;
}
@@ -1052,6 +1063,9 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid,
g_list_free(roster);
if (!sender) {
log_warning("[OMEMO][RECV] cannot find MUC message sender fulljid");
if (error) {
*error = OMEMO_ERR_MUC_SENDER_NOT_FOUND;
}
return NULL;
}
} else {
@@ -1069,6 +1083,9 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid,
res = session_cipher_create(&cipher, omemo_ctx.store, &address, omemo_ctx.signal);
if (res != 0) {
log_error("[OMEMO][RECV] cannot create session cipher");
if (error) {
*error = OMEMO_ERR_NO_SESSION;
}
return NULL;
}
@@ -1127,13 +1144,23 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid,
session_cipher_free(cipher);
if (res != 0) {
log_error("[OMEMO][RECV] cannot decrypt message key");
log_error("[OMEMO][RECV] cannot decrypt message key: %d", res);
if (error) {
if (!*trusted) {
*error = OMEMO_ERR_NOT_TRUSTED;
} else {
*error = OMEMO_ERR_DECRYPT_FAILED;
}
}
return NULL;
}
if (signal_buffer_len(plaintext_key) != AES128_GCM_KEY_LENGTH + AES128_GCM_TAG_LENGTH) {
log_error("[OMEMO][RECV] invalid key length");
signal_buffer_free(plaintext_key);
if (error) {
*error = OMEMO_ERR_DECRYPT_FAILED;
}
return NULL;
}
@@ -1146,6 +1173,9 @@ omemo_on_message_recv(const char* const from_jid, uint32_t sid,
if (res != 0) {
log_error("[OMEMO][RECV] cannot decrypt message: %s", gcry_strerror(res));
free(plaintext);
if (error) {
*error = OMEMO_ERR_DECRYPT_FAILED;
}
return NULL;
}

View File

@@ -98,8 +98,9 @@ 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);
char* omemo_on_message_send(ProfWin* win, const char* const message, gboolean request_receipt, gboolean muc, const char* const replace_id);
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, gboolean* trusted);
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, gboolean* trusted, omemo_error_t* error);
char* omemo_encrypt_file(FILE* in, FILE* out, off_t file_size, int* gcry_res);
gcry_error_t omemo_decrypt_file(FILE* in, FILE* out, off_t file_size, const char* fragment);

View File

@@ -356,6 +356,7 @@ message_init(void)
ProfMessage* message = g_new0(ProfMessage, 1);
message->enc = PROF_MSG_ENC_NONE;
message->omemo_err = OMEMO_ERR_NONE;
message->trusted = true;
message->type = PROF_MSG_TYPE_UNINITIALIZED;
@@ -1110,8 +1111,29 @@ _handle_groupchat(xmpp_stanza_t* const stanza)
// check omemo encryption
#ifdef HAVE_OMEMO
message->plain = omemo_receive_message(stanza, &message->trusted);
if (message->plain != NULL) {
message->plain = omemo_receive_message(stanza, &message->trusted, &message->omemo_err);
if (message->omemo_err != OMEMO_ERR_NONE) {
message->enc = PROF_MSG_ENC_OMEMO;
if (message->plain == NULL) {
switch (message->omemo_err) {
case OMEMO_ERR_NO_KEY:
message->plain = g_strdup("OMEMO message received but no key for this device found.");
break;
case OMEMO_ERR_NOT_TRUSTED:
message->plain = g_strdup("OMEMO message received but sender identity is untrusted.");
break;
case OMEMO_ERR_NO_SESSION:
message->plain = g_strdup("OMEMO message received but no session found. Try '/omemo start'.");
break;
case OMEMO_ERR_DECRYPT_FAILED:
message->plain = g_strdup("OMEMO message received but decryption failed.");
break;
default:
message->plain = g_strdup("OMEMO message received but could not be decrypted.");
break;
}
}
} else if (message->plain != NULL) {
message->enc = PROF_MSG_ENC_OMEMO;
}
#endif
@@ -1270,8 +1292,29 @@ _handle_muc_private_message(xmpp_stanza_t* const stanza)
// check omemo encryption
#ifdef HAVE_OMEMO
message->plain = omemo_receive_message(stanza, &message->trusted);
if (message->plain != NULL) {
message->plain = omemo_receive_message(stanza, &message->trusted, &message->omemo_err);
if (message->omemo_err != OMEMO_ERR_NONE) {
message->enc = PROF_MSG_ENC_OMEMO;
if (message->plain == NULL) {
switch (message->omemo_err) {
case OMEMO_ERR_NO_KEY:
message->plain = g_strdup("OMEMO message received but no key for this device found.");
break;
case OMEMO_ERR_NOT_TRUSTED:
message->plain = g_strdup("OMEMO message received but sender identity is untrusted.");
break;
case OMEMO_ERR_NO_SESSION:
message->plain = g_strdup("OMEMO message received but no session found. Try '/omemo start'.");
break;
case OMEMO_ERR_DECRYPT_FAILED:
message->plain = g_strdup("OMEMO message received but decryption failed.");
break;
default:
message->plain = g_strdup("OMEMO message received but could not be decrypted.");
break;
}
}
} else if (message->plain != NULL) {
message->enc = PROF_MSG_ENC_OMEMO;
}
#endif
@@ -1437,8 +1480,29 @@ _handle_chat(xmpp_stanza_t* const stanza, gboolean is_mam, gboolean is_carbon, c
#ifdef HAVE_OMEMO
// check omemo encryption
message->plain = omemo_receive_message(stanza, &message->trusted);
if (message->plain != NULL) {
message->plain = omemo_receive_message(stanza, &message->trusted, &message->omemo_err);
if (message->omemo_err != OMEMO_ERR_NONE) {
message->enc = PROF_MSG_ENC_OMEMO;
if (message->plain == NULL) {
switch (message->omemo_err) {
case OMEMO_ERR_NO_KEY:
message->plain = g_strdup("OMEMO message received but no key for this device found.");
break;
case OMEMO_ERR_NOT_TRUSTED:
message->plain = g_strdup("OMEMO message received but sender identity is untrusted.");
break;
case OMEMO_ERR_NO_SESSION:
message->plain = g_strdup("OMEMO message received but no session found. Try '/omemo start'.");
break;
case OMEMO_ERR_DECRYPT_FAILED:
message->plain = g_strdup("OMEMO message received but decryption failed.");
break;
default:
message->plain = g_strdup("OMEMO message received but could not be decrypted.");
break;
}
}
} else if (message->plain != NULL) {
message->enc = PROF_MSG_ENC_OMEMO;
}
#endif

View File

@@ -350,7 +350,7 @@ out:
}
char*
omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted)
omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted, omemo_error_t* error)
{
char* plaintext = NULL;
const char* type = xmpp_stanza_get_type(stanza);
@@ -360,6 +360,10 @@ omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted)
char* iv_text = NULL;
char* payload_text = NULL;
if (error) {
*error = OMEMO_ERR_NONE;
}
xmpp_stanza_t* encrypted = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_OMEMO);
if (!encrypted) {
return NULL;
@@ -367,40 +371,64 @@ omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted)
xmpp_stanza_t* header = xmpp_stanza_get_child_by_name(encrypted, "header");
if (!header) {
if (error) {
*error = OMEMO_ERR_OTHER;
}
return NULL;
}
const char* sid_text = xmpp_stanza_get_attribute(header, "sid");
if (!sid_text) {
if (error) {
*error = OMEMO_ERR_OTHER;
}
return NULL;
}
uint32_t sid = strtoul(sid_text, NULL, 10);
xmpp_stanza_t* iv = xmpp_stanza_get_child_by_name(header, "iv");
if (!iv) {
if (error) {
*error = OMEMO_ERR_OTHER;
}
return NULL;
}
iv_text = xmpp_stanza_get_text(iv);
if (!iv_text) {
if (error) {
*error = OMEMO_ERR_OTHER;
}
return NULL;
}
size_t iv_len;
iv_raw = g_base64_decode(iv_text, &iv_len);
if (!iv_raw) {
if (error) {
*error = OMEMO_ERR_OTHER;
}
return NULL;
}
xmpp_stanza_t* payload = xmpp_stanza_get_child_by_name(encrypted, "payload");
if (!payload) {
if (error) {
*error = OMEMO_ERR_OTHER;
}
goto quit;
}
payload_text = xmpp_stanza_get_text(payload);
if (!payload_text) {
if (error) {
*error = OMEMO_ERR_OTHER;
}
goto quit;
}
size_t payload_len;
payload_raw = g_base64_decode(payload_text, &payload_len);
if (!payload_raw) {
if (error) {
*error = OMEMO_ERR_OTHER;
}
goto quit;
}
@@ -439,7 +467,7 @@ omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted)
plaintext = omemo_on_message_recv(from, sid, iv_raw, iv_len,
keys, payload_raw, payload_len,
g_strcmp0(type, STANZA_TYPE_GROUPCHAT) == 0, trusted);
g_strcmp0(type, STANZA_TYPE_GROUPCHAT) == 0, trusted, error);
if (keys) {
g_list_free_full(keys, (GDestroyNotify)omemo_key_free);

View File

@@ -44,4 +44,5 @@ void omemo_devicelist_request(const char* const jid);
void omemo_bundle_publish(gboolean first);
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);
char* omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted);
char* omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted, omemo_error_t* error);

View File

@@ -150,6 +150,17 @@ typedef enum {
PROF_MSG_TYPE_MUCPM
} prof_msg_type_t;
typedef enum {
OMEMO_ERR_NONE = 0,
OMEMO_ERR_NO_KEY,
OMEMO_ERR_NOT_TRUSTED,
OMEMO_ERR_NO_SESSION,
OMEMO_ERR_DECRYPT_FAILED,
OMEMO_ERR_INVALID_JID,
OMEMO_ERR_MUC_SENDER_NOT_FOUND,
OMEMO_ERR_OTHER
} omemo_error_t;
typedef struct prof_message_t
{
Jid* from_jid;
@@ -172,6 +183,7 @@ typedef struct prof_message_t
char* plain;
GDateTime* timestamp;
prof_enc_t enc;
omemo_error_t omemo_err;
gboolean trusted;
gboolean is_mam;
prof_msg_type_t type;

View File

@@ -129,6 +129,27 @@ omemo_encrypt_file(FILE* in, FILE* out, off_t file_size, int* gcry_res)
};
void omemo_free(void* a) {};
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, gboolean* trusted, omemo_error_t* error)
{
if (error) {
*error = OMEMO_ERR_NONE;
}
return NULL;
}
char*
omemo_receive_message(xmpp_stanza_t* const stanza, gboolean* trusted, omemo_error_t* error)
{
if (error) {
*error = OMEMO_ERR_NONE;
}
return NULL;
}
uint32_t
omemo_device_id()
{