diff options
author | Matthew Holt <[email protected]> | 2017-05-02 11:20:50 -0600 |
---|---|---|
committer | Matthew Holt <[email protected]> | 2017-05-02 11:20:50 -0600 |
commit | 59a5afab292046b67526b6f38582d3a0efbfcc50 (patch) | |
tree | 4b0630fdde8a6a73623e2fa4d16d1a863b33bc89 | |
parent | d8fb2ddc2de33857acf294a050633b6b2560b93e (diff) | |
download | caddy-59a5afab292046b67526b6f38582d3a0efbfcc50.tar.gz caddy-59a5afab292046b67526b6f38582d3a0efbfcc50.zip |
fastcgi: Prepend missing leading slash when matching paths (see #1645)
httpserver: More path matching tests
-rw-r--r-- | caddyhttp/fastcgi/fastcgi.go | 22 | ||||
-rw-r--r-- | caddyhttp/httpserver/path_test.go | 39 |
2 files changed, 56 insertions, 5 deletions
diff --git a/caddyhttp/fastcgi/fastcgi.go b/caddyhttp/fastcgi/fastcgi.go index ca9eeb8d2..4cd34fc6f 100644 --- a/caddyhttp/fastcgi/fastcgi.go +++ b/caddyhttp/fastcgi/fastcgi.go @@ -36,9 +36,25 @@ type Handler struct { // ServeHTTP satisfies the httpserver.Handler interface. func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { for _, rule := range h.Rules { - - // First requirement: Base path must match and the path must be allowed. - if !httpserver.Path(r.URL.Path).Matches(rule.Path) || !rule.AllowedPath(r.URL.Path) { + // First requirement: Base path must match request path. If it doesn't, + // we check to make sure the leading slash is not missing, and if so, + // we check again with it prepended. This is in case people forget + // a leading slash when performing rewrites, and we don't want to expose + // the contents of the (likely PHP) script. See issue #1645. + hpath := httpserver.Path(r.URL.Path) + if !hpath.Matches(rule.Path) { + if strings.HasPrefix(string(hpath), "/") { + // this is a normal-looking path, and it doesn't match; try next rule + continue + } + hpath = httpserver.Path("/" + string(hpath)) // prepend leading slash + if !hpath.Matches(rule.Path) { + // even after fixing the request path, it still doesn't match; try next rule + continue + } + } + // The path must also be allowed (not ignored). + if !rule.AllowedPath(r.URL.Path) { continue } diff --git a/caddyhttp/httpserver/path_test.go b/caddyhttp/httpserver/path_test.go index 4e46cbe6b..6ae92e8f1 100644 --- a/caddyhttp/httpserver/path_test.go +++ b/caddyhttp/httpserver/path_test.go @@ -5,7 +5,7 @@ import "testing" func TestPathMatches(t *testing.T) { for i, testcase := range []struct { reqPath Path - rulePath string + rulePath string // or "base path" as in Caddyfile docs shouldMatch bool caseInsensitive bool }{ @@ -48,7 +48,42 @@ func TestPathMatches(t *testing.T) { }, { reqPath: "", - rulePath: "/", // a lone forward slash means to match all requests (see issue #1645) + rulePath: "/", // a lone forward slash means to match all requests (see issue #1645) - many future test cases related to this issue + shouldMatch: true, + }, + { + reqPath: "foobar.php", + rulePath: "/", + shouldMatch: true, + }, + { + reqPath: "", + rulePath: "", + shouldMatch: true, + }, + { + reqPath: "/foo/bar", + rulePath: "", + shouldMatch: true, + }, + { + reqPath: "/foo/bar", + rulePath: "", + shouldMatch: true, + }, + { + reqPath: "no/leading/slash", + rulePath: "/", + shouldMatch: true, + }, + { + reqPath: "no/leading/slash", + rulePath: "/no/leading/slash", + shouldMatch: false, + }, + { + reqPath: "no/leading/slash", + rulePath: "", shouldMatch: true, }, } { |