Files
cursor-byok/internal/cursor/darwin_cert.go
T

133 lines
4.1 KiB
Go

//go:build darwin
package cursor
import (
"crypto/sha1"
"crypto/x509"
"encoding/pem"
"fmt"
"os/exec"
"strings"
"cursor/internal/logger"
)
const (
darwinSecurityExe = "security"
darwinLoginKeychainName = "login.keychain-db"
legacySharedCASHA1 = "C14B7488C5AB83F098BEB2603F1135595A381FC0"
)
func getCertSHA1Fingerprint(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)
}
fingerprint := fmt.Sprintf("%X", sha1.Sum(cert.Raw))
return fingerprint, nil
}
func isCACertInstalled(certPEM []byte) (bool, error) {
fingerprint, err := getCertSHA1Fingerprint(certPEM)
if err != nil {
return false, fmt.Errorf("获取证书指纹失败: %w", err)
}
return isCACertFingerprintInstalled(fingerprint)
}
func isCACertFingerprintInstalled(fingerprint string) (bool, error) {
out, err := exec.Command(darwinSecurityExe, "find-certificate", "-a", "-Z", darwinLoginKeychainName).CombinedOutput()
if err != nil {
return false, fmt.Errorf("检查 macOS 登录钥匙串失败: %w: %s", err, strings.TrimSpace(string(out)))
}
installed := strings.Contains(strings.ToUpper(string(out)), fingerprint)
if installed {
logger.Infof("isCACertInstalled: cert found in macOS login keychain, fingerprint=%s", fingerprint)
} else {
logger.Infof("isCACertInstalled: cert not found in macOS login keychain, fingerprint=%s", fingerprint)
}
return installed, nil
}
// EnsureLegacySharedCACertRemoved removes the compromised CA shipped by older versions.
func EnsureLegacySharedCACertRemoved() error {
installed, err := isCACertFingerprintInstalled(legacySharedCASHA1)
if err != nil {
return fmt.Errorf("检查旧版共享 CA 失败: %w", err)
}
if !installed {
return nil
}
out, err := exec.Command(
darwinSecurityExe,
"delete-certificate",
"-Z", legacySharedCASHA1,
"-t",
darwinLoginKeychainName,
).CombinedOutput()
if err != nil {
return fmt.Errorf("从 macOS 登录钥匙串删除旧版共享 CA 失败: %w: %s", err, strings.TrimSpace(string(out)))
}
installed, err = isCACertFingerprintInstalled(legacySharedCASHA1)
if err != nil {
return fmt.Errorf("验证旧版共享 CA 删除状态失败: %w", err)
}
if installed {
return fmt.Errorf("删除命令已执行,但 macOS 登录钥匙串中仍存在旧版共享 CA")
}
logger.Infof("ensureLegacySharedCACertRemoved: legacy shared CA removed from macOS login keychain")
return nil
}
func installCACertToDarwinKeychain(certPEM []byte, certPath string) error {
fingerprint, err := getCertSHA1Fingerprint(certPEM)
if err != nil {
return fmt.Errorf("获取证书指纹失败: %w", err)
}
logger.Infof("installCACertToDarwinKeychain: installing cert into login keychain, path=%s fingerprint=%s", certPath, fingerprint)
out, err := exec.Command(
darwinSecurityExe,
"add-trusted-cert",
"-d",
"-r", "trustRoot",
"-p", "ssl",
"-k", darwinLoginKeychainName,
certPath,
).CombinedOutput()
if err != nil {
return fmt.Errorf("安装 CA 到 macOS 登录钥匙串失败: %w: %s", err, strings.TrimSpace(string(out)))
}
installed, err := isCACertInstalled(certPEM)
if err != nil {
return fmt.Errorf("验证 macOS 证书安装状态失败: %w", err)
}
if !installed {
return fmt.Errorf("证书导入命令已执行,但 macOS 登录钥匙串中未找到证书")
}
logger.Infof("installCACertToDarwinKeychain: cert installed successfully, fingerprint=%s", fingerprint)
return nil
}
// EnsureCACertInstalled 确保 CA 证书已安装到 macOS 登录钥匙串。
func EnsureCACertInstalled(certPEM []byte, certPath string) error {
installed, err := isCACertInstalled(certPEM)
if err != nil {
return fmt.Errorf("检查 macOS 证书安装状态失败: %w", err)
}
if installed {
logger.Infof("ensureCACertInstalled: cert already installed in macOS login keychain, skipping")
return nil
}
logger.Infof("ensureCACertInstalled: cert not installed in macOS login keychain, installing...")
return installCACertToDarwinKeychain(certPEM, certPath)
}