mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-16 21:56:40 -05:00
caddyhttp: Reject conflicting values in query strings
This commit is contained in:
parent
a999b70727
commit
7ce5c0aaac
2 changed files with 43 additions and 8 deletions
|
@ -123,6 +123,7 @@ type (
|
|||
// keyed by the query keys, with an array of string values to match for that key.
|
||||
// Query key matches are exact, but wildcards may be used for value matches. Both
|
||||
// keys and values may be placeholders.
|
||||
//
|
||||
// An example of the structure to match `?key=value&topic=api&query=something` is:
|
||||
//
|
||||
// ```json
|
||||
|
@ -808,19 +809,29 @@ func (m MatchQuery) Match(r *http.Request) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
for param, vals := range m {
|
||||
for param, allowedVals := range m {
|
||||
param = repl.ReplaceAll(param, "")
|
||||
paramVal, found := parsed[param]
|
||||
incomingVals, found := parsed[param]
|
||||
if found {
|
||||
for _, v := range vals {
|
||||
v = repl.ReplaceAll(v, "")
|
||||
if paramVal[0] == v || v == "*" {
|
||||
for _, allowedVal := range allowedVals {
|
||||
allowedVal = repl.ReplaceAll(allowedVal, "")
|
||||
if allowedVal == "*" {
|
||||
return true
|
||||
}
|
||||
matched := true
|
||||
for _, incomingVal := range incomingVals {
|
||||
if incomingVal != allowedVal {
|
||||
matched = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if matched {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return len(m) == 0 && len(r.URL.Query()) == 0
|
||||
return len(m) == 0 && len(parsed) == 0
|
||||
}
|
||||
|
||||
// CELLibrary produces options that expose this matcher for use in CEL
|
||||
|
|
|
@ -718,7 +718,7 @@ func TestQueryMatcher(t *testing.T) {
|
|||
expect: true,
|
||||
},
|
||||
{
|
||||
scenario: "non match against a wildcarded",
|
||||
scenario: "non match against a wildcard",
|
||||
match: MatchQuery{"debug": []string{"*"}},
|
||||
input: "/?other=something",
|
||||
expect: false,
|
||||
|
@ -765,6 +765,30 @@ func TestQueryMatcher(t *testing.T) {
|
|||
input: "/?somekey=1",
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
scenario: "don't match conflicting values",
|
||||
match: MatchQuery{"a": []string{"1"}},
|
||||
input: "/?a=1&a=2",
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
scenario: "conflicting values are ambiguous with multiple match values",
|
||||
match: MatchQuery{"a": []string{"1", "2"}},
|
||||
input: "/?a=1&a=2",
|
||||
expect: false,
|
||||
},
|
||||
{
|
||||
scenario: "repeated kv pairs in URI",
|
||||
match: MatchQuery{"a": []string{"1"}},
|
||||
input: "/?a=1&a=1",
|
||||
expect: true,
|
||||
},
|
||||
{
|
||||
scenario: "TODO: it's unclear whether the values should be AND'ed or OR'ed", // perhaps multiple query matchers could be used to "and"
|
||||
match: MatchQuery{"a": []string{"1", "2"}},
|
||||
input: "/?a=2",
|
||||
expect: true,
|
||||
},
|
||||
} {
|
||||
|
||||
u, _ := url.Parse(tc.input)
|
||||
|
@ -777,7 +801,7 @@ func TestQueryMatcher(t *testing.T) {
|
|||
req = req.WithContext(ctx)
|
||||
actual := tc.match.Match(req)
|
||||
if actual != tc.expect {
|
||||
t.Errorf("Test %d %v: Expected %t, got %t for '%s'", i, tc.match, tc.expect, actual, tc.input)
|
||||
t.Errorf("Test %d %v: Expected %t, got %t for '%s' (%s)", i, tc.match, tc.expect, actual, tc.input, tc.scenario)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue