chore: update vendor
This commit is contained in:
131
vendor/github.com/google/certificate-transparency-go/x509/name_constraints_test.go
generated
vendored
131
vendor/github.com/google/certificate-transparency-go/x509/name_constraints_test.go
generated
vendored
@ -9,6 +9,7 @@ import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@ -43,6 +44,7 @@ type nameConstraintsTest struct {
|
||||
roots []constraintsSpec
|
||||
intermediates [][]constraintsSpec
|
||||
leaf leafSpec
|
||||
requestedEKUs []ExtKeyUsage
|
||||
expectedError string
|
||||
noOpenSSL bool
|
||||
}
|
||||
@ -1445,6 +1447,118 @@ var nameConstraintsTests = []nameConstraintsTest{
|
||||
},
|
||||
expectedError: "\"https://example.com/test\" is excluded",
|
||||
},
|
||||
|
||||
// #75: While serverAuth in a CA certificate permits clientAuth in a leaf,
|
||||
// serverAuth in a leaf shouldn't permit clientAuth when requested in
|
||||
// VerifyOptions.
|
||||
nameConstraintsTest{
|
||||
roots: []constraintsSpec{
|
||||
constraintsSpec{},
|
||||
},
|
||||
intermediates: [][]constraintsSpec{
|
||||
[]constraintsSpec{
|
||||
constraintsSpec{},
|
||||
},
|
||||
},
|
||||
leaf: leafSpec{
|
||||
sans: []string{"dns:example.com"},
|
||||
ekus: []string{"serverAuth"},
|
||||
},
|
||||
requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth},
|
||||
expectedError: "incompatible key usage",
|
||||
},
|
||||
|
||||
// #76: However, MSSGC in a leaf should match a request for serverAuth.
|
||||
nameConstraintsTest{
|
||||
roots: []constraintsSpec{
|
||||
constraintsSpec{},
|
||||
},
|
||||
intermediates: [][]constraintsSpec{
|
||||
[]constraintsSpec{
|
||||
constraintsSpec{},
|
||||
},
|
||||
},
|
||||
leaf: leafSpec{
|
||||
sans: []string{"dns:example.com"},
|
||||
ekus: []string{"msSGC"},
|
||||
},
|
||||
requestedEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
|
||||
},
|
||||
|
||||
// An invalid DNS SAN should be detected only at validation time so
|
||||
// that we can process CA certificates in the wild that have invalid SANs.
|
||||
// See https://github.com/golang/go/issues/23995
|
||||
|
||||
// #77: an invalid DNS or mail SAN will not be detected if name constaint
|
||||
// checking is not triggered.
|
||||
nameConstraintsTest{
|
||||
roots: []constraintsSpec{
|
||||
constraintsSpec{},
|
||||
},
|
||||
intermediates: [][]constraintsSpec{
|
||||
[]constraintsSpec{
|
||||
constraintsSpec{},
|
||||
},
|
||||
},
|
||||
leaf: leafSpec{
|
||||
sans: []string{"dns:this is invalid", "email:this @ is invalid"},
|
||||
},
|
||||
},
|
||||
|
||||
// #78: an invalid DNS SAN will be detected if any name constraint checking
|
||||
// is triggered.
|
||||
nameConstraintsTest{
|
||||
roots: []constraintsSpec{
|
||||
constraintsSpec{
|
||||
bad: []string{"uri:"},
|
||||
},
|
||||
},
|
||||
intermediates: [][]constraintsSpec{
|
||||
[]constraintsSpec{
|
||||
constraintsSpec{},
|
||||
},
|
||||
},
|
||||
leaf: leafSpec{
|
||||
sans: []string{"dns:this is invalid"},
|
||||
},
|
||||
expectedError: "cannot parse dnsName",
|
||||
},
|
||||
|
||||
// #79: an invalid email SAN will be detected if any name constraint
|
||||
// checking is triggered.
|
||||
nameConstraintsTest{
|
||||
roots: []constraintsSpec{
|
||||
constraintsSpec{
|
||||
bad: []string{"uri:"},
|
||||
},
|
||||
},
|
||||
intermediates: [][]constraintsSpec{
|
||||
[]constraintsSpec{
|
||||
constraintsSpec{},
|
||||
},
|
||||
},
|
||||
leaf: leafSpec{
|
||||
sans: []string{"email:this @ is invalid"},
|
||||
},
|
||||
expectedError: "cannot parse rfc822Name",
|
||||
},
|
||||
|
||||
// #80: if several EKUs are requested, satisfying any of them is sufficient.
|
||||
nameConstraintsTest{
|
||||
roots: []constraintsSpec{
|
||||
constraintsSpec{},
|
||||
},
|
||||
intermediates: [][]constraintsSpec{
|
||||
[]constraintsSpec{
|
||||
constraintsSpec{},
|
||||
},
|
||||
},
|
||||
leaf: leafSpec{
|
||||
sans: []string{"dns:example.com"},
|
||||
ekus: []string{"email"},
|
||||
},
|
||||
requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageEmailProtection},
|
||||
},
|
||||
}
|
||||
|
||||
func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
|
||||
@ -1513,6 +1627,13 @@ func makeConstraintsLeafCert(leaf leafSpec, key *ecdsa.PrivateKey, parent *Certi
|
||||
}
|
||||
template.IPAddresses = append(template.IPAddresses, ip)
|
||||
|
||||
case strings.HasPrefix(name, "invalidip:"):
|
||||
ipBytes, err := hex.DecodeString(name[10:])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse invalid IP: %s", err)
|
||||
}
|
||||
template.IPAddresses = append(template.IPAddresses, net.IP(ipBytes))
|
||||
|
||||
case strings.HasPrefix(name, "email:"):
|
||||
template.EmailAddresses = append(template.EmailAddresses, name[6:])
|
||||
|
||||
@ -1782,6 +1903,7 @@ func TestConstraintCases(t *testing.T) {
|
||||
Roots: rootPool,
|
||||
Intermediates: intermediatePool,
|
||||
CurrentTime: time.Unix(1500, 0),
|
||||
KeyUsages: test.requestedEKUs,
|
||||
}
|
||||
_, err = leafCert.Verify(verifyOpts)
|
||||
|
||||
@ -1973,12 +2095,13 @@ func TestBadNamesInConstraints(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBadNamesInSANs(t *testing.T) {
|
||||
// Bad names in SANs should not parse.
|
||||
// Bad names in URI and IP SANs should not parse. Bad DNS and email SANs
|
||||
// will parse and are tested in name constraint tests at the top of this
|
||||
// file.
|
||||
badNames := []string{
|
||||
"dns:foo.com.",
|
||||
"email:abc@foo.com.",
|
||||
"email:foo.com.",
|
||||
"uri:https://example.com./dsf",
|
||||
"invalidip:0102",
|
||||
"invalidip:0102030405",
|
||||
}
|
||||
|
||||
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
|
119
vendor/github.com/google/certificate-transparency-go/x509/verify.go
generated
vendored
119
vendor/github.com/google/certificate-transparency-go/x509/verify.go
generated
vendored
@ -12,9 +12,12 @@ import (
|
||||
"net/url"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/google/certificate-transparency-go/asn1"
|
||||
)
|
||||
|
||||
type InvalidReason int
|
||||
@ -174,19 +177,29 @@ var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificat
|
||||
// VerifyOptions contains parameters for Certificate.Verify. It's a structure
|
||||
// because other PKIX verification APIs have ended up needing many options.
|
||||
type VerifyOptions struct {
|
||||
DNSName string
|
||||
Intermediates *CertPool
|
||||
Roots *CertPool // if nil, the system roots are used
|
||||
CurrentTime time.Time // if zero, the current time is used
|
||||
DisableTimeChecks bool
|
||||
// KeyUsage specifies which Extended Key Usage values are acceptable.
|
||||
// An empty list means ExtKeyUsageServerAuth. Key usage is considered a
|
||||
// constraint down the chain which mirrors Windows CryptoAPI behavior,
|
||||
// but not the spec. To accept any key usage, include ExtKeyUsageAny.
|
||||
DNSName string
|
||||
Intermediates *CertPool
|
||||
Roots *CertPool // if nil, the system roots are used
|
||||
CurrentTime time.Time // if zero, the current time is used
|
||||
// Options to disable various verification checks.
|
||||
DisableTimeChecks bool
|
||||
DisableCriticalExtensionChecks bool
|
||||
DisableNameChecks bool
|
||||
DisableEKUChecks bool
|
||||
DisablePathLenChecks bool
|
||||
DisableNameConstraintChecks bool
|
||||
// KeyUsage specifies which Extended Key Usage values are acceptable. A leaf
|
||||
// certificate is accepted if it contains any of the listed values. An empty
|
||||
// list means ExtKeyUsageServerAuth. To accept any key usage, include
|
||||
// ExtKeyUsageAny.
|
||||
//
|
||||
// Certificate chains are required to nest extended key usage values,
|
||||
// irrespective of this value. This matches the Windows CryptoAPI behavior,
|
||||
// but not the spec.
|
||||
KeyUsages []ExtKeyUsage
|
||||
// MaxConstraintComparisions is the maximum number of comparisons to
|
||||
// perform when checking a given certificate's name constraints. If
|
||||
// zero, a sensible default is used. This limit prevents pathalogical
|
||||
// zero, a sensible default is used. This limit prevents pathological
|
||||
// certificates from consuming excessive amounts of CPU time when
|
||||
// validating.
|
||||
MaxConstraintComparisions int
|
||||
@ -544,11 +557,16 @@ func (c *Certificate) checkNameConstraints(count *int,
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
checkingAgainstIssuerCert = iota
|
||||
checkingAgainstLeafCert
|
||||
)
|
||||
|
||||
// ekuPermittedBy returns true iff the given extended key usage is permitted by
|
||||
// the given EKU from a certificate. Normally, this would be a simple
|
||||
// comparison plus a special case for the “any” EKU. But, in order to support
|
||||
// existing certificates, some exceptions are made.
|
||||
func ekuPermittedBy(eku, certEKU ExtKeyUsage) bool {
|
||||
func ekuPermittedBy(eku, certEKU ExtKeyUsage, context int) bool {
|
||||
if certEKU == ExtKeyUsageAny || eku == certEKU {
|
||||
return true
|
||||
}
|
||||
@ -565,28 +583,33 @@ func ekuPermittedBy(eku, certEKU ExtKeyUsage) bool {
|
||||
eku = mapServerAuthEKUs(eku)
|
||||
certEKU = mapServerAuthEKUs(certEKU)
|
||||
|
||||
if eku == certEKU ||
|
||||
// ServerAuth in a CA permits ClientAuth in the leaf.
|
||||
(eku == ExtKeyUsageClientAuth && certEKU == ExtKeyUsageServerAuth) ||
|
||||
if eku == certEKU {
|
||||
return true
|
||||
}
|
||||
|
||||
// If checking a requested EKU against the list in a leaf certificate there
|
||||
// are fewer exceptions.
|
||||
if context == checkingAgainstLeafCert {
|
||||
return false
|
||||
}
|
||||
|
||||
// ServerAuth in a CA permits ClientAuth in the leaf.
|
||||
return (eku == ExtKeyUsageClientAuth && certEKU == ExtKeyUsageServerAuth) ||
|
||||
// Any CA may issue an OCSP responder certificate.
|
||||
eku == ExtKeyUsageOCSPSigning ||
|
||||
// Code-signing CAs can use Microsoft's commercial and
|
||||
// kernel-mode EKUs.
|
||||
((eku == ExtKeyUsageMicrosoftCommercialCodeSigning || eku == ExtKeyUsageMicrosoftKernelCodeSigning) && certEKU == ExtKeyUsageCodeSigning) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
(eku == ExtKeyUsageMicrosoftCommercialCodeSigning || eku == ExtKeyUsageMicrosoftKernelCodeSigning) && certEKU == ExtKeyUsageCodeSigning
|
||||
}
|
||||
|
||||
// isValid performs validity checks on c given that it is a candidate to append
|
||||
// to the chain in currentChain.
|
||||
func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
|
||||
if len(c.UnhandledCriticalExtensions) > 0 {
|
||||
if !opts.DisableCriticalExtensionChecks && len(c.UnhandledCriticalExtensions) > 0 {
|
||||
return UnhandledCriticalExtension{ID: c.UnhandledCriticalExtensions[0]}
|
||||
}
|
||||
|
||||
if len(currentChain) > 0 {
|
||||
if !opts.DisableNameChecks && len(currentChain) > 0 {
|
||||
child := currentChain[len(currentChain)-1]
|
||||
if !bytes.Equal(child.RawIssuer, c.RawSubject) {
|
||||
return CertificateInvalidError{c, NameMismatch, ""}
|
||||
@ -617,7 +640,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
|
||||
leaf = currentChain[0]
|
||||
}
|
||||
|
||||
if (certType == intermediateCertificate || certType == rootCertificate) && c.hasNameConstraints() {
|
||||
if !opts.DisableNameConstraintChecks && (certType == intermediateCertificate || certType == rootCertificate) && c.hasNameConstraints() {
|
||||
sanExtension, ok := leaf.getSANExtension()
|
||||
if !ok {
|
||||
// This is the deprecated, legacy case of depending on
|
||||
@ -633,8 +656,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
|
||||
name := string(data)
|
||||
mailbox, ok := parseRFC2821Mailbox(name)
|
||||
if !ok {
|
||||
// This certificate should not have parsed.
|
||||
return errors.New("x509: internal error: rfc822Name SAN failed to parse")
|
||||
return fmt.Errorf("x509: cannot parse rfc822Name %q", mailbox)
|
||||
}
|
||||
|
||||
if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox,
|
||||
@ -646,6 +668,10 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
|
||||
|
||||
case nameTypeDNS:
|
||||
name := string(data)
|
||||
if _, ok := domainToReverseLabels(name); !ok {
|
||||
return fmt.Errorf("x509: cannot parse dnsName %q", name)
|
||||
}
|
||||
|
||||
if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name,
|
||||
func(parsedName, constraint interface{}) (bool, error) {
|
||||
return matchDomainConstraint(parsedName.(string), constraint.(string))
|
||||
@ -692,7 +718,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
|
||||
}
|
||||
}
|
||||
|
||||
checkEKUs := certType == intermediateCertificate
|
||||
checkEKUs := !opts.DisableEKUChecks && certType == intermediateCertificate
|
||||
|
||||
// If no extended key usages are specified, then all are acceptable.
|
||||
if checkEKUs && (len(c.ExtKeyUsage) == 0 && len(c.UnknownExtKeyUsage) == 0) {
|
||||
@ -719,7 +745,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
|
||||
|
||||
for _, caEKU := range c.ExtKeyUsage {
|
||||
comparisonCount++
|
||||
if ekuPermittedBy(eku, caEKU) {
|
||||
if ekuPermittedBy(eku, caEKU, checkingAgainstIssuerCert) {
|
||||
continue NextEKU
|
||||
}
|
||||
}
|
||||
@ -766,7 +792,7 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
|
||||
return CertificateInvalidError{c, NotAuthorizedToSign, ""}
|
||||
}
|
||||
|
||||
if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
|
||||
if !opts.DisablePathLenChecks && c.BasicConstraintsValid && c.MaxPathLen >= 0 {
|
||||
numIntermediates := len(currentChain) - 1
|
||||
if numIntermediates > c.MaxPathLen {
|
||||
return CertificateInvalidError{c, TooManyIntermediates, ""}
|
||||
@ -776,6 +802,18 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
|
||||
return nil
|
||||
}
|
||||
|
||||
// formatOID formats an ASN.1 OBJECT IDENTIFER in the common, dotted style.
|
||||
func formatOID(oid asn1.ObjectIdentifier) string {
|
||||
ret := ""
|
||||
for i, v := range oid {
|
||||
if i > 0 {
|
||||
ret += "."
|
||||
}
|
||||
ret += strconv.Itoa(v)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Verify attempts to verify c by building one or more chains from c to a
|
||||
// certificate in opts.Roots, using certificates in opts.Intermediates if
|
||||
// needed. If successful, it returns one or more chains where the first
|
||||
@ -840,7 +878,7 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
|
||||
}
|
||||
|
||||
// If no key usages are specified, then any are acceptable.
|
||||
checkEKU := len(c.ExtKeyUsage) > 0
|
||||
checkEKU := !opts.DisableEKUChecks && len(c.ExtKeyUsage) > 0
|
||||
|
||||
for _, eku := range requestedKeyUsages {
|
||||
if eku == ExtKeyUsageAny {
|
||||
@ -850,16 +888,33 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
|
||||
}
|
||||
|
||||
if checkEKU {
|
||||
foundMatch := false
|
||||
NextUsage:
|
||||
for _, eku := range requestedKeyUsages {
|
||||
for _, leafEKU := range c.ExtKeyUsage {
|
||||
if ekuPermittedBy(eku, leafEKU) {
|
||||
continue NextUsage
|
||||
if ekuPermittedBy(eku, leafEKU, checkingAgainstLeafCert) {
|
||||
foundMatch = true
|
||||
break NextUsage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
oid, _ := oidFromExtKeyUsage(eku)
|
||||
return nil, CertificateInvalidError{c, IncompatibleUsage, fmt.Sprintf("%#v", oid)}
|
||||
if !foundMatch {
|
||||
msg := "leaf contains the following, recognized EKUs: "
|
||||
|
||||
for i, leafEKU := range c.ExtKeyUsage {
|
||||
oid, ok := oidFromExtKeyUsage(leafEKU)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
msg += ", "
|
||||
}
|
||||
msg += formatOID(oid)
|
||||
}
|
||||
|
||||
return nil, CertificateInvalidError{c, IncompatibleUsage, msg}
|
||||
}
|
||||
}
|
||||
|
||||
|
83
vendor/github.com/google/certificate-transparency-go/x509/verify_test.go
generated
vendored
83
vendor/github.com/google/certificate-transparency-go/x509/verify_test.go
generated
vendored
@ -19,16 +19,18 @@ import (
|
||||
var supportSHA2 = true
|
||||
|
||||
type verifyTest struct {
|
||||
leaf string
|
||||
intermediates []string
|
||||
roots []string
|
||||
currentTime int64
|
||||
dnsName string
|
||||
systemSkip bool
|
||||
keyUsages []ExtKeyUsage
|
||||
testSystemRootsError bool
|
||||
sha2 bool
|
||||
disableTimeChecks bool
|
||||
leaf string
|
||||
intermediates []string
|
||||
roots []string
|
||||
currentTime int64
|
||||
dnsName string
|
||||
systemSkip bool
|
||||
keyUsages []ExtKeyUsage
|
||||
testSystemRootsError bool
|
||||
sha2 bool
|
||||
disableTimeChecks bool
|
||||
disableCriticalExtensionChecks bool
|
||||
disableNameChecks bool
|
||||
|
||||
errorCallback func(*testing.T, int, error) bool
|
||||
expectedChains [][]string
|
||||
@ -296,7 +298,18 @@ var verifyTests = []verifyTest{
|
||||
currentTime: 1475787715,
|
||||
systemSkip: true,
|
||||
|
||||
errorCallback: expectSubjectIssuerMismatcthError,
|
||||
errorCallback: expectSubjectIssuerMismatchError,
|
||||
},
|
||||
{
|
||||
leaf: issuerSubjectMatchLeaf,
|
||||
roots: []string{issuerSubjectMatchRoot},
|
||||
currentTime: 1475787715,
|
||||
systemSkip: true,
|
||||
disableNameChecks: true,
|
||||
|
||||
expectedChains: [][]string{
|
||||
{"Leaf", "Root ca"},
|
||||
},
|
||||
},
|
||||
{
|
||||
// An X.509 v1 certificate should not be accepted as an
|
||||
@ -355,6 +368,40 @@ var verifyTests = []verifyTest{
|
||||
|
||||
errorCallback: expectUnhandledCriticalExtension,
|
||||
},
|
||||
{
|
||||
leaf: criticalExtLeafWithExt,
|
||||
dnsName: "example.com",
|
||||
intermediates: []string{criticalExtIntermediate},
|
||||
roots: []string{criticalExtRoot},
|
||||
currentTime: 1486684488,
|
||||
systemSkip: true,
|
||||
disableCriticalExtensionChecks: true,
|
||||
|
||||
expectedChains: [][]string{
|
||||
{
|
||||
"example.com",
|
||||
"Intermediate",
|
||||
"Root",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
leaf: criticalExtLeaf,
|
||||
dnsName: "example.com",
|
||||
intermediates: []string{criticalExtIntermediateWithExt},
|
||||
roots: []string{criticalExtRoot},
|
||||
currentTime: 1486684488,
|
||||
systemSkip: true,
|
||||
disableCriticalExtensionChecks: true,
|
||||
|
||||
expectedChains: [][]string{
|
||||
{
|
||||
"example.com",
|
||||
"Intermediate with Critical Extension",
|
||||
"Root",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
|
||||
@ -414,7 +461,7 @@ func expectHashError(t *testing.T, i int, err error) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func expectSubjectIssuerMismatcthError(t *testing.T, i int, err error) (ok bool) {
|
||||
func expectSubjectIssuerMismatchError(t *testing.T, i int, err error) (ok bool) {
|
||||
if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != NameMismatch {
|
||||
t.Errorf("#%d: error was not a NameMismatch: %s", i, err)
|
||||
return false
|
||||
@ -467,11 +514,13 @@ func testVerify(t *testing.T, useSystemRoots bool) {
|
||||
}
|
||||
|
||||
opts := VerifyOptions{
|
||||
Intermediates: NewCertPool(),
|
||||
DNSName: test.dnsName,
|
||||
CurrentTime: time.Unix(test.currentTime, 0),
|
||||
KeyUsages: test.keyUsages,
|
||||
DisableTimeChecks: test.disableTimeChecks,
|
||||
Intermediates: NewCertPool(),
|
||||
DNSName: test.dnsName,
|
||||
CurrentTime: time.Unix(test.currentTime, 0),
|
||||
KeyUsages: test.keyUsages,
|
||||
DisableTimeChecks: test.disableTimeChecks,
|
||||
DisableCriticalExtensionChecks: test.disableCriticalExtensionChecks,
|
||||
DisableNameChecks: test.disableNameChecks,
|
||||
}
|
||||
|
||||
if !useSystemRoots {
|
||||
|
107
vendor/github.com/google/certificate-transparency-go/x509/x509.go
generated
vendored
107
vendor/github.com/google/certificate-transparency-go/x509/x509.go
generated
vendored
@ -737,7 +737,9 @@ type Certificate struct {
|
||||
OCSPServer []string
|
||||
IssuingCertificateURL []string
|
||||
|
||||
// Subject Alternate Name values
|
||||
// Subject Alternate Name values. (Note that these values may not be valid
|
||||
// if invalid values were contained within a parsed certificate. For
|
||||
// example, an element of DNSNames may not be a valid DNS domain name.)
|
||||
DNSNames []string
|
||||
EmailAddresses []string
|
||||
IPAddresses []net.IP
|
||||
@ -792,6 +794,20 @@ func (c *Certificate) Equal(other *Certificate) bool {
|
||||
return bytes.Equal(c.Raw, other.Raw)
|
||||
}
|
||||
|
||||
// IsPrecertificate checks whether the certificate is a precertificate, by
|
||||
// checking for the presence of the CT Poison extension.
|
||||
func (c *Certificate) IsPrecertificate() bool {
|
||||
if c == nil {
|
||||
return false
|
||||
}
|
||||
for _, ext := range c.Extensions {
|
||||
if ext.Id.Equal(OIDExtensionCTPoison) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Certificate) hasSANExtension() bool {
|
||||
return oidInExtensions(OIDExtensionSubjectAltName, c.Extensions)
|
||||
}
|
||||
@ -995,6 +1011,50 @@ func (h UnhandledCriticalExtension) Error() string {
|
||||
return fmt.Sprintf("x509: unhandled critical extension (%v)", h.ID)
|
||||
}
|
||||
|
||||
// removeExtension takes a DER-encoded TBSCertificate, removes the extension
|
||||
// specified by oid (preserving the order of other extensions), and returns the
|
||||
// result still as a DER-encoded TBSCertificate. This function will fail if
|
||||
// there is not exactly 1 extension of the type specified by the oid present.
|
||||
func removeExtension(tbsData []byte, oid asn1.ObjectIdentifier) ([]byte, error) {
|
||||
var tbs tbsCertificate
|
||||
rest, err := asn1.Unmarshal(tbsData, &tbs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse TBSCertificate: %v", err)
|
||||
} else if rLen := len(rest); rLen > 0 {
|
||||
return nil, fmt.Errorf("trailing data (%d bytes) after TBSCertificate", rLen)
|
||||
}
|
||||
extAt := -1
|
||||
for i, ext := range tbs.Extensions {
|
||||
if ext.Id.Equal(oid) {
|
||||
if extAt != -1 {
|
||||
return nil, errors.New("multiple extensions of specified type present")
|
||||
}
|
||||
extAt = i
|
||||
}
|
||||
}
|
||||
if extAt == -1 {
|
||||
return nil, errors.New("no extension of specified type present")
|
||||
}
|
||||
tbs.Extensions = append(tbs.Extensions[:extAt], tbs.Extensions[extAt+1:]...)
|
||||
// Clear out the asn1.RawContent so the re-marshal operation sees the
|
||||
// updated structure (rather than just copying the out-of-date DER data).
|
||||
tbs.Raw = nil
|
||||
|
||||
data, err := asn1.Marshal(tbs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to re-marshal TBSCertificate: %v", err)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// RemoveSCTList takes a DER-encoded TBSCertificate and removes the CT SCT
|
||||
// extension that contains the SCT list (preserving the order of other
|
||||
// extensions), and returns the result still as a DER-encoded TBSCertificate.
|
||||
// This function will fail if there is not exactly 1 CT SCT extension present.
|
||||
func RemoveSCTList(tbsData []byte) ([]byte, error) {
|
||||
return removeExtension(tbsData, OIDExtensionCTSCT)
|
||||
}
|
||||
|
||||
// RemoveCTPoison takes a DER-encoded TBSCertificate and removes the CT poison
|
||||
// extension (preserving the order of other extensions), and returns the result
|
||||
// still as a DER-encoded TBSCertificate. This function will fail if there is
|
||||
@ -1019,27 +1079,18 @@ func RemoveCTPoison(tbsData []byte) ([]byte, error) {
|
||||
// - The precert's AuthorityKeyId is changed to the AuthorityKeyId of the
|
||||
// intermediate.
|
||||
func BuildPrecertTBS(tbsData []byte, preIssuer *Certificate) ([]byte, error) {
|
||||
data, err := removeExtension(tbsData, OIDExtensionCTPoison)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var tbs tbsCertificate
|
||||
rest, err := asn1.Unmarshal(tbsData, &tbs)
|
||||
rest, err := asn1.Unmarshal(data, &tbs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse TBSCertificate: %v", err)
|
||||
} else if rLen := len(rest); rLen > 0 {
|
||||
return nil, fmt.Errorf("trailing data (%d bytes) after TBSCertificate", rLen)
|
||||
}
|
||||
poisonAt := -1
|
||||
for i, ext := range tbs.Extensions {
|
||||
if ext.Id.Equal(OIDExtensionCTPoison) {
|
||||
if poisonAt != -1 {
|
||||
return nil, errors.New("multiple CT poison extensions present")
|
||||
}
|
||||
poisonAt = i
|
||||
}
|
||||
}
|
||||
if poisonAt == -1 {
|
||||
return nil, errors.New("no CT poison extension present")
|
||||
}
|
||||
tbs.Extensions = append(tbs.Extensions[:poisonAt], tbs.Extensions[poisonAt+1:]...)
|
||||
tbs.Raw = nil
|
||||
|
||||
if preIssuer != nil {
|
||||
// Update the precert's Issuer field. Use the RawIssuer rather than the
|
||||
@ -1092,9 +1143,13 @@ func BuildPrecertTBS(tbsData []byte, preIssuer *Certificate) ([]byte, error) {
|
||||
}
|
||||
tbs.Extensions = append(tbs.Extensions, authKeyIDExt)
|
||||
}
|
||||
|
||||
// Clear out the asn1.RawContent so the re-marshal operation sees the
|
||||
// updated structure (rather than just copying the out-of-date DER data).
|
||||
tbs.Raw = nil
|
||||
}
|
||||
|
||||
data, err := asn1.Marshal(tbs)
|
||||
data, err = asn1.Marshal(tbs)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to re-marshal TBSCertificate: %v", err)
|
||||
}
|
||||
@ -1235,7 +1290,7 @@ type NonFatalErrors struct {
|
||||
Errors []error
|
||||
}
|
||||
|
||||
// Adds an error to the list of errors contained by NonFatalErrors.
|
||||
// AddError adds an error to the list of errors contained by NonFatalErrors.
|
||||
func (e *NonFatalErrors) AddError(err error) {
|
||||
e.Errors = append(e.Errors, err)
|
||||
}
|
||||
@ -1250,7 +1305,7 @@ func (e NonFatalErrors) Error() string {
|
||||
return r
|
||||
}
|
||||
|
||||
// Returns true if |e| contains at least one error
|
||||
// HasError returns true if |e| contains at least one error
|
||||
func (e *NonFatalErrors) HasError() bool {
|
||||
return len(e.Errors) > 0
|
||||
}
|
||||
@ -1337,17 +1392,9 @@ func parseSANExtension(value []byte, nfe *NonFatalErrors) (dnsNames, emailAddres
|
||||
err = forEachSAN(value, func(tag int, data []byte) error {
|
||||
switch tag {
|
||||
case nameTypeEmail:
|
||||
mailbox := string(data)
|
||||
if _, ok := parseRFC2821Mailbox(mailbox); !ok {
|
||||
return fmt.Errorf("x509: cannot parse rfc822Name %q", mailbox)
|
||||
}
|
||||
emailAddresses = append(emailAddresses, mailbox)
|
||||
emailAddresses = append(emailAddresses, string(data))
|
||||
case nameTypeDNS:
|
||||
domain := string(data)
|
||||
if _, ok := domainToReverseLabels(domain); !ok {
|
||||
return fmt.Errorf("x509: cannot parse dnsName %q", string(data))
|
||||
}
|
||||
dnsNames = append(dnsNames, domain)
|
||||
dnsNames = append(dnsNames, string(data))
|
||||
case nameTypeURI:
|
||||
uri, err := url.Parse(string(data))
|
||||
if err != nil {
|
||||
@ -1364,7 +1411,7 @@ func parseSANExtension(value []byte, nfe *NonFatalErrors) (dnsNames, emailAddres
|
||||
case net.IPv4len, net.IPv6len:
|
||||
ipAddresses = append(ipAddresses, data)
|
||||
default:
|
||||
nfe.AddError(fmt.Errorf("x509: certificate contained IP address of length %d : %v", len(data), data))
|
||||
nfe.AddError(errors.New("x509: cannot parse IP address of length " + strconv.Itoa(len(data))))
|
||||
}
|
||||
}
|
||||
|
||||
|
65
vendor/github.com/google/certificate-transparency-go/x509/x509_test.go
generated
vendored
65
vendor/github.com/google/certificate-transparency-go/x509/x509_test.go
generated
vendored
@ -1085,7 +1085,8 @@ func TestRSAPSSSelfSigned(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
const pemCertificate = `-----BEGIN CERTIFICATE-----
|
||||
const (
|
||||
pemCertificate = `-----BEGIN CERTIFICATE-----
|
||||
MIIDATCCAemgAwIBAgIRAKQkkrFx1T/dgB/Go/xBM5swDQYJKoZIhvcNAQELBQAw
|
||||
EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA4MTcyMDM2MDdaFw0xNzA4MTcyMDM2
|
||||
MDdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||
@ -1104,6 +1105,64 @@ fnnktsblSUV4lRCit0ymC7Ojhe+gzCCwkgs5kDzVVag+tnl/0e2DloIjASwOhpbH
|
||||
KVcg7fBd484ht/sS+l0dsB4KDOSpd8JzVDMF8OZqlaydizoJO0yWr9GbCN1+OKq5
|
||||
EhLrEqU=
|
||||
-----END CERTIFICATE-----`
|
||||
pemPrecertificate = `-----BEGIN CERTIFICATE-----
|
||||
MIIC3zCCAkigAwIBAgIBBzANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
|
||||
MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
|
||||
YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
|
||||
MDAwMDBaMFIxCzAJBgNVBAYTAkdCMSEwHwYDVQQKExhDZXJ0aWZpY2F0ZSBUcmFu
|
||||
c3BhcmVuY3kxDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGfMA0G
|
||||
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+75jnwmh3rjhfdTJaDB0ym+3xj6r015a/
|
||||
BH634c4VyVui+A7kWL19uG+KSyUhkaeb1wDDjpwDibRc1NyaEgqyHgy0HNDnKAWk
|
||||
EM2cW9tdSSdyba8XEPYBhzd+olsaHjnu0LiBGdwVTcaPfajjDK8VijPmyVCfSgWw
|
||||
FAn/Xdh+tQIDAQABo4HBMIG+MB0GA1UdDgQWBBQgMVQa8lwF/9hli2hDeU9ekDb3
|
||||
tDB9BgNVHSMEdjB0gBRfnYgNyHPmVNT4DdjmsMEktEfDVaFZpFcwVTELMAkGA1UE
|
||||
BhMCR0IxJDAiBgNVBAoTG0NlcnRpZmljYXRlIFRyYW5zcGFyZW5jeSBDQTEOMAwG
|
||||
A1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW6CAQAwCQYDVR0TBAIwADATBgor
|
||||
BgEEAdZ5AgQDAQH/BAIFADANBgkqhkiG9w0BAQUFAAOBgQACocOeAVr1Tf8CPDNg
|
||||
h1//NDdVLx8JAb3CVDFfM3K3I/sV+87MTfRxoM5NjFRlXYSHl/soHj36u0YtLGhL
|
||||
BW/qe2O0cP8WbjLURgY1s9K8bagkmyYw5x/DTwjyPdTuIo+PdPY9eGMR3QpYEUBf
|
||||
kGzKLC0+6/yBmWTr2M98CIY/vg==
|
||||
-----END CERTIFICATE-----`
|
||||
)
|
||||
|
||||
func TestIsPrecertificate(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
certPEM string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
desc: "certificate",
|
||||
certPEM: pemCertificate,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
desc: "precertificate",
|
||||
certPEM: pemPrecertificate,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
desc: "nil",
|
||||
certPEM: "",
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
var cert *Certificate
|
||||
if test.certPEM != "" {
|
||||
var err error
|
||||
cert, err = certificateFromPEM(test.certPEM)
|
||||
if err != nil {
|
||||
t.Errorf("%s: error parsing certificate: %s", test.desc, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if got := cert.IsPrecertificate(); got != test.want {
|
||||
t.Errorf("%s: c.IsPrecertificate() = %t, want %t", test.desc, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCRLCreation(t *testing.T) {
|
||||
block, _ := pem.Decode([]byte(pemPrivateKey))
|
||||
@ -1338,8 +1397,8 @@ func TestRemoveCTPoison(t *testing.T) {
|
||||
}{
|
||||
{name: "invalid-der", tbs: "01020304", errstr: "failed to parse"},
|
||||
{name: "trailing-data", tbs: tbsPoisonMiddle + "01020304", errstr: "trailing data"},
|
||||
{name: "no-poison-ext", tbs: tbsNoPoison, errstr: "no CT poison extension present"},
|
||||
{name: "two-poison-exts", tbs: tbsPoisonTwice, errstr: "multiple CT poison extensions present"},
|
||||
{name: "no-poison-ext", tbs: tbsNoPoison, errstr: "no extension of specified type present"},
|
||||
{name: "two-poison-exts", tbs: tbsPoisonTwice, errstr: "multiple extensions of specified type present"},
|
||||
{name: "poison-first", tbs: tbsPoisonFirst, want: tbsNoPoison},
|
||||
{name: "poison-last", tbs: tbsPoisonLast, want: tbsNoPoison},
|
||||
{name: "poison-middle", tbs: tbsPoisonMiddle, want: tbsNoPoison},
|
||||
|
Reference in New Issue
Block a user