Browse Source

fix: WELCOME wire format — flags+update_sig parsing, peer_needed gap, invalid join_sig skip

topo_upd
Evgeny 2 months ago
parent
commit
586d46f1e6
  1. 4
      src/topo_node_sqlite.c
  2. 58
      tools/chatgui/transport/chat_sync.c

4
src/topo_node_sqlite.c

@ -431,7 +431,8 @@ int topo_node_sqlite_channel_peers_all(sqlite3* db, const char* channel_id,
}
sqlite3_finalize(ast);
size_t peer_needed = 8 + 32 + 32 + 1 + 64 + 8 + 64 + 8 + 1 + (size_t)nl + 1;
uint8_t flags = (join_sig && join_ts) ? PEERS_FLAG_HAS_JOIN : 0;
size_t peer_needed = 8 + 32 + 32 + 1 + (flags & PEERS_FLAG_HAS_JOIN ? 64+8 : 0) + 64 + 8 + 1 + (size_t)nl + 1;
size_t addr_sz = off - addr_start;
if (addr_cnt > 0) {
if (off + peer_needed > buf_sz) { sqlite3_finalize(stmt); return -2; }
@ -444,7 +445,6 @@ int topo_node_sqlite_channel_peers_all(sqlite3* db, const char* channel_id,
memcpy(buf + off, &node_id, 8); off += 8;
memcpy(buf + off, x25519, 32); off += 32;
memcpy(buf + off, ed_pub, 32); off += 32;
uint8_t flags = (join_sig && join_ts) ? PEERS_FLAG_HAS_JOIN : 0;
buf[off++] = flags;
if (flags & PEERS_FLAG_HAS_JOIN) {
memcpy(buf + off, join_sig, 64); off += 64;

58
tools/chatgui/transport/chat_sync.c

@ -1258,36 +1258,48 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer,
uint16_t pc; memcpy(&pc, p, 2); p += 2;
DEBUG_TRACE(DEBUG_CATEGORY_DB_SYNC, "%s: WELCOME ch=%s from=%016llx peers=%u", CS_ID, ch_id, (unsigned long long)peer, pc);
for (uint16_t i = 0; i < pc; i++) {
if ((size_t)(p - pl) + 8 + 32 + 32 + 64 + 8 + 1 + 1 > len) break;
if ((size_t)(p - pl) + 8 + 32 + 32 + 1 + 64 + 8 + 1 > len) break; /* min: id+x25519+ed+flags+update_sig(64+8)+nl+ac */
uint64_t node_id; memcpy(&node_id, p, 8); p += 8;
const uint8_t* x25519 = p; p += 32;
const uint8_t* ed_pub = p; p += 32;
const uint8_t* join_sig = p; p += 64;
uint64_t join_ts; memcpy(&join_ts, p, 8); p += 8;
uint8_t flags = *p++;
const uint8_t* join_sig = NULL; uint64_t join_ts = 0;
if (flags & PEERS_FLAG_HAS_JOIN) {
if (p + 64 + 8 > pl + len) break;
join_sig = p; p += 64;
memcpy(&join_ts, p, 8); p += 8;
}
const uint8_t* update_sig = p; p += 64;
uint64_t update_ts; memcpy(&update_ts, p, 8); p += 8;
(void)update_sig; (void)update_ts;
uint8_t nl = *p++;
char peer_name[256] = "";
if (nl && p + nl <= pl + len) { memcpy(peer_name, p, nl); peer_name[nl] = '\0'; p += nl; }
uint8_t ac = *p++;
/* verify join_sig — all fields present in WELCOME wire */
uint8_t vmsg[256]; size_t vlen = 0;
vlen += snprintf((char*)vmsg + vlen, sizeof(vmsg) - vlen, "%s", ch_id) + 1;
memcpy(vmsg + vlen, &node_id, 8); vlen += 8;
memcpy(vmsg + vlen, x25519, 32); vlen += 32;
{ const char* nm = peer_name[0] ? peer_name : "";
size_t nls = strlen(nm); memcpy(vmsg + vlen, nm, nls); vlen += nls; vmsg[vlen++] = '\0'; }
memcpy(vmsg + vlen, &join_ts, 8); vlen += 8;
{ EVP_PKEY* pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, ed_pub, 32);
if (pkey) {
EVP_MD_CTX* ver = EVP_MD_CTX_new();
if (ver) {
if (EVP_DigestVerifyInit(ver, NULL, NULL, NULL, pkey) != 1
|| EVP_DigestVerify(ver, join_sig, 64, vmsg, vlen) != 1)
DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: WELCOME invalid join_sig node=0x%016llx", CS_ID, (unsigned long long)node_id);
EVP_MD_CTX_free(ver);
/* verify join_sig if present */
if (join_sig) {
uint8_t vmsg[256]; size_t vlen = 0;
vlen += snprintf((char*)vmsg + vlen, sizeof(vmsg) - vlen, "%s", ch_id) + 1;
memcpy(vmsg + vlen, &node_id, 8); vlen += 8;
memcpy(vmsg + vlen, x25519, 32); vlen += 32;
{ const char* nm = peer_name[0] ? peer_name : "";
size_t nls = strlen(nm); memcpy(vmsg + vlen, nm, nls); vlen += nls; vmsg[vlen++] = '\0'; }
memcpy(vmsg + vlen, &join_ts, 8); vlen += 8;
EVP_PKEY* pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, ed_pub, 32);
if (pkey) {
EVP_MD_CTX* ver = EVP_MD_CTX_new();
if (ver) {
if (EVP_DigestVerifyInit(ver, NULL, NULL, NULL, pkey) != 1
|| EVP_DigestVerify(ver, join_sig, 64, vmsg, vlen) != 1) {
DEBUG_ERROR(DEBUG_CATEGORY_DB_SYNC, "%s: WELCOME invalid join_sig node=0x%016llx — skipping", CS_ID, (unsigned long long)node_id);
EVP_MD_CTX_free(ver); EVP_PKEY_free(pkey);
continue;
}
EVP_MD_CTX_free(ver);
}
EVP_PKEY_free(pkey);
}
EVP_PKEY_free(pkey);
}
}
int rc = topo_node_sqlite_member_put(db, ch_id, node_id, join_sig, join_ts, NULL, 0, x25519, ed_pub, peer_name, NULL);
@ -1323,8 +1335,8 @@ static void cs_handle_welcome(struct chat_sync* cs, uint64_t peer,
DEBUG_INFO(DEBUG_CATEGORY_DEBUG, "%s: [ADDR_SYNC] WELCOME INSERT v6 node=0x%016llx sock=%d port=%d",
CS_ID, (unsigned long long)node_id, sid, port);
}
member_sync_cancel(g_cs->inst, peer, ch_id);
member_sync_set_online(g_cs->inst, peer, 0);
member_sync_cancel(g_cs->inst, node_id, ch_id);
member_sync_set_online(g_cs->inst, node_id, 0);
}
cs_refresh_channels(cs);

Loading…
Cancel
Save