summaryrefslogtreecommitdiff
path: root/admin.go
diff options
context:
space:
mode:
authorTom Barrett <tom@tombarrett.xyz>2023-11-01 17:57:48 +0100
committerTom Barrett <tom@tombarrett.xyz>2023-11-01 18:11:33 +0100
commit240c3d1338415e5d82ef7ca0e52c4284be6441bd (patch)
tree4b0ee5d208c2cdffa78d65f1b0abe0ec85f15652 /admin.go
parent73e78ab226f21e6c6c68961af88c4ab9c746f4f4 (diff)
parent0e204b730aa2b1fa0835336b1117eff8c420f713 (diff)
vbump to v2.7.5HEADcaddy-cgi
Diffstat (limited to 'admin.go')
-rw-r--r--admin.go52
1 files changed, 47 insertions, 5 deletions
diff --git a/admin.go b/admin.go
index 674d06a..0a9bfc4 100644
--- a/admin.go
+++ b/admin.go
@@ -71,6 +71,11 @@ type AdminConfig struct {
// parsed by Caddy. Accepts placeholders.
// Default: the value of the `CADDY_ADMIN` environment variable,
// or `localhost:2019` otherwise.
+ //
+ // Remember: When changing this value through a config reload,
+ // be sure to use the `--address` CLI flag to specify the current
+ // admin address if the currently-running admin endpoint is not
+ // the default address.
Listen string `json:"listen,omitempty"`
// If true, CORS headers will be emitted, and requests to the
@@ -313,7 +318,32 @@ func (admin AdminConfig) allowedOrigins(addr NetworkAddress) []*url.URL {
// messages. If the requested URI does not include an Internet host
// name for the service being requested, then the Host header field MUST
// be given with an empty value."
+ //
+ // UPDATE July 2023: Go broke this by patching a minor security bug in 1.20.6.
+ // Understandable, but frustrating. See:
+ // https://github.com/golang/go/issues/60374
+ // See also the discussion here:
+ // https://github.com/golang/go/issues/61431
+ //
+ // We can no longer conform to RFC 2616 Section 14.26 from either Go or curl
+ // in purity. (Curl allowed no host between 7.40 and 7.50, but now requires a
+ // bogus host; see https://superuser.com/a/925610.) If we disable Host/Origin
+ // security checks, the infosec community assures me that it is secure to do
+ // so, because:
+ // 1) Browsers do not allow access to unix sockets
+ // 2) DNS is irrelevant to unix sockets
+ //
+ // I am not quite ready to trust either of those external factors, so instead
+ // of disabling Host/Origin checks, we now allow specific Host values when
+ // accessing the admin endpoint over unix sockets. I definitely don't trust
+ // DNS (e.g. I don't trust 'localhost' to always resolve to the local host),
+ // and IP shouldn't even be used, but if it is for some reason, I think we can
+ // at least be reasonably assured that 127.0.0.1 and ::1 route to the local
+ // machine, meaning that a hypothetical browser origin would have to be on the
+ // local machine as well.
uniqueOrigins[""] = struct{}{}
+ uniqueOrigins["127.0.0.1"] = struct{}{}
+ uniqueOrigins["::1"] = struct{}{}
} else {
uniqueOrigins[net.JoinHostPort("localhost", addr.port())] = struct{}{}
uniqueOrigins[net.JoinHostPort("::1", addr.port())] = struct{}{}
@@ -1011,9 +1041,9 @@ func handleConfigID(w http.ResponseWriter, r *http.Request) error {
id := parts[2]
// map the ID to the expanded path
- currentCtxMu.RLock()
+ rawCfgMu.RLock()
expanded, ok := rawCfgIndex[id]
- defer currentCtxMu.RUnlock()
+ rawCfgMu.RUnlock()
if !ok {
return APIError{
HTTPStatus: http.StatusNotFound,
@@ -1166,15 +1196,27 @@ traverseLoop:
}
case http.MethodPut:
if _, ok := v[part]; ok {
- return fmt.Errorf("[%s] key already exists: %s", path, part)
+ return APIError{
+ HTTPStatus: http.StatusConflict,
+ Err: fmt.Errorf("[%s] key already exists: %s", path, part),
+ }
}
v[part] = val
case http.MethodPatch:
if _, ok := v[part]; !ok {
- return fmt.Errorf("[%s] key does not exist: %s", path, part)
+ return APIError{
+ HTTPStatus: http.StatusNotFound,
+ Err: fmt.Errorf("[%s] key does not exist: %s", path, part),
+ }
}
v[part] = val
case http.MethodDelete:
+ if _, ok := v[part]; !ok {
+ return APIError{
+ HTTPStatus: http.StatusNotFound,
+ Err: fmt.Errorf("[%s] key does not exist: %s", path, part),
+ }
+ }
delete(v, part)
default:
return fmt.Errorf("unrecognized method %s", method)
@@ -1316,7 +1358,7 @@ var (
// will get deleted before the process gracefully exits.
func PIDFile(filename string) error {
pid := []byte(strconv.Itoa(os.Getpid()) + "\n")
- err := os.WriteFile(filename, pid, 0600)
+ err := os.WriteFile(filename, pid, 0o600)
if err != nil {
return err
}