...
1
2
3
4
5 package x509
6
7 import (
8 "encoding/pem"
9 "errors"
10 "runtime"
11 )
12
13
14 type CertPool struct {
15 bySubjectKeyId map[string][]int
16 byName map[string][]int
17 certs []*Certificate
18 }
19
20
21 func NewCertPool() *CertPool {
22 return &CertPool{
23 bySubjectKeyId: make(map[string][]int),
24 byName: make(map[string][]int),
25 }
26 }
27
28 func (s *CertPool) copy() *CertPool {
29 p := &CertPool{
30 bySubjectKeyId: make(map[string][]int, len(s.bySubjectKeyId)),
31 byName: make(map[string][]int, len(s.byName)),
32 certs: make([]*Certificate, len(s.certs)),
33 }
34 for k, v := range s.bySubjectKeyId {
35 indexes := make([]int, len(v))
36 copy(indexes, v)
37 p.bySubjectKeyId[k] = indexes
38 }
39 for k, v := range s.byName {
40 indexes := make([]int, len(v))
41 copy(indexes, v)
42 p.byName[k] = indexes
43 }
44 copy(p.certs, s.certs)
45 return p
46 }
47
48
49
50
51
52
53
54
55 func SystemCertPool() (*CertPool, error) {
56 if runtime.GOOS == "windows" {
57
58 return nil, errors.New("crypto/x509: system root pool is not available on Windows")
59 }
60
61 if sysRoots := systemRootsPool(); sysRoots != nil {
62 return sysRoots.copy(), nil
63 }
64
65 return loadSystemRoots()
66 }
67
68
69
70 func (s *CertPool) findPotentialParents(cert *Certificate) []int {
71 if s == nil {
72 return nil
73 }
74
75 var candidates []int
76 if len(cert.AuthorityKeyId) > 0 {
77 candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
78 }
79 if len(candidates) == 0 {
80 candidates = s.byName[string(cert.RawIssuer)]
81 }
82 return candidates
83 }
84
85 func (s *CertPool) contains(cert *Certificate) bool {
86 if s == nil {
87 return false
88 }
89
90 candidates := s.byName[string(cert.RawSubject)]
91 for _, c := range candidates {
92 if s.certs[c].Equal(cert) {
93 return true
94 }
95 }
96
97 return false
98 }
99
100
101 func (s *CertPool) AddCert(cert *Certificate) {
102 if cert == nil {
103 panic("adding nil Certificate to CertPool")
104 }
105
106
107 if s.contains(cert) {
108 return
109 }
110
111 n := len(s.certs)
112 s.certs = append(s.certs, cert)
113
114 if len(cert.SubjectKeyId) > 0 {
115 keyId := string(cert.SubjectKeyId)
116 s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
117 }
118 name := string(cert.RawSubject)
119 s.byName[name] = append(s.byName[name], n)
120 }
121
122
123
124
125
126
127
128 func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
129 for len(pemCerts) > 0 {
130 var block *pem.Block
131 block, pemCerts = pem.Decode(pemCerts)
132 if block == nil {
133 break
134 }
135 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
136 continue
137 }
138
139 cert, err := ParseCertificate(block.Bytes)
140 if IsFatal(err) {
141 continue
142 }
143
144 s.AddCert(cert)
145 ok = true
146 }
147
148 return
149 }
150
151
152
153 func (s *CertPool) Subjects() [][]byte {
154 res := make([][]byte, len(s.certs))
155 for i, c := range s.certs {
156 res[i] = c.RawSubject
157 }
158 return res
159 }
160
View as plain text