Browse Source

Preserve complete signed profiles in channel bootstrap messages

master
evgeny 1 week ago
parent
commit
76c02012eb
  1. 73
      src/chat/chat_sync.c

73
src/chat/chat_sync.c

@ -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; uint8_t my_update_sig[64] = {0}; uint64_t my_update_ts;
{ char juser[MS_USERINFO_MAX + 1];
char juser[256]; snprintf(juser, sizeof(juser), "{\"name\":\"%s\"}", cs->inst->name[0] ? cs->inst->name : ""); if (chat_core_get_my_profile(cs->inst, ch_id, juser, sizeof(juser), my_update_sig, &my_update_ts) < 0) {
my_update_ts = (uint64_t)ntp_time_get_seconds(cs->inst); uint8_t err[1] = { CS_MSG_ERROR }; cs_send(cs, ch_id, peer, err, sizeof(err)); return;
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);
} }
uint64_t my_signed_by = 0; uint8_t my_signature[64] = {0}; 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); topo_node_sqlite_member_get_sign(cs->inst->topo_sqlite_db, ch_id, myid, &my_signed_by, my_signature);
/* 5. JOIN_INFO_RESP: инфо канала + мой мембер-рекорд */ /* 5. JOIN_INFO_RESP: инфо канала + мой мембер-рекорд */
char juser[256]; snprintf(juser, sizeof(juser), "{\"name\":\"%s\"}", cs->inst->name[0] ? cs->inst->name : ""); size_t il = strlen(juser);
uint8_t il = (uint8_t)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; buf[boff++] = CS_MSG_JOIN_INFO_RESP;
uint8_t cnl = (uint8_t)strlen(name); buf[boff++] = cnl; memcpy(buf + boff, name, cnl); boff += cnl; uint8_t cnl = (uint8_t)strlen(name); buf[boff++] = cnl; memcpy(buf + boff, name, cnl); boff += cnl;
memcpy(buf + boff, &owner, 8); boff += 8; 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_join_ts, 8); boff += 8;
memcpy(buf + boff, my_update_sig, 64); boff += 64; memcpy(buf + boff, my_update_sig, 64); boff += 64;
memcpy(buf + boff, &my_update_ts, 8); boff += 8; 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_signed_by, 8); boff += 8;
memcpy(buf + boff, my_signature, 64); boff += 64; memcpy(buf + boff, my_signature, 64); boff += 64;
cs_send(cs, ch_id, peer, buf, boff); 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; } 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; const uint8_t* p = pl;
uint8_t cnl = *p++; 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; 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; 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; uint64_t c_join_ts; memcpy(&c_join_ts, p, 8); p += 8;
const uint8_t* c_update_sig = p; p += 64; const uint8_t* c_update_sig = p; p += 64;
uint64_t c_update_ts; memcpy(&c_update_ts, p, 8); p += 8; uint64_t c_update_ts; memcpy(&c_update_ts, p, 8); p += 8;
uint8_t c_uil = *p++; size_t c_uil = ((size_t)p[0] << 8) | p[1]; p += 2;
char c_userinfo[256] = ""; char c_userinfo[MS_USERINFO_MAX + 1] = "";
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; } 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; uint64_t c_signed_by; memcpy(&c_signed_by, p, 8); p += 8;
const uint8_t* c_signature = p; p += 64; 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); 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; 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); my_update_ts = (uint64_t)ntp_time_get_seconds(cs->inst);
uint8_t umsg[256]; uint8_t umsg[MS_USERINFO_MAX + 73];
int ulen = member_sync_build_update_msg(join_sig, my_update_ts, juser, umsg, (int)sizeof(umsg)); 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); 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.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.join_sig = join_sig; jm.join_ts = join_ts;
jm.update_sig = my_update_sig; jm.update_ts = my_update_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) { 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); DEBUG_ERROR(DEBUG_CATEGORY_MEMBER_SYNC, "%s: JOIN_REQUEST serialize failed", CS_ID);
return; 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; jbuf[joff++] = CS_MSG_JOIN_REQUEST;
memcpy(jbuf + joff, &cs->pending_join_key, 8); joff += 8; memcpy(jbuf + joff, &cs->pending_join_key, 8); joff += 8;
memcpy(jbuf + joff, jm_buf, jm_len); joff += jm_len; 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) { 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", DEBUG_TRACE(DEBUG_CATEGORY_MEMBER_SYNC, "%s: CHANNEL_INVITE ch=%s from=%016llx len=%zu",
CS_ID, ch_id, (unsigned long long)peer, len); 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); DEBUG_WARN(DEBUG_CATEGORY_MEMBER_SYNC, "%s: CHANNEL_INVITE too short len=%zu peer=%016llx", CS_ID, len, (unsigned long long)peer);
return; return;
} }
/* Same payload format as CHANNEL_INFO_RESP */ /* Same payload format as CHANNEL_INFO_RESP */
const uint8_t* p = pl; const uint8_t* p = pl;
uint8_t nl = *p++; 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; char name[128]; memcpy(name, p, nl); name[nl] = '\0'; p += nl;
uint64_t owner; memcpy(&owner, p, 8); p += 8; uint64_t owner; memcpy(&owner, p, 8); p += 8;
const uint8_t* x25519 = p; p += 32; 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 (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; } 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; } 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 */ /* 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; 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 байт */ /* join-ключ (зарегистрирован инвайтером) — хвостовые 8 байт */
uint64_t join_key = 0; 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; } 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; uint8_t join_sig[64] = {0}; uint64_t join_ts = 0;
{ sqlite3* vdb = inst->topo_sqlite_db; { sqlite3* vdb = inst->topo_sqlite_db;
topo_node_sqlite_member_get_join(vdb, ch_id, inst->node_id, join_sig, &join_ts); } 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); uint8_t upd_sig[64] = {0}; uint64_t upd_ts;
{ char juser[MS_USERINFO_MAX + 1];
char juser[256]; snprintf(juser, sizeof(juser), "{\"name\":\"%s\"}", inst->name[0] ? inst->name : ""); if (chat_core_get_my_profile(inst, ch_id, juser, sizeof(juser), upd_sig, &upd_ts) < 0) return -1;
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);
}
/* join-ключ: генерируем и регистрируем локально (инвайтер == connection-узел), /* join-ключ: генерируем и регистрируем локально (инвайтер == connection-узел),
чтобы джойнер смог пройти JOIN_INFO_REQ с валидным ключом. */ чтобы джойнер смог пройти JOIN_INFO_REQ с валидным ключом. */
uint64_t join_key = 0; 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; 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; buf[boff++] = CS_MSG_CHANNEL_INVITE;
uint8_t cnl = (uint8_t)strlen(ch_name); uint8_t cnl = (uint8_t)strlen(ch_name);
buf[boff++] = cnl; memcpy(buf + boff, ch_name, cnl); boff += cnl; 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_sig, 64); boff += 64;
memcpy(buf + boff, &upd_ts, 8); boff += 8; memcpy(buf + boff, &upd_ts, 8); boff += 8;
char juser[256]; snprintf(juser, sizeof(juser), "{\"name\":\"%s\"}", inst->name[0] ? inst->name : ""); size_t il = strlen(juser);
uint8_t il = (uint8_t)strlen(juser); buf[boff++] = (uint8_t)(il >> 8); buf[boff++] = (uint8_t)il; memcpy(buf + boff, juser, il); boff += il;
buf[boff++] = il; memcpy(buf + boff, juser, il); boff += il;
memcpy(buf + boff, &join_key, 8); boff += 8; memcpy(buf + boff, &join_key, 8); boff += 8;
int rc = cs_send(cs, ch_id, target_node_id, buf, boff); 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", DEBUG_INFO(DEBUG_CATEGORY_MEMBER_SYNC, "%s: sent CHANNEL_INVITE to 0x%016llx ch=%s key=%016llx rc=%d",

Loading…
Cancel
Save