Files
remote-core/remote/vnc.go
T

189 lines
6.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//go:build windows
package remote
import (
"fmt"
"os"
"github.com/KarpelesLab/vncpasswd"
"github.com/kardianos/service"
"golang.org/x/sys/windows/registry"
)
var VncService service.Service
// ReadVncServerConfig 从注册表读取 TightVNC 服务端配置(键值缺失按零值返回)
func ReadVncServerConfig() (VncServerConfig, error) {
var config VncServerConfig
key, err := registry.OpenKey(registry.LOCAL_MACHINE, "SOFTWARE\\TightVNC\\Server", registry.ALL_ACCESS)
if err != nil {
return config, err
}
defer key.Close()
config.ExtraPorts, _, _ = key.GetStringValue("ExtraPorts")
config.QueryTimeout, _, _ = GetDwordValue(key, "QueryTimeout")
config.QueryAcceptOnTimeout, _, _ = GetDwordValue(key, "QueryAcceptOnTimeout")
config.LocalInputPriorityTimeout, _, _ = GetDwordValue(key, "LocalInputPriorityTimeout")
config.LocalInputPriority, _, _ = GetDwordValue(key, "LocalInputPriority")
config.BlockRemoteInput, _, _ = GetDwordValue(key, "BlockRemoteInput")
config.BlockLocalInput, _, _ = GetDwordValue(key, "BlockLocalInput")
config.IpAccessControl, _, _ = key.GetStringValue("IpAccessControl")
config.RfbPort, _, _ = GetDwordValue(key, "RfbPort")
config.HttpPort, _, _ = GetDwordValue(key, "HttpPort")
config.DisconnectAction, _, _ = GetDwordValue(key, "DisconnectAction")
config.AcceptRfbConnections, _, _ = GetDwordValue(key, "AcceptRfbConnections")
config.UseVncAuthentication, _, _ = GetDwordValue(key, "UseVncAuthentication")
config.UseControlAuthentication, _, _ = GetDwordValue(key, "UseControlAuthentication")
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")
config.UseMirrorDriver, _, _ = GetDwordValue(key, "UseMirrorDriver")
config.EnableUrlParams, _, _ = GetDwordValue(key, "EnableUrlParams")
config.Password, _, _ = key.GetBinaryValue("Password")
config.AlwaysShared, _, _ = GetDwordValue(key, "AlwaysShared")
config.NeverShared, _, _ = GetDwordValue(key, "NeverShared")
config.DisconnectClients, _, _ = GetDwordValue(key, "DisconnectClients")
config.PollingInterval, _, _ = GetDwordValue(key, "PollingInterval")
config.AllowLoopback, _, _ = GetDwordValue(key, "AllowLoopback")
config.VideoRecognitionInterval, _, _ = GetDwordValue(key, "VideoRecognitionInterval")
config.GrabTransparentWindows, _, _ = GetDwordValue(key, "GrabTransparentWindows")
config.SaveLogToAllUsersPath, _, _ = GetDwordValue(key, "SaveLogToAllUsersPath")
config.RunControlInterface, _, _ = GetDwordValue(key, "RunControlInterface")
config.IdleTimeout, _, _ = GetDwordValue(key, "IdleTimeout")
config.VideoClasses, _, _ = key.GetStringValue("VideoClasses")
config.VideoRects, _, _ = key.GetStringValue("VideoRects")
config.ConnectToRdp, _, _ = GetDwordValue(key, "ConnectToRdp")
return config, nil
}
// GetDwordValue 读取 REG_DWORD 类型注册表值
func GetDwordValue(k registry.Key, name string) (val uint32, valtype uint32, err error) {
val64 := uint64(0)
val64, valtype, err = k.GetIntegerValue(name)
val = uint32(val64)
return
}
var vncSvcConfig = &service.Config{
Name: "tvnserver",
DisplayName: "TightVNC Server",
Description: "TightVNC Server (managed by remote-core)",
Arguments: []string{"-service"},
}
// InstallVncServer 绿色安装 TightVNC 服务端(需管理员权限)。
// 最新版注册表全集配置(VncClientDefaultConfig 37 项, 随机 8 位密码)→ 注册系统服务。
// 装而不启:服务注册后保持 Stopped, 等远程指令再 VncStart(避免常驻监听开端口);
// 若服务已在运行则重启以加载新配置。返回生成的明文密码(调用方自行上报/展示)。
func InstallVncServer(exePath string) (string, error) {
if finfo, err := os.Stat(exePath); err != nil || finfo.IsDir() {
return "", fmt.Errorf("tvnserver.exe 不存在: %s", exePath)
}
// 最新版 TightVNC 注册表配置全集(含随机密码)
config := VncClientDefaultConfig(true)
if err := WriteVncServerConfig(config); err != nil {
return "", err
}
// 注册系统服务:未安装→安装; 运行中→重启加载新配置; 已停止→保持
vncSvcConfig.Executable = exePath
if err := VncInit(); err != nil {
return "", err
}
status, err := VncService.Status()
switch {
case err != nil: // 未安装(kardianos 对未安装服务 Status 返回错误)
if err := VncInstall(); err != nil {
return "", err
}
case status == service.StatusRunning:
if err := VncRestart(); err != nil {
return "", err
}
}
return VncPasswordDecrypt(config.Password), nil
}
// VncInit 初始化 VNC 服务对象,VncInstall/VncStart 等操作前必须调用
func VncInit() error {
var err error
VncService, err = service.New(nil, vncSvcConfig)
if err != nil {
return err
}
return nil
}
// VncInstall 安装 TightVNC 服务
func VncInstall() error {
err := VncService.Install()
if err != nil {
return err
}
return nil
}
// VncUninstall 停止并卸载 TightVNC 服务
func VncUninstall() error {
_ = VncService.Stop()
err := VncService.Uninstall()
if err != nil {
return err
}
return nil
}
// VncStart 启动 TightVNC 服务
func VncStart() error {
err := VncService.Start()
if err != nil {
return err
}
return nil
}
// VncStop 停止 TightVNC 服务
func VncStop() error {
err := VncService.Stop()
if err != nil {
return err
}
return nil
}
// VncRestart 重启 TightVNC 服务
func VncRestart() error {
err := VncService.Stop()
if err != nil {
return err
}
err = VncService.Start()
if err != nil {
return err
}
return nil
}
// VncPasswordCrypt 加密 VNC 密码(TightVNC 注册表存储格式)
func VncPasswordCrypt(password string) []byte {
return vncpasswd.Crypt(password)
}
// VncPasswordDecrypt 解密 VNC 密码。密文恒为 8 字节(标准 VNC DES),
// 不足 8 字节(缺失/截断)直接返回空串——底层 DES 解密会按前 8 字节切片,短输入必 panic。
func VncPasswordDecrypt(data []byte) string {
if len(data) < 8 {
return ""
}
return vncpasswd.Decrypt(data)
}