Issue #43 and Issue #205

This commit is contained in:
Richard Barnes 2015-05-30 11:11:33 -04:00
parent a684177a09
commit 138c946bd6
2 changed files with 129 additions and 35 deletions

View File

@ -166,7 +166,14 @@ func (ra *RegistrationAuthorityImpl) NewCertificate(req core.CertificateRequest,
logEvent.CommonName = csr.Subject.CommonName
logEvent.Names = csr.DNSNames
csrPreviousDenied, err := ra.SA.AlreadyDeniedCSR(append(csr.DNSNames, csr.Subject.CommonName))
// Validate that authorization key is authorized for all domains
names := make([]string, len(csr.DNSNames))
copy(names, csr.DNSNames)
if len(csr.Subject.CommonName) > 0 {
names = append(names, csr.Subject.CommonName)
}
csrPreviousDenied, err := ra.SA.AlreadyDeniedCSR(names)
if err != nil {
logEvent.Error = err.Error()
return emptyCert, err
@ -220,12 +227,6 @@ func (ra *RegistrationAuthorityImpl) NewCertificate(req core.CertificateRequest,
}
logEvent.VerificationMethods = verificationMethods
// Validate that authorization key is authorized for all domains
names := csr.DNSNames
if len(csr.Subject.CommonName) > 0 {
names = append(names, csr.Subject.CommonName)
}
// Validate all domains
for _, name := range names {
if !authorizedDomains[name] {

View File

@ -112,11 +112,33 @@ var (
ExampleCSR = &x509.CertificateRequest{}
// These values are populated by the tests as we go
AuthzInitial = core.Authorization{}
url0, _ = url.Parse("http://acme.invalid/authz/60p2Dc_XmUB2UUJBV4wYkF7BJbPD9KlDnUL3SmFMuTE?challenge=0")
url1, _ = url.Parse("http://acme.invalid/authz/60p2Dc_XmUB2UUJBV4wYkF7BJbPD9KlDnUL3SmFMuTE?challenge=0")
Registration = core.Registration{}
AuthzInitial = core.Authorization{
ID: "60p2Dc_XmUB2UUJBV4wYkF7BJbPD9KlDnUL3SmFMuTE",
Identifier: core.AcmeIdentifier{Type: "dns", Value: "not-example.com"},
RegistrationID: 1,
Status: "pending",
Challenges: []core.Challenge{
core.Challenge{
Type: "simpleHttps",
Status: "pending",
URI: core.AcmeURL(*url0),
Token: "pDX9vBFJ043_gEc9Wyp8of-SqZMN2H3-fvj5iUgP7mg",
},
core.Challenge{
Type: "dvsni",
Status: "pending",
URI: core.AcmeURL(*url1),
R: "AI83O7gCMPDr4z7OIdl8T6axx6nui4HV1aAFQ5LJvVs",
Nonce: "f011c9a0ce1a4fe0f18f2252d64c4239",
},
},
Combinations: [][]int{[]int{0}, []int{1}},
}
AuthzUpdated = core.Authorization{}
AuthzFromVA = core.Authorization{}
AuthzFinal = core.Authorization{}
AuthzFinalWWW = core.Authorization{}
)
func initAuthorities(t *testing.T) (core.CertificateAuthority, *DummyValidationAuthority, *sa.SQLStorageAuthority, core.RegistrationAuthority) {
@ -148,13 +170,24 @@ func initAuthorities(t *testing.T) (core.CertificateAuthority, *DummyValidationA
ExampleCSR, _ = x509.ParseCertificateRequest(csrDER)
// This registration implicitly gets ID = 1
sa.NewRegistration(core.Registration{Key: AccountKey})
Registration, _ = sa.NewRegistration(core.Registration{Key: AccountKey})
ra := NewRegistrationAuthorityImpl()
ra.SA = sa
ra.VA = va
ra.CA = &ca
ra.PA = pa
ra.AuthzBase = "http://acme.invalid/authz/"
AuthzInitial.RegistrationID = Registration.ID
AuthzUpdated = AuthzInitial
AuthzUpdated.Challenges[0].Path = "Hf5GrX4Q7EBax9hc2jJnfw"
AuthzFinal = AuthzUpdated
AuthzFinal.Status = "valid"
AuthzFinal.Expires = time.Now().Add(24 * time.Hour)
AuthzFinal.Challenges[0].Status = "valid"
return &ca, va, sa, &ra
}
@ -164,7 +197,7 @@ func assertAuthzEqual(t *testing.T, a1, a2 core.Authorization) {
test.Assert(t, a1.Identifier == a2.Identifier, "ret != DB: Identifier")
test.Assert(t, a1.Status == a2.Status, "ret != DB: Status")
test.Assert(t, a1.RegistrationID == a2.RegistrationID, "ret != DB: RegID")
// Not testing: Contact, Challenges
// Not testing: Challenges
}
func TestNewRegistration(t *testing.T) {
@ -217,7 +250,6 @@ func TestNewRegistrationNoFieldOverwrite(t *testing.T) {
test.AssertNotError(t, err, "Could not update registration")
test.Assert(t, result2.ID != 33, "ID shouldn't be overwritten.")
test.Assert(t, !core.KeyDigestEquals(result2.Key, ShortKey), "Key shouldn't be overwritten")
test.Assert(t, result2.RecoveryToken != "RecoverMe2", "Recovery token shouldn't be overwritten by user")
}
@ -258,6 +290,7 @@ func TestNewAuthorization(t *testing.T) {
test.Assert(t, authz.Challenges[1].Type == core.ChallengeTypeDVSNI, "Challenge 1 not DVSNI")
// If we get to here, we'll use this authorization for the next test
fmt.Printf("AuthzInitial: %+v\n", authz)
AuthzInitial = authz
// TODO Test failure cases
@ -286,9 +319,6 @@ func TestUpdateAuthorization(t *testing.T) {
simpleHttps := va.Argument.Challenges[0]
test.Assert(t, simpleHttps.Path == Response.Path, "simpleHttps changed")
// If we get to here, we'll use this authorization for the next test
AuthzUpdated = authz
// TODO Test failure cases
t.Log("DONE TestUpdateAuthorization")
}
@ -299,22 +329,19 @@ func TestOnValidationUpdate(t *testing.T) {
sa.UpdatePendingAuthorization(AuthzUpdated)
// Simulate a successful simpleHTTPS challenge
AuthzFromVA = AuthzUpdated
AuthzFromVA.Challenges[0].Status = core.StatusValid
authzFromVA := AuthzUpdated
authzFromVA.Challenges[0].Status = core.StatusValid
ra.OnValidationUpdate(AuthzFromVA)
ra.OnValidationUpdate(authzFromVA)
// Verify that the Authz in the DB is the same except for Status->StatusValid
AuthzFromVA.Status = core.StatusValid
dbAuthz, err := sa.GetAuthorization(AuthzFromVA.ID)
authzFromVA.Status = core.StatusValid
dbAuthz, err := sa.GetAuthorization(authzFromVA.ID)
test.AssertNotError(t, err, "Could not fetch authorization from database")
assertAuthzEqual(t, AuthzFromVA, dbAuthz)
t.Log(" ~~> from VA: ", AuthzFromVA.Status)
assertAuthzEqual(t, authzFromVA, dbAuthz)
t.Log(" ~~> from VA: ", authzFromVA.Status)
t.Log(" ~~> from DB: ", dbAuthz.Status)
// If we get to here, we'll use this authorization for the next test
AuthzFinal = dbAuthz
// TODO Test failure cases
t.Log("DONE TestOnValidationUpdate")
}
@ -348,6 +375,31 @@ func TestCertificateKeyNotEqualAccountKey(t *testing.T) {
_, err = ra.NewCertificate(certRequest, 1)
test.AssertError(t, err, "Should have rejected cert with key = account key")
test.AssertEquals(t, err.Error(), "Certificate public key must be different than account key")
t.Log("DONE TestCertificateKeyNotEqualAccountKey")
}
func TestAuthorizationRequired(t *testing.T) {
_, _, sa, ra := initAuthorities(t)
AuthzFinal.RegistrationID = 1
AuthzFinal, _ = sa.NewPendingAuthorization(AuthzFinal)
sa.UpdatePendingAuthorization(AuthzFinal)
sa.FinalizeAuthorization(AuthzFinal)
// Construct a cert request referencing the authorization
url1, _ := url.Parse("http://doesnt.matter/" + AuthzFinal.ID)
// ExampleCSR requests not-example.com and www.not-example.com,
// but the authorization only covers not-example.com
certRequest := core.CertificateRequest{
CSR: ExampleCSR,
Authorizations: []core.AcmeURL{core.AcmeURL(*url1)},
}
_, err := ra.NewCertificate(certRequest, 1)
test.Assert(t, err != nil, "Issued certificate with insufficient authorization")
t.Log("DONE TestAuthorizationRequired")
}
func TestNewCertificate(t *testing.T) {
@ -358,14 +410,14 @@ func TestNewCertificate(t *testing.T) {
sa.FinalizeAuthorization(AuthzFinal)
// Inject another final authorization to cover www.example.com
AuthzFinalWWW = AuthzFinal
AuthzFinalWWW.Identifier.Value = "www.example.com"
AuthzFinalWWW, _ = sa.NewPendingAuthorization(AuthzFinalWWW)
sa.FinalizeAuthorization(AuthzFinalWWW)
authzFinalWWW := AuthzFinal
authzFinalWWW.Identifier.Value = "www.not-example.com"
authzFinalWWW, _ = sa.NewPendingAuthorization(authzFinalWWW)
sa.FinalizeAuthorization(authzFinalWWW)
// Construct a cert request referencing the two authorizations
url1, _ := url.Parse("http://doesnt.matter/" + AuthzFinal.ID)
url2, _ := url.Parse("http://doesnt.matter/" + AuthzFinalWWW.ID)
url2, _ := url.Parse("http://doesnt.matter/" + authzFinalWWW.ID)
certRequest := core.CertificateRequest{
CSR: ExampleCSR,
@ -374,16 +426,25 @@ func TestNewCertificate(t *testing.T) {
cert, err := ra.NewCertificate(certRequest, 1)
test.AssertNotError(t, err, "Failed to issue certificate")
if err != nil {
return
}
parsedCert, err := x509.ParseCertificate(cert.DER)
test.AssertNotError(t, err, "Failed to parse certificate")
if err != nil {
return
}
// Verify that cert shows up and is as expected
dbCert, err := sa.GetCertificate(core.SerialToString(parsedCert.SerialNumber))
test.AssertNotError(t, err, fmt.Sprintf("Could not fetch certificate %032x from database",
parsedCert.SerialNumber))
if err != nil {
return
}
test.Assert(t, bytes.Compare(cert.DER, dbCert) == 0, "Certificates differ")
// TODO Test failure cases
t.Log("DONE TestOnValidationUpdate")
}
@ -476,7 +537,8 @@ var CA_CERT_PEM = "-----BEGIN CERTIFICATE-----\n" +
// CSR generated by Go:
// * Random public key
// * CN = not-example.com
// * DNSNames = not-example.com
// * DNSNames = not-example.com, www.not-example.com
/*
var CSR_HEX = "3082028c30820174020100301a311830160603550403130f" +
"6e6f742d6578616d706c652e636f6d30820122300d06092a" +
"864886f70d01010105000382010f003082010a0282010100" +
@ -505,3 +567,34 @@ var CSR_HEX = "3082028c30820174020100301a311830160603550403130f" +
"53f07e1654e6077f4aaaf5c5b27edaf0385b48e0fc281424" +
"6363a01370c89e666169276eb133731cff2379d46d2fff9d" +
"f277b6d23fa24f9b"
*/
var CSR_HEX = "308202ae308201960201003027310b300906035504061302" +
"5553311830160603550403130f6e6f742d6578616d706c65" +
"2e636f6d30820122300d06092a864886f70d010101050003" +
"82010f003082010a0282010100a4f507b52ca2766e2cea7b" +
"aaada9c3e08ea3423d6617ae84df65b6ed7e6c031605851b" +
"f0a14f3461a9f1882de9808b8e59d639c85eec58dbe653e3" +
"855e94d81904b7ce6675a1930e0ea6537aa3936fdc9d9780" +
"bc9596e5ec183811b137f83f28781d619fae8471ff3db1ad" +
"5a4b5cbf96d127d0f16e3c6ccbb97c48b43a7ddfcc17fdf3" +
"eac049cc81e4703ba90ce15d3cdfd9d0a3b0ec138f1c06e0" +
"8212c94e6884480d4b8f16fcf38f1b10d942cfca558b322e" +
"d8896be3104fb40e6851f3b414929b4f54fae89668ab0cbf" +
"76b7eb94703b17a73c9189409b088e7d61f39560a413562e" +
"64f26b650aede2d27bd2bacfc55d6a106243ba6ce07046d4" +
"fda618881b0203010001a042304006092a864886f70d0109" +
"0e31333031302f0603551d1104283026820f6e6f742d6578" +
"616d706c652e636f6d82137777772e6e6f742d6578616d70" +
"6c652e636f6d300d06092a864886f70d01010b0500038201" +
"01006e168e521ea37595698ceab29a3815c57b301dcd9c86" +
"6fdc7cfb966afde87da52c699f43133a6abfbbeb031f1b02" +
"cb072c8543b73fdffff6ee002ed367fe3b09992ac496c4ef" +
"1b7487e68c25f66b8d1223a07feebfad8fd7f19727bff7b4" +
"02bf6bef705c0a48e800e15bafbc622cb62ee446814234a3" +
"ebf9b8ba3c094d64b64aaa1b2b955f769ce60e9e304f7781" +
"57814f2f1cb1c4e2ee58bcdc0640dd2f0ff387ddb61ed479" +
"7ea935e79638a63dd64bd36723f34c1e6725ae57d8ff63f8" +
"749ac154cfaa55b3d3cccd7d42994c922cbb171a43c7ab68" +
"5170d833829d28a574fb25ffcf0fd5d3f19becaef2223541" +
"c2a8e596a80c8cde27bc78e20d7171fe43d8"