cert_pool.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  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
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package sm2
  14. import (
  15. "encoding/pem"
  16. "errors"
  17. "io/ioutil"
  18. "os"
  19. "runtime"
  20. "sync"
  21. )
  22. // Possible certificate files; stop after finding one.
  23. var certFiles = []string{
  24. "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
  25. "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
  26. "/etc/ssl/ca-bundle.pem", // OpenSUSE
  27. "/etc/pki/tls/cacert.pem", // OpenELEC
  28. "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
  29. }
  30. // CertPool is a set of certificates.
  31. type CertPool struct {
  32. bySubjectKeyId map[string][]int
  33. byName map[string][]int
  34. certs []*Certificate
  35. }
  36. // NewCertPool returns a new, empty CertPool.
  37. func NewCertPool() *CertPool {
  38. return &CertPool{
  39. bySubjectKeyId: make(map[string][]int),
  40. byName: make(map[string][]int),
  41. }
  42. }
  43. // Possible directories with certificate files; stop after successfully
  44. // reading at least one file from a directory.
  45. var certDirectories = []string{
  46. "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139
  47. "/system/etc/security/cacerts", // Android
  48. }
  49. var (
  50. once sync.Once
  51. systemRoots *CertPool
  52. systemRootsErr error
  53. )
  54. func systemRootsPool() *CertPool {
  55. once.Do(initSystemRoots)
  56. return systemRoots
  57. }
  58. func initSystemRoots() {
  59. systemRoots, systemRootsErr = loadSystemRoots()
  60. }
  61. func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
  62. return nil, nil
  63. }
  64. func loadSystemRoots() (*CertPool, error) {
  65. roots := NewCertPool()
  66. var firstErr error
  67. for _, file := range certFiles {
  68. data, err := ioutil.ReadFile(file)
  69. if err == nil {
  70. roots.AppendCertsFromPEM(data)
  71. return roots, nil
  72. }
  73. if firstErr == nil && !os.IsNotExist(err) {
  74. firstErr = err
  75. }
  76. }
  77. for _, directory := range certDirectories {
  78. fis, err := ioutil.ReadDir(directory)
  79. if err != nil {
  80. if firstErr == nil && !os.IsNotExist(err) {
  81. firstErr = err
  82. }
  83. continue
  84. }
  85. rootsAdded := false
  86. for _, fi := range fis {
  87. data, err := ioutil.ReadFile(directory + "/" + fi.Name())
  88. if err == nil && roots.AppendCertsFromPEM(data) {
  89. rootsAdded = true
  90. }
  91. }
  92. if rootsAdded {
  93. return roots, nil
  94. }
  95. }
  96. return nil, firstErr
  97. }
  98. // SystemCertPool returns a copy of the system cert pool.
  99. //
  100. // Any mutations to the returned pool are not written to disk and do
  101. // not affect any other pool.
  102. func SystemCertPool() (*CertPool, error) {
  103. if runtime.GOOS == "windows" {
  104. // Issue 16736, 18609:
  105. return nil, errors.New("crypto/x509: system root pool is not available on Windows")
  106. }
  107. return loadSystemRoots()
  108. }
  109. // findVerifiedParents attempts to find certificates in s which have signed the
  110. // given certificate. If any candidates were rejected then errCert will be set
  111. // to one of them, arbitrarily, and err will contain the reason that it was
  112. // rejected.
  113. func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
  114. if s == nil {
  115. return
  116. }
  117. var candidates []int
  118. if len(cert.AuthorityKeyId) > 0 {
  119. candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
  120. }
  121. if len(candidates) == 0 {
  122. candidates = s.byName[string(cert.RawIssuer)]
  123. }
  124. for _, c := range candidates {
  125. if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
  126. parents = append(parents, c)
  127. } else {
  128. errCert = s.certs[c]
  129. }
  130. }
  131. return
  132. }
  133. func (s *CertPool) contains(cert *Certificate) bool {
  134. if s == nil {
  135. return false
  136. }
  137. candidates := s.byName[string(cert.RawSubject)]
  138. for _, c := range candidates {
  139. if s.certs[c].Equal(cert) {
  140. return true
  141. }
  142. }
  143. return false
  144. }
  145. // AddCert adds a certificate to a pool.
  146. func (s *CertPool) AddCert(cert *Certificate) {
  147. if cert == nil {
  148. panic("adding nil Certificate to CertPool")
  149. }
  150. // Check that the certificate isn't being added twice.
  151. if s.contains(cert) {
  152. return
  153. }
  154. n := len(s.certs)
  155. s.certs = append(s.certs, cert)
  156. if len(cert.SubjectKeyId) > 0 {
  157. keyId := string(cert.SubjectKeyId)
  158. s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
  159. }
  160. name := string(cert.RawSubject)
  161. s.byName[name] = append(s.byName[name], n)
  162. }
  163. // AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
  164. // It appends any certificates found to s and reports whether any certificates
  165. // were successfully parsed.
  166. //
  167. // On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
  168. // of root CAs in a format suitable for this function.
  169. func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
  170. for len(pemCerts) > 0 {
  171. var block *pem.Block
  172. block, pemCerts = pem.Decode(pemCerts)
  173. if block == nil {
  174. break
  175. }
  176. if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
  177. continue
  178. }
  179. cert, err := ParseCertificate(block.Bytes)
  180. if err != nil {
  181. continue
  182. }
  183. s.AddCert(cert)
  184. ok = true
  185. }
  186. return
  187. }
  188. // Subjects returns a list of the DER-encoded subjects of
  189. // all of the certificates in the pool.
  190. func (s *CertPool) Subjects() [][]byte {
  191. res := make([][]byte, len(s.certs))
  192. for i, c := range s.certs {
  193. res[i] = c.RawSubject
  194. }
  195. return res
  196. }