diff --git a/va/caa.go b/va/caa.go index da41ad5305c..1e21915cd8e 100644 --- a/va/caa.go +++ b/va/caa.go @@ -494,7 +494,12 @@ func caaAccountURIMatches(caaParams []caaParameter, accountURIPrefixes []string, var found bool var accountURI string for _, c := range caaParams { - if c.tag == "accounturi" { + // RFC 8659 Section 4.1 makes matching of Property Tags case insensitive but + // specifies no comparison rule for parameter tags. We lowercase the parameter + // tag as a safety choice: treating a differently-cased "accounturi" as an + // unrecognized parameter would drop the restriction the subscriber intended + // and make this Property match any account, a false-positive validation. + if strings.ToLower(c.tag) == "accounturi" { if found { // A Property with multiple "accounturi" parameters is // unsatisfiable. @@ -536,7 +541,8 @@ func caaValidationMethodMatches(caaParams []caaParameter, method core.AcmeChalle var validationMethods string var found bool for _, param := range caaParams { - if param.tag == "validationmethods" { + // Match the parameter tag case insensitively, as in caaAccountURIMatches. + if strings.ToLower(param.tag) == "validationmethods" { if found { // RFC 8657 does not define what behavior to take when multiple // "validationmethods" parameters exist, but we make the diff --git a/va/caa_test.go b/va/caa_test.go index 4d5922ced04..b86ef1f2825 100644 --- a/va/caa_test.go +++ b/va/caa_test.go @@ -1421,6 +1421,24 @@ func TestAccountURIMatches(t *testing.T) { id: 654321, want: false, }, + { + name: "mixed-case tag matches the expected account", + params: []caaParameter{{tag: "AccountURI", val: "https://acme-v02.api.letsencrypt.org/acme/acct/123456"}}, + prefixes: []string{ + "https://acme-v02.api.letsencrypt.org/acme/acct/", + }, + id: 123456, + want: true, + }, + { + name: "mixed-case tag still restricts a non-matching account", + params: []caaParameter{{tag: "AccountURI", val: "https://acme-v02.api.letsencrypt.org/acme/acct/123456"}}, + prefixes: []string{ + "https://acme-v02.api.letsencrypt.org/acme/acct/", + }, + id: 654321, + want: false, + }, } for _, tc := range tests { @@ -1536,6 +1554,18 @@ func TestValidationMethodMatches(t *testing.T) { method: core.ChallengeTypeTLSALPN01, want: false, }, + { + name: "mixed-case tag matches the method in use", + params: []caaParameter{{tag: "ValidationMethods", val: "dns-01"}}, + method: core.ChallengeTypeDNS01, + want: true, + }, + { + name: "mixed-case tag still restricts a non-matching method", + params: []caaParameter{{tag: "ValidationMethods", val: "dns-01"}}, + method: core.ChallengeTypeHTTP01, + want: false, + }, } for _, tc := range tests {