...
Run Format

Source file src/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	// 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			// Issue 16736, 18609:
    35			return nil, errors.New("crypto/x509: system root pool is not available on Windows")
    36		}
    37	
    38		return loadSystemRoots()
    39	}
    40	
    41	// findVerifiedParents attempts to find certificates in s which have signed the
    42	// given certificate. If any candidates were rejected then errCert will be set
    43	// to one of them, arbitrarily, and err will contain the reason that it was
    44	// rejected.
    45	func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
    46		if s == nil {
    47			return
    48		}
    49		var candidates []int
    50	
    51		if len(cert.AuthorityKeyId) > 0 {
    52			candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
    53		}
    54		if len(candidates) == 0 {
    55			candidates = s.byName[string(cert.RawIssuer)]
    56		}
    57	
    58		for _, c := range candidates {
    59			if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
    60				parents = append(parents, c)
    61			} else {
    62				errCert = s.certs[c]
    63			}
    64		}
    65	
    66		return
    67	}
    68	
    69	func (s *CertPool) contains(cert *Certificate) bool {
    70		if s == nil {
    71			return false
    72		}
    73	
    74		candidates := s.byName[string(cert.RawSubject)]
    75		for _, c := range candidates {
    76			if s.certs[c].Equal(cert) {
    77				return true
    78			}
    79		}
    80	
    81		return false
    82	}
    83	
    84	// AddCert adds a certificate to a pool.
    85	func (s *CertPool) AddCert(cert *Certificate) {
    86		if cert == nil {
    87			panic("adding nil Certificate to CertPool")
    88		}
    89	
    90		// Check that the certificate isn't being added twice.
    91		if s.contains(cert) {
    92			return
    93		}
    94	
    95		n := len(s.certs)
    96		s.certs = append(s.certs, cert)
    97	
    98		if len(cert.SubjectKeyId) > 0 {
    99			keyId := string(cert.SubjectKeyId)
   100			s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
   101		}
   102		name := string(cert.RawSubject)
   103		s.byName[name] = append(s.byName[name], n)
   104	}
   105	
   106	// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
   107	// It appends any certificates found to s and reports whether any certificates
   108	// were successfully parsed.
   109	//
   110	// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
   111	// of root CAs in a format suitable for this function.
   112	func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
   113		for len(pemCerts) > 0 {
   114			var block *pem.Block
   115			block, pemCerts = pem.Decode(pemCerts)
   116			if block == nil {
   117				break
   118			}
   119			if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
   120				continue
   121			}
   122	
   123			cert, err := ParseCertificate(block.Bytes)
   124			if err != nil {
   125				continue
   126			}
   127	
   128			s.AddCert(cert)
   129			ok = true
   130		}
   131	
   132		return
   133	}
   134	
   135	// Subjects returns a list of the DER-encoded subjects of
   136	// all of the certificates in the pool.
   137	func (s *CertPool) Subjects() [][]byte {
   138		res := make([][]byte, len(s.certs))
   139		for i, c := range s.certs {
   140			res[i] = c.RawSubject
   141		}
   142		return res
   143	}
   144	

View as plain text