-
Notifications
You must be signed in to change notification settings - Fork 14
/
truststore_darwin.go
134 lines (116 loc) · 3.68 KB
/
truststore_darwin.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright (c) 2018 The truststore Authors. All rights reserved.
// Copyright (c) 2018 The mkcert Authors. All rights reserved.
package truststore
import (
"bytes"
"crypto/x509"
"encoding/asn1"
"fmt"
"os"
"os/exec"
plist "howett.net/plist"
)
var (
// NSSProfile is the path of the Firefox profiles.
NSSProfile = os.Getenv("HOME") + "/Library/Application Support/Firefox/Profiles/*"
// CertutilInstallHelp is the command to run on macOS to add NSS support.
CertutilInstallHelp = "brew install nss"
)
// https://github.com/golang/go/issues/24652#issuecomment-399826583
var trustSettings []interface{}
var _, _ = plist.Unmarshal(trustSettingsData, &trustSettings)
var trustSettingsData = []byte(`
<array>
<dict>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAED
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>sslServer</string>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
<dict>
<key>kSecTrustSettingsPolicy</key>
<data>
KoZIhvdjZAEC
</data>
<key>kSecTrustSettingsPolicyName</key>
<string>basicX509</string>
<key>kSecTrustSettingsResult</key>
<integer>1</integer>
</dict>
</array>
`)
func installPlatform(filename string, cert *x509.Certificate) error {
cmd := exec.Command("sudo", "security", "add-trusted-cert", "-d", "-k", "/Library/Keychains/System.keychain", filename)
out, err := cmd.CombinedOutput()
if err != nil {
return NewCmdError(err, cmd, out)
}
// Make trustSettings explicit, as older Go does not know the defaults.
// https://github.com/golang/go/issues/24652
plistFile, err := os.CreateTemp("", "trust-settings")
if err != nil {
return wrapError(err, "failed to create temp file")
}
defer os.Remove(plistFile.Name())
//nolint:gosec // tolerable risk necessary for function
cmd = exec.Command("sudo", "security", "trust-settings-export", "-d", plistFile.Name())
out, err = cmd.CombinedOutput()
if err != nil {
return NewCmdError(err, cmd, out)
}
plistData, err := os.ReadFile(plistFile.Name())
if err != nil {
return wrapError(err, "failed to read trust settings")
}
var plistRoot map[string]interface{}
_, err = plist.Unmarshal(plistData, &plistRoot)
if err != nil {
return wrapError(err, "failed to parse trust settings")
}
if v, ok := plistRoot["trustVersion"].(uint64); v != 1 || !ok {
return fmt.Errorf("unsupported trust settings version: %v", plistRoot["trustVersion"])
}
trustList := plistRoot["trustList"].(map[string]interface{})
rootSubjectASN1, _ := asn1.Marshal(cert.Subject.ToRDNSequence())
for key := range trustList {
entry := trustList[key].(map[string]interface{})
if _, ok := entry["issuerName"]; !ok {
continue
}
issuerName := entry["issuerName"].([]byte)
if !bytes.Equal(rootSubjectASN1, issuerName) {
continue
}
entry["trustSettings"] = trustSettings
break
}
plistData, err = plist.MarshalIndent(plistRoot, plist.XMLFormat, "\t")
if err != nil {
return wrapError(err, "failed to serialize trust settings")
}
err = os.WriteFile(plistFile.Name(), plistData, 0600)
if err != nil {
return wrapError(err, "failed to write trust settings")
}
//nolint:gosec // tolerable risk necessary for function
cmd = exec.Command("sudo", "security", "trust-settings-import", "-d", plistFile.Name())
out, err = cmd.CombinedOutput()
if err != nil {
return NewCmdError(err, cmd, out)
}
debug("certificate installed properly in macOS keychain")
return nil
}
func uninstallPlatform(filename string, _ *x509.Certificate) error {
cmd := exec.Command("sudo", "security", "remove-trusted-cert", "-d", filename)
out, err := cmd.CombinedOutput()
if err != nil {
return NewCmdError(err, cmd, out)
}
debug("certificate uninstalled properly from macOS keychain")
return nil
}