summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/caddyhttp.go
diff options
context:
space:
mode:
authorMatt Holt <mholt@users.noreply.github.com>2021-06-17 09:59:08 -0600
committerGitHub <noreply@github.com>2021-06-17 09:59:08 -0600
commit9d4ed3a3236df06e54c80c4f6633b66d68ad3673 (patch)
treef516a98ff44465f2434a03c4625dc969d87857e2 /modules/caddyhttp/caddyhttp.go
parentfbd6560976dc73052bd5d3277869912de68f6731 (diff)
caddyhttp: Refactor and export SanitizedPathJoin for use in fastcgi (#4207)
Diffstat (limited to 'modules/caddyhttp/caddyhttp.go')
-rw-r--r--modules/caddyhttp/caddyhttp.go29
1 files changed, 29 insertions, 0 deletions
diff --git a/modules/caddyhttp/caddyhttp.go b/modules/caddyhttp/caddyhttp.go
index d93a5c8..784b2b9 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)