Browse Source

Make feedback roots depend on signed state and validate rebuilt keys

master
evgeny 1 week ago
parent
commit
f6cc3b6e53
  1. 20
      src/chat/chat_feedback.c

20
src/chat/chat_feedback.c

@ -133,9 +133,6 @@ static int fb_author_key(struct UTUN_INSTANCE* inst, const char* channel, uint64
int chat_feedback_ensure_channel(struct UTUN_INSTANCE* inst, const char* channel) {
char table[40], sql[1024]; uint64_t id;
if (fb_table(inst, channel, table, &id) < 0) return -1;
if (topo_node_sqlite_channel_get(inst->topo_sqlite_db, channel, NULL, 0, NULL, NULL, NULL, NULL) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: unknown channel=%s", channel); return -1;
}
snprintf(sql, sizeof(sql), "CREATE TABLE IF NOT EXISTS %s("
"record_key BLOB PRIMARY KEY CHECK(length(record_key)=32),"
"bucket INTEGER NOT NULL,message_id BLOB NOT NULL CHECK(length(message_id)=32),"
@ -189,6 +186,8 @@ static int fb_apply_row(struct UTUN_INSTANCE* inst, const char* channel, const s
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: invalid signature ch=%s node=%016llx kind=%u ver=%llu",
channel, (unsigned long long)r->node_id, r->kind, (unsigned long long)r->ver); return -1;
}
char message_hex[65];
for (unsigned i = 0; i < 32; i++) snprintf(message_hex + 2 * i, 3, "%02x", r->message_id[i]);
struct chat_feedback_record old;
int found = chat_feedback_get(inst, channel, r->message_id, r->node_id, r->kind, &old);
if (found < 0) return -1;
@ -217,8 +216,8 @@ static int fb_apply_row(struct UTUN_INSTANCE* inst, const char* channel, const s
int rc = sqlite3_step(st); sqlite3_finalize(st);
if (rc != SQLITE_DONE) return fb_db_error(inst, channel, "put step");
if (merkle_sync_recompute_path(inst, MT_DATA_FEEDBACK, channel, fb_read64(record_key.bytes)) < 0) return -1;
DEBUG_DEBUG(DEBUG_CATEGORY_CHAT_SYNC, "feedback: applied ch=%s node=%016llx kind=%u ver=%llu previous=%llu bytes=%u",
channel, (unsigned long long)r->node_id, r->kind, (unsigned long long)r->ver,
DEBUG_DEBUG(DEBUG_CATEGORY_CHAT_SYNC, "feedback: applied ch=%s message=%s node=%016llx kind=%u ver=%llu previous=%llu bytes=%u",
channel, message_hex, (unsigned long long)r->node_id, r->kind, (unsigned long long)r->ver,
(unsigned long long)(found ? old.ver : 0), r->data_len); return 1;
}
@ -313,7 +312,7 @@ static int fb_page(void* ctx, const char* channel, uint64_t prefix, int av, cons
sqlite3_finalize(st); data[0] = count >> 8; data[1] = count & 255; *len = off; return result;
}
/* Хеширует подписанные записи листа в том же порядке, что и страничный обход. */
/* Хеширует подписанные тела: разные валидные подписи одного тела не меняют корень. */
static int fb_hash(void* ctx, const char* channel, uint8_t level, uint64_t prefix, EVP_MD_CTX* hash) {
struct UTUN_INSTANCE* inst = ctx; char table[40], sql[256];
if (fb_table(inst, channel, table, NULL) < 0 || level != MT_MAX_LEVEL) {
@ -328,7 +327,7 @@ static int fb_hash(void* ctx, const char* channel, uint8_t level, uint64_t prefi
struct chat_feedback_record r; uint8_t wire[FB_WIRE_MAX];
if (fb_read_row(st, &r) < 0) { count = -1; break; }
int bytes = fb_encode(&r, wire);
if (bytes < 0 || EVP_DigestUpdate(hash, wire, bytes) != 1) {
if (bytes < 0 || EVP_DigestUpdate(hash, wire, bytes - 64) != 1) {
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: leaf digest failed ch=%s", channel); count = -1; break;
}
count++;
@ -397,7 +396,7 @@ int chat_feedback_init(struct UTUN_INSTANCE* inst) {
char channel[21]; snprintf(channel, sizeof(channel), "%s", sqlite3_column_text(channels, 0));
char table[40], sql[256];
if (chat_feedback_ensure_channel(inst, channel) < 0 || fb_table(inst, channel, table, NULL) < 0) { result = -1; break; }
snprintf(sql, sizeof(sql), "SELECT message_id,node_id,kind,ver,data,signature FROM %s", table);
snprintf(sql, sizeof(sql), "SELECT message_id,node_id,kind,ver,data,signature,record_key,bucket FROM %s", table);
sqlite3_stmt* st = NULL;
if (sqlite3_prepare_v2(inst->topo_sqlite_db, sql, -1, &st, NULL) != SQLITE_OK) {
result = fb_db_error(inst, channel, "init records"); break;
@ -413,6 +412,11 @@ int chat_feedback_init(struct UTUN_INSTANCE* inst) {
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: rebuild failed ch=%s node=%016llx",
channel, (unsigned long long)r.node_id); result = -1; break;
}
if (sqlite3_column_bytes(st, 6) != 32 || memcmp(record_key.bytes, sqlite3_column_blob(st, 6), 32)
|| (uint64_t)sqlite3_column_int64(st, 7) != (fb_read64(record_key.bytes) >> 39)) {
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "feedback: corrupt local index ch=%s node=%016llx",
channel, (unsigned long long)r.node_id); result = -1; break;
}
records++;
}
sqlite3_finalize(st);

Loading…
Cancel
Save