|
|
@ -21,6 +21,7 @@ import ( |
|
|
|
"net/http" |
|
|
|
"net/textproto" |
|
|
|
"net/url" |
|
|
|
"path" |
|
|
|
"path/filepath" |
|
|
|
"regexp" |
|
|
|
"sort" |
|
|
@ -314,7 +315,15 @@ func (m MatchPath) Provision(_ caddy.Context) error { |
|
|
|
|
|
|
|
// Match returns true if r matches m.
|
|
|
|
func (m MatchPath) Match(r *http.Request) bool { |
|
|
|
lowerPath := strings.ToLower(r.URL.Path) |
|
|
|
// PathUnescape returns an error if the escapes aren't
|
|
|
|
// well-formed, meaning the count % matches the RFC.
|
|
|
|
// Return early if the escape is improper.
|
|
|
|
unescapedPath, err := url.PathUnescape(r.URL.Path) |
|
|
|
if err != nil { |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
lowerPath := strings.ToLower(unescapedPath) |
|
|
|
|
|
|
|
// see #2917; Windows ignores trailing dots and spaces
|
|
|
|
// when accessing files (sigh), potentially causing a
|
|
|
@ -323,6 +332,16 @@ func (m MatchPath) Match(r *http.Request) bool { |
|
|
|
// being matched by *.php to be treated as PHP scripts
|
|
|
|
lowerPath = strings.TrimRight(lowerPath, ". ") |
|
|
|
|
|
|
|
// Clean the path, merges doubled slashes, etc.
|
|
|
|
// This ensures maliciously crafted requests can't bypass
|
|
|
|
// the path matcher. See #4407
|
|
|
|
lowerPath = path.Clean(lowerPath) |
|
|
|
|
|
|
|
// Cleaning may remove the trailing slash, but we want to keep it
|
|
|
|
if lowerPath != "/" && strings.HasSuffix(r.URL.Path, "/") { |
|
|
|
lowerPath = lowerPath + "/" |
|
|
|
} |
|
|
|
|
|
|
|
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer) |
|
|
|
|
|
|
|
for _, matchPath := range m { |
|
|
@ -396,7 +415,26 @@ func (MatchPathRE) CaddyModule() caddy.ModuleInfo { |
|
|
|
// Match returns true if r matches m.
|
|
|
|
func (m MatchPathRE) Match(r *http.Request) bool { |
|
|
|
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer) |
|
|
|
return m.MatchRegexp.Match(r.URL.Path, repl) |
|
|
|
|
|
|
|
// PathUnescape returns an error if the escapes aren't
|
|
|
|
// well-formed, meaning the count % matches the RFC.
|
|
|
|
// Return early if the escape is improper.
|
|
|
|
unescapedPath, err := url.PathUnescape(r.URL.Path) |
|
|
|
if err != nil { |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// Clean the path, merges doubled slashes, etc.
|
|
|
|
// This ensures maliciously crafted requests can't bypass
|
|
|
|
// the path matcher. See #4407
|
|
|
|
cleanedPath := path.Clean(unescapedPath) |
|
|
|
|
|
|
|
// Cleaning may remove the trailing slash, but we want to keep it
|
|
|
|
if cleanedPath != "/" && strings.HasSuffix(r.URL.Path, "/") { |
|
|
|
cleanedPath = cleanedPath + "/" |
|
|
|
} |
|
|
|
|
|
|
|
return m.MatchRegexp.Match(cleanedPath, repl) |
|
|
|
} |
|
|
|
|
|
|
|
// CaddyModule returns the Caddy module information.
|
|
|
|