From 1ef5dcd6bdfa1cfe8d7e6f418a6daf5c2ec93af6 Mon Sep 17 00:00:00 2001 From: qbisi Date: Mon, 27 Jul 2026 17:15:55 +0800 Subject: [PATCH] feat(server): trust configured Unix socket requests - add unix_file_trusted configuration with a disabled zero-value default - grant trusted Unix socket requests an admin identity without credentials - bypass WebDAV authentication and download signatures only on the trusted socket Co-authored-by: Codex <267193182+codex@users.noreply.github.com> --- internal/bootstrap/run.go | 6 +++++- internal/conf/config.go | 21 +++++++++++---------- server/middlewares/auth.go | 38 ++++++++++++++++++++++++++++++++++++++ server/middlewares/down.go | 2 +- server/webdav.go | 11 +++++++++++ 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/internal/bootstrap/run.go b/internal/bootstrap/run.go index 6740dba657..151651ffd2 100644 --- a/internal/bootstrap/run.go +++ b/internal/bootstrap/run.go @@ -170,7 +170,11 @@ func Start() { if conf.Conf.Scheme.UnixFile != "" { fmt.Printf("start unix server @ %s\n", conf.Conf.Scheme.UnixFile) utils.Log.Infof("start unix server @ %s", conf.Conf.Scheme.UnixFile) - unixSrv = &http.Server{Handler: httpHandler} + unixHandler := httpHandler + if conf.Conf.Scheme.UnixFileTrusted { + unixHandler = middlewares.UnixFileTrusted(unixHandler) + } + unixSrv = &http.Server{Handler: unixHandler} go func() { listener, err := net.Listen("unix", conf.Conf.Scheme.UnixFile) if err != nil { diff --git a/internal/conf/config.go b/internal/conf/config.go index 0f66761168..491d1b86bb 100644 --- a/internal/conf/config.go +++ b/internal/conf/config.go @@ -26,16 +26,17 @@ type Meilisearch struct { } type Scheme struct { - Address string `json:"address" env:"ADDR"` - HttpPort int `json:"http_port" env:"HTTP_PORT"` - HttpsPort int `json:"https_port" env:"HTTPS_PORT"` - ForceHttps bool `json:"force_https" env:"FORCE_HTTPS"` - CertFile string `json:"cert_file" env:"CERT_FILE"` - KeyFile string `json:"key_file" env:"KEY_FILE"` - UnixFile string `json:"unix_file" env:"UNIX_FILE"` - UnixFilePerm string `json:"unix_file_perm" env:"UNIX_FILE_PERM"` - EnableH2c bool `json:"enable_h2c" env:"ENABLE_H2C"` - EnableH3 bool `json:"enable_h3" env:"ENABLE_H3"` + Address string `json:"address" env:"ADDR"` + HttpPort int `json:"http_port" env:"HTTP_PORT"` + HttpsPort int `json:"https_port" env:"HTTPS_PORT"` + ForceHttps bool `json:"force_https" env:"FORCE_HTTPS"` + CertFile string `json:"cert_file" env:"CERT_FILE"` + KeyFile string `json:"key_file" env:"KEY_FILE"` + UnixFile string `json:"unix_file" env:"UNIX_FILE"` + UnixFileTrusted bool `json:"unix_file_trusted" env:"UNIX_FILE_TRUSTED"` + UnixFilePerm string `json:"unix_file_perm" env:"UNIX_FILE_PERM"` + EnableH2c bool `json:"enable_h2c" env:"ENABLE_H2C"` + EnableH3 bool `json:"enable_h3" env:"ENABLE_H3"` } type LogConfig struct { diff --git a/server/middlewares/auth.go b/server/middlewares/auth.go index ca67e4a6dd..de0c5cb298 100644 --- a/server/middlewares/auth.go +++ b/server/middlewares/auth.go @@ -1,7 +1,9 @@ package middlewares import ( + "context" "crypto/subtle" + "net/http" "github.com/OpenListTeam/OpenList/v4/internal/conf" "github.com/OpenListTeam/OpenList/v4/internal/model" @@ -16,6 +18,9 @@ import ( // if token is empty, set user to guest func Auth(allowDisabledGuest bool) func(c *gin.Context) { return func(c *gin.Context) { + if authenticateUnixFileTrusted(c) { + return + } token := c.GetHeader("Authorization") if subtle.ConstantTimeCompare([]byte(token), []byte(setting.GetStr(conf.Token))) == 1 { admin, err := op.GetAdmin() @@ -76,6 +81,9 @@ func Auth(allowDisabledGuest bool) func(c *gin.Context) { } func Authn(c *gin.Context) { + if authenticateUnixFileTrusted(c) { + return + } token := c.GetHeader("Authorization") if subtle.ConstantTimeCompare([]byte(token), []byte(setting.GetStr(conf.Token))) == 1 { admin, err := op.GetAdmin() @@ -129,6 +137,36 @@ func Authn(c *gin.Context) { c.Next() } +func authenticateUnixFileTrusted(c *gin.Context) bool { + if !IsUnixFileTrusted(c) { + return false + } + admin, err := op.GetAdmin() + if err != nil { + common.ErrorResp(c, err, 500) + c.Abort() + return true + } + common.GinAppendValues(c, conf.UserKey, admin) + log.Debug("use admin identity for trusted Unix socket request") + c.Next() + return true +} + +type unixFileTrustedKey struct{} + +func UnixFileTrusted(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), unixFileTrustedKey{}, true) + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} + +func IsUnixFileTrusted(c *gin.Context) bool { + trusted, _ := c.Request.Context().Value(unixFileTrustedKey{}).(bool) + return conf.Conf.Scheme.UnixFileTrusted && trusted +} + func AuthNotGuest(c *gin.Context) { user := c.Request.Context().Value(conf.UserKey).(*model.User) if user.IsGuest() { diff --git a/server/middlewares/down.go b/server/middlewares/down.go index d71be00b36..349dc243aa 100644 --- a/server/middlewares/down.go +++ b/server/middlewares/down.go @@ -31,7 +31,7 @@ func Down(verifyFunc func(string, string) error) func(c *gin.Context) { } common.GinAppendValues(c, conf.MetaKey, meta) // verify sign - if needSign(meta, rawPath) { + if !IsUnixFileTrusted(c) && needSign(meta, rawPath) { s := c.Query("sign") err = verifyFunc(rawPath, strings.TrimSuffix(s, "/")) if err != nil { diff --git a/server/webdav.go b/server/webdav.go index 74523b0b30..807b86feb4 100644 --- a/server/webdav.go +++ b/server/webdav.go @@ -48,6 +48,17 @@ func ServeWebDAV(c *gin.Context) { } func WebDAVAuth(c *gin.Context) { + if middlewares.IsUnixFileTrusted(c) { + admin, err := op.GetAdmin() + if err != nil { + common.ErrorResp(c, err, http.StatusInternalServerError) + c.Abort() + return + } + common.GinAppendValues(c, conf.UserKey, admin) + c.Next() + return + } // check count of login ip := c.ClientIP() guest, _ := op.GetGuest()