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  }