fix: check if the req path is relative path (close #2531)

This commit is contained in:
Noah Hsu
2022-11-30 21:38:00 +08:00
parent f9788ea7cf
commit b5bf5f4325
8 changed files with 172 additions and 68 deletions

View File

@ -56,8 +56,12 @@ func FsList(c *gin.Context) {
}
req.Validate()
user := c.MustGet("user").(*model.User)
req.Path = stdpath.Join(user.BasePath, req.Path)
meta, err := db.GetNearestMeta(req.Path)
reqPath, err := user.JoinPath(req.Path)
if err != nil {
common.ErrorResp(c, err, 403)
return
}
meta, err := db.GetNearestMeta(reqPath)
if err != nil {
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
common.ErrorResp(c, err, 500, true)
@ -65,30 +69,30 @@ func FsList(c *gin.Context) {
}
}
c.Set("meta", meta)
if !common.CanAccess(user, meta, req.Path, req.Password) {
if !common.CanAccess(user, meta, reqPath, req.Password) {
common.ErrorStrResp(c, "password is incorrect", 403)
return
}
if !user.CanWrite() && !common.CanWrite(meta, req.Path) && req.Refresh {
if !user.CanWrite() && !common.CanWrite(meta, reqPath) && req.Refresh {
common.ErrorStrResp(c, "Refresh without permission", 403)
return
}
objs, err := fs.List(c, req.Path, req.Refresh)
objs, err := fs.List(c, reqPath, req.Refresh)
if err != nil {
common.ErrorResp(c, err, 500)
return
}
total, objs := pagination(objs, &req.PageReq)
provider := "unknown"
storage, err := fs.GetStorage(req.Path)
storage, err := fs.GetStorage(reqPath)
if err == nil {
provider = storage.GetStorage().Driver
}
common.SuccessResp(c, FsListResp{
Content: toObjsResp(objs, req.Path, isEncrypt(meta, req.Path)),
Content: toObjsResp(objs, reqPath, isEncrypt(meta, reqPath)),
Total: int64(total),
Readme: getReadme(meta, req.Path),
Write: user.CanWrite() || common.CanWrite(meta, req.Path),
Readme: getReadme(meta, reqPath),
Write: user.CanWrite() || common.CanWrite(meta, reqPath),
Provider: provider,
})
}
@ -100,15 +104,21 @@ func FsDirs(c *gin.Context) {
return
}
user := c.MustGet("user").(*model.User)
var reqPath string
if req.ForceRoot {
if !user.IsAdmin() {
common.ErrorStrResp(c, "Permission denied", 403)
return
}
} else {
req.Path = stdpath.Join(user.BasePath, req.Path)
tmp, err := user.JoinPath(req.Path)
if err != nil {
common.ErrorResp(c, err, 403)
return
}
reqPath = tmp
}
meta, err := db.GetNearestMeta(req.Path)
meta, err := db.GetNearestMeta(reqPath)
if err != nil {
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
common.ErrorResp(c, err, 500, true)
@ -116,11 +126,11 @@ func FsDirs(c *gin.Context) {
}
}
c.Set("meta", meta)
if !common.CanAccess(user, meta, req.Path, req.Password) {
if !common.CanAccess(user, meta, reqPath, req.Password) {
common.ErrorStrResp(c, "password is incorrect", 403)
return
}
objs, err := fs.List(c, req.Path)
objs, err := fs.List(c, reqPath)
if err != nil {
common.ErrorResp(c, err, 500)
return
@ -218,8 +228,12 @@ func FsGet(c *gin.Context) {
return
}
user := c.MustGet("user").(*model.User)
req.Path = stdpath.Join(user.BasePath, req.Path)
meta, err := db.GetNearestMeta(req.Path)
reqPath, err := user.JoinPath(req.Path)
if err != nil {
common.ErrorResp(c, err, 403)
return
}
meta, err := db.GetNearestMeta(reqPath)
if err != nil {
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {
common.ErrorResp(c, err, 500)
@ -227,18 +241,18 @@ func FsGet(c *gin.Context) {
}
}
c.Set("meta", meta)
if !common.CanAccess(user, meta, req.Path, req.Password) {
if !common.CanAccess(user, meta, reqPath, req.Password) {
common.ErrorStrResp(c, "password is incorrect", 403)
return
}
obj, err := fs.Get(c, req.Path)
obj, err := fs.Get(c, reqPath)
if err != nil {
common.ErrorResp(c, err, 500)
return
}
var rawURL string
storage, err := fs.GetStorage(req.Path)
storage, err := fs.GetStorage(reqPath)
provider := "unknown"
if err == nil {
provider = storage.Config().Name
@ -252,13 +266,13 @@ func FsGet(c *gin.Context) {
if storage.GetStorage().DownProxyUrl != "" {
rawURL = fmt.Sprintf("%s%s?sign=%s",
strings.Split(storage.GetStorage().DownProxyUrl, "\n")[0],
utils.EncodePath(req.Path, true),
sign.Sign(req.Path))
utils.EncodePath(reqPath, true),
sign.Sign(reqPath))
} else {
rawURL = fmt.Sprintf("%s/p%s?sign=%s",
common.GetApiUrl(c.Request),
utils.EncodePath(req.Path, true),
sign.Sign(req.Path))
utils.EncodePath(reqPath, true),
sign.Sign(reqPath))
}
} else {
// file have raw url
@ -266,7 +280,7 @@ func FsGet(c *gin.Context) {
rawURL = u.URL()
} else {
// if storage is not proxy, use raw url by fs.Link
link, _, err := fs.Link(c, req.Path, model.LinkArgs{IP: c.ClientIP(), Header: c.Request.Header})
link, _, err := fs.Link(c, reqPath, model.LinkArgs{IP: c.ClientIP(), Header: c.Request.Header})
if err != nil {
common.ErrorResp(c, err, 500)
return
@ -276,7 +290,7 @@ func FsGet(c *gin.Context) {
}
}
var related []model.Obj
parentPath := stdpath.Dir(req.Path)
parentPath := stdpath.Dir(reqPath)
sameLevelFiles, err := fs.List(c, parentPath)
if err == nil {
related = filterRelated(sameLevelFiles, obj)
@ -288,11 +302,11 @@ func FsGet(c *gin.Context) {
Size: obj.GetSize(),
IsDir: obj.IsDir(),
Modified: obj.ModTime(),
Sign: common.Sign(obj, parentPath, isEncrypt(meta, req.Path)),
Sign: common.Sign(obj, parentPath, isEncrypt(meta, reqPath)),
Type: utils.GetFileType(obj.GetName()),
},
RawURL: rawURL,
Readme: getReadme(meta, req.Path),
Readme: getReadme(meta, reqPath),
Provider: provider,
Related: toObjsResp(related, parentPath, isEncrypt(parentMeta, parentPath)),
})
@ -324,7 +338,12 @@ func FsOther(c *gin.Context) {
return
}
user := c.MustGet("user").(*model.User)
req.Path = stdpath.Join(user.BasePath, req.Path)
var err error
req.Path, err = user.JoinPath(req.Path)
if err != nil {
common.ErrorResp(c, err, 403)
return
}
meta, err := db.GetNearestMeta(req.Path)
if err != nil {
if !errors.Is(errors.Cause(err), errs.MetaNotFound) {