|
|
|
|
@ -1159,21 +1159,17 @@ static void cs_handle_join_info_req(struct chat_sync* cs, uint64_t peer,
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
uint8_t my_update_sig[64] = {0}; uint64_t my_update_ts; |
|
|
|
|
{ |
|
|
|
|
char juser[256]; snprintf(juser, sizeof(juser), "{\"name\":\"%s\"}", cs->inst->name[0] ? cs->inst->name : ""); |
|
|
|
|
my_update_ts = (uint64_t)ntp_time_get_seconds(cs->inst); |
|
|
|
|
uint8_t umsg[256]; |
|
|
|
|
int ulen = member_sync_build_update_msg(my_join_sig, my_update_ts, juser, umsg, (int)sizeof(umsg)); |
|
|
|
|
if (ulen >= 0) cs_ed25519_sign(cs->inst->my_ed25519_privkey, umsg, (size_t)ulen, my_update_sig); |
|
|
|
|
char juser[MS_USERINFO_MAX + 1]; |
|
|
|
|
if (chat_core_get_my_profile(cs->inst, ch_id, juser, sizeof(juser), my_update_sig, &my_update_ts) < 0) { |
|
|
|
|
uint8_t err[1] = { CS_MSG_ERROR }; cs_send(cs, ch_id, peer, err, sizeof(err)); return; |
|
|
|
|
} |
|
|
|
|
uint64_t my_signed_by = 0; uint8_t my_signature[64] = {0}; |
|
|
|
|
topo_node_sqlite_member_get_sign(cs->inst->topo_sqlite_db, ch_id, myid, &my_signed_by, my_signature); |
|
|
|
|
|
|
|
|
|
/* 5. JOIN_INFO_RESP: инфо канала + мой мембер-рекорд */ |
|
|
|
|
char juser[256]; snprintf(juser, sizeof(juser), "{\"name\":\"%s\"}", cs->inst->name[0] ? cs->inst->name : ""); |
|
|
|
|
uint8_t il = (uint8_t)strlen(juser); |
|
|
|
|
size_t il = strlen(juser); |
|
|
|
|
|
|
|
|
|
uint8_t buf[1536]; size_t boff = 0; |
|
|
|
|
uint8_t buf[MS_USERINFO_MAX + 768]; size_t boff = 0; |
|
|
|
|
buf[boff++] = CS_MSG_JOIN_INFO_RESP; |
|
|
|
|
uint8_t cnl = (uint8_t)strlen(name); buf[boff++] = cnl; memcpy(buf + boff, name, cnl); boff += cnl; |
|
|
|
|
memcpy(buf + boff, &owner, 8); boff += 8; |
|
|
|
|
@ -1187,7 +1183,7 @@ static void cs_handle_join_info_req(struct chat_sync* cs, uint64_t peer,
|
|
|
|
|
memcpy(buf + boff, &my_join_ts, 8); boff += 8; |
|
|
|
|
memcpy(buf + boff, my_update_sig, 64); boff += 64; |
|
|
|
|
memcpy(buf + boff, &my_update_ts, 8); boff += 8; |
|
|
|
|
buf[boff++] = il; memcpy(buf + boff, juser, il); boff += il; |
|
|
|
|
buf[boff++] = (uint8_t)(il >> 8); buf[boff++] = (uint8_t)il; memcpy(buf + boff, juser, il); boff += il; |
|
|
|
|
memcpy(buf + boff, &my_signed_by, 8); boff += 8; |
|
|
|
|
memcpy(buf + boff, my_signature, 64); boff += 64; |
|
|
|
|
cs_send(cs, ch_id, peer, buf, boff); |
|
|
|
|
@ -1202,7 +1198,7 @@ static void cs_handle_join_info_resp(struct chat_sync* cs, uint64_t peer,
|
|
|
|
|
if (len < 1) { DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: JOIN_INFO_RESP too short len=%zu", CS_ID, len); return; } |
|
|
|
|
const uint8_t* p = pl; |
|
|
|
|
uint8_t cnl = *p++; |
|
|
|
|
if (cnl + 8 + 32 + 32 + 64 + 8 + 32 + 32 + 64 + 8 + 64 + 8 + 1 + 8 + 64 > len) { |
|
|
|
|
if (1 + cnl + 8 + 32 + 32 + 64 + 8 + 32 + 32 + 64 + 8 + 64 + 8 + 2 + 8 + 64 > len) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: JOIN_INFO_RESP truncated len=%zu", CS_ID, len); return; |
|
|
|
|
} |
|
|
|
|
char name[128]; size_t cn = cnl > 127 ? 127 : cnl; memcpy(name, p, cn); name[cn] = '\0'; p += cnl; |
|
|
|
|
@ -1218,9 +1214,13 @@ static void cs_handle_join_info_resp(struct chat_sync* cs, uint64_t peer,
|
|
|
|
|
uint64_t c_join_ts; memcpy(&c_join_ts, p, 8); p += 8; |
|
|
|
|
const uint8_t* c_update_sig = p; p += 64; |
|
|
|
|
uint64_t c_update_ts; memcpy(&c_update_ts, p, 8); p += 8; |
|
|
|
|
uint8_t c_uil = *p++; |
|
|
|
|
char c_userinfo[256] = ""; |
|
|
|
|
if (c_uil && p + c_uil <= pl + len) { size_t u = c_uil > 255 ? 255 : c_uil; memcpy(c_userinfo, p, u); c_userinfo[u] = '\0'; p += c_uil; } |
|
|
|
|
size_t c_uil = ((size_t)p[0] << 8) | p[1]; p += 2; |
|
|
|
|
char c_userinfo[MS_USERINFO_MAX + 1] = ""; |
|
|
|
|
if (c_uil > MS_USERINFO_MAX || (size_t)(pl + len - p) != c_uil + 8 + 64 || memchr(p, 0, c_uil)) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: JOIN_INFO_RESP invalid profile bytes=%zu remaining=%zu", CS_ID, c_uil, |
|
|
|
|
(size_t)(pl + len - p)); return; |
|
|
|
|
} |
|
|
|
|
memcpy(c_userinfo, p, c_uil); p += c_uil; |
|
|
|
|
uint64_t c_signed_by; memcpy(&c_signed_by, p, 8); p += 8; |
|
|
|
|
const uint8_t* c_signature = p; p += 64; |
|
|
|
|
|
|
|
|
|
@ -1274,11 +1274,12 @@ static void cs_handle_join_info_resp(struct chat_sync* cs, uint64_t peer,
|
|
|
|
|
cs_ed25519_sign(cs->inst->my_ed25519_privkey, msg, (size_t)mlen, join_sig); |
|
|
|
|
} |
|
|
|
|
uint8_t my_update_sig[64] = {0}; uint64_t my_update_ts; |
|
|
|
|
char own_info[MS_USERINFO_MAX + 1]; |
|
|
|
|
if (chat_core_name_userinfo(cs->inst->name, own_info, sizeof(own_info)) < 0) return; |
|
|
|
|
{ |
|
|
|
|
char juser[256]; snprintf(juser, sizeof(juser), "{\"name\":\"%s\"}", cs->inst->name[0] ? cs->inst->name : ""); |
|
|
|
|
my_update_ts = (uint64_t)ntp_time_get_seconds(cs->inst); |
|
|
|
|
uint8_t umsg[256]; |
|
|
|
|
int ulen = member_sync_build_update_msg(join_sig, my_update_ts, juser, umsg, (int)sizeof(umsg)); |
|
|
|
|
uint8_t umsg[MS_USERINFO_MAX + 73]; |
|
|
|
|
int ulen = member_sync_build_update_msg(join_sig, my_update_ts, own_info, umsg, (int)sizeof(umsg)); |
|
|
|
|
if (ulen >= 0) cs_ed25519_sign(cs->inst->my_ed25519_privkey, umsg, (size_t)ulen, my_update_sig); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1288,14 +1289,14 @@ static void cs_handle_join_info_resp(struct chat_sync* cs, uint64_t peer,
|
|
|
|
|
jm.node_id = myid; jm.x25519 = my_x25519; jm.ed25519 = cs->inst->my_ed25519_pubkey; |
|
|
|
|
jm.join_sig = join_sig; jm.join_ts = join_ts; |
|
|
|
|
jm.update_sig = my_update_sig; jm.update_ts = my_update_ts; |
|
|
|
|
snprintf(jm.userinfo, sizeof(jm.userinfo), "{\"name\":\"%s\"}", cs->inst->name[0] ? cs->inst->name : ""); |
|
|
|
|
snprintf(jm.userinfo, sizeof(jm.userinfo), "%s", own_info); |
|
|
|
|
|
|
|
|
|
uint8_t jm_buf[512]; size_t jm_len = 0; |
|
|
|
|
uint8_t jm_buf[MS_USERINFO_MAX + 256]; size_t jm_len = 0; |
|
|
|
|
if (chat_join_serialize_member(&jm, jm_buf, sizeof(jm_buf), &jm_len) != 0) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: JOIN_REQUEST serialize failed", CS_ID); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
uint8_t jbuf[520]; size_t joff = 0; |
|
|
|
|
uint8_t jbuf[MS_USERINFO_MAX + 265]; size_t joff = 0; |
|
|
|
|
jbuf[joff++] = CS_MSG_JOIN_REQUEST; |
|
|
|
|
memcpy(jbuf + joff, &cs->pending_join_key, 8); joff += 8; |
|
|
|
|
memcpy(jbuf + joff, jm_buf, jm_len); joff += jm_len; |
|
|
|
|
@ -1479,14 +1480,16 @@ static void cs_handle_channel_invite(struct chat_sync* cs, uint64_t peer,
|
|
|
|
|
const char* ch_id, const uint8_t* pl, size_t len) { |
|
|
|
|
DEBUG_TRACE(DEBUG_CATEGORY_MEMBER_SYNC, "%s: CHANNEL_INVITE ch=%s from=%016llx len=%zu", |
|
|
|
|
CS_ID, ch_id, (unsigned long long)peer, len); |
|
|
|
|
if (len < 1 + 8 + 32 + 32 + 64 + 1 + 64 + 8 + 1) { |
|
|
|
|
if (len < 1 + 8 + 32 + 32 + 64 + 1 + 64 + 8 + 2 + 8) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: CHANNEL_INVITE too short len=%zu peer=%016llx", CS_ID, len, (unsigned long long)peer); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
/* Same payload format as CHANNEL_INFO_RESP */ |
|
|
|
|
const uint8_t* p = pl; |
|
|
|
|
uint8_t nl = *p++; |
|
|
|
|
if (1 + nl + 8 + 32 + 32 + 64 + 1 + 64 + 8 + 1 > (int)len) { DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: CHANNEL_INVITE truncated", CS_ID); return; } |
|
|
|
|
if (nl >= 128 || 1 + nl + 8 + 32 + 32 + 64 + 1 + 64 + 8 + 2 + 8 > (int)len) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: CHANNEL_INVITE truncated or name too long", CS_ID); return; |
|
|
|
|
} |
|
|
|
|
char name[128]; memcpy(name, p, nl); name[nl] = '\0'; p += nl; |
|
|
|
|
uint64_t owner; memcpy(&owner, p, 8); p += 8; |
|
|
|
|
const uint8_t* x25519 = p; p += 32; |
|
|
|
|
@ -1497,9 +1500,16 @@ static void cs_handle_channel_invite(struct chat_sync* cs, uint64_t peer,
|
|
|
|
|
if (inv_flags & PEERS_FLAG_HAS_JOIN) { |
|
|
|
|
if (p + 72 > pl + len) { DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: CHANNEL_INVITE truncated at join_sig/ts from=%016llx", CS_ID, (unsigned long long)peer); return; } |
|
|
|
|
inviter_join_sig = p; p += 64; memcpy(&inviter_join_ts, p, 8); p += 8; } |
|
|
|
|
if ((size_t)(pl + len - p) < 64 + 8 + 2 + 8) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: CHANNEL_INVITE truncated profile header", CS_ID); return; |
|
|
|
|
} |
|
|
|
|
/* skip inviter_update_sig/ts/userinfo for now — verify channel sig only */ |
|
|
|
|
p += 64; uint64_t inviter_update_ts; memcpy(&inviter_update_ts, p, 8); p += 8; |
|
|
|
|
uint8_t userinfo_len = *p++; p += userinfo_len; |
|
|
|
|
size_t userinfo_len = ((size_t)p[0] << 8) | p[1]; p += 2; |
|
|
|
|
if (userinfo_len > MS_USERINFO_MAX || (size_t)(pl + len - p) != userinfo_len + 8 || memchr(p, 0, userinfo_len)) { |
|
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: CHANNEL_INVITE invalid profile bytes=%zu", CS_ID, userinfo_len); return; |
|
|
|
|
} |
|
|
|
|
p += userinfo_len; |
|
|
|
|
/* join-ключ (зарегистрирован инвайтером) — хвостовые 8 байт */ |
|
|
|
|
uint64_t join_key = 0; |
|
|
|
|
if (p + 8 > pl + len) { DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: CHANNEL_INVITE truncated (no join_key) from=%016llx", CS_ID, (unsigned long long)peer); return; } |
|
|
|
|
@ -1597,13 +1607,9 @@ static int cs_send_channel_invite(struct chat_sync* cs, struct UTUN_INSTANCE* in
|
|
|
|
|
uint8_t join_sig[64] = {0}; uint64_t join_ts = 0; |
|
|
|
|
{ sqlite3* vdb = inst->topo_sqlite_db; |
|
|
|
|
topo_node_sqlite_member_get_join(vdb, ch_id, inst->node_id, join_sig, &join_ts); } |
|
|
|
|
uint8_t upd_sig[64] = {0}; uint64_t upd_ts = (uint64_t)ntp_time_get_seconds(inst); |
|
|
|
|
{ |
|
|
|
|
char juser[256]; snprintf(juser, sizeof(juser), "{\"name\":\"%s\"}", inst->name[0] ? inst->name : ""); |
|
|
|
|
uint8_t umsg[256]; |
|
|
|
|
int ulen = member_sync_build_update_msg(join_sig, upd_ts, juser, umsg, (int)sizeof(umsg)); |
|
|
|
|
if (ulen >= 0) cs_ed25519_sign(inst->my_ed25519_privkey, umsg, (size_t)ulen, upd_sig); |
|
|
|
|
} |
|
|
|
|
uint8_t upd_sig[64] = {0}; uint64_t upd_ts; |
|
|
|
|
char juser[MS_USERINFO_MAX + 1]; |
|
|
|
|
if (chat_core_get_my_profile(inst, ch_id, juser, sizeof(juser), upd_sig, &upd_ts) < 0) return -1; |
|
|
|
|
/* join-ключ: генерируем и регистрируем локально (инвайтер == connection-узел),
|
|
|
|
|
чтобы джойнер смог пройти JOIN_INFO_REQ с валидным ключом. */ |
|
|
|
|
uint64_t join_key = 0; |
|
|
|
|
@ -1613,7 +1619,7 @@ static int cs_send_channel_invite(struct chat_sync* cs, struct UTUN_INSTANCE* in
|
|
|
|
|
} |
|
|
|
|
if (chat_join_store_local_key(inst, strtoull(ch_id, NULL, 10), join_key) != 0) return -1; |
|
|
|
|
|
|
|
|
|
uint8_t buf[1024]; size_t boff = 0; |
|
|
|
|
uint8_t buf[MS_USERINFO_MAX + 768]; size_t boff = 0; |
|
|
|
|
buf[boff++] = CS_MSG_CHANNEL_INVITE; |
|
|
|
|
uint8_t cnl = (uint8_t)strlen(ch_name); |
|
|
|
|
buf[boff++] = cnl; memcpy(buf + boff, ch_name, cnl); boff += cnl; |
|
|
|
|
@ -1629,9 +1635,8 @@ static int cs_send_channel_invite(struct chat_sync* cs, struct UTUN_INSTANCE* in
|
|
|
|
|
} |
|
|
|
|
memcpy(buf + boff, upd_sig, 64); boff += 64; |
|
|
|
|
memcpy(buf + boff, &upd_ts, 8); boff += 8; |
|
|
|
|
char juser[256]; snprintf(juser, sizeof(juser), "{\"name\":\"%s\"}", inst->name[0] ? inst->name : ""); |
|
|
|
|
uint8_t il = (uint8_t)strlen(juser); |
|
|
|
|
buf[boff++] = il; memcpy(buf + boff, juser, il); boff += il; |
|
|
|
|
size_t il = strlen(juser); |
|
|
|
|
buf[boff++] = (uint8_t)(il >> 8); buf[boff++] = (uint8_t)il; memcpy(buf + boff, juser, il); boff += il; |
|
|
|
|
memcpy(buf + boff, &join_key, 8); boff += 8; |
|
|
|
|
int rc = cs_send(cs, ch_id, target_node_id, buf, boff); |
|
|
|
|
DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: sent CHANNEL_INVITE to 0x%016llx ch=%s key=%016llx rc=%d", |
|
|
|
|
|