203 lines
4.7 KiB
Go
203 lines
4.7 KiB
Go
package csr
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"crypto/x509/pkix"
|
|
"errors"
|
|
"net"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/letsencrypt/boulder/core"
|
|
"github.com/letsencrypt/boulder/goodkey"
|
|
"github.com/letsencrypt/boulder/test"
|
|
)
|
|
|
|
var testingPolicy = &goodkey.KeyPolicy{
|
|
AllowRSA: true,
|
|
AllowECDSANISTP256: true,
|
|
AllowECDSANISTP384: true,
|
|
}
|
|
|
|
type mockPA struct{}
|
|
|
|
func (pa *mockPA) ChallengesFor(identifier core.AcmeIdentifier, registrationID int64, revalidation bool) (challenges []core.Challenge, combinations [][]int, err error) {
|
|
return
|
|
}
|
|
|
|
func (pa *mockPA) WillingToIssue(id core.AcmeIdentifier) error {
|
|
if id.Value == "bad-name.com" || id.Value == "other-bad-name.com" {
|
|
return errors.New("")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (pa *mockPA) WillingToIssueWildcard(id core.AcmeIdentifier) error {
|
|
return nil
|
|
}
|
|
|
|
func (pa *mockPA) ChallengeTypeEnabled(t string, registrationID int64) bool {
|
|
return true
|
|
}
|
|
|
|
func TestVerifyCSR(t *testing.T) {
|
|
private, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
test.AssertNotError(t, err, "error generating test key")
|
|
signedReqBytes, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{PublicKey: private.PublicKey, SignatureAlgorithm: x509.SHA256WithRSA}, private)
|
|
test.AssertNotError(t, err, "error generating test CSR")
|
|
signedReq, err := x509.ParseCertificateRequest(signedReqBytes)
|
|
test.AssertNotError(t, err, "error parsing test CSR")
|
|
brokenSignedReq := new(x509.CertificateRequest)
|
|
*brokenSignedReq = *signedReq
|
|
brokenSignedReq.Signature = []byte{1, 1, 1, 1}
|
|
signedReqWithHosts := new(x509.CertificateRequest)
|
|
*signedReqWithHosts = *signedReq
|
|
signedReqWithHosts.DNSNames = []string{"a.com", "b.com"}
|
|
signedReqWithLongCN := new(x509.CertificateRequest)
|
|
*signedReqWithLongCN = *signedReq
|
|
signedReqWithLongCN.Subject.CommonName = strings.Repeat("a", maxCNLength+1)
|
|
signedReqWithBadNames := new(x509.CertificateRequest)
|
|
*signedReqWithBadNames = *signedReq
|
|
signedReqWithBadNames.DNSNames = []string{"bad-name.com", "other-bad-name.com"}
|
|
signedReqWithEmailAddress := new(x509.CertificateRequest)
|
|
*signedReqWithEmailAddress = *signedReq
|
|
signedReqWithEmailAddress.EmailAddresses = []string{"foo@bar.com"}
|
|
signedReqWithIPAddress := new(x509.CertificateRequest)
|
|
*signedReqWithIPAddress = *signedReq
|
|
signedReqWithIPAddress.IPAddresses = []net.IP{net.IPv4(1, 2, 3, 4)}
|
|
|
|
cases := []struct {
|
|
csr *x509.CertificateRequest
|
|
maxNames int
|
|
keyPolicy *goodkey.KeyPolicy
|
|
pa core.PolicyAuthority
|
|
regID int64
|
|
expectedError error
|
|
}{
|
|
{
|
|
&x509.CertificateRequest{},
|
|
100,
|
|
testingPolicy,
|
|
&mockPA{},
|
|
0,
|
|
invalidPubKey,
|
|
},
|
|
{
|
|
&x509.CertificateRequest{PublicKey: private.PublicKey},
|
|
100,
|
|
testingPolicy,
|
|
&mockPA{},
|
|
0,
|
|
unsupportedSigAlg,
|
|
},
|
|
{
|
|
brokenSignedReq,
|
|
100,
|
|
testingPolicy,
|
|
&mockPA{},
|
|
0,
|
|
invalidSig,
|
|
},
|
|
{
|
|
signedReq,
|
|
100,
|
|
testingPolicy,
|
|
&mockPA{},
|
|
0,
|
|
invalidNoDNS,
|
|
},
|
|
{
|
|
signedReqWithLongCN,
|
|
100,
|
|
testingPolicy,
|
|
&mockPA{},
|
|
0,
|
|
errors.New("CN was longer than 64 bytes"),
|
|
},
|
|
{
|
|
signedReqWithHosts,
|
|
1,
|
|
testingPolicy,
|
|
&mockPA{},
|
|
0,
|
|
errors.New("CSR contains more than 1 DNS names"),
|
|
},
|
|
{
|
|
signedReqWithBadNames,
|
|
100,
|
|
testingPolicy,
|
|
&mockPA{},
|
|
0,
|
|
errors.New("policy forbids issuing for: \"bad-name.com\", \"other-bad-name.com\""),
|
|
},
|
|
{
|
|
signedReqWithEmailAddress,
|
|
100,
|
|
testingPolicy,
|
|
&mockPA{},
|
|
0,
|
|
invalidEmailPresent,
|
|
},
|
|
{
|
|
signedReqWithIPAddress,
|
|
100,
|
|
testingPolicy,
|
|
&mockPA{},
|
|
0,
|
|
invalidIPPresent,
|
|
},
|
|
}
|
|
|
|
for _, c := range cases {
|
|
err := VerifyCSR(c.csr, c.maxNames, c.keyPolicy, c.pa, false, c.regID)
|
|
test.AssertDeepEquals(t, c.expectedError, err)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeCSR(t *testing.T) {
|
|
cases := []struct {
|
|
csr *x509.CertificateRequest
|
|
forceCN bool
|
|
expectedCN string
|
|
expectedNames []string
|
|
}{
|
|
{
|
|
&x509.CertificateRequest{DNSNames: []string{"a.com"}},
|
|
true,
|
|
"a.com",
|
|
[]string{"a.com"},
|
|
},
|
|
{
|
|
&x509.CertificateRequest{Subject: pkix.Name{CommonName: "A.com"}, DNSNames: []string{"a.com"}},
|
|
true,
|
|
"a.com",
|
|
[]string{"a.com"},
|
|
},
|
|
{
|
|
&x509.CertificateRequest{DNSNames: []string{"a.com"}},
|
|
false,
|
|
"",
|
|
[]string{"a.com"},
|
|
},
|
|
{
|
|
&x509.CertificateRequest{DNSNames: []string{"a.com", "a.com"}},
|
|
false,
|
|
"",
|
|
[]string{"a.com"},
|
|
},
|
|
{
|
|
&x509.CertificateRequest{Subject: pkix.Name{CommonName: "A.com"}, DNSNames: []string{"B.com"}},
|
|
false,
|
|
"a.com",
|
|
[]string{"a.com", "b.com"},
|
|
},
|
|
}
|
|
for _, c := range cases {
|
|
normalizeCSR(c.csr, c.forceCN)
|
|
test.AssertEquals(t, c.expectedCN, c.csr.Subject.CommonName)
|
|
test.AssertDeepEquals(t, c.expectedNames, c.csr.DNSNames)
|
|
}
|
|
}
|