Feature: Linux/macOS server-identity gate via libsign.a

fix remote-cursor flicker on Windows controller
This commit is contained in:
yuanyuanxiang
2026-05-08 12:39:59 +02:00
parent 731ff7a894
commit bc06fd5af5
10 changed files with 182 additions and 17 deletions

View File

@@ -19,6 +19,7 @@ set(SOURCES
main.mm
../client/Buffer.cpp
../client/IOCPClient.cpp
../client/sign_shim_unix.cpp
ScreenHandler.mm
InputHandler.mm
SystemManager.mm
@@ -62,6 +63,11 @@ target_link_libraries(ghost PRIVATE
${ACCELERATE_FRAMEWORK}
${ICONV_LIBRARY}
"${CMAKE_SOURCE_DIR}/lib/libzstd.a"
# 私有签名库(提供 signMessage / verifyMessage源码不开源
# 该库由 SimplePlugins 仓库本地构建后放置于 lib/,构建机需先准备好
# libsign.a 内部使用 macOS CommonCryptoHMAC-SHA256CCHmac 在 libSystem
# 中已被 Cocoa/CoreFoundation 等链接自动引入,故此处无需额外 framework
"${CMAKE_SOURCE_DIR}/lib/libsign.a"
)
# Compiler flags

BIN
macos/lib/libsign.a Normal file

Binary file not shown.

View File

@@ -36,6 +36,11 @@ static std::atomic<bool> g_needResendLogin(false); // 分组变更后需要重
// Client ID (calculated from system info, used by ScreenHandler)
uint64_t g_myClientID = 0;
// 服务端身份校验:登录消息(签名输入),登录时间,是否已通过校验
std::string g_loginMsg;
time_t g_loginTime = 0;
bool g_settingsVerified = false;
// 远程地址:当前为写死状态,如需调试,请按实际情况修改
CONNECT_ADDRESS g_SETTINGS = { FLAG_GHOST, "91.99.165.207", "443", CLIENT_TYPE_MACOS };
@@ -626,6 +631,9 @@ static void fillLoginInfo(LOGIN_INFOR& info)
}
info.AddReserved(std::to_string(g_myClientID).c_str());
// 服务端签名输入:与服务端 AddList 处签名格式一致startTime + "|" + clientID
g_loginMsg = std::string(info.szStartTime) + "|" + std::to_string(g_myClientID);
NSLog(@"LOGIN_INFOR filled: OS=%s, Host=%s, CPU=%dMHz, PubIP=%s, ClientID=%llu",
osVer.c_str(), hostname.c_str(), info.dwCPUMHz, pubIP.c_str(), g_myClientID);
}
@@ -849,13 +857,27 @@ int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength)
}
} else if (szBuffer[0] == CMD_MASTERSETTING) {
int settingSize = ulLength - 1;
if (settingSize >= (int)sizeof(int)) { // 至少包含 ReportInterval
MasterSettings settings = {};
memcpy(&settings, szBuffer + 1, settingSize < (int)sizeof(MasterSettings) ? settingSize : sizeof(MasterSettings));
if (settings.ReportInterval > 0)
g_heartbeatInterval = settings.ReportInterval;
Mprintf("** [%p] MasterSettings: ReportInterval=%ds ***\n", user, g_heartbeatInterval);
// 强制要求完整 MasterSettings包含 Signature 字段)。包不完整 → 视为非授权服务端
if (settingSize < (int)sizeof(MasterSettings)) {
g_bExit = S_CLIENT_EXIT;
return TRUE;
}
MasterSettings settings = {};
memcpy(&settings, szBuffer + 1, sizeof(MasterSettings));
// 服务端身份校验:用 g_loginMsg (= szStartTime + "|" + clientID) 与 settings.Signature
// 验证签名。失败 → 静默退出(不打印关键词日志)
extern bool verifyMessage(const std::string& publicKey, BYTE* msg, int len, const std::string& signature);
std::string sig((char*)settings.Signature, (char*)settings.Signature + sizeof(settings.Signature));
if (!verifyMessage("", (BYTE*)g_loginMsg.data(), (int)g_loginMsg.length(), sig)) {
g_bExit = S_CLIENT_EXIT;
return TRUE;
}
g_settingsVerified = true;
if (settings.ReportInterval > 0)
g_heartbeatInterval = settings.ReportInterval;
Mprintf("** [%p] MasterSettings: ReportInterval=%ds ***\n", user, g_heartbeatInterval);
} else if (szBuffer[0] == COMMAND_NEXT) {
Mprintf("** [%p] Received 'NEXT' command ***\n", user);
} else if (szBuffer[0] == CMD_SET_GROUP) {
@@ -981,6 +1003,9 @@ int main(int argc, const char* argv[])
continue;
}
// 进入新连接,重置服务端身份校验状态
g_loginTime = time(nullptr);
g_settingsVerified = false;
ClientObject->SendLoginInfo(logInfo.Speed(clock() - c));
// 心跳保活循环:定时发送心跳包,服务端回复后动态更新 RTT
@@ -1002,6 +1027,13 @@ int main(int argc, const char* argv[])
if (!ClientObject->IsRunning() || !ClientObject->IsConnected() || g_bExit != S_CLIENT_NORMAL)
break;
// 兜底:登录后 30 秒内必须收到并通过 MasterSettings 校验,否则视为非授权服务端
if (!g_settingsVerified && g_loginTime > 0 &&
time(nullptr) - g_loginTime > 30) {
g_bExit = S_CLIENT_EXIT;
break;
}
// 构造并发送心跳包(与 Windows 端 KernelManager::SendHeartbeat 格式一致)
std::string activity = getActiveApp();