| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package tls | |
| import ( | |
| "crypto/x509" | |
| "encoding/pem" | |
| ) | |
| // A CASet is a set of certificates. | |
| type CASet struct { | |
| bySubjectKeyId map[string]*x509.Certificate | |
| byName map[string]*x509.Certificate | |
| } | |
| func NewCASet() *CASet { | |
| return &CASet{ | |
| make(map[string]*x509.Certificate), | |
| make(map[string]*x509.Certificate), | |
| } | |
| } | |
| func nameToKey(name *x509.Name) string { | |
| return name.Country + "/" + name.Organization + "/" + name.OrganizationalUnit + "/" + name.CommonName | |
| } | |
| // FindParent attempts to find the certificate in s which signs the given | |
| // certificate. If no such certificate can be found, it returns nil. | |
| func (s *CASet) FindParent(cert *x509.Certificate) (parent *x509.Certificate) { | |
| var ok bool | |
| if len(cert.AuthorityKeyId) > 0 { | |
| parent, ok = s.bySubjectKeyId[string(cert.AuthorityKeyId)] | |
| } else { | |
| parent, ok = s.byName[nameToKey(&cert.Issuer)] | |
| } | |
| if !ok { | |
| return nil | |
| } | |
| return parent | |
| } | |
| // SetFromPEM attempts to parse a series of PEM encoded root certificates. It | |
| // appends any certificates found to s and returns true if any certificates | |
| // were successfully parsed. On many Linux systems, /etc/ssl/cert.pem will | |
| // contains the system wide set of root CAs in a format suitable for this | |
| // function. | |
| func (s *CASet) SetFromPEM(pemCerts []byte) (ok bool) { | |
| for len(pemCerts) > 0 { | |
| var block *pem.Block | |
| block, pemCerts = pem.Decode(pemCerts) | |
| if block == nil { | |
| break | |
| } | |
| if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { | |
| continue | |
| } | |
| cert, err := x509.ParseCertificate(block.Bytes) | |
| if err != nil { | |
| continue | |
| } | |
| if len(cert.SubjectKeyId) > 0 { | |
| s.bySubjectKeyId[string(cert.SubjectKeyId)] = cert | |
| } | |
| s.byName[nameToKey(&cert.Subject)] = cert | |
| ok = true | |
| } | |
| return | |
| } |