Fix: reissue client_id on clone collision and harden V1 file-transfer command
撞 ID 的克隆机(同镜像 MachineGuid 相同导致 client_id 相同)此前会被服务端暂存为 替补、永远无法转正,从而不显示在主机列表。现在服务端检测到「client_id 相同但主机名 不同」时,主动下发 COMMAND_REGEN_CLIENT_ID,客户端在旧 ID 基础上掺随机 UUID 重算后 重连,以新 ID 正常上线;触发条件仅看主机名,排除 IP 漂移与纯用户名变化,避免误伤 正常重连的机器。 同时加固 V1 服务端→客户端文件传输:COMMAND_GET_FILE 指令的一次性 md5 令牌绑定登记 时的客户端源 IP(PutCmd/PopCmd 均带 peerIP),防止异常客户端冒用;并对指令包增加边界 校验(len 与 NUL 结尾),杜绝无 NUL 包导致的越界读。 Co-Authored-By: deepseek-v4-pro
This commit is contained in:
1 parent
d3a339247b
commit
e6b4fe3a85
7 files changed
+96
-13
No files matched your search
@@ -43,18 +43,30 @@ typedef struct DllInfo {
|
||||
|
||||
typedef struct FileTransformCmd {
|
||||
CLock Lock;
|
||||
std::map<std::string, uint64_t> CmdTime;
|
||||
void PutCmd(const std::string& str)
|
||||
// md5 -> (目标客户端源 IP, 登记时间)。源 IP 绑定:只有与 PutCmd 登记时同源 IP 的
|
||||
// 子连接才能消费该 md5,防止异常客户端在别的 IP 上冒用文件传输指令。
|
||||
std::map<std::string, std::pair<std::string, uint64_t>> CmdInfo;
|
||||
void PutCmd(const std::string& str, const std::string& peerIP)
|
||||
{
|
||||
Lock.Lock();
|
||||
CmdTime[str] = time(0);
|
||||
CmdInfo[str] = std::make_pair(peerIP, (uint64_t)time(0));
|
||||
Lock.Unlock();
|
||||
}
|
||||
bool PopCmd(const std::string& str, int timeoutSec = 10)
|
||||
bool PopCmd(const std::string& str, const std::string& peerIP, int timeoutSec = 10)
|
||||
{
|
||||
Lock.Lock();
|
||||
bool valid = CmdTime.find(str) != CmdTime.end() && time(0) - CmdTime[str] < timeoutSec;
|
||||
CmdTime.erase(str);
|
||||
auto it = CmdInfo.find(str);
|
||||
if (it == CmdInfo.end()) {
|
||||
Lock.Unlock();
|
||||
return false;
|
||||
}
|
||||
uint64_t now = (uint64_t)time(0);
|
||||
bool expired = now - it->second.second >= (uint64_t)timeoutSec;
|
||||
bool matched = it->second.first == peerIP;
|
||||
// 过期或成功消费才删除;源 IP 不匹配(冒用)保留,让合法客户端在 TTL 内仍可取回。
|
||||
bool valid = !expired && matched;
|
||||
if (expired || valid)
|
||||
CmdInfo.erase(it);
|
||||
Lock.Unlock();
|
||||
return valid;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user