diff options
author | Matt Holt <[email protected]> | 2021-06-17 09:59:08 -0600 |
---|---|---|
committer | GitHub <[email protected]> | 2021-06-17 09:59:08 -0600 |
commit | 9d4ed3a3236df06e54c80c4f6633b66d68ad3673 (patch) | |
tree | f516a98ff44465f2434a03c4625dc969d87857e2 /modules/caddyhttp/caddyhttp.go | |
parent | fbd6560976dc73052bd5d3277869912de68f6731 (diff) | |
download | caddy-9d4ed3a3236df06e54c80c4f6633b66d68ad3673.tar.gz caddy-9d4ed3a3236df06e54c80c4f6633b66d68ad3673.zip |
caddyhttp: Refactor and export SanitizedPathJoin for use in fastcgi (#4207)v2.4.3
Diffstat (limited to 'modules/caddyhttp/caddyhttp.go')
-rw-r--r-- | modules/caddyhttp/caddyhttp.go | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/modules/caddyhttp/caddyhttp.go b/modules/caddyhttp/caddyhttp.go index d93a5c8a2..784b2b900 100644 --- a/modules/caddyhttp/caddyhttp.go +++ b/modules/caddyhttp/caddyhttp.go @@ -20,7 +20,9 @@ import ( "io" "net" "net/http" + "path/filepath" "strconv" + "strings" "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" @@ -217,6 +219,31 @@ func StatusCodeMatches(actual, configured int) bool { return false } +// SanitizedPathJoin performs filepath.Join(root, reqPath) that +// is safe against directory traversal attacks. It uses logic +// similar to that in the Go standard library, specifically +// in the implementation of http.Dir. The root is assumed to +// be a trusted path, but reqPath is not; and the output will +// never be outside of root. The resulting path can be used +// with the local file system. +func SanitizedPathJoin(root, reqPath string) string { + if root == "" { + root = "." + } + + path := filepath.Join(root, filepath.Clean("/"+reqPath)) + + // filepath.Join also cleans the path, and cleaning strips + // the trailing slash, so we need to re-add it afterwards. + // if the length is 1, then it's a path to the root, + // and that should return ".", so we don't append the separator. + if strings.HasSuffix(reqPath, "/") && len(reqPath) > 1 { + path += separator + } + + return path +} + // tlsPlaceholderWrapper is a no-op listener wrapper that marks // where the TLS listener should be in a chain of listener wrappers. // It should only be used if another listener wrapper must be placed @@ -242,6 +269,8 @@ const ( DefaultHTTPSPort = 443 ) +const separator = string(filepath.Separator) + // Interface guard var _ caddy.ListenerWrapper = (*tlsPlaceholderWrapper)(nil) var _ caddyfile.Unmarshaler = (*tlsPlaceholderWrapper)(nil) |