github.com/gidoBOSSftw5731/go/src@v0.0.0-20210226122457-d24b0edbf019/crypto/x509/root_darwin.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build !ios 6 // +build !ios 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 // macOS has three trust domains: one for CAs added by users to their 29 // "login" keychain, one for CAs added by Admins to the "System" keychain, 30 // and one for the CAs that ship with the OS. 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 // Certs found in the system domain are always trusted. If the user 57 // configures "Never Trust" on such a cert, it will also be found in the 58 // admin or user domain, causing it to be added to untrustedRoots. 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 // "Note the distinction between the results kSecTrustSettingsResultTrustRoot 75 // and kSecTrustSettingsResultTrustAsRoot: The former can only be applied to 76 // root (self-signed) certificates; the latter can only be applied to 77 // non-root certificates." 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 // Add this certificate to untrustedRoots, which are subtracted 89 // from trustedRoots, so that we don't have to evaluate policies 90 // for every root in the system domain, but still apply user and 91 // admin policies that override system roots. 92 untrustedRoots[string(cert.Raw)] = true 93 94 case macOS.SecTrustSettingsResultUnspecified: 95 // Certificates with unspecified trust should be added to a pool 96 // of intermediates for chain building, but we don't support it 97 // at the moment. This is Issue 35631. 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 // exportCertificate returns a *Certificate for a SecCertificateRef. 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 // isRootCertificate reports whether Subject and Issuer match. 129 func isRootCertificate(cert *Certificate) bool { 130 return bytes.Equal(cert.RawSubject, cert.RawIssuer) 131 } 132 133 // sslTrustSettingsResult obtains the final kSecTrustSettingsResult value for a 134 // certificate in the user or admin domain, combining usage constraints for the 135 // SSL SecTrustSettingsPolicy, 136 // 137 // It ignores SecTrustSettingsKeyUsage and kSecTrustSettingsAllowedError, and 138 // doesn't support kSecTrustSettingsDefaultRootCertSetting. 139 // 140 // https://developer.apple.com/documentation/security/1400261-sectrustsettingscopytrustsetting 141 func sslTrustSettingsResult(cert macOS.CFRef) (macOS.SecTrustSettingsResult, error) { 142 // In Apple's implementation user trust settings override admin trust settings 143 // (which themselves override system trust settings). If SecTrustSettingsCopyTrustSettings 144 // fails, or returns a NULL trust settings, when looking for the user trust 145 // settings then fallback to checking the admin trust settings. 146 // 147 // See Security-59306.41.2/trust/headers/SecTrustSettings.h for a description of 148 // the trust settings overrides, and SecLegacyAnchorSourceCopyUsageConstraints in 149 // Security-59306.41.2/trust/trustd/SecCertificateSource.c for a concrete example 150 // of how Apple applies the override in the case of NULL trust settings, or non 151 // success errors. 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 // If there are neither user nor admin trust settings for a certificate returned 161 // from SecTrustSettingsCopyCertificates Apple returns kSecTrustSettingsResultInvalid, 162 // as this method is intended to return certificates _which have trust settings_. 163 // The most likely case for this being triggered is that the existing trust settings 164 // are invalid and cannot be properly parsed. In this case SecTrustSettingsCopyTrustSettings 165 // returns errSecInvalidTrustSettings. The existing cgo implementation returns 166 // kSecTrustSettingsResultUnspecified in this case, which mostly matches the Apple 167 // implementation because we don't do anything with certificates marked with this 168 // result. 169 // 170 // See SecPVCGetTrustSettingsResult in Security-59306.41.2/trust/trustd/SecPolicyServer.c 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 // "An empty trust settings array means 'always trust this certificate' with an 179 // overall trust setting for the certificate of kSecTrustSettingsResultTrustRoot." 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 // First, check if this trust setting is constrained to a non-SSL policy. 197 if policyRef, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsPolicy); ok { 198 if !isSSLPolicy(policyRef) { 199 continue 200 } 201 } 202 203 // Then check if it is restricted to a hostname, so not a root. 204 if _, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsPolicyString); ok { 205 continue 206 } 207 208 cfNum, ok := macOS.CFDictionaryGetValueIfPresent(tSetting, macOS.SecTrustSettingsResultKey) 209 // "If this key is not present, a default value of kSecTrustSettingsResultTrustRoot is assumed." 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 // If multiple dictionaries match, we are supposed to "OR" them, 219 // the semantics of which are not clear. Since TrustRoot and TrustAsRoot 220 // are mutually exclusive, Deny should probably override, and Invalid and 221 // Unspecified be overridden, approximate this by stopping at the first 222 // TrustRoot, TrustAsRoot or Deny. 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 // If trust settings are present, but none of them match the policy... 232 // the docs don't tell us what to do. 233 // 234 // "Trust settings for a given use apply if any of the dictionaries in the 235 // certificate’s trust settings array satisfies the specified use." suggests 236 // that it's as if there were no trust settings at all, so we should maybe 237 // fallback to the admin trust settings? TODO(golang.org/issue/38888). 238 239 return macOS.SecTrustSettingsResultUnspecified, nil 240 }