f4b6e2236c
The key/value format of X.500 names means that it's possible to encode a name with multiple values for, say, organisation. RFC5280 doesn't seem to consider this, but there are Verisign root certificates which do this and, in order to find the correct root certificate in some cases, we need to handle it. Also, CA certificates should set the CA flag and we now check this. After looking at the other X.509 extensions it appears that they are universally ignored/bit rotted away so we ignore them. R=rsc CC=golang-dev https://golang.org/cl/2249042
69 lines
1.8 KiB
Go
69 lines
1.8 KiB
Go
// 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"
|
|
"strings"
|
|
)
|
|
|
|
// 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 strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(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) {
|
|
if len(cert.AuthorityKeyId) > 0 {
|
|
return s.bySubjectKeyId[string(cert.AuthorityKeyId)]
|
|
}
|
|
return s.byName[nameToKey(&cert.Issuer)]
|
|
}
|
|
|
|
// 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
|
|
}
|