2 Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
7 http://www.apache.org/licenses/LICENSE-2.0
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
27 // Possible certificate files; stop after finding one.
28 var certFiles = []string{
29 "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
30 "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
31 "/etc/ssl/ca-bundle.pem", // OpenSUSE
32 "/etc/pki/tls/cacert.pem", // OpenELEC
33 "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
36 // CertPool is a set of certificates.
37 type CertPool struct {
38 bySubjectKeyId map[string][]int
39 byName map[string][]int
43 // NewCertPool returns a new, empty CertPool.
44 func NewCertPool() *CertPool {
46 bySubjectKeyId: make(map[string][]int),
47 byName: make(map[string][]int),
51 // Possible directories with certificate files; stop after successfully
52 // reading at least one file from a directory.
53 var certDirectories = []string{
54 "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139
55 "/system/etc/security/cacerts", // Android
64 func systemRootsPool() *CertPool {
65 once.Do(initSystemRoots)
69 func initSystemRoots() {
70 systemRoots, systemRootsErr = loadSystemRoots()
73 func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
77 func loadSystemRoots() (*CertPool, error) {
78 roots := NewCertPool()
80 for _, file := range certFiles {
81 data, err := ioutil.ReadFile(file)
83 roots.AppendCertsFromPEM(data)
86 if firstErr == nil && !os.IsNotExist(err) {
91 for _, directory := range certDirectories {
92 fis, err := ioutil.ReadDir(directory)
94 if firstErr == nil && !os.IsNotExist(err) {
100 for _, fi := range fis {
101 data, err := ioutil.ReadFile(directory + "/" + fi.Name())
102 if err == nil && roots.AppendCertsFromPEM(data) {
114 // SystemCertPool returns a copy of the system cert pool.
116 // Any mutations to the returned pool are not written to disk and do
117 // not affect any other pool.
118 func SystemCertPool() (*CertPool, error) {
119 if runtime.GOOS == "windows" {
120 // Issue 16736, 18609:
121 return nil, errors.New("crypto/x509: system root pool is not available on Windows")
124 return loadSystemRoots()
127 // findVerifiedParents attempts to find certificates in s which have signed the
128 // given certificate. If any candidates were rejected then errCert will be set
129 // to one of them, arbitrarily, and err will contain the reason that it was
131 func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
137 if len(cert.AuthorityKeyId) > 0 {
138 candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
140 if len(candidates) == 0 {
141 candidates = s.byName[string(cert.RawIssuer)]
144 for _, c := range candidates {
145 if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
146 parents = append(parents, c)
155 func (s *CertPool) contains(cert *Certificate) bool {
160 candidates := s.byName[string(cert.RawSubject)]
161 for _, c := range candidates {
162 if s.certs[c].Equal(cert) {
170 // AddCert adds a certificate to a pool.
171 func (s *CertPool) AddCert(cert *Certificate) {
173 panic("adding nil Certificate to CertPool")
176 // Check that the certificate isn't being added twice.
177 if s.contains(cert) {
182 s.certs = append(s.certs, cert)
184 if len(cert.SubjectKeyId) > 0 {
185 keyId := string(cert.SubjectKeyId)
186 s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
188 name := string(cert.RawSubject)
189 s.byName[name] = append(s.byName[name], n)
192 // AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
193 // It appends any certificates found to s and reports whether any certificates
194 // were successfully parsed.
196 // On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
197 // of root CAs in a format suitable for this function.
198 func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
199 for len(pemCerts) > 0 {
201 block, pemCerts = pem.Decode(pemCerts)
205 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
209 cert, err := ParseCertificate(block.Bytes)
221 // Subjects returns a list of the DER-encoded subjects of
222 // all of the certificates in the pool.
223 func (s *CertPool) Subjects() [][]byte {
224 res := make([][]byte, len(s.certs))
225 for i, c := range s.certs {
226 res[i] = c.RawSubject