Merge pull request #664 from letsencrypt/sig-misuse

Mitigate signature misuse vulnerability
This commit is contained in:
Jacob Hoffman-Andrews 2015-08-28 16:18:56 -07:00
commit 5afb1187bf
11 changed files with 183 additions and 63 deletions

View File

@ -80,7 +80,7 @@ type RegistrationAuthority interface {
// ValidationAuthority defines the public interface for the Boulder VA // ValidationAuthority defines the public interface for the Boulder VA
type ValidationAuthority interface { type ValidationAuthority interface {
// [RegistrationAuthority] // [RegistrationAuthority]
UpdateValidations(Authorization, int, jose.JsonWebKey) error UpdateValidations(Authorization, int) error
CheckCAARecords(AcmeIdentifier) (bool, bool, error) CheckCAARecords(AcmeIdentifier) (bool, bool, error)
} }

View File

@ -269,6 +269,16 @@ type Challenge struct {
// Contains information about URLs used or redirected to and IPs resolved and // Contains information about URLs used or redirected to and IPs resolved and
// used // used
ValidationRecord []ValidationRecord `json:"validationRecord,omitempty"` ValidationRecord []ValidationRecord `json:"validationRecord,omitempty"`
// The account key used to create this challenge. This is not part of the
// spec, but clients are required to ignore unknown fields, so it's harmless
// to include.
//
// Boulder needs to remember what key was used to create a challenge in order
// to prevent an attacker from re-using a validation signature with a different,
// unauthorized key. See:
// https://mailarchive.ietf.org/arch/msg/acme/F71iz6qq1o_QPVhJCV4dqWf-4Yc
AccountKey *jose.JsonWebKey `json:"accountKey,omitempty"`
} }
// RecordsSane checks the sanity of a ValidationRecord object before sending it // RecordsSane checks the sanity of a ValidationRecord object before sending it
@ -311,6 +321,10 @@ func (ch Challenge) IsSane(completed bool) bool {
return false return false
} }
if ch.AccountKey == nil {
return false
}
switch ch.Type { switch ch.Type {
case ChallengeTypeSimpleHTTP: case ChallengeTypeSimpleHTTP:
// check extra fields aren't used // check extra fields aren't used

View File

@ -67,9 +67,22 @@ func TestRecordSanityCheck(t *testing.T) {
} }
func TestChallengeSanityCheck(t *testing.T) { func TestChallengeSanityCheck(t *testing.T) {
// Make a temporary account key
var accountKey *jose.JsonWebKey
err := json.Unmarshal([]byte(`{
"kty":"RSA",
"n":"yNWVhtYEKJR21y9xsHV-PD_bYwbXSeNuFal46xYxVfRL5mqha7vttvjB_vc7Xg2RvgCxHPCqoxgMPTzHrZT75LjCwIW2K_klBYN8oYvTwwmeSkAz6ut7ZxPv-nZaT5TJhGk0NT2kh_zSpdriEJ_3vW-mqxYbbBmpvHqsa1_zx9fSuHYctAZJWzxzUZXykbWMWQZpEiE0J4ajj51fInEzVn7VxV-mzfMyboQjujPh7aNJxAWSq4oQEJJDgWwSh9leyoJoPpONHxh5nEE5AjE01FkGICSxjpZsF-w8hOTI3XXohUdu29Se26k2B0PolDSuj0GIQU6-W9TdLXSjBb2SpQ",
"e":"AQAB"
}`), &accountKey)
test.AssertNotError(t, err, "Error unmarshaling JWK")
types := []string{ChallengeTypeSimpleHTTP, ChallengeTypeDVSNI, ChallengeTypeDNS} types := []string{ChallengeTypeSimpleHTTP, ChallengeTypeDVSNI, ChallengeTypeDNS}
for _, challengeType := range types { for _, challengeType := range types {
chall := Challenge{Type: challengeType, Status: StatusInvalid} chall := Challenge{
Type: challengeType,
Status: StatusInvalid,
AccountKey: accountKey,
}
test.Assert(t, !chall.IsSane(false), "IsSane should be false") test.Assert(t, !chall.IsSane(false), "IsSane should be false")
chall.Status = StatusPending chall.Status = StatusPending
test.Assert(t, !chall.IsSane(false), "IsSane should be false") test.Assert(t, !chall.IsSane(false), "IsSane should be false")
@ -80,6 +93,7 @@ func TestChallengeSanityCheck(t *testing.T) {
chall.Token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ+PCt92wr+o!" chall.Token = "evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ+PCt92wr+o!"
test.Assert(t, !chall.IsSane(false), "IsSane should be false") test.Assert(t, !chall.IsSane(false), "IsSane should be false")
chall.Token = "KQqLsiS5j0CONR_eUXTUSUDNVaHODtc-0pD6ACif7U4" chall.Token = "KQqLsiS5j0CONR_eUXTUSUDNVaHODtc-0pD6ACif7U4"
test.Assert(t, chall.IsSane(false), "IsSane should be true")
// Post-completion tests differ by type // Post-completion tests differ by type
if challengeType == ChallengeTypeSimpleHTTP { if challengeType == ChallengeTypeSimpleHTTP {
@ -92,7 +106,7 @@ func TestChallengeSanityCheck(t *testing.T) {
AddressesResolved: []net.IP{net.IP{127, 0, 0, 1}}, AddressesResolved: []net.IP{net.IP{127, 0, 0, 1}},
AddressUsed: net.IP{127, 0, 0, 1}, AddressUsed: net.IP{127, 0, 0, 1},
}} }}
test.Assert(t, chall.IsSane(false), "IsSane should be true") test.Assert(t, chall.IsSane(true), "IsSane should be true")
} else if challengeType == ChallengeTypeDVSNI || challengeType == ChallengeTypeDNS { } else if challengeType == ChallengeTypeDVSNI || challengeType == ChallengeTypeDNS {
chall.Validation = new(jose.JsonWebSignature) chall.Validation = new(jose.JsonWebSignature)
if challengeType == ChallengeTypeDVSNI { if challengeType == ChallengeTypeDVSNI {

View File

@ -144,6 +144,9 @@ func Fingerprint256(data []byte) string {
func KeyDigest(key crypto.PublicKey) (string, error) { func KeyDigest(key crypto.PublicKey) (string, error) {
switch t := key.(type) { switch t := key.(type) {
case *jose.JsonWebKey: case *jose.JsonWebKey:
if t == nil {
return "", fmt.Errorf("Cannot compute digest of nil key")
}
return KeyDigest(t.Key) return KeyDigest(t.Key)
case jose.JsonWebKey: case jose.JsonWebKey:
return KeyDigest(t.Key) return KeyDigest(t.Key)

View File

@ -132,7 +132,8 @@ func (ra *RegistrationAuthorityImpl) NewRegistration(init core.Registration) (re
// NewAuthorization constuct a new Authz from a request. // NewAuthorization constuct a new Authz from a request.
func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization, regID int64) (authz core.Authorization, err error) { func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization, regID int64) (authz core.Authorization, err error) {
if regID <= 0 { reg, err := ra.SA.GetRegistration(regID)
if err != nil {
err = core.MalformedRequestError(fmt.Sprintf("Invalid registration ID: %d", regID)) err = core.MalformedRequestError(fmt.Sprintf("Invalid registration ID: %d", regID))
return authz, err return authz, err
} }
@ -184,6 +185,9 @@ func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization
challengeURI, _ := core.ParseAcmeURL(ra.AuthzBase + authz.ID + "?challenge=" + strconv.Itoa(i)) challengeURI, _ := core.ParseAcmeURL(ra.AuthzBase + authz.ID + "?challenge=" + strconv.Itoa(i))
authz.Challenges[i].URI = challengeURI authz.Challenges[i].URI = challengeURI
// Add the account key used to generate the challenge
authz.Challenges[i].AccountKey = &reg.Key
if !authz.Challenges[i].IsSane(false) { if !authz.Challenges[i].IsSane(false) {
// InternalServerError because we generated these challenges, they should // InternalServerError because we generated these challenges, they should
// be OK. // be OK.
@ -374,8 +378,15 @@ func (ra *RegistrationAuthorityImpl) UpdateAuthorization(base core.Authorization
return return
} }
// Reject the update if the challenge in question was created
// with a different account key
if !core.KeyDigestEquals(reg.Key, authz.Challenges[challengeIndex].AccountKey) {
err = core.UnauthorizedError("Challenge cannot be updated with a different key")
return
}
// Dispatch to the VA for service // Dispatch to the VA for service
ra.VA.UpdateValidations(authz, challengeIndex, reg.Key) ra.VA.UpdateValidations(authz, challengeIndex)
return return
} }

View File

@ -34,7 +34,7 @@ type DummyValidationAuthority struct {
Argument core.Authorization Argument core.Authorization
} }
func (dva *DummyValidationAuthority) UpdateValidations(authz core.Authorization, index int, key jose.JsonWebKey) (err error) { func (dva *DummyValidationAuthority) UpdateValidations(authz core.Authorization, index int) (err error) {
dva.Called = true dva.Called = true
dva.Argument = authz dva.Argument = authz
return return
@ -380,6 +380,9 @@ func TestNewAuthorization(t *testing.T) {
test.Assert(t, authz.Challenges[0].Type == core.ChallengeTypeSimpleHTTP, "Challenge 0 not SimpleHTTP") test.Assert(t, authz.Challenges[0].Type == core.ChallengeTypeSimpleHTTP, "Challenge 0 not SimpleHTTP")
test.Assert(t, authz.Challenges[1].Type == core.ChallengeTypeDVSNI, "Challenge 1 not DVSNI") test.Assert(t, authz.Challenges[1].Type == core.ChallengeTypeDVSNI, "Challenge 1 not DVSNI")
test.Assert(t, authz.Challenges[2].Type == core.ChallengeTypeDNS, "Challenge 2 not DNS") test.Assert(t, authz.Challenges[2].Type == core.ChallengeTypeDNS, "Challenge 2 not DNS")
test.Assert(t, authz.Challenges[0].IsSane(false), "Challenge 0 is not sane")
test.Assert(t, authz.Challenges[1].IsSane(false), "Challenge 1 is not sane")
test.Assert(t, authz.Challenges[2].IsSane(false), "Challenge 2 is not sane")
t.Log("DONE TestNewAuthorization") t.Log("DONE TestNewAuthorization")
} }
@ -387,10 +390,12 @@ func TestNewAuthorization(t *testing.T) {
func TestUpdateAuthorization(t *testing.T) { func TestUpdateAuthorization(t *testing.T) {
va, sa, ra, cleanUp := initAuthorities(t) va, sa, ra, cleanUp := initAuthorities(t)
defer cleanUp() defer cleanUp()
AuthzInitial, _ = sa.NewPendingAuthorization(AuthzInitial)
sa.UpdatePendingAuthorization(AuthzInitial)
authz, err := ra.UpdateAuthorization(AuthzInitial, ResponseIndex, Response) // We know this is OK because of TestNewAuthorization
authz, err := ra.NewAuthorization(AuthzRequest, Registration.ID)
test.AssertNotError(t, err, "NewAuthorization failed")
authz, err = ra.UpdateAuthorization(authz, ResponseIndex, Response)
test.AssertNotError(t, err, "UpdateAuthorization failed") test.AssertNotError(t, err, "UpdateAuthorization failed")
// Verify that returned authz same as DB // Verify that returned authz same as DB
@ -408,6 +413,28 @@ func TestUpdateAuthorization(t *testing.T) {
t.Log("DONE TestUpdateAuthorization") t.Log("DONE TestUpdateAuthorization")
} }
func TestUpdateAuthorizationReject(t *testing.T) {
_, sa, ra, cleanUp := initAuthorities(t)
defer cleanUp()
// We know this is OK because of TestNewAuthorization
authz, err := ra.NewAuthorization(AuthzRequest, Registration.ID)
test.AssertNotError(t, err, "NewAuthorization failed")
// Change the account key
reg, err := sa.GetRegistration(authz.RegistrationID)
test.AssertNotError(t, err, "GetRegistration failed")
reg.Key = AccountKeyC // was AccountKeyA
err = sa.UpdateRegistration(reg)
test.AssertNotError(t, err, "UpdateRegistration failed")
// Verify that the RA rejected the authorization request
_, err = ra.UpdateAuthorization(authz, ResponseIndex, Response)
test.AssertEquals(t, err, core.UnauthorizedError("Challenge cannot be updated with a different key"))
t.Log("DONE TestUpdateAuthorizationReject")
}
func TestOnValidationUpdate(t *testing.T) { func TestOnValidationUpdate(t *testing.T) {
_, sa, ra, cleanUp := initAuthorities(t) _, sa, ra, cleanUp := initAuthorities(t)
defer cleanUp() defer cleanUp()

View File

@ -124,7 +124,6 @@ type caaRequest struct {
type validationRequest struct { type validationRequest struct {
Authz core.Authorization Authz core.Authorization
Index int Index int
Key jose.JsonWebKey
} }
type alreadyDeniedCSRReq struct { type alreadyDeniedCSRReq struct {
@ -449,7 +448,7 @@ func NewValidationAuthorityServer(rpc RPCServer, impl core.ValidationAuthority)
return return
} }
err = impl.UpdateValidations(vaReq.Authz, vaReq.Index, vaReq.Key) err = impl.UpdateValidations(vaReq.Authz, vaReq.Index)
return return
}) })
@ -494,11 +493,10 @@ func NewValidationAuthorityClient(client RPCClient) (vac ValidationAuthorityClie
} }
// UpdateValidations sends an Update Validations request // UpdateValidations sends an Update Validations request
func (vac ValidationAuthorityClient) UpdateValidations(authz core.Authorization, index int, key jose.JsonWebKey) error { func (vac ValidationAuthorityClient) UpdateValidations(authz core.Authorization, index int) error {
vaReq := validationRequest{ vaReq := validationRequest{
Authz: authz, Authz: authz,
Index: index, Index: index,
Key: key,
} }
data, err := json.Marshal(vaReq) data, err := json.Marshal(vaReq)
if err != nil { if err != nil {

View File

@ -0,0 +1,12 @@
-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied
ALTER TABLE `challenges` ADD COLUMN (
`accountKey` mediumblob
);
-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back
ALTER TABLE `challenges` DROP COLUMN `accountKey`;

View File

@ -41,6 +41,7 @@ type challModel struct {
TLS *bool `db:"tls"` TLS *bool `db:"tls"`
Validation []byte `db:"validation"` Validation []byte `db:"validation"`
ValidationRecord []byte `db:"validationRecord"` ValidationRecord []byte `db:"validationRecord"`
AccountKey []byte `db:"accountKey"`
LockCol int64 LockCol int64
} }
@ -123,6 +124,16 @@ func challengeToModel(c *core.Challenge, authID string) (*challModel, error) {
} }
cm.ValidationRecord = vrJSON cm.ValidationRecord = vrJSON
} }
if c.AccountKey != nil {
akJSON, err := json.Marshal(c.AccountKey)
if err != nil {
return nil, err
}
if len(akJSON) > mediumBlobSize {
return nil, fmt.Errorf("Account key object is too large to store in the database")
}
cm.AccountKey = akJSON
}
return &cm, nil return &cm, nil
} }
@ -164,5 +175,13 @@ func modelToChallenge(cm *challModel) (core.Challenge, error) {
} }
c.ValidationRecord = vr c.ValidationRecord = vr
} }
if len(cm.AccountKey) > 0 {
var ak jose.JsonWebKey
err := json.Unmarshal(cm.AccountKey, &ak)
if err != nil {
return core.Challenge{}, err
}
c.AccountKey = &ak
}
return c, nil return c, nil
} }

View File

@ -191,7 +191,7 @@ func (va *ValidationAuthorityImpl) resolveAndConstructDialer(name, defaultPort s
// Validation methods // Validation methods
func (va *ValidationAuthorityImpl) validateSimpleHTTP(identifier core.AcmeIdentifier, input core.Challenge, accountKey jose.JsonWebKey) (core.Challenge, error) { func (va *ValidationAuthorityImpl) validateSimpleHTTP(identifier core.AcmeIdentifier, input core.Challenge) (core.Challenge, error) {
challenge := input challenge := input
if identifier.Type != core.IdentifierDNS { if identifier.Type != core.IdentifierDNS {
@ -357,7 +357,7 @@ func (va *ValidationAuthorityImpl) validateSimpleHTTP(identifier core.AcmeIdenti
"token": challenge.Token, "token": challenge.Token,
"tls": (challenge.TLS == nil) || *challenge.TLS, "tls": (challenge.TLS == nil) || *challenge.TLS,
} }
err = verifyValidationJWS(parsedJws, &accountKey, target) err = verifyValidationJWS(parsedJws, challenge.AccountKey, target)
if err != nil { if err != nil {
va.log.Debug(err.Error()) va.log.Debug(err.Error())
challenge.Status = core.StatusInvalid challenge.Status = core.StatusInvalid
@ -372,7 +372,7 @@ func (va *ValidationAuthorityImpl) validateSimpleHTTP(identifier core.AcmeIdenti
return challenge, nil return challenge, nil
} }
func (va *ValidationAuthorityImpl) validateDvsni(identifier core.AcmeIdentifier, input core.Challenge, accountKey jose.JsonWebKey) (core.Challenge, error) { func (va *ValidationAuthorityImpl) validateDvsni(identifier core.AcmeIdentifier, input core.Challenge) (core.Challenge, error) {
challenge := input challenge := input
if identifier.Type != "dns" { if identifier.Type != "dns" {
@ -392,7 +392,7 @@ func (va *ValidationAuthorityImpl) validateDvsni(identifier core.AcmeIdentifier,
"type": core.ChallengeTypeDVSNI, "type": core.ChallengeTypeDVSNI,
"token": challenge.Token, "token": challenge.Token,
} }
err := verifyValidationJWS((*jose.JsonWebSignature)(challenge.Validation), &accountKey, target) err := verifyValidationJWS(challenge.Validation, challenge.AccountKey, target)
if err != nil { if err != nil {
va.log.Debug(err.Error()) va.log.Debug(err.Error())
challenge.Status = core.StatusInvalid challenge.Status = core.StatusInvalid
@ -493,7 +493,7 @@ func parseHTTPConnError(err error) core.ProblemType {
return core.ConnectionProblem return core.ConnectionProblem
} }
func (va *ValidationAuthorityImpl) validateDNS(identifier core.AcmeIdentifier, input core.Challenge, accountKey jose.JsonWebKey) (core.Challenge, error) { func (va *ValidationAuthorityImpl) validateDNS(identifier core.AcmeIdentifier, input core.Challenge) (core.Challenge, error) {
challenge := input challenge := input
if identifier.Type != core.IdentifierDNS { if identifier.Type != core.IdentifierDNS {
@ -513,7 +513,7 @@ func (va *ValidationAuthorityImpl) validateDNS(identifier core.AcmeIdentifier, i
"type": core.ChallengeTypeDNS, "type": core.ChallengeTypeDNS,
"token": challenge.Token, "token": challenge.Token,
} }
err := verifyValidationJWS((*jose.JsonWebSignature)(challenge.Validation), &accountKey, target) err := verifyValidationJWS(challenge.Validation, challenge.AccountKey, target)
if err != nil { if err != nil {
va.log.Debug(err.Error()) va.log.Debug(err.Error())
challenge.Status = core.StatusInvalid challenge.Status = core.StatusInvalid
@ -553,7 +553,7 @@ func (va *ValidationAuthorityImpl) validateDNS(identifier core.AcmeIdentifier, i
// Overall validation process // Overall validation process
func (va *ValidationAuthorityImpl) validate(authz core.Authorization, challengeIndex int, accountKey jose.JsonWebKey) { func (va *ValidationAuthorityImpl) validate(authz core.Authorization, challengeIndex int) {
logEvent := verificationRequestEvent{ logEvent := verificationRequestEvent{
ID: authz.ID, ID: authz.ID,
Requester: authz.RegistrationID, Requester: authz.RegistrationID,
@ -571,11 +571,11 @@ func (va *ValidationAuthorityImpl) validate(authz core.Authorization, challengeI
switch authz.Challenges[challengeIndex].Type { switch authz.Challenges[challengeIndex].Type {
case core.ChallengeTypeSimpleHTTP: case core.ChallengeTypeSimpleHTTP:
authz.Challenges[challengeIndex], err = va.validateSimpleHTTP(authz.Identifier, authz.Challenges[challengeIndex], accountKey) authz.Challenges[challengeIndex], err = va.validateSimpleHTTP(authz.Identifier, authz.Challenges[challengeIndex])
case core.ChallengeTypeDVSNI: case core.ChallengeTypeDVSNI:
authz.Challenges[challengeIndex], err = va.validateDvsni(authz.Identifier, authz.Challenges[challengeIndex], accountKey) authz.Challenges[challengeIndex], err = va.validateDvsni(authz.Identifier, authz.Challenges[challengeIndex])
case core.ChallengeTypeDNS: case core.ChallengeTypeDNS:
authz.Challenges[challengeIndex], err = va.validateDNS(authz.Identifier, authz.Challenges[challengeIndex], accountKey) authz.Challenges[challengeIndex], err = va.validateDNS(authz.Identifier, authz.Challenges[challengeIndex])
} }
if err != nil { if err != nil {
@ -599,8 +599,8 @@ func (va *ValidationAuthorityImpl) validate(authz core.Authorization, challengeI
} }
// UpdateValidations runs the validate() method asynchronously using goroutines. // UpdateValidations runs the validate() method asynchronously using goroutines.
func (va *ValidationAuthorityImpl) UpdateValidations(authz core.Authorization, challengeIndex int, accountKey jose.JsonWebKey) error { func (va *ValidationAuthorityImpl) UpdateValidations(authz core.Authorization, challengeIndex int) error {
go va.validate(authz, challengeIndex, accountKey) go va.validate(authz, challengeIndex)
return nil return nil
} }

View File

@ -57,7 +57,7 @@ var TheKey = rsa.PrivateKey{
Primes: []*big.Int{p, q}, Primes: []*big.Int{p, q},
} }
var AccountKey = jose.JsonWebKey{Key: TheKey.Public()} var accountKey = &jose.JsonWebKey{Key: TheKey.Public()}
var ident = core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "localhost"} var ident = core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "localhost"}
@ -231,7 +231,12 @@ func brokenTLSSrv() *httptest.Server {
} }
func TestSimpleHttpTLS(t *testing.T) { func TestSimpleHttpTLS(t *testing.T) {
chall := core.Challenge{Type: core.ChallengeTypeSimpleHTTP, Token: expectedToken, ValidationRecord: []core.ValidationRecord{}} chall := core.Challenge{
Type: core.ChallengeTypeSimpleHTTP,
Token: expectedToken,
ValidationRecord: []core.ValidationRecord{},
AccountKey: accountKey,
}
hs := simpleSrv(t, expectedToken, true) hs := simpleSrv(t, expectedToken, true)
defer hs.Close() defer hs.Close()
@ -242,7 +247,7 @@ func TestSimpleHttpTLS(t *testing.T) {
va.DNSResolver = &mocks.MockDNS{} va.DNSResolver = &mocks.MockDNS{}
log.Clear() log.Clear()
finChall, err := va.validateSimpleHTTP(ident, chall, AccountKey) finChall, err := va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertEquals(t, finChall.Status, core.StatusValid)
test.AssertNotError(t, err, "Error validating simpleHttp") test.AssertNotError(t, err, "Error validating simpleHttp")
logs := log.GetAllMatching(`^\[AUDIT\] Attempting to validate SimpleHTTPS for `) logs := log.GetAllMatching(`^\[AUDIT\] Attempting to validate SimpleHTTPS for `)
@ -252,7 +257,13 @@ func TestSimpleHttpTLS(t *testing.T) {
func TestSimpleHttp(t *testing.T) { func TestSimpleHttp(t *testing.T) {
tls := false tls := false
chall := core.Challenge{Type: core.ChallengeTypeSimpleHTTP, Token: expectedToken, TLS: &tls, ValidationRecord: []core.ValidationRecord{}} chall := core.Challenge{
Type: core.ChallengeTypeSimpleHTTP,
Token: expectedToken,
TLS: &tls,
ValidationRecord: []core.ValidationRecord{},
AccountKey: accountKey,
}
// NOTE: We do not attempt to shut down the server. The problem is that the // NOTE: We do not attempt to shut down the server. The problem is that the
// "wait-long" handler sleeps for ten seconds, but this test finishes in less // "wait-long" handler sleeps for ten seconds, but this test finishes in less
@ -276,7 +287,7 @@ func TestSimpleHttp(t *testing.T) {
va := NewValidationAuthorityImpl(&PortConfig{SimpleHTTPPort: badPort}) va := NewValidationAuthorityImpl(&PortConfig{SimpleHTTPPort: badPort})
va.DNSResolver = &mocks.MockDNS{} va.DNSResolver = &mocks.MockDNS{}
invalidChall, err := va.validateSimpleHTTP(ident, chall, AccountKey) invalidChall, err := va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid)
test.AssertError(t, err, "Server's down; expected refusal. Where did we connect?") test.AssertError(t, err, "Server's down; expected refusal. Where did we connect?")
test.AssertEquals(t, invalidChall.Error.Type, core.ConnectionProblem) test.AssertEquals(t, invalidChall.Error.Type, core.ConnectionProblem)
@ -284,14 +295,14 @@ func TestSimpleHttp(t *testing.T) {
va = NewValidationAuthorityImpl(&PortConfig{SimpleHTTPPort: goodPort}) va = NewValidationAuthorityImpl(&PortConfig{SimpleHTTPPort: goodPort})
va.DNSResolver = &mocks.MockDNS{} va.DNSResolver = &mocks.MockDNS{}
log.Clear() log.Clear()
finChall, err := va.validateSimpleHTTP(ident, chall, AccountKey) finChall, err := va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertEquals(t, finChall.Status, core.StatusValid)
test.AssertNotError(t, err, "Error validating simpleHttp") test.AssertNotError(t, err, "Error validating simpleHttp")
test.AssertEquals(t, len(log.GetAllMatching(`^\[AUDIT\] `)), 1) test.AssertEquals(t, len(log.GetAllMatching(`^\[AUDIT\] `)), 1)
log.Clear() log.Clear()
chall.Token = path404 chall.Token = path404
invalidChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) invalidChall, err = va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid)
test.AssertError(t, err, "Should have found a 404 for the challenge.") test.AssertError(t, err, "Should have found a 404 for the challenge.")
test.AssertEquals(t, invalidChall.Error.Type, core.UnauthorizedProblem) test.AssertEquals(t, invalidChall.Error.Type, core.UnauthorizedProblem)
@ -301,7 +312,7 @@ func TestSimpleHttp(t *testing.T) {
chall.Token = pathWrongToken chall.Token = pathWrongToken
// The "wrong token" will actually be the expectedToken. It's wrong // The "wrong token" will actually be the expectedToken. It's wrong
// because it doesn't match pathWrongToken. // because it doesn't match pathWrongToken.
invalidChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) invalidChall, err = va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid)
test.AssertError(t, err, "Should have found the wrong token value.") test.AssertError(t, err, "Should have found the wrong token value.")
test.AssertEquals(t, invalidChall.Error.Type, core.UnauthorizedProblem) test.AssertEquals(t, invalidChall.Error.Type, core.UnauthorizedProblem)
@ -309,33 +320,33 @@ func TestSimpleHttp(t *testing.T) {
log.Clear() log.Clear()
chall.Token = pathMoved chall.Token = pathMoved
finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) finChall, err = va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertEquals(t, finChall.Status, core.StatusValid)
test.AssertNotError(t, err, "Failed to follow 301 redirect") test.AssertNotError(t, err, "Failed to follow 301 redirect")
test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1)
log.Clear() log.Clear()
chall.Token = pathFound chall.Token = pathFound
finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) finChall, err = va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertEquals(t, finChall.Status, core.StatusValid)
test.AssertNotError(t, err, "Failed to follow 302 redirect") test.AssertNotError(t, err, "Failed to follow 302 redirect")
test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/302" to ".*/301"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/302" to ".*/301"`)), 1)
test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1)
ipIdentifier := core.AcmeIdentifier{Type: core.IdentifierType("ip"), Value: "127.0.0.1"} ipIdentifier := core.AcmeIdentifier{Type: core.IdentifierType("ip"), Value: "127.0.0.1"}
invalidChall, err = va.validateSimpleHTTP(ipIdentifier, chall, AccountKey) invalidChall, err = va.validateSimpleHTTP(ipIdentifier, chall)
test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid)
test.AssertError(t, err, "IdentifierType IP shouldn't have worked.") test.AssertError(t, err, "IdentifierType IP shouldn't have worked.")
test.AssertEquals(t, invalidChall.Error.Type, core.MalformedProblem) test.AssertEquals(t, invalidChall.Error.Type, core.MalformedProblem)
invalidChall, err = va.validateSimpleHTTP(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "always.invalid"}, chall, AccountKey) invalidChall, err = va.validateSimpleHTTP(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "always.invalid"}, chall)
test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid)
test.AssertError(t, err, "Domain name is invalid.") test.AssertError(t, err, "Domain name is invalid.")
test.AssertEquals(t, invalidChall.Error.Type, core.UnknownHostProblem) test.AssertEquals(t, invalidChall.Error.Type, core.UnknownHostProblem)
chall.Token = "wait-long" chall.Token = "wait-long"
started := time.Now() started := time.Now()
invalidChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) invalidChall, err = va.validateSimpleHTTP(ident, chall)
took := time.Since(started) took := time.Since(started)
// Check that the HTTP connection times out after 5 seconds and doesn't block for 10 seconds // Check that the HTTP connection times out after 5 seconds and doesn't block for 10 seconds
test.Assert(t, (took > (time.Second * 5)), "HTTP timed out before 5 seconds") test.Assert(t, (took > (time.Second * 5)), "HTTP timed out before 5 seconds")
@ -347,7 +358,12 @@ func TestSimpleHttp(t *testing.T) {
func TestSimpleHttpRedirectLookup(t *testing.T) { func TestSimpleHttpRedirectLookup(t *testing.T) {
tls := false tls := false
chall := core.Challenge{Token: expectedToken, TLS: &tls, ValidationRecord: []core.ValidationRecord{}} chall := core.Challenge{
Token: expectedToken,
TLS: &tls,
ValidationRecord: []core.ValidationRecord{},
AccountKey: accountKey,
}
hs := simpleSrv(t, expectedToken, tls) hs := simpleSrv(t, expectedToken, tls)
defer hs.Close() defer hs.Close()
@ -358,7 +374,7 @@ func TestSimpleHttpRedirectLookup(t *testing.T) {
log.Clear() log.Clear()
chall.Token = pathMoved chall.Token = pathMoved
finChall, err := va.validateSimpleHTTP(ident, chall, AccountKey) finChall, err := va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertEquals(t, finChall.Status, core.StatusValid)
test.AssertNotError(t, err, chall.Token) test.AssertNotError(t, err, chall.Token)
test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/301" to ".*/valid"`)), 1)
@ -366,7 +382,7 @@ func TestSimpleHttpRedirectLookup(t *testing.T) {
log.Clear() log.Clear()
chall.Token = pathFound chall.Token = pathFound
finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) finChall, err = va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertEquals(t, finChall.Status, core.StatusValid)
test.AssertNotError(t, err, chall.Token) test.AssertNotError(t, err, chall.Token)
test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/302" to ".*/301"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/302" to ".*/301"`)), 1)
@ -375,7 +391,7 @@ func TestSimpleHttpRedirectLookup(t *testing.T) {
log.Clear() log.Clear()
chall.Token = pathRedirectLookupInvalid chall.Token = pathRedirectLookupInvalid
finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) finChall, err = va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, finChall.Status, core.StatusInvalid) test.AssertEquals(t, finChall.Status, core.StatusInvalid)
test.AssertError(t, err, chall.Token) test.AssertError(t, err, chall.Token)
test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1)
@ -383,7 +399,7 @@ func TestSimpleHttpRedirectLookup(t *testing.T) {
log.Clear() log.Clear()
chall.Token = pathRedirectLookup chall.Token = pathRedirectLookup
finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) finChall, err = va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertEquals(t, finChall.Status, core.StatusValid)
test.AssertNotError(t, err, chall.Token) test.AssertNotError(t, err, chall.Token)
test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/re-lookup" to ".*other.valid/path"`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`redirect from ".*/re-lookup" to ".*other.valid/path"`)), 1)
@ -392,7 +408,7 @@ func TestSimpleHttpRedirectLookup(t *testing.T) {
log.Clear() log.Clear()
chall.Token = pathRedirectPort chall.Token = pathRedirectPort
finChall, err = va.validateSimpleHTTP(ident, chall, AccountKey) finChall, err = va.validateSimpleHTTP(ident, chall)
fmt.Println(finChall.ValidationRecord) fmt.Println(finChall.ValidationRecord)
test.AssertEquals(t, finChall.Status, core.StatusInvalid) test.AssertEquals(t, finChall.Status, core.StatusInvalid)
test.AssertError(t, err, chall.Token) test.AssertError(t, err, chall.Token)
@ -403,7 +419,11 @@ func TestSimpleHttpRedirectLookup(t *testing.T) {
func TestSimpleHttpRedirectLoop(t *testing.T) { func TestSimpleHttpRedirectLoop(t *testing.T) {
tls := false tls := false
chall := core.Challenge{Token: "looper", TLS: &tls, ValidationRecord: []core.ValidationRecord{}} chall := core.Challenge{
Token: "looper",
TLS: &tls,
ValidationRecord: []core.ValidationRecord{},
}
hs := simpleSrv(t, expectedToken, tls) hs := simpleSrv(t, expectedToken, tls)
defer hs.Close() defer hs.Close()
@ -413,7 +433,7 @@ func TestSimpleHttpRedirectLoop(t *testing.T) {
va.DNSResolver = &mocks.MockDNS{} va.DNSResolver = &mocks.MockDNS{}
log.Clear() log.Clear()
finChall, err := va.validateSimpleHTTP(ident, chall, AccountKey) finChall, err := va.validateSimpleHTTP(ident, chall)
test.AssertEquals(t, finChall.Status, core.StatusInvalid) test.AssertEquals(t, finChall.Status, core.StatusInvalid)
test.AssertError(t, err, chall.Token) test.AssertError(t, err, chall.Token)
fmt.Println(finChall) fmt.Println(finChall)
@ -447,7 +467,7 @@ func TestDvsni(t *testing.T) {
va.DNSResolver = &mocks.MockDNS{} va.DNSResolver = &mocks.MockDNS{}
log.Clear() log.Clear()
finChall, err := va.validateDvsni(ident, chall, AccountKey) finChall, err := va.validateDvsni(ident, chall)
test.AssertEquals(t, finChall.Status, core.StatusValid) test.AssertEquals(t, finChall.Status, core.StatusValid)
test.AssertNotError(t, err, "") test.AssertNotError(t, err, "")
test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1) test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1)
@ -456,13 +476,13 @@ func TestDvsni(t *testing.T) {
invalidChall, err := va.validateDvsni(core.AcmeIdentifier{ invalidChall, err := va.validateDvsni(core.AcmeIdentifier{
Type: core.IdentifierType("ip"), Type: core.IdentifierType("ip"),
Value: net.JoinHostPort("127.0.0.1", fmt.Sprintf("%d", port)), Value: net.JoinHostPort("127.0.0.1", fmt.Sprintf("%d", port)),
}, chall, AccountKey) }, chall)
test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid)
test.AssertError(t, err, "IdentifierType IP shouldn't have worked.") test.AssertError(t, err, "IdentifierType IP shouldn't have worked.")
test.AssertEquals(t, invalidChall.Error.Type, core.MalformedProblem) test.AssertEquals(t, invalidChall.Error.Type, core.MalformedProblem)
log.Clear() log.Clear()
invalidChall, err = va.validateDvsni(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "always.invalid"}, chall, AccountKey) invalidChall, err = va.validateDvsni(core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "always.invalid"}, chall)
test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid)
test.AssertError(t, err, "Domain name was supposed to be invalid.") test.AssertError(t, err, "Domain name was supposed to be invalid.")
test.AssertEquals(t, invalidChall.Error.Type, core.UnknownHostProblem) test.AssertEquals(t, invalidChall.Error.Type, core.UnknownHostProblem)
@ -478,7 +498,7 @@ func TestDvsni(t *testing.T) {
log.Clear() log.Clear()
started := time.Now() started := time.Now()
invalidChall, err = va.validateDvsni(ident, chall, AccountKey) invalidChall, err = va.validateDvsni(ident, chall)
took := time.Since(started) took := time.Since(started)
// Check that the HTTP connection times out after 5 seconds and doesn't block for 10 seconds // Check that the HTTP connection times out after 5 seconds and doesn't block for 10 seconds
test.Assert(t, (took > (time.Second * 5)), "HTTP timed out before 5 seconds") test.Assert(t, (took > (time.Second * 5)), "HTTP timed out before 5 seconds")
@ -490,7 +510,7 @@ func TestDvsni(t *testing.T) {
// Take down DVSNI validation server and check that validation fails. // Take down DVSNI validation server and check that validation fails.
hs.Close() hs.Close()
invalidChall, err = va.validateDvsni(ident, chall, AccountKey) invalidChall, err = va.validateDvsni(ident, chall)
test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid)
test.AssertError(t, err, "Server's down; expected refusal. Where did we connect?") test.AssertError(t, err, "Server's down; expected refusal. Where did we connect?")
test.AssertEquals(t, invalidChall.Error.Type, core.ConnectionProblem) test.AssertEquals(t, invalidChall.Error.Type, core.ConnectionProblem)
@ -505,7 +525,7 @@ func TestTLSError(t *testing.T) {
va := NewValidationAuthorityImpl(&PortConfig{DVSNIPort: port}) va := NewValidationAuthorityImpl(&PortConfig{DVSNIPort: port})
va.DNSResolver = &mocks.MockDNS{} va.DNSResolver = &mocks.MockDNS{}
invalidChall, err := va.validateDvsni(ident, chall, AccountKey) invalidChall, err := va.validateDvsni(ident, chall)
test.AssertEquals(t, invalidChall.Status, core.StatusInvalid) test.AssertEquals(t, invalidChall.Status, core.StatusInvalid)
test.AssertError(t, err, "What cert was used?") test.AssertError(t, err, "What cert was used?")
test.AssertEquals(t, invalidChall.Error.Type, core.TLSProblem) test.AssertEquals(t, invalidChall.Error.Type, core.TLSProblem)
@ -516,6 +536,7 @@ func TestValidateHTTP(t *testing.T) {
challHTTP := core.SimpleHTTPChallenge() challHTTP := core.SimpleHTTPChallenge()
challHTTP.TLS = &tls challHTTP.TLS = &tls
challHTTP.ValidationRecord = []core.ValidationRecord{} challHTTP.ValidationRecord = []core.ValidationRecord{}
challHTTP.AccountKey = accountKey
hs := simpleSrv(t, challHTTP.Token, tls) hs := simpleSrv(t, challHTTP.Token, tls)
port, err := getPort(hs) port, err := getPort(hs)
@ -533,7 +554,7 @@ func TestValidateHTTP(t *testing.T) {
Identifier: ident, Identifier: ident,
Challenges: []core.Challenge{challHTTP}, Challenges: []core.Challenge{challHTTP},
} }
va.validate(authz, 0, AccountKey) va.validate(authz, 0)
test.AssertEquals(t, core.StatusValid, mockRA.lastAuthz.Challenges[0].Status) test.AssertEquals(t, core.StatusValid, mockRA.lastAuthz.Challenges[0].Status)
} }
@ -545,6 +566,7 @@ func createChallenge(challengeType string) core.Challenge {
Status: core.StatusPending, Status: core.StatusPending,
Token: core.NewToken(), Token: core.NewToken(),
ValidationRecord: []core.ValidationRecord{}, ValidationRecord: []core.ValidationRecord{},
AccountKey: accountKey,
} }
validationPayload, _ := json.Marshal(map[string]interface{}{ validationPayload, _ := json.Marshal(map[string]interface{}{
@ -576,7 +598,7 @@ func TestValidateDvsni(t *testing.T) {
Identifier: ident, Identifier: ident,
Challenges: []core.Challenge{chall}, Challenges: []core.Challenge{chall},
} }
va.validate(authz, 0, AccountKey) va.validate(authz, 0)
test.AssertEquals(t, core.StatusValid, mockRA.lastAuthz.Challenges[0].Status) test.AssertEquals(t, core.StatusValid, mockRA.lastAuthz.Challenges[0].Status)
} }
@ -597,7 +619,7 @@ func TestValidateDvsniNotSane(t *testing.T) {
Identifier: ident, Identifier: ident,
Challenges: []core.Challenge{chall}, Challenges: []core.Challenge{chall},
} }
va.validate(authz, 0, AccountKey) va.validate(authz, 0)
test.AssertEquals(t, core.StatusInvalid, mockRA.lastAuthz.Challenges[0].Status) test.AssertEquals(t, core.StatusInvalid, mockRA.lastAuthz.Challenges[0].Status)
} }
@ -621,7 +643,7 @@ func TestUpdateValidations(t *testing.T) {
} }
started := time.Now() started := time.Now()
va.UpdateValidations(authz, 0, AccountKey) va.UpdateValidations(authz, 0)
took := time.Since(started) took := time.Since(started)
// Check that the call to va.UpdateValidations didn't block for 3 seconds // Check that the call to va.UpdateValidations didn't block for 3 seconds
@ -703,7 +725,7 @@ func TestDNSValidationFailure(t *testing.T) {
Identifier: ident, Identifier: ident,
Challenges: []core.Challenge{chalDNS}, Challenges: []core.Challenge{chalDNS},
} }
va.validate(authz, 0, AccountKey) va.validate(authz, 0)
t.Logf("Resulting Authz: %+v", authz) t.Logf("Resulting Authz: %+v", authz)
test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization") test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization")
@ -731,7 +753,7 @@ func TestDNSValidationInvalid(t *testing.T) {
mockRA := &MockRegistrationAuthority{} mockRA := &MockRegistrationAuthority{}
va.RA = mockRA va.RA = mockRA
va.validate(authz, 0, AccountKey) va.validate(authz, 0)
test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization") test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization")
test.Assert(t, authz.Challenges[0].Status == core.StatusInvalid, "Should be invalid.") test.Assert(t, authz.Challenges[0].Status == core.StatusInvalid, "Should be invalid.")
@ -762,7 +784,7 @@ func TestDNSValidationNotSane(t *testing.T) {
} }
for i := 0; i < len(authz.Challenges); i++ { for i := 0; i < len(authz.Challenges); i++ {
va.validate(authz, i, AccountKey) va.validate(authz, i)
test.AssertEquals(t, authz.Challenges[i].Status, core.StatusInvalid) test.AssertEquals(t, authz.Challenges[i].Status, core.StatusInvalid)
test.AssertEquals(t, authz.Challenges[i].Error.Type, core.MalformedProblem) test.AssertEquals(t, authz.Challenges[i].Error.Type, core.MalformedProblem)
} }
@ -786,7 +808,7 @@ func TestDNSValidationServFail(t *testing.T) {
Identifier: badIdent, Identifier: badIdent,
Challenges: []core.Challenge{chalDNS}, Challenges: []core.Challenge{chalDNS},
} }
va.validate(authz, 0, AccountKey) va.validate(authz, 0)
test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization") test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization")
test.Assert(t, authz.Challenges[0].Status == core.StatusInvalid, "Should be invalid.") test.Assert(t, authz.Challenges[0].Status == core.StatusInvalid, "Should be invalid.")
@ -807,7 +829,7 @@ func TestDNSValidationNoServer(t *testing.T) {
Identifier: ident, Identifier: ident,
Challenges: []core.Challenge{chalDNS}, Challenges: []core.Challenge{chalDNS},
} }
va.validate(authz, 0, AccountKey) va.validate(authz, 0)
test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization") test.AssertNotNil(t, mockRA.lastAuthz, "Should have gotten an authorization")
test.Assert(t, authz.Challenges[0].Status == core.StatusInvalid, "Should be invalid.") test.Assert(t, authz.Challenges[0].Status == core.StatusInvalid, "Should be invalid.")
@ -844,7 +866,7 @@ func TestDNSValidationLive(t *testing.T) {
Challenges: []core.Challenge{goodChalDNS}, Challenges: []core.Challenge{goodChalDNS},
} }
va.validate(authzGood, 0, AccountKey) va.validate(authzGood, 0)
if authzGood.Challenges[0].Status != core.StatusValid { if authzGood.Challenges[0].Status != core.StatusValid {
t.Logf("TestDNSValidationLive on Good did not succeed.") t.Logf("TestDNSValidationLive on Good did not succeed.")
@ -861,7 +883,7 @@ func TestDNSValidationLive(t *testing.T) {
Challenges: []core.Challenge{badChalDNS}, Challenges: []core.Challenge{badChalDNS},
} }
va.validate(authzBad, 0, AccountKey) va.validate(authzBad, 0)
if authzBad.Challenges[0].Status != core.StatusInvalid { if authzBad.Challenges[0].Status != core.StatusInvalid {
t.Logf("TestDNSValidationLive on Bad did succeed inappropriately.") t.Logf("TestDNSValidationLive on Bad did succeed inappropriately.")
} }