Source file
src/crypto/x509/root_darwin.go
1
2
3
4
5
6
7
8 package x509
9
10 import (
11 "bytes"
12 macOS "crypto/x509/internal/macos"
13 "fmt"
14 "os"
15 "strings"
16 )
17
18 var debugDarwinRoots = strings.Contains(os.Getenv("GODEBUG"), "x509roots=1")
19
20 func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
21 return nil, nil
22 }
23
24 func loadSystemRoots() (*CertPool, error) {
25 var trustedRoots []*Certificate
26 untrustedRoots := make(map[string]bool)
27
28
29
30
31 for _, domain := range []macOS.SecTrustSettingsDomain{
32 macOS.SecTrustSettingsDomainUser,
33 macOS.SecTrustSettingsDomainAdmin,
34 macOS.SecTrustSettingsDomainSystem,
35 } {
36 certs, err := macOS.SecTrustSettingsCopyCertificates(domain)
37 if err == macOS.ErrNoTrustSettings {
38 continue
39 } else if err != nil {
40 return nil, err
41 }
42 defer macOS.CFRelease(certs)
43
44 for i := 0; i < macOS.CFArrayGetCount(certs); i++ {
45 c := macOS.CFArrayGetValueAtIndex(certs, i)
46 cert, err := exportCertificate(c)
47 if err != nil {
48 if debugDarwinRoots {
49 fmt.Fprintf(os.Stderr, "crypto/x509: domain %d, certificate #%d: %v\n", domain, i, err)
50 }
51 continue
52 }
53
54 var result macOS.SecTrustSettingsResult
55 if domain == macOS.SecTrustSettingsDomainSystem {
56
57
58
59 result = macOS.SecTrustSettingsResultTrustRoot
60 } else {
61 result, err = sslTrustSettingsResult(c)
62 if err != nil {
63 if debugDarwinRoots {
64 fmt.Fprintf(os.Stderr, "crypto/x509: trust settings for %v: %v\n", cert.Subject, err)
65 }
66 continue
67 }
68 if debugDarwinRoots {
69 fmt.Fprintf(os.Stderr, "crypto/x509: trust settings for %v: %d\n", cert.Subject, result)
70 }
71 }
72
73 switch result {
74
75
76
77
78 case macOS.SecTrustSettingsResultTrustRoot:
79 if isRootCertificate(cert) {
80 trustedRoots = append(trustedRoots, cert)
81 }
82 case macOS.SecTrustSettingsResultTrustAsRoot:
83 if !isRootCertificate(cert) {
84 trustedRoots = append(trustedRoots, cert)
85 }
86
87 case macOS.SecTrustSettingsResultDeny:
88
89
90
91
92 untrustedRoots[string(cert.Raw)] = true
93
94 case macOS.SecTrustSettingsResultUnspecified:
95
96
97
98
99 default:
100 if debugDarwinRoots {
101 fmt.Fprintf(os.Stderr, "crypto/x509: unknown trust setting for %v: %d\n", cert.Subject, result)
102 }
103 }
104 }
105 }
106
107 pool := NewCertPool()
108 for _, cert := range trustedRoots {
109 if !untrustedRoots[string(cert.Raw)] {
110 pool.AddCert(cert)
111 }
112 }
113 return pool, nil
114 }
115
116
117 func exportCertificate(cert macOS.CFRef) (*Certificate, error) {
118 data, err := macOS.SecItemExport(cert)
119 if err != nil {
120 return nil, err
121 }
122 defer macOS.CFRelease(data)
123 der := macOS.CFDataToSlice(data)
124
125 return ParseCertificate(der)
126 }
127
128
129 func isRootCertificate(cert *Certificate) bool {
130 return bytes.Equal(cert.RawSubject, cert.RawIssuer)
131 }
132
133
134
135
136
137
138
139
140
141 func sslTrustSettingsResult(cert macOS.CFRef) (macOS.SecTrustSettingsResult, error) {
142
143
144
145
146
147
148
149
150
151
152 trustSettings, err := macOS.SecTrustSettingsCopyTrustSettings(cert, macOS.SecTrustSettingsDomainUser)
153 if err != nil || trustSettings == 0 {
154 if debugDarwinRoots && err != macOS.ErrNoTrustSettings {
155 fmt.Fprintf(os.Stderr, "crypto/x509: SecTrustSettingsCopyTrustSettings for SecTrustSettingsDomainUser failed: %s\n", err)
156 }
157 trustSettings, err = macOS.SecTrustSettingsCopyTrustSettings(cert, macOS.SecTrustSettingsDomainAdmin)
158 }
159 if err != nil || trustSettings == 0 {
160
161
162
163
164
165
166
167
168
169
170
171 if debugDarwinRoots && err != macOS.ErrNoTrustSettings {
172 fmt.Fprintf(os.Stderr, "crypto/x509: SecTrustSettingsCopyTrustSettings for SecTrustSettingsDomainAdmin failed: %s\n", err)
173 }
174 return macOS.SecTrustSettingsResultUnspecified, nil
175 }
176 defer macOS.CFRelease(trustSettings)
177
178
179
180 if macOS.CFArrayGetCount(trustSettings) == 0 {
181 return macOS.SecTrustSettingsResultTrustRoot, nil
182 }
183
184 isSSLPolicy := func(policyRef macOS.CFRef) bool {
185 properties := macOS.SecPolicyCopyProperties(policyRef)
186 defer macOS.CFRelease(properties)
187 if v, ok := macOS.CFDictionaryGetValueIfPresent(properties, macOS.SecPolicyOid); ok {
188 return macOS.CFEqual(v, macOS.CFRef(macOS.SecPolicyAppleSSL))
189 }
190 return false
191 }
192
193 for i := 0; i < macOS.CFArrayGetCount(trustSettings); i++ {
194 tSetting := macOS.CFArrayGetValueAtIndex(trustSettings, i)
195
196
197 if policyRef, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsPolicy); ok {
198 if !isSSLPolicy(policyRef) {
199 continue
200 }
201 }
202
203
204 if _, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsPolicyString); ok {
205 continue
206 }
207
208 cfNum, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsResultKey)
209
210 if !ok {
211 return macOS.SecTrustSettingsResultTrustRoot, nil
212 }
213 result, err := macOS.CFNumberGetValue(cfNum)
214 if err != nil {
215 return 0, err
216 }
217
218
219
220
221
222
223 switch r := macOS.SecTrustSettingsResult(result); r {
224 case macOS.SecTrustSettingsResultTrustRoot,
225 macOS.SecTrustSettingsResultTrustAsRoot,
226 macOS.SecTrustSettingsResultDeny:
227 return r, nil
228 }
229 }
230
231
232
233
234
235
236
237
238
239 return macOS.SecTrustSettingsResultUnspecified, nil
240 }
241
View as plain text