Disallow the use of valid authorizations that used currently disabled challenges for issuance

This commit is contained in:
Roland Shoemaker 2018-01-09 18:52:29 -08:00
parent b16e788c4b
commit 5ca646c5dd
6 changed files with 93 additions and 0 deletions

View File

@ -108,6 +108,7 @@ type PolicyAuthority interface {
WillingToIssue(domain AcmeIdentifier) error
WillingToIssueWildcard(domain AcmeIdentifier) error
ChallengesFor(domain AcmeIdentifier) (challenges []Challenge, validCombinations [][]int, err error)
ChallengeStillAllowed(authz *Authorization) bool
}
// StorageGetter are the Boulder SA's read-only methods

View File

@ -453,3 +453,14 @@ func extractDomainIANASuffix(name string) (string, error) {
return suffix, nil
}
// AuthzStillValid checks if the challenge type that was used in a valid authorization
// is still enabled
func (pa *AuthorityImpl) ChallengeStillAllowed(authz *core.Authorization) bool {
for _, chall := range authz.Challenges {
if chall.Status == core.StatusValid {
return pa.enabledChallenges[chall.Type]
}
}
return false
}

View File

@ -461,3 +461,13 @@ func TestMalformedExactBlacklist(t *testing.T) {
test.AssertError(t, err, "Loaded invalid exact blacklist content without error")
test.AssertEquals(t, err.Error(), "Malformed exact blacklist entry, only one label: \"com\"")
}
func TestChallengeStillAllowed(t *testing.T) {
pa := paImpl(t)
pa.enabledChallenges[core.ChallengeTypeHTTP01] = false
test.Assert(t, !pa.ChallengeStillAllowed(&core.Authorization{}), "pa.ChallengeStillAllowed didn't fail with empty authorization")
test.Assert(t, !pa.ChallengeStillAllowed(&core.Authorization{Challenges: []core.Challenge{{Status: core.StatusPending}}}), "pa.ChallengeStillAllowed didn't fail with no valid challenges")
test.Assert(t, !pa.ChallengeStillAllowed(&core.Authorization{Challenges: []core.Challenge{{Status: core.StatusValid, Type: core.ChallengeTypeHTTP01}}}), "pa.ChallengeStillAllowed didn't fail with disabled challenge")
test.Assert(t, pa.ChallengeStillAllowed(&core.Authorization{Challenges: []core.Challenge{{Status: core.StatusValid, Type: core.ChallengeTypeTLSSNI01}}}), "pa.ChallengeStillAllowed failed with enabled challenge")
}

View File

@ -721,6 +721,9 @@ func (ra *RegistrationAuthorityImpl) checkAuthorizationsCAA(
// Ensure that CAA is rechecked for this name
recheckNames = append(recheckNames, name)
}
if authz != nil && !ra.PA.ChallengeStillAllowed(authz) {
return berrors.UnauthorizedError("challenge used to validate authorization with ID %q no longer allowed", authz.ID)
}
}
if err := ra.recheckCAA(ctx, recheckNames); err != nil {

View File

@ -1958,22 +1958,27 @@ func (m *mockSAWithRecentAndOlder) GetValidAuthorizations(
"recent.com": &core.Authorization{
Identifier: makeIdentifier("recent.com"),
Expires: &m.recent,
Challenges: []core.Challenge{{Status: core.StatusValid, Type: core.ChallengeTypeHTTP01}},
},
"older.com": &core.Authorization{
Identifier: makeIdentifier("older.com"),
Expires: &m.older,
Challenges: []core.Challenge{{Status: core.StatusValid, Type: core.ChallengeTypeHTTP01}},
},
"older2.com": &core.Authorization{
Identifier: makeIdentifier("older2.com"),
Expires: &m.older,
Challenges: []core.Challenge{{Status: core.StatusValid, Type: core.ChallengeTypeHTTP01}},
},
"wildcard.com": &core.Authorization{
Identifier: makeIdentifier("wildcard.com"),
Expires: &m.older,
Challenges: []core.Challenge{{Status: core.StatusValid, Type: core.ChallengeTypeHTTP01}},
},
"*.wildcard.com": &core.Authorization{
Identifier: makeIdentifier("*.wildcard.com"),
Expires: &m.older,
Challenges: []core.Challenge{{Status: core.StatusValid, Type: core.ChallengeTypeHTTP01}},
},
}, nil
}
@ -2862,6 +2867,48 @@ func TestUpdateMissingAuthorization(t *testing.T) {
test.AssertEquals(t, berrors.Is(err, berrors.NotFound), true)
}
func TestDisabledChallengeValidAuthz(t *testing.T) {
_, _, ra, fc, cleanUp := initAuthorities(t)
defer cleanUp()
challenges := map[string]bool{
core.ChallengeTypeHTTP01: true,
}
pa, err := policy.New(challenges)
test.AssertNotError(t, err, "Couldn't create PA")
ra.PA = pa
exp := fc.Now().Add(10 * time.Hour)
err = ra.checkAuthorizationsCAA(
context.Background(),
[]string{"test.com"},
map[string]*core.Authorization{"test.com": &core.Authorization{
Expires: &exp,
Challenges: []core.Challenge{
{Status: core.StatusValid, Type: core.ChallengeTypeTLSSNI01},
},
}},
0,
fc.Now(),
)
test.AssertError(t, err, "RA didn't prevent use of an authorization which used an disabled challenge type")
err = ra.checkAuthorizationsCAA(
context.Background(),
[]string{"test.com"},
map[string]*core.Authorization{"test.com": &core.Authorization{
Expires: &exp,
Challenges: []core.Challenge{
{Status: core.StatusValid, Type: core.ChallengeTypeHTTP01},
},
}},
0,
fc.Now(),
)
test.AssertNotError(t, err, "RA prevented use of an authorization which used an enabled challenge type")
}
var CAkeyPEM = `
-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEAqmM0dEf/J9MCk2ItzevL0dKJ84lVUtf/vQ7AXFi492vFXc3b

View File

@ -1621,6 +1621,27 @@ func (ssa *SQLStorageAuthority) getAuthorizations(ctx context.Context, table str
if auth.Expires == nil {
continue
}
// Retrieve challenges for the authzvar challObjs []challModel
var challObjs []challModel
_, err = ssa.dbMap.Select(
&challObjs,
getChallengesQuery,
map[string]interface{}{"authID": auth.ID},
)
if err != nil {
return nil, err
}
var challs []core.Challenge
for _, c := range challObjs {
chall, err := modelToChallenge(&c)
if err != nil {
return nil, err
}
challs = append(challs, chall)
}
auth.Challenges = challs
if auth.Identifier.Type != core.IdentifierDNS {
return nil, fmt.Errorf("unknown identifier type: %q on authz id %q", auth.Identifier.Type, auth.ID)
}