Files
Local-Cursor/internal/cursor/windows_cert.go
FuDie0915 db73cf5a39 chore: import Local-Cursor v1.1.8 source snapshot
Includes the current working directory changes. Historical commits and release binaries are excluded to limit Gitea storage.
Source base: d7515973fbfd6dd2001fa156c483455b8081c7cb
2026-11-10 01:24:28 +08:00

163 lines
4.9 KiB
Go
Raw Permalink 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 cursor
import (
"crypto/sha1"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"os/exec"
"strings"
"syscall"
"cursor/internal/logger"
)
const (
windowsRootStoreName = "Root"
windowsCertutilExe = "certutil.exe"
windowsPowerShellExe = "powershell.exe"
windowsUserCancelCode = 1223
)
// getCertThumbprint 获取证书的SHA1指纹,用于唯一标识证书
func getCertThumbprint(certPEM []byte) (string, error) {
block, _ := pem.Decode(certPEM)
if block == nil {
return "", fmt.Errorf("无法解析证书 PEM")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return "", fmt.Errorf("解析证书失败: %w", err)
}
// SHA1 指纹,certutil 使用此格式
thumbprint := fmt.Sprintf("%X", sha1.Sum(cert.Raw))
return thumbprint, nil
}
// hideWindow 返回隐藏命令行窗口的 SysProcAttr
func hideWindow() *syscall.SysProcAttr {
return &syscall.SysProcAttr{
HideWindow: true,
}
}
// isCACertInstalled 检查 CA 证书是否已安装到 Windows 系统根证书存储。
// 默认不带 -user,表示 LocalMachine\Root。
func isCACertInstalled(certPEM []byte) (bool, error) {
thumbprint, err := getCertThumbprint(certPEM)
if err != nil {
return false, fmt.Errorf("获取证书指纹失败: %w", err)
}
cmd := exec.Command(windowsCertutilExe, "-verifystore", windowsRootStoreName, thumbprint)
cmd.SysProcAttr = hideWindow()
output, err := cmd.CombinedOutput()
if err != nil {
var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
// certutil 在找不到证书时返回非零退出码。
logger.Infof("isCACertInstalled: cert not found in system store, thumbprint=%s exitCode=%d", thumbprint, exitErr.ExitCode())
return false, nil
}
return false, fmt.Errorf("执行 certutil 检查系统证书存储失败: %w", err)
}
outStr := strings.ToUpper(string(output))
if strings.Contains(outStr, thumbprint) {
logger.Infof("isCACertInstalled: cert found in system store, thumbprint=%s", thumbprint)
return true, nil
}
// 某些 Windows 语言环境下 certutil 的文本不同,这里仍然按未找到处理。
logger.Infof("isCACertInstalled: cert not found in certutil output, thumbprint=%s", thumbprint)
return false, nil
}
func quotePowerShellLiteral(value string) string {
return "'" + strings.ReplaceAll(value, "'", "''") + "'"
}
func runElevatedCertutil(args ...string) error {
quotedArgs := make([]string, 0, len(args))
for _, arg := range args {
quotedArgs = append(quotedArgs, quotePowerShellLiteral(arg))
}
script := fmt.Sprintf(
"$process = Start-Process -FilePath %s -ArgumentList @(%s) -Verb RunAs -WindowStyle Hidden -Wait -PassThru; exit $process.ExitCode",
quotePowerShellLiteral(windowsCertutilExe),
strings.Join(quotedArgs, ","),
)
cmd := exec.Command(
windowsPowerShellExe,
"-NoProfile",
"-NonInteractive",
"-ExecutionPolicy",
"Bypass",
"-Command",
script,
)
cmd.SysProcAttr = hideWindow()
output, err := cmd.CombinedOutput()
if err == nil {
return nil
}
var exitErr *exec.ExitError
if errors.As(err, &exitErr) && exitErr.ExitCode() == windowsUserCancelCode {
return fmt.Errorf("用户取消了管理员权限授予")
}
trimmedOutput := strings.TrimSpace(string(output))
if trimmedOutput == "" {
return fmt.Errorf("通过管理员权限执行 certutil 失败: %w", err)
}
return fmt.Errorf("通过管理员权限执行 certutil 失败: %w, output: %s", err, trimmedOutput)
}
// installCACertToWindowsStore 将 CA 证书安装到 Windows 系统根证书存储。
// LocalMachine\Root 需要管理员权限,因此这里会触发 UAC 提权。
func installCACertToWindowsStore(certPEM []byte, certPath string) error {
thumbprint, err := getCertThumbprint(certPEM)
if err != nil {
return fmt.Errorf("获取证书指纹失败: %w", err)
}
logger.Infof("installCACertToWindowsStore: installing cert into system store, path=%s thumbprint=%s", certPath, thumbprint)
if err := runElevatedCertutil("-addstore", windowsRootStoreName, certPath); err != nil {
return err
}
installed, err := isCACertInstalled(certPEM)
if err != nil {
return fmt.Errorf("验证系统证书安装状态失败: %w", err)
}
if !installed {
return fmt.Errorf("证书导入命令已执行,但系统信任存储中未找到证书")
}
logger.Infof("installCACertToWindowsStore: cert installed successfully into system store, thumbprint=%s", thumbprint)
return nil
}
// EnsureCACertInstalled 确保证书已安装到 Windows 系统信任存储。
func EnsureCACertInstalled(certPEM []byte, certPath string) error {
installed, err := isCACertInstalled(certPEM)
if err != nil {
return fmt.Errorf("检查系统证书安装状态失败: %w", err)
}
if installed {
logger.Infof("ensureCACertInstalled: cert already installed in system store, skipping")
return nil
}
logger.Infof("ensureCACertInstalled: cert not installed in system store, installing...")
return installCACertToWindowsStore(certPEM, certPath)
}