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