fix(chat): verify incoming JOIN profiles before local insertion

This commit is contained in:
evgeny committed 2026-10-27 11:48:09 +01:00
1 parent 054ade0dcd
commit ce3287ac94
5 files changed
+89 -37

No files matched your search

+27 -2
View File
@@ -7,10 +7,11 @@
// Задача 2 (интеграция): два инстанса A(инвайтер) и C(connection) — регистрация join-ключа
// через etcp_router, после сходимости BGP lookup_inviter(C) == A.node_id.
//
// chat_core/chat_sync (глобальные синглтоны) НЕ используются: конфиг без секции [chatserver],
// Сервис chat_core/chat_sync не запускается: конфиг без секции [chatserver],
// member_sync/chat_join инициализируются вручную.
#include "chat_join.h"
#include "chat_event.h"
#include "../routing_layer/etcp_router.h"
#include "../routing_layer/route_crypto.h"
#include "../transport_layer/etcp_api.h"
@@ -31,6 +32,7 @@
#include "test_net.h"
#include <sqlite3.h>
#include <assert.h>
#define OPENSSL_API_COMPAT 0x10100000L
#include <openssl/evp.h>
#include <stdio.h>
@@ -58,6 +60,14 @@ static char g_tdir[256] = "/tmp/utun_cj_XXXXXX";
static char g_cfg[MAX_NODES][256];
static char g_db_dir[MAX_NODES][320];
static uint64_t g_group_id = 0;
static unsigned join_results;
static void check_join_event(struct UTUN_INSTANCE* inst, int type, const uint8_t* data, int len) {
(void)inst;
if (type != CHAT_EVT_CONNECT_RESULT) return;
uint64_t request; int32_t result;
assert(len == 28); memcpy(&request, data + 20, 8); memcpy(&result, data + 8, 4);
assert(request == 0 && result == 0); join_results++;
}
/* ── крипто-хелперы ── */
@@ -415,6 +425,7 @@ static void t_process_request(void) {
/* 1. валидный join_sig → мембер добавлен, signed_by=self, подпись валидна */
TEST("process_request: valid join_sig accepted"); {
chat_event_set_handler(inst, check_join_event);
struct joiner j; make_joiner(&j, ch_x_pub, ch_ed_pub);
uint8_t buf[512]; size_t len = 0;
serialize_member(j.node_id, j.x_pub, j.ed_pub, j.join_sig, j.join_ts, buf, sizeof(buf), &len);
@@ -427,8 +438,22 @@ static void t_process_request(void) {
rec.x25519 = j.x_pub; rec.signature = sig; rec.signed_by = sb;
int vs = (gs == 0) ? member_sync_verify_signature(db, CH_COMP, &rec) : -99;
if (in_ch == 1 && gs == 0 && sb == inst->node_id && vs == 1) OK();
if (in_ch == 1 && gs == 0 && sb == inst->node_id && vs == 1 && join_results == 1) OK();
else FAIL("in_ch=%d gs=%d sb=%016llx vs=%d", in_ch, gs, (unsigned long long)sb, vs);
chat_event_set_handler(inst, NULL);
}
TEST("process_request: signed profile accepted"); {
struct joiner j; make_joiner(&j, ch_x_pub, ch_ed_pub);
uint8_t update[64], message[MS_USERINFO_MAX + 73], buf[MS_USERINFO_MAX + 256]; size_t len;
struct join_member_data m = {.node_id = j.node_id, .x25519 = j.x_pub, .ed25519 = j.ed_pub,
.join_sig = j.join_sig, .join_ts = j.join_ts, .update_sig = update, .update_ts = 1};
strcpy(m.userinfo, "{\"name\":\"signed profile\"}");
int bytes = member_sync_build_update_msg(j.join_sig, m.update_ts, m.userinfo, message, sizeof(message));
assert(bytes > 0 && sc_ed25519_sign(j.ed_priv, message, (size_t)bytes, update) == SC_OK);
assert(!chat_join_serialize_member(&m, buf, sizeof(buf), &len));
chat_join_process_request(inst, group_id, j.node_id, JOIN_KEY, buf, len);
if (topo_node_sqlite_member_in_channel(db, CH_COMP, j.node_id)) OK(); else FAIL();
}
/* 2. невалидный join_sig → отклонён */