...
1
2
3
4
5
6
7
8
9 package main
10
11 import (
12 "crypto/x509"
13 "fmt"
14 "log"
15 "os"
16 "os/exec"
17 "time"
18 "unsafe"
19 )
20
21 type CertPool struct {
22 bySubjectKeyId map[string][]int
23 byName map[string][]int
24 certs []*x509.Certificate
25 }
26
27 func (s *CertPool) contains(cert *x509.Certificate) bool {
28 if s == nil {
29 return false
30 }
31
32 candidates := s.byName[string(cert.RawSubject)]
33 for _, c := range candidates {
34 if s.certs[c].Equal(cert) {
35 return true
36 }
37 }
38
39 return false
40 }
41
42 func main() {
43 var failed bool
44
45 t0 := time.Now()
46 sysRootsExt, err := loadSystemRoots()
47 sysRootsDuration := time.Since(t0)
48
49 if err != nil {
50 log.Fatalf("failed to read system roots (cgo): %v", err)
51 }
52 sysRoots := (*CertPool)(unsafe.Pointer(sysRootsExt))
53
54 t1 := time.Now()
55 execRootsExt, err := execSecurityRoots()
56 execSysRootsDuration := time.Since(t1)
57
58 if err != nil {
59 log.Fatalf("failed to read system roots (nocgo): %v", err)
60 }
61 execRoots := (*CertPool)(unsafe.Pointer(execRootsExt))
62
63 fmt.Printf(" cgo sys roots: %v\n", sysRootsDuration)
64 fmt.Printf("non-cgo sys roots: %v\n", execSysRootsDuration)
65
66
67
68
69
70
71 if want, have := 100, len(sysRoots.certs); have < want {
72 failed = true
73 fmt.Printf("want at least %d system roots, have %d\n", want, have)
74 }
75
76
77 sysPool := make(map[string]*x509.Certificate, len(sysRoots.certs))
78 for _, c := range sysRoots.certs {
79 sysPool[string(c.Raw)] = c
80 }
81 for _, c := range execRoots.certs {
82 if _, ok := sysPool[string(c.Raw)]; ok {
83 delete(sysPool, string(c.Raw))
84 } else {
85
86
87
88 if _, err := c.Verify(x509.VerifyOptions{
89 Roots: sysRootsExt,
90 Intermediates: execRootsExt,
91 KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny},
92 }); err != nil {
93 failed = true
94 fmt.Printf("certificate only present in non-cgo pool: %v (verify error: %v)\n", c.Subject, err)
95 } else {
96 fmt.Printf("signed certificate only present in non-cgo pool (acceptable): %v\n", c.Subject)
97 }
98 }
99 }
100 for _, c := range sysPool {
101 failed = true
102 fmt.Printf("certificate only present in cgo pool: %v\n", c.Subject)
103 }
104
105 if failed && debugDarwinRoots {
106 cmd := exec.Command("security", "dump-trust-settings")
107 cmd.Stdout = os.Stdout
108 cmd.Stderr = os.Stderr
109 cmd.Run()
110 cmd = exec.Command("security", "dump-trust-settings", "-d")
111 cmd.Stdout = os.Stdout
112 cmd.Stderr = os.Stderr
113 cmd.Run()
114 }
115
116 if failed {
117 fmt.Printf("\n\n!!! The test failed!\n\nPlease report *the whole output* at https://github.com/golang/go/issues/24652 wrapping it in ``` a code block ```\nThank you!\n")
118 } else {
119 fmt.Printf("\n\nThe test passed, no need to report the output. Thank you.\n")
120 }
121 }
122
View as plain text