1
2
3
4
5 package x509
6
7 import (
8 "internal/godebug"
9 "sync"
10 _ "unsafe"
11 )
12
13
14
15
16
17
18
19
20
21
22 var (
23 once sync.Once
24 systemRootsMu sync.RWMutex
25 systemRoots *CertPool
26 systemRootsErr error
27 fallbacksSet bool
28 useFallbackRoots bool
29 )
30
31 func systemRootsPool() *CertPool {
32 once.Do(initSystemRoots)
33 systemRootsMu.RLock()
34 defer systemRootsMu.RUnlock()
35 return systemRoots
36 }
37
38 func initSystemRoots() {
39 systemRootsMu.Lock()
40 defer systemRootsMu.Unlock()
41
42 fallbackRoots := systemRoots
43 systemRoots, systemRootsErr = loadSystemRoots()
44 if systemRootsErr != nil {
45 systemRoots = nil
46 }
47
48 if fallbackRoots == nil {
49 return
50 }
51
52 systemCertsAvail := systemRoots != nil && (systemRoots.len() > 0 || systemRoots.systemPool)
53
54 if !useFallbackRoots && systemCertsAvail {
55 return
56 }
57
58 if useFallbackRoots && systemCertsAvail {
59 x509usefallbackroots.IncNonDefault()
60 }
61
62 systemRoots, systemRootsErr = fallbackRoots, nil
63 }
64
65 var x509usefallbackroots = godebug.New("x509usefallbackroots")
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 func SetFallbackRoots(roots *CertPool) {
81 if roots == nil {
82 panic("roots must be non-nil")
83 }
84
85 systemRootsMu.Lock()
86 defer systemRootsMu.Unlock()
87
88 if fallbacksSet {
89 panic("SetFallbackRoots has already been called")
90 }
91 fallbacksSet = true
92
93
94
95
96
97 if systemRoots == nil && systemRootsErr == nil {
98 systemRoots = roots
99 useFallbackRoots = x509usefallbackroots.Value() == "1"
100 return
101 }
102
103 once.Do(func() { panic("unreachable") })
104
105 forceFallbackRoots := x509usefallbackroots.Value() == "1"
106 systemCertsAvail := systemRoots != nil && (systemRoots.len() > 0 || systemRoots.systemPool)
107
108 if !forceFallbackRoots && systemCertsAvail {
109 return
110 }
111
112 if forceFallbackRoots && systemCertsAvail {
113 x509usefallbackroots.IncNonDefault()
114 }
115
116 systemRoots, systemRootsErr = roots, nil
117 }
118
View as plain text