From 006138172fc605390880a573a93ba6ca97a66d00 Mon Sep 17 00:00:00 2001 From: W11 Date: Wed, 23 Sep 2026 19:55:37 +0800 Subject: [PATCH] =?UTF-8?q?fix(remote):=20=E8=A1=A5=20ReadVncServerConfig?= =?UTF-8?q?=20=E6=BC=8F=E8=AF=BB=E7=9A=84=20LogLevel(=E8=AF=BB/=E5=86=99/?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BD=93=E4=B8=89=E5=A4=84=E5=9D=87=E8=BE=BE?= =?UTF-8?q?=2037=20=E9=A1=B9=E5=85=A8=E9=9B=86)+VncPasswordDecrypt=20?= =?UTF-8?q?=E7=9F=AD=E4=BA=8E=208=20=E5=AD=97=E8=8A=82=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E7=A9=BA=E4=B8=B2(=E5=BA=95=E5=B1=82=20DES?= =?UTF-8?q?=20=E6=8C=89=E5=89=8D=208=20=E5=AD=97=E8=8A=82=E5=88=87?= =?UTF-8?q?=E7=89=87,=20=E7=9F=AD=E8=BE=93=E5=85=A5=E5=BF=85=20panic);=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AD=97=E6=AE=B5=E6=95=B0=E9=94=81=E5=AE=9A?= =?UTF-8?q?=E4=B8=8E=E7=9F=AD=E5=AF=86=E6=96=87=E9=98=B2=E6=8A=A4=E5=8D=95?= =?UTF-8?q?=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- remote/remote_test.go | 24 +++++++++++++++++++++++- remote/vnc.go | 7 ++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/remote/remote_test.go b/remote/remote_test.go index daeffa1..9afa883 100644 --- a/remote/remote_test.go +++ b/remote/remote_test.go @@ -2,7 +2,10 @@ package remote -import "testing" +import ( + "reflect" + "testing" +) func TestGetServiceStatusNonExist(t *testing.T) { // 不存在的服务应返回错误(Radmin 服务普通机器上不会安装) @@ -91,3 +94,22 @@ func TestInstallVncServerMissingExe(t *testing.T) { t.Fatal("exe 不存在时应返回错误") } } + +// TestVncServerConfigFieldCount 锁定配置字段总数:必须与本机最新版 TightVNC(2.8.x) +// 注册表 SOFTWARE\TightVNC\Server 下的 37 个值一一对应。加/删字段前先核对注册表全集, +// 并同步检查 ReadVncServerConfig / WriteVncServerConfig 的逐项覆盖(此前曾漏 LogLevel 写、 +// ConnectToRdp 误读、LogLevel 漏读, 靠本测试与脚本对账拦截)。 +func TestVncServerConfigFieldCount(t *testing.T) { + if got := reflect.TypeOf(VncServerConfig{}).NumField(); got != 37 { + t.Errorf("VncServerConfig 字段数 = %d, want 37(最新版注册表全集)", got) + } +} + +// TestVncPasswordDecryptShortInput 短于 8 字节的密文(缺失/截断)必须返回空串而非 panic +func TestVncPasswordDecryptShortInput(t *testing.T) { + for _, data := range [][]byte{nil, {}, []byte("abc"), []byte("1234567")} { + if got := VncPasswordDecrypt(data); got != "" { + t.Errorf("VncPasswordDecrypt(len=%d) = %q, want 空串且不 panic", len(data), got) + } + } +} diff --git a/remote/vnc.go b/remote/vnc.go index eb100bf..7cea12f 100644 --- a/remote/vnc.go +++ b/remote/vnc.go @@ -40,6 +40,7 @@ func ReadVncServerConfig() (VncServerConfig, error) { config.RepeatControlAuthentication, _, _ = GetDwordValue(key, "RepeatControlAuthentication") config.LoopbackOnly, _, _ = GetDwordValue(key, "LoopbackOnly") config.AcceptHttpConnections, _, _ = GetDwordValue(key, "AcceptHttpConnections") + config.LogLevel, _, _ = GetDwordValue(key, "LogLevel") config.EnableFileTransfers, _, _ = GetDwordValue(key, "EnableFileTransfers") config.RemoveWallpaper, _, _ = GetDwordValue(key, "RemoveWallpaper") config.UseD3D, _, _ = GetDwordValue(key, "UseD3D") @@ -177,7 +178,11 @@ func VncPasswordCrypt(password string) []byte { return vncpasswd.Crypt(password) } -// VncPasswordDecrypt 解密 VNC 密码 +// VncPasswordDecrypt 解密 VNC 密码。密文恒为 8 字节(标准 VNC DES), +// 不足 8 字节(缺失/截断)直接返回空串——底层 DES 解密会按前 8 字节切片,短输入必 panic。 func VncPasswordDecrypt(data []byte) string { + if len(data) < 8 { + return "" + } return vncpasswd.Decrypt(data) }