mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2026-10-10 04:53:09 +08:00
fix(upload): authorize direct upload destinations
- Resolve and authorize the canonical destination from the request payload - Reject upload capabilities that cross virtual storage mount boundaries - Remove the unrelated File-Path middleware authorization check Co-authored-by: Codex <267193182+codex@users.noreply.github.com> Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
This commit is contained in:
@@ -30,6 +30,20 @@ func GetStorageAndActualPath(rawPath string) (storage driver.Driver, actualPath
|
||||
return
|
||||
}
|
||||
|
||||
// GetStorageVirtualMountPath returns the deterministic virtual mount path
|
||||
// without advancing the balanced-storage counter.
|
||||
func GetStorageVirtualMountPath(rawPath string) (string, error) {
|
||||
rawPath = utils.FixAndCleanPath(rawPath)
|
||||
storages := getStoragesByPath(rawPath)
|
||||
if len(storages) == 0 {
|
||||
if rawPath == "/" {
|
||||
return "", errs.NewErr(errs.StorageNotFound, "please add a storage first")
|
||||
}
|
||||
return "", errs.NewErr(errs.StorageNotFound, "rawPath: %s", rawPath)
|
||||
}
|
||||
return utils.FixAndCleanPath(utils.GetActualMountPath(storages[0].GetStorage().MountPath)), nil
|
||||
}
|
||||
|
||||
// urlTreeSplitLineFormPath 分割path中分割真实路径和UrlTree定义字符串
|
||||
func urlTreeSplitLineFormPath(path string) (pp string, file string) {
|
||||
// url.PathUnescape 会移除 // ,手动加回去
|
||||
|
||||
@@ -8,8 +8,10 @@ import (
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/server/common"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type FsGetDirectUploadInfoReq struct {
|
||||
@@ -44,8 +46,40 @@ func FsGetDirectUploadInfo(c *gin.Context) {
|
||||
common.ErrorResp(c, err, 403)
|
||||
return
|
||||
}
|
||||
overwrite := c.GetHeader("Overwrite") != "false"
|
||||
// Resolve the destination once so permission checks and the issued upload
|
||||
// capability cannot target different paths.
|
||||
dstPath := stdpath.Join(path, req.FileName)
|
||||
path = stdpath.Dir(dstPath)
|
||||
req.FileName = stdpath.Base(dstPath)
|
||||
parentMeta, err := op.GetNearestMeta(path)
|
||||
if err != nil && !errors.Is(errors.Cause(err), errs.MetaNotFound) {
|
||||
common.ErrorResp(c, err, 500, true)
|
||||
return
|
||||
}
|
||||
if !user.CanWriteContent() && !common.CanWriteContentBypassUserPerms(parentMeta, path) {
|
||||
common.ErrorResp(c, errs.PermissionDenied, 403)
|
||||
return
|
||||
}
|
||||
if !common.CanWrite(user, parentMeta, path) {
|
||||
common.ErrorResp(c, errs.PermissionDenied, 403)
|
||||
return
|
||||
}
|
||||
// A single-segment file name can still name a nested mount point.
|
||||
parentMountPath, err := op.GetStorageVirtualMountPath(path)
|
||||
if err != nil {
|
||||
common.ErrorResp(c, err, 500)
|
||||
return
|
||||
}
|
||||
targetMountPath, err := op.GetStorageVirtualMountPath(dstPath)
|
||||
if err != nil {
|
||||
common.ErrorResp(c, err, 500)
|
||||
return
|
||||
}
|
||||
if parentMountPath != targetMountPath {
|
||||
common.ErrorResp(c, errs.PermissionDenied, 403)
|
||||
return
|
||||
}
|
||||
overwrite := c.GetHeader("Overwrite") != "false"
|
||||
if !overwrite {
|
||||
res, err := fs.Get(c.Request.Context(), dstPath, &fs.GetArgs{NoLog: true})
|
||||
if err != nil && !errs.IsObjectNotFound(err) {
|
||||
|
||||
+1
-1
@@ -233,7 +233,7 @@ func _fs(g *gin.RouterGroup) {
|
||||
g.POST("/torrent/rapid_upload", handles.TorrentRapidUpload)
|
||||
g.POST("/torrent/generate", handles.GenerateTorrentForPath)
|
||||
// Direct upload (client-side upload to storage)
|
||||
g.POST("/get_direct_upload_info", middlewares.FsUp, handles.FsGetDirectUploadInfo)
|
||||
g.POST("/get_direct_upload_info", handles.FsGetDirectUploadInfo)
|
||||
}
|
||||
|
||||
func _task(g *gin.RouterGroup) {
|
||||
|
||||
Reference in New Issue
Block a user