fix: WELCOME wire format — flags+update_sig parsing, peer_needed gap, invalid join_sig skip
This commit is contained in:
1 parent
39a376e255
commit
586d46f1e6
2 files changed
+37
-25
No files matched your search
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user