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