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  }