Disallow the use of valid authorizations that used currently disabled challenges for issuance
This commit is contained in:
parent
b16e788c4b
commit
5ca646c5dd
|
|
@ -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
|
||||
|
|
|
|||
11
policy/pa.go
11
policy/pa.go
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
}
|
||||
|
|
|
|||
3
ra/ra.go
3
ra/ra.go
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
21
sa/sa.go
21
sa/sa.go
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue