github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/crypto/x509/cert_pool.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package x509 6 7 import "encoding/pem" 8 9 // CertPool is a set of certificates. 10 type CertPool struct { 11 bySubjectKeyId map[string][]int 12 byName map[string][]int 13 certs []*Certificate 14 } 15 16 // NewCertPool returns a new, empty CertPool. 17 func NewCertPool() *CertPool { 18 return &CertPool{ 19 bySubjectKeyId: make(map[string][]int), 20 byName: make(map[string][]int), 21 } 22 } 23 24 // SystemCertPool returns a copy of the system cert pool. 25 // 26 // Any mutations to the returned pool are not written to disk and do 27 // not affect any other pool. 28 func SystemCertPool() (*CertPool, error) { 29 return loadSystemRoots() 30 } 31 32 // findVerifiedParents attempts to find certificates in s which have signed the 33 // given certificate. If any candidates were rejected then errCert will be set 34 // to one of them, arbitrarily, and err will contain the reason that it was 35 // rejected. 36 func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) { 37 if s == nil { 38 return 39 } 40 var candidates []int 41 42 if len(cert.AuthorityKeyId) > 0 { 43 candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)] 44 } 45 if len(candidates) == 0 { 46 candidates = s.byName[string(cert.RawIssuer)] 47 } 48 49 for _, c := range candidates { 50 if err = cert.CheckSignatureFrom(s.certs[c]); err == nil { 51 parents = append(parents, c) 52 } else { 53 errCert = s.certs[c] 54 } 55 } 56 57 return 58 } 59 60 func (s *CertPool) contains(cert *Certificate) bool { 61 if s == nil { 62 return false 63 } 64 65 candidates := s.byName[string(cert.RawSubject)] 66 for _, c := range candidates { 67 if s.certs[c].Equal(cert) { 68 return true 69 } 70 } 71 72 return false 73 } 74 75 // AddCert adds a certificate to a pool. 76 func (s *CertPool) AddCert(cert *Certificate) { 77 if cert == nil { 78 panic("adding nil Certificate to CertPool") 79 } 80 81 // Check that the certificate isn't being added twice. 82 if s.contains(cert) { 83 return 84 } 85 86 n := len(s.certs) 87 s.certs = append(s.certs, cert) 88 89 if len(cert.SubjectKeyId) > 0 { 90 keyId := string(cert.SubjectKeyId) 91 s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n) 92 } 93 name := string(cert.RawSubject) 94 s.byName[name] = append(s.byName[name], n) 95 } 96 97 // AppendCertsFromPEM attempts to parse a series of PEM encoded certificates. 98 // It appends any certificates found to s and reports whether any certificates 99 // were successfully parsed. 100 // 101 // On many Linux systems, /etc/ssl/cert.pem will contain the system wide set 102 // of root CAs in a format suitable for this function. 103 func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) { 104 for len(pemCerts) > 0 { 105 var block *pem.Block 106 block, pemCerts = pem.Decode(pemCerts) 107 if block == nil { 108 break 109 } 110 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { 111 continue 112 } 113 114 cert, err := ParseCertificate(block.Bytes) 115 if err != nil { 116 continue 117 } 118 119 s.AddCert(cert) 120 ok = true 121 } 122 123 return 124 } 125 126 // Subjects returns a list of the DER-encoded subjects of 127 // all of the certificates in the pool. 128 func (s *CertPool) Subjects() [][]byte { 129 res := make([][]byte, len(s.certs)) 130 for i, c := range s.certs { 131 res[i] = c.RawSubject 132 } 133 return res 134 }