|
|
|
|
@ -296,6 +296,16 @@ static int dm_build_body(struct dm_state* dm, const struct dm_conv* c, uint64_t
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint8_t ct_len = (uint8_t)strnlen(ct, 255); |
|
|
|
|
const uint8_t* media = NULL; |
|
|
|
|
if (!strcmp(ct, "file")) { |
|
|
|
|
if (data_len <= DM_MEDIA_DESC_SIZE) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: file message lacks descriptor/name", DM_ID); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
media = data; |
|
|
|
|
data += DM_MEDIA_DESC_SIZE; |
|
|
|
|
data_len -= DM_MEDIA_DESC_SIZE; |
|
|
|
|
} |
|
|
|
|
uint64_t conv_num = (uint64_t)strtoull(c->conv_id, NULL, 10); |
|
|
|
|
uint8_t nonce[DM_NONCE_SIZE]; |
|
|
|
|
dm_build_nonce(conv_num, dm->inst->node_id, seq, nonce); |
|
|
|
|
@ -311,7 +321,7 @@ static int dm_build_body(struct dm_state* dm, const struct dm_conv* c, uint64_t
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint64_t author = dm->inst->node_id; |
|
|
|
|
size_t body_len = DM_MSG_FIXED_HDR + ct_len + 2 + enc_len + DM_MSG_SIG_SIZE; |
|
|
|
|
size_t body_len = DM_MSG_FIXED_HDR + ct_len + 2 + enc_len + (media ? DM_MEDIA_DESC_SIZE : 0) + DM_MSG_SIG_SIZE; |
|
|
|
|
uint8_t* body = u_malloc(body_len); |
|
|
|
|
if (!body) { u_free(enc); return -1; } |
|
|
|
|
size_t off = 0; |
|
|
|
|
@ -324,6 +334,7 @@ static int dm_build_body(struct dm_state* dm, const struct dm_conv* c, uint64_t
|
|
|
|
|
uint16_t el = (uint16_t)enc_len; |
|
|
|
|
memcpy(body + off, &el, 2); off += 2; |
|
|
|
|
memcpy(body + off, enc, enc_len); off += enc_len; |
|
|
|
|
if (media) { memcpy(body + off, media, DM_MEDIA_DESC_SIZE); off += DM_MEDIA_DESC_SIZE; } |
|
|
|
|
/* подпись по всем полям до sig */ |
|
|
|
|
if (sc_ed25519_sign(dm->inst->my_ed25519_privkey, body, off, body + off) != SC_OK) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: message signing failed", DM_ID); |
|
|
|
|
@ -349,6 +360,12 @@ int dm_verify_message(struct UTUN_INSTANCE* inst, uint64_t recipient, const uint
|
|
|
|
|
memcpy(&author, msg + 24, 8); |
|
|
|
|
if (!recipient || !author || author == recipient || !seq || seq > INT64_MAX || |
|
|
|
|
conv != dm_derive_conv_id(author, recipient)) goto invalid; |
|
|
|
|
const uint8_t* media = dm_message_media(msg, len); |
|
|
|
|
if (media) { |
|
|
|
|
uint64_t size; |
|
|
|
|
memcpy(&size, media + 16, 8); |
|
|
|
|
if (size > DM_MEDIA_MAX_SIZE) goto invalid; |
|
|
|
|
} |
|
|
|
|
uint8_t x[32], ed[32]; |
|
|
|
|
if (dm_node_pubkeys(&view, author, x, ed) != 0 || |
|
|
|
|
sc_ed25519_verify(ed, msg, len - DM_MSG_SIG_SIZE, msg + len - DM_MSG_SIG_SIZE) != SC_OK) goto invalid; |
|
|
|
|
@ -453,7 +470,7 @@ int dm_accept_message(struct UTUN_INSTANCE* inst, const uint8_t* msg, size_t len
|
|
|
|
|
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_exec(dm, "COMMIT") != 0) { |
|
|
|
|
if (inserted < 0 || dm_conv_save(dm, &c) != 0 || dm_media_track(inst, 0, msg, len) != 0 || dm_exec(dm, "COMMIT") != 0) { |
|
|
|
|
dm_exec(dm, "ROLLBACK"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
@ -734,7 +751,8 @@ int dm_send(struct UTUN_INSTANCE* inst, const char* conv_id, const char* content
|
|
|
|
|
if (dm_exec(dm, "BEGIN IMMEDIATE") != 0) { u_free(body); return -1; } |
|
|
|
|
c.last_out_seq = seq; |
|
|
|
|
if (ts > c.last_ts) c.last_ts = ts; |
|
|
|
|
if (dm_store_message(dm, conv_id, 1, body, len) != 1 || dm_conv_save(dm, &c) != 0) goto rollback; |
|
|
|
|
if (dm_store_message(dm, conv_id, 1, body, len) != 1 || dm_conv_save(dm, &c) != 0 || |
|
|
|
|
dm_media_track(inst, 1, body, len) != 0) goto rollback; |
|
|
|
|
int rc = sqlite3_prepare_v2(dm->db, "INSERT INTO dm_outbox(conv_id,seq,body) VALUES(?,?,?)", -1, &st, NULL); |
|
|
|
|
if (rc == SQLITE_OK) { |
|
|
|
|
sqlite3_bind_text(st, 1, conv_id, -1, SQLITE_STATIC); |
|
|
|
|
|