package x509
import (
"bytes"
macOS "crypto/x509/internal/macos"
"fmt"
"os"
"strings"
)
var debugDarwinRoots = strings .Contains (os .Getenv ("GODEBUG" ), "x509roots=1" )
func (c *Certificate ) systemVerify (opts *VerifyOptions ) (chains [][]*Certificate , err error ) {
return nil , nil
}
func loadSystemRoots () (*CertPool , error ) {
var trustedRoots []*Certificate
untrustedRoots := make (map [string ]bool )
for _ , domain := range []macOS .SecTrustSettingsDomain {
macOS .SecTrustSettingsDomainUser ,
macOS .SecTrustSettingsDomainAdmin ,
macOS .SecTrustSettingsDomainSystem ,
} {
certs , err := macOS .SecTrustSettingsCopyCertificates (domain )
if err == macOS .ErrNoTrustSettings {
continue
} else if err != nil {
return nil , err
}
defer macOS .CFRelease (certs )
for i := 0 ; i < macOS .CFArrayGetCount (certs ); i ++ {
c := macOS .CFArrayGetValueAtIndex (certs , i )
cert , err := exportCertificate (c )
if err != nil {
if debugDarwinRoots {
fmt .Fprintf (os .Stderr , "crypto/x509: domain %d, certificate #%d: %v\n" , domain , i , err )
}
continue
}
var result macOS .SecTrustSettingsResult
if domain == macOS .SecTrustSettingsDomainSystem {
result = macOS .SecTrustSettingsResultTrustRoot
} else {
result , err = sslTrustSettingsResult (c )
if err != nil {
if debugDarwinRoots {
fmt .Fprintf (os .Stderr , "crypto/x509: trust settings for %v: %v\n" , cert .Subject , err )
}
continue
}
if debugDarwinRoots {
fmt .Fprintf (os .Stderr , "crypto/x509: trust settings for %v: %d\n" , cert .Subject , result )
}
}
switch result {
case macOS .SecTrustSettingsResultTrustRoot :
if isRootCertificate (cert ) {
trustedRoots = append (trustedRoots , cert )
}
case macOS .SecTrustSettingsResultTrustAsRoot :
if !isRootCertificate (cert ) {
trustedRoots = append (trustedRoots , cert )
}
case macOS .SecTrustSettingsResultDeny :
untrustedRoots [string (cert .Raw )] = true
case macOS .SecTrustSettingsResultUnspecified :
default :
if debugDarwinRoots {
fmt .Fprintf (os .Stderr , "crypto/x509: unknown trust setting for %v: %d\n" , cert .Subject , result )
}
}
}
}
pool := NewCertPool ()
for _ , cert := range trustedRoots {
if !untrustedRoots [string (cert .Raw )] {
pool .AddCert (cert )
}
}
return pool , nil
}
func exportCertificate (cert macOS .CFRef ) (*Certificate , error ) {
data , err := macOS .SecItemExport (cert )
if err != nil {
return nil , err
}
defer macOS .CFRelease (data )
der := macOS .CFDataToSlice (data )
return ParseCertificate (der )
}
func isRootCertificate (cert *Certificate ) bool {
return bytes .Equal (cert .RawSubject , cert .RawIssuer )
}
func sslTrustSettingsResult (cert macOS .CFRef ) (macOS .SecTrustSettingsResult , error ) {
trustSettings , err := macOS .SecTrustSettingsCopyTrustSettings (cert , macOS .SecTrustSettingsDomainUser )
if err != nil || trustSettings == 0 {
if debugDarwinRoots && err != macOS .ErrNoTrustSettings {
fmt .Fprintf (os .Stderr , "crypto/x509: SecTrustSettingsCopyTrustSettings for SecTrustSettingsDomainUser failed: %s\n" , err )
}
trustSettings , err = macOS .SecTrustSettingsCopyTrustSettings (cert , macOS .SecTrustSettingsDomainAdmin )
}
if err != nil || trustSettings == 0 {
if debugDarwinRoots && err != macOS .ErrNoTrustSettings {
fmt .Fprintf (os .Stderr , "crypto/x509: SecTrustSettingsCopyTrustSettings for SecTrustSettingsDomainAdmin failed: %s\n" , err )
}
return macOS .SecTrustSettingsResultUnspecified , nil
}
defer macOS .CFRelease (trustSettings )
if macOS .CFArrayGetCount (trustSettings ) == 0 {
return macOS .SecTrustSettingsResultTrustRoot , nil
}
isSSLPolicy := func (policyRef macOS .CFRef ) bool {
properties := macOS .SecPolicyCopyProperties (policyRef )
defer macOS .CFRelease (properties )
if v , ok := macOS .CFDictionaryGetValueIfPresent (properties , macOS .SecPolicyOid ); ok {
return macOS .CFEqual (v , macOS .CFRef (macOS .SecPolicyAppleSSL ))
}
return false
}
for i := 0 ; i < macOS .CFArrayGetCount (trustSettings ); i ++ {
tSetting := macOS .CFArrayGetValueAtIndex (trustSettings , i )
if policyRef , ok := macOS .CFDictionaryGetValueIfPresent (tSetting , macOS .SecTrustSettingsPolicy ); ok {
if !isSSLPolicy (policyRef ) {
continue
}
}
if _ , ok := macOS .CFDictionaryGetValueIfPresent (tSetting , macOS .SecTrustSettingsPolicyString ); ok {
continue
}
cfNum , ok := macOS .CFDictionaryGetValueIfPresent (tSetting , macOS .SecTrustSettingsResultKey )
if !ok {
return macOS .SecTrustSettingsResultTrustRoot , nil
}
result , err := macOS .CFNumberGetValue (cfNum )
if err != nil {
return 0 , err
}
switch r := macOS .SecTrustSettingsResult (result ); r {
case macOS .SecTrustSettingsResultTrustRoot ,
macOS .SecTrustSettingsResultTrustAsRoot ,
macOS .SecTrustSettingsResultDeny :
return r , nil
}
}
return macOS .SecTrustSettingsResultUnspecified , nil
}
The pages are generated with Golds v0.3.6 . (GOOS=darwin GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .