...

Source file src/pkg/crypto/x509/cert_pool.go

     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	func (s *CertPool) copy() *CertPool {
    29		p := &CertPool{
    30			bySubjectKeyId: make(map[string][]int, len(s.bySubjectKeyId)),
    31			byName:         make(map[string][]int, len(s.byName)),
    32			certs:          make([]*Certificate, len(s.certs)),
    33		}
    34		for k, v := range s.bySubjectKeyId {
    35			indexes := make([]int, len(v))
    36			copy(indexes, v)
    37			p.bySubjectKeyId[k] = indexes
    38		}
    39		for k, v := range s.byName {
    40			indexes := make([]int, len(v))
    41			copy(indexes, v)
    42			p.byName[k] = indexes
    43		}
    44		copy(p.certs, s.certs)
    45		return p
    46	}
    47	
    48	// SystemCertPool returns a copy of the system cert pool.
    49	//
    50	// Any mutations to the returned pool are not written to disk and do
    51	// not affect any other pool returned by SystemCertPool.
    52	//
    53	// New changes in the system cert pool might not be reflected
    54	// in subsequent calls.
    55	func SystemCertPool() (*CertPool, error) {
    56		if runtime.GOOS == "windows" {
    57			// Issue 16736, 18609:
    58			return nil, errors.New("crypto/x509: system root pool is not available on Windows")
    59		}
    60	
    61		if sysRoots := systemRootsPool(); sysRoots != nil {
    62			return sysRoots.copy(), nil
    63		}
    64	
    65		return loadSystemRoots()
    66	}
    67	
    68	// findPotentialParents returns the indexes of certificates in s which might
    69	// have signed cert. The caller must not modify the returned slice.
    70	func (s *CertPool) findPotentialParents(cert *Certificate) []int {
    71		if s == nil {
    72			return nil
    73		}
    74	
    75		var candidates []int
    76		if len(cert.AuthorityKeyId) > 0 {
    77			candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
    78		}
    79		if len(candidates) == 0 {
    80			candidates = s.byName[string(cert.RawIssuer)]
    81		}
    82		return candidates
    83	}
    84	
    85	func (s *CertPool) contains(cert *Certificate) bool {
    86		if s == nil {
    87			return false
    88		}
    89	
    90		candidates := s.byName[string(cert.RawSubject)]
    91		for _, c := range candidates {
    92			if s.certs[c].Equal(cert) {
    93				return true
    94			}
    95		}
    96	
    97		return false
    98	}
    99	
   100	// AddCert adds a certificate to a pool.
   101	func (s *CertPool) AddCert(cert *Certificate) {
   102		if cert == nil {
   103			panic("adding nil Certificate to CertPool")
   104		}
   105	
   106		// Check that the certificate isn't being added twice.
   107		if s.contains(cert) {
   108			return
   109		}
   110	
   111		n := len(s.certs)
   112		s.certs = append(s.certs, cert)
   113	
   114		if len(cert.SubjectKeyId) > 0 {
   115			keyId := string(cert.SubjectKeyId)
   116			s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
   117		}
   118		name := string(cert.RawSubject)
   119		s.byName[name] = append(s.byName[name], n)
   120	}
   121	
   122	// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
   123	// It appends any certificates found to s and reports whether any certificates
   124	// were successfully parsed.
   125	//
   126	// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
   127	// of root CAs in a format suitable for this function.
   128	func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
   129		for len(pemCerts) > 0 {
   130			var block *pem.Block
   131			block, pemCerts = pem.Decode(pemCerts)
   132			if block == nil {
   133				break
   134			}
   135			if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
   136				continue
   137			}
   138	
   139			cert, err := ParseCertificate(block.Bytes)
   140			if err != nil {
   141				continue
   142			}
   143	
   144			s.AddCert(cert)
   145			ok = true
   146		}
   147	
   148		return
   149	}
   150	
   151	// Subjects returns a list of the DER-encoded subjects of
   152	// all of the certificates in the pool.
   153	func (s *CertPool) Subjects() [][]byte {
   154		res := make([][]byte, len(s.certs))
   155		for i, c := range s.certs {
   156			res[i] = c.RawSubject
   157		}
   158		return res
   159	}
   160	

View as plain text