Accept subgroup messages and distinguish own device replicas
This commit is contained in:
1 parent
02087b1878
commit
7e508f720d
2 files changed
+33
-11
No files matched your search
+32
-10
@@ -542,7 +542,11 @@ int dm_accept_message(struct UTUN_INSTANCE* inst, const uint8_t* msg, size_t len
|
||||
return -1;
|
||||
}
|
||||
if (dm_verify_message(inst, inst->node_id, msg, len) != 0) return -1;
|
||||
int deleted = dm_history_deleted(inst, msg, len, 0, NULL);
|
||||
struct dm_message_view message;
|
||||
if (dm_message_parse(msg, len, &message)) return -1;
|
||||
int side = message.mode == DM_MODE_GROUPS ? dm_message_target(&message, inst->node_id, NULL, NULL) : 1;
|
||||
int dir = side == 0;
|
||||
int deleted = dm_history_deleted(inst, msg, len, dir, NULL);
|
||||
if (deleted < 0) return -1;
|
||||
uint64_t conv, seq, author;
|
||||
memcpy(&conv, msg, 8);
|
||||
@@ -558,38 +562,56 @@ int dm_accept_message(struct UTUN_INSTANCE* inst, const uint8_t* msg, size_t len
|
||||
if (created) {
|
||||
memset(&c, 0, sizeof(c));
|
||||
snprintf(c.conv_id, sizeof(c.conv_id), "%s", conv_id);
|
||||
c.mode = message.mode;
|
||||
c.peer_node_id = author;
|
||||
if (!dm_shared_group_id(dm, author, &c.group_id)) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_DM, "%s: unknown correspondent peer=%llu", DM_ID, (unsigned long long)author);
|
||||
return -1;
|
||||
}
|
||||
if (dm_node_pubkeys(dm, author, c.peer_x25519, c.peer_ed25519) != 0 ||
|
||||
if (c.mode == DM_MODE_GROUPS) {
|
||||
c.parties[0] = message.parties[side]; c.parties[1] = message.parties[1 - side];
|
||||
if (!side) {
|
||||
c.peer_node_id = 0;
|
||||
for (unsigned i = 0; i < message.target_count; i++) {
|
||||
struct dm_target target;
|
||||
if (dm_message_target_at(&message, i, &target)) return -1;
|
||||
if (target.side == 1) { c.peer_node_id = target.node; break; }
|
||||
}
|
||||
}
|
||||
memcpy(c.peer_x25519, c.parties[1].x, 32); memcpy(c.peer_ed25519, c.parties[1].ed, 32);
|
||||
uint8_t private_key[32];
|
||||
if (dm_party_private(inst, c.parties, private_key)) return -1;
|
||||
int error = dm_derive_content_key(private_key, c.parties[1].x, c.content_key);
|
||||
OPENSSL_cleanse(private_key, sizeof(private_key));
|
||||
if (error) return -1;
|
||||
} else if (dm_node_pubkeys(dm, author, c.peer_x25519, c.peer_ed25519) != 0 ||
|
||||
dm_derive_content_key(inst->my_keys.private_key, c.peer_x25519, c.content_key) != 0) return -1;
|
||||
char name[128] = {0};
|
||||
chat_core_get_node_name(inst, author, name, sizeof(name));
|
||||
chat_core_get_node_name(inst, c.peer_node_id, name, sizeof(name));
|
||||
dm_copy_peer_name(c.peer_name, name, strlen(name), conv_id);
|
||||
}
|
||||
if (c.peer_node_id != author) {
|
||||
if (c.mode != message.mode || (c.mode == DM_MODE_DEVICE && c.peer_node_id != author) ||
|
||||
(c.mode == DM_MODE_GROUPS && (!dm_party_equal(c.parties, message.parties + side) ||
|
||||
!dm_party_equal(c.parties + 1, message.parties + 1 - side)))) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: conversation author mismatch conv=%s", DM_ID, conv_id);
|
||||
return -1;
|
||||
}
|
||||
uint16_t enc_len;
|
||||
memcpy(&enc_len, msg + 33 + msg[32], 2);
|
||||
if (!dm_conv_active(dm, &c)) return -1;
|
||||
uint8_t nonce[DM_NONCE_SIZE], plain[DM_DATA_MAX + 1];
|
||||
size_t plain_len = 0;
|
||||
dm_build_nonce(conv, author, seq, nonce);
|
||||
if (media_ccm_decrypt(c.content_key, nonce, msg + 35 + msg[32], enc_len, plain, &plain_len) != 0) return -1;
|
||||
if (media_ccm_decrypt(c.content_key, nonce, message.ciphertext, message.ciphertext_size, plain, &plain_len) != 0) return -1;
|
||||
if (dm_message_media(msg, len)) {
|
||||
struct attachment_info info;
|
||||
if (attachment_decode(plain, plain_len, &info)) return -1;
|
||||
}
|
||||
if (dm_exec(dm, "BEGIN IMMEDIATE") != 0) return -1;
|
||||
int inserted = dm_store_message(dm, conv_id, 0, msg, len);
|
||||
if (seq > c.last_in_seq) c.last_in_seq = seq; /* Только статистика; не курсор dedup. */
|
||||
int inserted = dm_store_message(dm, conv_id, dir, msg, len);
|
||||
if (!dir && seq > c.last_in_seq) c.last_in_seq = seq; /* Только статистика; не курсор dedup. */
|
||||
uint64_t ts;
|
||||
memcpy(&ts, msg + 16, 8);
|
||||
if (ts > c.last_ts) c.last_ts = ts;
|
||||
if (inserted < 0 || dm_conv_save(dm, &c) != 0 || dm_media_track(inst, 0, msg, len) != 0 ||
|
||||
if (inserted < 0 || dm_conv_save(dm, &c) != 0 || dm_media_track(inst, dir, msg, len) != 0 ||
|
||||
(inserted && dm_history_show(inst, conv_id)) || dm_exec(dm, "COMMIT") != 0) {
|
||||
dm_exec(dm, "ROLLBACK");
|
||||
return -1;
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ int dm_history_init(struct UTUN_INSTANCE* inst) {
|
||||
const char* sql =
|
||||
"CREATE TABLE IF NOT EXISTS dm_history(conv_id TEXT PRIMARY KEY,generation INTEGER NOT NULL,hidden INTEGER NOT NULL);"
|
||||
"CREATE TABLE IF NOT EXISTS dm_deleted_messages(conv_id TEXT NOT NULL,dir INTEGER NOT NULL,seq INTEGER NOT NULL,"
|
||||
"body_hash BLOB NOT NULL,media_id BLOB,media_receipt BLOB,PRIMARY KEY(conv_id,dir,seq));"
|
||||
"author INTEGER NOT NULL,body_hash BLOB NOT NULL,media_id BLOB,media_receipt BLOB,PRIMARY KEY(conv_id,author,seq));"
|
||||
"CREATE TABLE IF NOT EXISTS dm_local_files(path TEXT PRIMARY KEY,conv_id TEXT NOT NULL,generation INTEGER NOT NULL,"
|
||||
"busy INTEGER NOT NULL DEFAULT 0,retry_at INTEGER NOT NULL DEFAULT 0);"
|
||||
"UPDATE dm_local_files SET busy=0;";
|
||||
|
||||
Reference in new issue
Block a user