Update cfssl to latest master.
Picks up fix for specifying User Notice policy qualifier. Specify user notice in test configs.
This commit is contained in:
parent
c41c0a6b41
commit
dd19f0a529
|
|
@ -12,51 +12,51 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/auth",
|
"ImportPath": "github.com/cloudflare/cfssl/auth",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/config",
|
"ImportPath": "github.com/cloudflare/cfssl/config",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs11key",
|
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs11key",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs12",
|
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs12",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs7",
|
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs7",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/csr",
|
"ImportPath": "github.com/cloudflare/cfssl/csr",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/errors",
|
"ImportPath": "github.com/cloudflare/cfssl/errors",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/helpers",
|
"ImportPath": "github.com/cloudflare/cfssl/helpers",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/info",
|
"ImportPath": "github.com/cloudflare/cfssl/info",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/log",
|
"ImportPath": "github.com/cloudflare/cfssl/log",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/ocsp",
|
"ImportPath": "github.com/cloudflare/cfssl/ocsp",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/cloudflare/cfssl/signer",
|
"ImportPath": "github.com/cloudflare/cfssl/signer",
|
||||||
"Rev": "6f428f654df58d23d1321bcbe3598f6b8a02167a"
|
"Rev": "fd649feb9eb317e3ed24afee0d92c0ea55bf4a33"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/codegangsta/cli",
|
"ImportPath": "github.com/codegangsta/cli",
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,19 @@ type CSRWhitelist struct {
|
||||||
// JSON marshal / unmarshal.
|
// JSON marshal / unmarshal.
|
||||||
type OID asn1.ObjectIdentifier
|
type OID asn1.ObjectIdentifier
|
||||||
|
|
||||||
// CertificatePolicy is a flattening of the ASN.1 PolicyInformation structure from
|
// CertificatePolicy represents the ASN.1 PolicyInformation structure from
|
||||||
// https://tools.ietf.org/html/rfc3280.html#page-106.
|
// https://tools.ietf.org/html/rfc3280.html#page-106.
|
||||||
// Valid values of Type are "id-qt-unotice" and "id-qt-cps"
|
// Valid values of Type are "id-qt-unotice" and "id-qt-cps"
|
||||||
type CertificatePolicy struct {
|
type CertificatePolicy struct {
|
||||||
ID OID
|
ID OID
|
||||||
|
Qualifiers []CertificatePolicyQualifier
|
||||||
|
}
|
||||||
|
|
||||||
|
// CertificatePolicyQualifier represents a single qualifier from an ASN.1
|
||||||
|
// PolicyInformation structure.
|
||||||
|
type CertificatePolicyQualifier struct {
|
||||||
Type string
|
Type string
|
||||||
Qualifier string
|
Value string
|
||||||
}
|
}
|
||||||
|
|
||||||
// A SigningProfile stores information that the CA needs to store
|
// A SigningProfile stores information that the CA needs to store
|
||||||
|
|
@ -62,6 +68,7 @@ type SigningProfile struct {
|
||||||
RemoteName string `json:"remote"`
|
RemoteName string `json:"remote"`
|
||||||
NotBefore time.Time `json:"not_before"`
|
NotBefore time.Time `json:"not_before"`
|
||||||
NotAfter time.Time `json:"not_after"`
|
NotAfter time.Time `json:"not_after"`
|
||||||
|
NameWhitelistString string `json:"name_whitelist"`
|
||||||
|
|
||||||
Policies []CertificatePolicy
|
Policies []CertificatePolicy
|
||||||
Expiry time.Duration
|
Expiry time.Duration
|
||||||
|
|
@ -70,6 +77,7 @@ type SigningProfile struct {
|
||||||
RemoteServer string
|
RemoteServer string
|
||||||
UseSerialSeq bool
|
UseSerialSeq bool
|
||||||
CSRWhitelist *CSRWhitelist
|
CSRWhitelist *CSRWhitelist
|
||||||
|
NameWhitelist *regexp.Regexp
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals a JSON string into an OID.
|
// UnmarshalJSON unmarshals a JSON string into an OID.
|
||||||
|
|
@ -162,8 +170,11 @@ func (p *SigningProfile) populate(cfg *Config) error {
|
||||||
|
|
||||||
if len(p.Policies) > 0 {
|
if len(p.Policies) > 0 {
|
||||||
for _, policy := range p.Policies {
|
for _, policy := range p.Policies {
|
||||||
if policy.Type != "" && policy.Type != "id-qt-unotice" && policy.Type != "id-qt-cps" {
|
for _, qualifier := range policy.Qualifiers {
|
||||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
|
if qualifier.Type != "" && qualifier.Type != "id-qt-unotice" && qualifier.Type != "id-qt-cps" {
|
||||||
|
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||||
|
errors.New("invalid policy qualifier type"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -200,6 +211,16 @@ func (p *SigningProfile) populate(cfg *Config) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.NameWhitelistString != "" {
|
||||||
|
log.Debug("compiling whitelist regular expression")
|
||||||
|
rule, err := regexp.Compile(p.NameWhitelistString)
|
||||||
|
if err != nil {
|
||||||
|
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||||
|
errors.New("failed to compile name whitelist section"))
|
||||||
|
}
|
||||||
|
p.NameWhitelist = rule
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,20 @@ func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
||||||
OverrideHosts(&safeTemplate, req.Hosts)
|
OverrideHosts(&safeTemplate, req.Hosts)
|
||||||
safeTemplate.Subject = PopulateSubjectFromCSR(req.Subject, safeTemplate.Subject)
|
safeTemplate.Subject = PopulateSubjectFromCSR(req.Subject, safeTemplate.Subject)
|
||||||
|
|
||||||
|
// If there is a whitelist, ensure that both the Common Name and SAN DNSNames match
|
||||||
|
if profile.NameWhitelist != nil {
|
||||||
|
if safeTemplate.Subject.CommonName != "" {
|
||||||
|
if profile.NameWhitelist.Find([]byte(safeTemplate.Subject.CommonName)) == nil {
|
||||||
|
return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, name := range safeTemplate.DNSNames {
|
||||||
|
if profile.NameWhitelist.Find([]byte(name)) == nil {
|
||||||
|
return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return s.sign(&safeTemplate, profile, serialSeq)
|
return s.sign(&safeTemplate, profile, serialSeq)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -807,3 +808,75 @@ func TestWhitelistSign(t *testing.T) {
|
||||||
cert.SignatureAlgorithm)
|
cert.SignatureAlgorithm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNameWhitelistSign(t *testing.T) {
|
||||||
|
csrPEM, err := ioutil.ReadFile(fullSubjectCSR)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
subInvalid := &signer.Subject{
|
||||||
|
CN: "localhost.com",
|
||||||
|
}
|
||||||
|
subValid := &signer.Subject{
|
||||||
|
CN: "1lab41.cf",
|
||||||
|
}
|
||||||
|
|
||||||
|
wl := regexp.MustCompile("^1[a-z]*[0-9]*\\.cf$")
|
||||||
|
|
||||||
|
s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)
|
||||||
|
// Whitelist only key-related fields. Subject, DNSNames, etc shouldn't get
|
||||||
|
// passed through from CSR.
|
||||||
|
s.policy = &config.Signing{
|
||||||
|
Default: &config.SigningProfile{
|
||||||
|
Usage: []string{"cert sign", "crl sign"},
|
||||||
|
ExpiryString: "1h",
|
||||||
|
Expiry: 1 * time.Hour,
|
||||||
|
CA: true,
|
||||||
|
NameWhitelist: wl,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
request := signer.SignRequest{
|
||||||
|
Hosts: []string{"127.0.0.1", "1machine23.cf"},
|
||||||
|
Request: string(csrPEM),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = s.Sign(request)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
request = signer.SignRequest{
|
||||||
|
Hosts: []string{"invalid.cf", "1machine23.cf"},
|
||||||
|
Request: string(csrPEM),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = s.Sign(request)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected a policy error")
|
||||||
|
}
|
||||||
|
|
||||||
|
request = signer.SignRequest{
|
||||||
|
Hosts: []string{"1machine23.cf"},
|
||||||
|
Request: string(csrPEM),
|
||||||
|
Subject: subInvalid,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = s.Sign(request)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected a policy error")
|
||||||
|
}
|
||||||
|
|
||||||
|
request = signer.SignRequest{
|
||||||
|
Hosts: []string{"1machine23.cf"},
|
||||||
|
Request: string(csrPEM),
|
||||||
|
Subject: subValid,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = s.Sign(request)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,9 +83,9 @@ func (s *Signer) remoteOp(req interface{}, profile, target string) (resp interfa
|
||||||
if target == "info" {
|
if target == "info" {
|
||||||
resp, err = server.Info(jsonData)
|
resp, err = server.Info(jsonData)
|
||||||
} else if p.Provider != nil {
|
} else if p.Provider != nil {
|
||||||
resp, err = server.AuthReq(jsonData, nil, p.Provider, target)
|
resp, err = server.AuthSign(jsonData, nil, p.Provider)
|
||||||
} else {
|
} else {
|
||||||
resp, err = server.Req(jsonData, target)
|
resp, err = server.Sign(jsonData)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -27,19 +27,11 @@ import (
|
||||||
// MaxPathLen is the default path length for a new CA certificate.
|
// MaxPathLen is the default path length for a new CA certificate.
|
||||||
var MaxPathLen = 2
|
var MaxPathLen = 2
|
||||||
|
|
||||||
// A Whitelist marks which fields should be set. As a bool's default
|
|
||||||
// value is false, a whitelist should only keep those fields marked
|
|
||||||
// true.
|
|
||||||
type Whitelist struct {
|
|
||||||
CN, C, ST, L, O, OU bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subject contains the information that should be used to override the
|
// Subject contains the information that should be used to override the
|
||||||
// subject information when signing a certificate.
|
// subject information when signing a certificate.
|
||||||
type Subject struct {
|
type Subject struct {
|
||||||
CN string
|
CN string
|
||||||
Names []csr.Name `json:"names"`
|
Names []csr.Name `json:"names"`
|
||||||
Whitelist *Whitelist `json:"whitelist,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignRequest stores a signature request, which contains the hostname,
|
// SignRequest stores a signature request, which contains the hostname,
|
||||||
|
|
@ -351,13 +343,26 @@ func FillTemplate(template *x509.Certificate, defaultProfile, profile *config.Si
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type policyQualifier struct {
|
type policyInformation struct {
|
||||||
|
PolicyIdentifier asn1.ObjectIdentifier
|
||||||
|
Qualifiers []interface{}
|
||||||
|
CPSPolicyQualifiers []cpsPolicyQualifier `asn1:"omitempty"`
|
||||||
|
// User Notice policy qualifiers have a slightly different ASN.1 structure
|
||||||
|
// from that used for CPS policy qualifiers.
|
||||||
|
UserNoticePolicyQualifiers []userNoticePolicyQualifier `asn1:"omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type cpsPolicyQualifier struct {
|
||||||
PolicyQualifierID asn1.ObjectIdentifier
|
PolicyQualifierID asn1.ObjectIdentifier
|
||||||
Qualifier string `asn1:"tag:optional,ia5"`
|
Qualifier string `asn1:"tag:optional,ia5"`
|
||||||
}
|
}
|
||||||
type policyInformation struct {
|
|
||||||
PolicyIdentifier asn1.ObjectIdentifier
|
type userNotice struct {
|
||||||
PolicyQualifiers []policyQualifier `asn1:"omitempty"`
|
ExplicitText string `asn1:"tag:optional,utf8"`
|
||||||
|
}
|
||||||
|
type userNoticePolicyQualifier struct {
|
||||||
|
PolicyQualifierID asn1.ObjectIdentifier
|
||||||
|
Qualifier userNotice
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -382,26 +387,25 @@ func addPolicies(template *x509.Certificate, policies []config.CertificatePolicy
|
||||||
// The PolicyIdentifier is an OID assigned to a given issuer.
|
// The PolicyIdentifier is an OID assigned to a given issuer.
|
||||||
PolicyIdentifier: asn1.ObjectIdentifier(policy.ID),
|
PolicyIdentifier: asn1.ObjectIdentifier(policy.ID),
|
||||||
}
|
}
|
||||||
switch policy.Type {
|
for _, qualifier := range policy.Qualifiers {
|
||||||
|
switch qualifier.Type {
|
||||||
case "id-qt-unotice":
|
case "id-qt-unotice":
|
||||||
pi.PolicyQualifiers = []policyQualifier{
|
pi.Qualifiers = append(pi.Qualifiers,
|
||||||
policyQualifier{
|
userNoticePolicyQualifier{
|
||||||
PolicyQualifierID: iDQTUserNotice,
|
PolicyQualifierID: iDQTUserNotice,
|
||||||
Qualifier: policy.Qualifier,
|
Qualifier: userNotice{
|
||||||
|
ExplicitText: qualifier.Value,
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
case "id-qt-cps":
|
case "id-qt-cps":
|
||||||
pi.PolicyQualifiers = []policyQualifier{
|
pi.Qualifiers = append(pi.Qualifiers,
|
||||||
policyQualifier{
|
cpsPolicyQualifier{
|
||||||
PolicyQualifierID: iDQTCertificationPracticeStatement,
|
PolicyQualifierID: iDQTCertificationPracticeStatement,
|
||||||
Qualifier: policy.Qualifier,
|
Qualifier: qualifier.Value,
|
||||||
},
|
})
|
||||||
}
|
|
||||||
case "":
|
|
||||||
// Empty qualifier type is fine: Include this Certificate Policy, but
|
|
||||||
// don't include a Policy Qualifier.
|
|
||||||
default:
|
default:
|
||||||
return errors.New("Invalid qualifier type in Policies " + policy.Type)
|
return errors.New("Invalid qualifier type in Policies " + qualifier.Type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
asn1PolicyList = append(asn1PolicyList, pi)
|
asn1PolicyList = append(asn1PolicyList, pi)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,15 @@
|
||||||
package signer
|
package signer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/asn1"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSplitHosts(t *testing.T) {
|
func TestSplitHosts(t *testing.T) {
|
||||||
|
|
@ -23,3 +31,63 @@ func TestSplitHosts(t *testing.T) {
|
||||||
t.Fatal("SplitHost fails to split multiple domains")
|
t.Fatal("SplitHost fails to split multiple domains")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAddPolicies(t *testing.T) {
|
||||||
|
var cert x509.Certificate
|
||||||
|
addPolicies(&cert, []config.CertificatePolicy{
|
||||||
|
config.CertificatePolicy{
|
||||||
|
ID: config.OID{1, 2, 3, 4},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(cert.ExtraExtensions) != 1 {
|
||||||
|
t.Fatal("No extension added")
|
||||||
|
}
|
||||||
|
ext := cert.ExtraExtensions[0]
|
||||||
|
if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
|
||||||
|
t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
|
||||||
|
}
|
||||||
|
if ext.Critical {
|
||||||
|
t.Fatal("Policy qualifier marked critical")
|
||||||
|
}
|
||||||
|
expectedBytes, _ := hex.DecodeString("3009300706032a03043000")
|
||||||
|
if !bytes.Equal(ext.Value, expectedBytes) {
|
||||||
|
t.Fatal(fmt.Sprintf("Value didn't match expected bytes: %s vs %s",
|
||||||
|
hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddPoliciesWithQualifiers(t *testing.T) {
|
||||||
|
var cert x509.Certificate
|
||||||
|
addPolicies(&cert, []config.CertificatePolicy{
|
||||||
|
config.CertificatePolicy{
|
||||||
|
ID: config.OID{1, 2, 3, 4},
|
||||||
|
Qualifiers: []config.CertificatePolicyQualifier{
|
||||||
|
config.CertificatePolicyQualifier{
|
||||||
|
Type: "id-qt-cps",
|
||||||
|
Value: "http://example.com/cps",
|
||||||
|
},
|
||||||
|
config.CertificatePolicyQualifier{
|
||||||
|
Type: "id-qt-unotice",
|
||||||
|
Value: "Do What Thou Wilt",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if len(cert.ExtraExtensions) != 1 {
|
||||||
|
t.Fatal("No extension added")
|
||||||
|
}
|
||||||
|
ext := cert.ExtraExtensions[0]
|
||||||
|
if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
|
||||||
|
t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
|
||||||
|
}
|
||||||
|
if ext.Critical {
|
||||||
|
t.Fatal("Policy qualifier marked critical")
|
||||||
|
}
|
||||||
|
expectedBytes, _ := hex.DecodeString("304e304c06032a03043045302206082b060105050702011616687474703a2f2f6578616d706c652e636f6d2f637073301f06082b0601050507020230130c11446f20576861742054686f752057696c74")
|
||||||
|
if !bytes.Equal(ext.Value, expectedBytes) {
|
||||||
|
t.Fatal(fmt.Sprintf("Value didn't match expected bytes: %s vs %s",
|
||||||
|
hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,9 +74,14 @@
|
||||||
"ID": "2.23.140.1.2.1"
|
"ID": "2.23.140.1.2.1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ID": "1.3.6.1.4.1.44947.1.1.1",
|
"ID": "1.2.3.4",
|
||||||
|
"Qualifiers": [ {
|
||||||
"type": "id-qt-cps",
|
"type": "id-qt-cps",
|
||||||
"qualifier": "http://cps.root-x1.letsencrypt.org"
|
"value": "http://example.com/cps"
|
||||||
|
}, {
|
||||||
|
"type": "id-qt-unotice",
|
||||||
|
"value": "Do What Thou Wilt"
|
||||||
|
} ]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"expiry": "8760h",
|
"expiry": "8760h",
|
||||||
|
|
|
||||||
|
|
@ -74,11 +74,6 @@
|
||||||
{
|
{
|
||||||
"ID": "2.23.140.1.2.1"
|
"ID": "2.23.140.1.2.1"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ID": "1.3.6.1.4.1.44947.1.1.1",
|
|
||||||
"type": "id-qt-cps",
|
|
||||||
"qualifier": "http://cps.root-x1.letsencrypt.org"
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
"expiry": "8760h",
|
"expiry": "8760h",
|
||||||
"CSRWhitelist": {
|
"CSRWhitelist": {
|
||||||
|
|
|
||||||
|
|
@ -69,9 +69,14 @@
|
||||||
"ID": "2.23.140.1.2.1"
|
"ID": "2.23.140.1.2.1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ID": "1.3.6.1.4.1.44947.1.1.1",
|
"ID": "1.2.3.4",
|
||||||
|
"Qualifiers": [ {
|
||||||
"type": "id-qt-cps",
|
"type": "id-qt-cps",
|
||||||
"qualifier": "http://cps.root-x1.letsencrypt.org"
|
"value": "http://example.com/cps"
|
||||||
|
}, {
|
||||||
|
"type": "id-qt-unotice",
|
||||||
|
"value": "Do What Thou Wilt"
|
||||||
|
} ]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"expiry": "8760h",
|
"expiry": "8760h",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue