Bind encrypted manifests and request keys after verified download

This commit is contained in:
evgeny committed 2026-10-18 02:14:31 +02:00
1 parent 41696b7e0b
commit 61d1561612
1 file changed
+33 -1
+33 -1
View File
@@ -5,6 +5,7 @@
*/
#include "chat_core_priv.h"
#include "chat_attachment.h"
#include "chat_event.h"
#include "chat_feedback.h"
#include "chat_poll.h"
@@ -266,6 +267,15 @@ static void on_media_registered(void* arg, int err, const struct media_index_res
const char* filename = base ? base + 1 : mctx->media_dest;
char attrs[1100]; snprintf(attrs, sizeof(attrs), "{\"st\":\"fl\",\"fp\":\"%s\"}", filename);
if (!strcmp(mctx->content_type, ENCRYPTED_ATTACHMENT_TYPE)) {
uint8_t crypto_id[16], message_id[32];
if (chat_attachment_identity(full_data, full_data_len, crypto_id) ||
chat_message_id(db_sync_instance_group_id(si), ts, json_sig, message_id) ||
chat_attachment_bind(mctx->inst, mctx->channel_id, crypto_id, message_id, result->content_hash)) {
DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "encrypted media: cannot publish without bound author key ch=%s", mctx->channel_id);
u_free(sig_msg); u_free(json); u_free(full_data); media_submit_finish(mctx, 0); return;
}
}
int ret = db_sync_insert_signed(si, json, strlen(json), json_sig, 64, ts, attrs);
if (ret != 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "%s: media insert failed ret=%d", CC_ID, ret);
@@ -680,6 +690,11 @@ static void md_download_done_cb(void* arg, int err) {
struct md_done_ctx* ctx = (struct md_done_ctx*)arg;
struct chat_core_ctx* cc = CC(ctx->inst);
if (!err) {
if (!strcmp(ctx->content_type, ENCRYPTED_ATTACHMENT_TYPE)) {
uint8_t message[32];
if (!chat_message_id(strtoull(ctx->channel_id, NULL, 10), ctx->ts, ctx->author_sig, message))
chat_attachment_downloaded(ctx->inst, ctx->channel_id, message);
}
char attrs[1024];
snprintf(attrs, sizeof(attrs), "{\"st\":\"fl\",\"fp\":\"%s\"}", ctx->dest_relpath);
chat_core_update_local_attrs(ctx->inst, ctx->channel_id, ctx->ts, ctx->author_sig, attrs);
@@ -783,7 +798,7 @@ static void extract_base_filename(const char* body, char* out, size_t out_sz) {
/* Разбор тела "d" медиасообщения в media_index_result. Формат:
* <name>|<file_size>|<block_size>|<num_blocks>|<media_id_hex>|<content_hash_hex>|<id_hex>,<sig_hex>,...
* Выделяет result->block_ids/block_sigs (освобождать через media_index_result_free). */
static int chat_msg_parse_media_body(const char* body, struct media_index_result* result) {
int chat_msg_parse_media_body(const char* body, struct media_index_result* result) {
memset(result, 0, sizeof(*result));
if (!body) return -1;
const char* p = body;
@@ -917,6 +932,9 @@ void on_msg_inserted(struct DB_SYNC_INSTANCE* si, const uint8_t message_id[32],
struct chat_core_ctx* cc = CC(inst);
if (!cc) return;
char ch_id[32]; snprintf(ch_id, sizeof(ch_id), "%llu", (unsigned long long)db_sync_instance_group_id(si));
if (chat_attachment_observe(inst, ch_id, message_id, author, data, len)) {
DEBUG_WARN(DEBUG_CATEGORY_MEDIA, "encrypted media: invalid manifest ch=%s", ch_id); return;
}
chat_feedback_check_message(inst, ch_id, message_id);
uint8_t evt[73]; uint8_t cl = (uint8_t)strlen(ch_id); evt[0] = cl; memcpy(evt + 1, ch_id, cl);
memcpy(evt + 1 + cl, &author, 8);
@@ -1041,6 +1059,20 @@ void chat_core_attachment_download(struct UTUN_INSTANCE* inst, const char* chann
uint8_t author_sig[64]; memcpy(author_sig, sig_blob, 64);
sqlite3_finalize(st);
if (!strcmp(content_type, ENCRYPTED_ATTACHMENT_TYPE)) {
uint8_t message[32];
if (chat_message_id(strtoull(channel_id, NULL, 10), (uint64_t)db_ts, author_sig, message)) return;
chat_attachment_want(inst, channel_id, message);
sqlite3_stmt* encrypted = NULL;
if (sqlite3_prepare_v2(cc->db, "SELECT cipher_path FROM attachment_keys WHERE channel=? AND message_id=? AND downloaded=1",
-1, &encrypted, NULL) == SQLITE_OK) {
sqlite3_bind_text(encrypted, 1, channel_id, -1, SQLITE_STATIC); sqlite3_bind_blob(encrypted, 2, message, 32, SQLITE_STATIC);
int present = sqlite3_step(encrypted) == SQLITE_ROW && ma_file_size((const char*)sqlite3_column_text(encrypted, 0)) > 0;
sqlite3_finalize(encrypted);
if (present) { chat_attachment_downloaded(inst, channel_id, message); return; }
} else DEBUG_ERROR(DEBUG_CATEGORY_MEDIA, "encrypted media: local file lookup failed: %s", sqlite3_errmsg(cc->db));
}
/* сбрасываем пометку «файл есть»: файл мог быть вычищен кешем, а local_attrs ещё "fl".
по завершении md_download_done_cb снова запишет st=fl (успех) или st=er (ошибка). */
chat_core_update_local_attrs(inst, channel_id, (uint64_t)db_ts, author_sig, "{}");