src/pkg/crypto/x509/cert_pool.go - The Go Programming Language

Golang

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	)
    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 no such certificate can be found or the signature
    29	// doesn't match, it returns nil.
    30	func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
    31		if s == nil {
    32			return
    33		}
    34		var candidates []int
    35	
    36		if len(cert.AuthorityKeyId) > 0 {
    37			candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
    38		}
    39		if len(candidates) == 0 {
    40			candidates = s.byName[string(cert.RawIssuer)]
    41		}
    42	
    43		for _, c := range candidates {
    44			if cert.CheckSignatureFrom(s.certs[c]) == nil {
    45				parents = append(parents, c)
    46			}
    47		}
    48	
    49		return
    50	}
    51	
    52	// AddCert adds a certificate to a pool.
    53	func (s *CertPool) AddCert(cert *Certificate) {
    54		if cert == nil {
    55			panic("adding nil Certificate to CertPool")
    56		}
    57	
    58		// Check that the certificate isn't being added twice.
    59		for _, c := range s.certs {
    60			if c.Equal(cert) {
    61				return
    62			}
    63		}
    64	
    65		n := len(s.certs)
    66		s.certs = append(s.certs, cert)
    67	
    68		if len(cert.SubjectKeyId) > 0 {
    69			keyId := string(cert.SubjectKeyId)
    70			s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
    71		}
    72		name := string(cert.RawSubject)
    73		s.byName[name] = append(s.byName[name], n)
    74	}
    75	
    76	// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
    77	// It appends any certificates found to s and returns true if any certificates
    78	// were successfully parsed.
    79	//
    80	// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
    81	// of root CAs in a format suitable for this function.
    82	func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
    83		for len(pemCerts) > 0 {
    84			var block *pem.Block
    85			block, pemCerts = pem.Decode(pemCerts)
    86			if block == nil {
    87				break
    88			}
    89			if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
    90				continue
    91			}
    92	
    93			cert, err := ParseCertificate(block.Bytes)
    94			if err != nil {
    95				continue
    96			}
    97	
    98			s.AddCert(cert)
    99			ok = true
   100		}
   101	
   102		return
   103	}
   104	
   105	// Subjects returns a list of the DER-encoded subjects of
   106	// all of the certificates in the pool. 
   107	func (s *CertPool) Subjects() (res [][]byte) {
   108		res = make([][]byte, len(s.certs))
   109		for i, c := range s.certs {
   110			res[i] = c.RawSubject
   111		}
   112		return
   113	}