mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-23 22:27:38 -05:00
Hopefully, this is the final nail on the coffin.
This commit is contained in:
parent
e92a911e7d
commit
008ad398ce
2 changed files with 25 additions and 30 deletions
|
@ -122,7 +122,7 @@ func (fh *fileHandler) serveFile(w http.ResponseWriter, r *http.Request, name st
|
||||||
}
|
}
|
||||||
|
|
||||||
// If file is on hide list.
|
// If file is on hide list.
|
||||||
if fh.isHidden(d.Name()) {
|
if fh.isHidden(d) {
|
||||||
return http.StatusNotFound, nil
|
return http.StatusNotFound, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,30 +133,20 @@ func (fh *fileHandler) serveFile(w http.ResponseWriter, r *http.Request, name st
|
||||||
return http.StatusOK, nil
|
return http.StatusOK, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// isHidden checks if file with name is on hide list.
|
// isHidden checks if file with FileInfo d is on hide list.
|
||||||
func (fh fileHandler) isHidden(name string) bool {
|
func (fh fileHandler) isHidden(d os.FileInfo) bool {
|
||||||
// Clean up on Windows.
|
|
||||||
// Remove trailing dots and trim whitespaces.
|
|
||||||
if runtimeGoos == "windows" {
|
|
||||||
name = strings.TrimSpace(name)
|
|
||||||
for strings.HasSuffix(name, ".") {
|
|
||||||
name = name[:len(name)-1]
|
|
||||||
name = strings.TrimSpace(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the file is supposed to be hidden, return a 404
|
// If the file is supposed to be hidden, return a 404
|
||||||
// (TODO: If the slice gets large, a set may be faster)
|
// (TODO: If the slice gets large, a set may be faster)
|
||||||
for _, hiddenPath := range fh.hide {
|
for _, hiddenPath := range fh.hide {
|
||||||
// Case-insensitive file systems may have loaded "CaddyFile" when
|
// Check if the served file is exactly the hidden file.
|
||||||
// we think we got "Caddyfile", which poses a security risk if we
|
if hFile, err := fh.root.Open(hiddenPath); err == nil {
|
||||||
// aren't careful here: case-insensitive comparison is required!
|
fs, _ := hFile.Stat()
|
||||||
// TODO: This matches file NAME only, regardless of path. In other
|
hFile.Close()
|
||||||
// words, trying to serve another file with the same name as the
|
if os.SameFile(d, fs) {
|
||||||
// active config file will result in a 404 when it shouldn't.
|
|
||||||
if strings.EqualFold(name, filepath.Base(hiddenPath)) {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ func TestServeHTTP(t *testing.T) {
|
||||||
beforeServeHTTPTest(t)
|
beforeServeHTTPTest(t)
|
||||||
defer afterServeHTTPTest(t)
|
defer afterServeHTTPTest(t)
|
||||||
|
|
||||||
fileserver := FileServer(http.Dir(testDir), []string{"hidden.html"})
|
fileserver := FileServer(http.Dir(testDir), []string{"dir/hidden.html"})
|
||||||
|
|
||||||
movedPermanently := "Moved Permanently"
|
movedPermanently := "Moved Permanently"
|
||||||
|
|
||||||
|
@ -84,54 +84,59 @@ func TestServeHTTP(t *testing.T) {
|
||||||
expectedStatus: http.StatusMovedPermanently,
|
expectedStatus: http.StatusMovedPermanently,
|
||||||
expectedBodyContent: movedPermanently,
|
expectedBodyContent: movedPermanently,
|
||||||
},
|
},
|
||||||
// Test 6 - access file with trailing slash
|
// Test 7 - access file with trailing slash
|
||||||
{
|
{
|
||||||
url: "https://foo/file1.html/",
|
url: "https://foo/file1.html/",
|
||||||
expectedStatus: http.StatusMovedPermanently,
|
expectedStatus: http.StatusMovedPermanently,
|
||||||
expectedBodyContent: movedPermanently,
|
expectedBodyContent: movedPermanently,
|
||||||
},
|
},
|
||||||
// Test 7 - access not existing path
|
// Test 8 - access not existing path
|
||||||
{
|
{
|
||||||
url: "https://foo/not_existing",
|
url: "https://foo/not_existing",
|
||||||
expectedStatus: http.StatusNotFound,
|
expectedStatus: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
// Test 8 - access a file, marked as hidden
|
// Test 9 - access a file, marked as hidden
|
||||||
{
|
{
|
||||||
url: "https://foo/dir/hidden.html",
|
url: "https://foo/dir/hidden.html",
|
||||||
expectedStatus: http.StatusNotFound,
|
expectedStatus: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
// Test 9 - access a index file directly
|
// Test 10 - access a index file directly
|
||||||
{
|
{
|
||||||
url: "https://foo/dirwithindex/index.html",
|
url: "https://foo/dirwithindex/index.html",
|
||||||
expectedStatus: http.StatusOK,
|
expectedStatus: http.StatusOK,
|
||||||
expectedBodyContent: testFiles[filepath.Join("dirwithindex", "index.html")],
|
expectedBodyContent: testFiles[filepath.Join("dirwithindex", "index.html")],
|
||||||
},
|
},
|
||||||
// Test 10 - send a request with query params
|
// Test 11 - send a request with query params
|
||||||
{
|
{
|
||||||
url: "https://foo/dir?param1=val",
|
url: "https://foo/dir?param1=val",
|
||||||
expectedStatus: http.StatusMovedPermanently,
|
expectedStatus: http.StatusMovedPermanently,
|
||||||
expectedBodyContent: movedPermanently,
|
expectedBodyContent: movedPermanently,
|
||||||
},
|
},
|
||||||
// Test 11 - attempt to bypass hidden file
|
// Test 12 - attempt to bypass hidden file
|
||||||
{
|
{
|
||||||
url: "https://foo/dir/hidden.html%20",
|
url: "https://foo/dir/hidden.html%20",
|
||||||
expectedStatus: http.StatusNotFound,
|
expectedStatus: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
// Test 12 - attempt to bypass hidden file
|
// Test 13 - attempt to bypass hidden file
|
||||||
{
|
{
|
||||||
url: "https://foo/dir/hidden.html.",
|
url: "https://foo/dir/hidden.html.",
|
||||||
expectedStatus: http.StatusNotFound,
|
expectedStatus: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
// Test 13 - attempt to bypass hidden file
|
// Test 14 - attempt to bypass hidden file
|
||||||
{
|
{
|
||||||
url: "https://foo/dir/hidden.html.%20",
|
url: "https://foo/dir/hidden.html.%20",
|
||||||
expectedStatus: http.StatusNotFound,
|
expectedStatus: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
// Test 14 - attempt to bypass hidden file
|
// Test 15 - attempt to bypass hidden file
|
||||||
{
|
{
|
||||||
url: "https://foo/dir/hidden.html%20.",
|
url: "https://foo/dir/hidden.html%20.",
|
||||||
expectedStatus: http.StatusNotFound,
|
expectedStatus: http.StatusNotFound,
|
||||||
},
|
},
|
||||||
|
// Test 16 - serve another file with same name as hidden file.
|
||||||
|
{
|
||||||
|
url: "https://foo/hidden.html",
|
||||||
|
expectedStatus: http.StatusNotFound,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
|
|
Loading…
Reference in a new issue