fix: limit user access to shared dir

This commit is contained in:
Oleg Lobanov 2020-12-28 17:20:21 +01:00
parent b483e8d0bc
commit 5eeb74af3f
No known key found for this signature in database
GPG Key ID: 7CC64E41212621B0
2 changed files with 29 additions and 38 deletions

View File

@ -101,7 +101,7 @@ export default {
}, },
data: () => ({ data: () => ({
error: null, error: null,
filePath: '', path: '',
showLimit: 500 showLimit: 500
}), }),
watch: { watch: {
@ -128,28 +128,8 @@ export default {
if (this.req.type === 'video') return 'movie' if (this.req.type === 'video') return 'movie'
return 'insert_drive_file' return 'insert_drive_file'
}, },
path: function () {
let absoluteParts = this.filePath.split('/')
let urlParts = this.$route.params.pathMatch.split('/')
absoluteParts.shift()
absoluteParts.forEach((_, i) => absoluteParts[i] = encodeURIComponent(absoluteParts[i]))
urlParts.forEach((_, i) => urlParts[i] = encodeURIComponent(urlParts[i]))
if (absoluteParts[absoluteParts.length - 1] === '') absoluteParts.pop()
if (urlParts[urlParts.length - 1] === '') urlParts.pop()
if (urlParts.length === 1) return absoluteParts[absoluteParts.length - 1]
let len = Math.min(absoluteParts.length, urlParts.length)
for (let i = 0; i < len; i++) {
if (urlParts[urlParts.length - 1 - i] !== absoluteParts[absoluteParts.length - 1 - i]) return urlParts.slice(urlParts.length - i).join('/')
}
return absoluteParts.slice(absoluteParts.length - len).join('/')
},
link: function () { link: function () {
return `${baseURL}/api/public/dl/${this.hash}/${this.path}` return `${baseURL}/api/public/dl/${this.hash}${this.path}`
}, },
fullLink: function () { fullLink: function () {
return window.location.origin + this.link return window.location.origin + this.link
@ -185,8 +165,6 @@ export default {
} }
} }
breadcrumbs.shift()
if (breadcrumbs.length > 3) { if (breadcrumbs.length > 3) {
while (breadcrumbs.length !== 4) { while (breadcrumbs.length !== 4) {
breadcrumbs.shift() breadcrumbs.shift()
@ -216,10 +194,10 @@ export default {
try { try {
let file = await api.getHash(encodeURIComponent(this.$route.params.pathMatch)) let file = await api.getHash(encodeURIComponent(this.$route.params.pathMatch))
this.filePath = file.path this.path = file.path
if (file.isDir) file.items = file.items.map((item, index) => { if (file.isDir) file.items = file.items.map((item, index) => {
item.index = index item.index = index
item.url = `/share/${this.hash}/${this.path}/${encodeURIComponent(item.name)}` item.url = `/share/${this.hash}${this.path}/${encodeURIComponent(item.name)}`
return item return item
}) })
this.updateRequest(file) this.updateRequest(file)

View File

@ -2,25 +2,23 @@ package http
import ( import (
"net/http" "net/http"
"path"
"path/filepath" "path/filepath"
"strings" "strings"
libErrors "github.com/filebrowser/filebrowser/v2/errors" "github.com/spf13/afero"
"github.com/filebrowser/filebrowser/v2/files" "github.com/filebrowser/filebrowser/v2/files"
) )
var withHashFile = func(fn handleFunc) handleFunc { var withHashFile = func(fn handleFunc) handleFunc {
return func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { return func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
id, rootName, path := ifPathWithName(r) id, path := ifPathWithName(r)
link, err := d.store.Share.GetByHash(id) link, err := d.store.Share.GetByHash(id)
if err != nil { if err != nil {
return errToStatus(err), err return errToStatus(err), err
} }
if rootName != "" && filepath.Base(rootName) != filepath.Base(link.Path) {
return errToStatus(libErrors.ErrNotExist), libErrors.ErrNotExist
}
user, err := d.store.Users.Get(d.server.Root, link.UserID) user, err := d.store.Users.Get(d.server.Root, link.UserID)
if err != nil { if err != nil {
return errToStatus(err), err return errToStatus(err), err
@ -30,7 +28,7 @@ var withHashFile = func(fn handleFunc) handleFunc {
file, err := files.NewFileInfo(files.FileOptions{ file, err := files.NewFileInfo(files.FileOptions{
Fs: d.user.Fs, Fs: d.user.Fs,
Path: filepath.Join(link.Path, path), Path: link.Path,
Modify: d.user.Perm.Modify, Modify: d.user.Perm.Modify,
Expand: true, Expand: true,
Checker: d, Checker: d,
@ -39,6 +37,22 @@ var withHashFile = func(fn handleFunc) handleFunc {
return errToStatus(err), err return errToStatus(err), err
} }
if file.IsDir {
// set fs root to the shared folder
d.user.Fs = afero.NewBasePathFs(d.user.Fs, filepath.Dir(link.Path))
file, err = files.NewFileInfo(files.FileOptions{
Fs: d.user.Fs,
Path: path,
Modify: d.user.Perm.Modify,
Expand: true,
Checker: d,
})
if err != nil {
return errToStatus(err), err
}
}
d.raw = file d.raw = file
return fn(w, r, d) return fn(w, r, d)
} }
@ -46,17 +60,16 @@ var withHashFile = func(fn handleFunc) handleFunc {
// ref to https://github.com/filebrowser/filebrowser/pull/727 // ref to https://github.com/filebrowser/filebrowser/pull/727
// `/api/public/dl/MEEuZK-v/file-name.txt` for old browsers to save file with correct name // `/api/public/dl/MEEuZK-v/file-name.txt` for old browsers to save file with correct name
func ifPathWithName(r *http.Request) (id, rootName, path string) { func ifPathWithName(r *http.Request) (id, filePath string) {
pathElements := strings.Split(r.URL.Path, "/") pathElements := strings.Split(r.URL.Path, "/")
// prevent maliciously constructed parameters like `/api/public/dl/XZzCDnK2_not_exists_hash_name` // prevent maliciously constructed parameters like `/api/public/dl/XZzCDnK2_not_exists_hash_name`
// len(pathElements) will be 1, and golang will panic `runtime error: index out of range` // len(pathElements) will be 1, and golang will panic `runtime error: index out of range`
switch len(pathElements) { switch len(pathElements) {
case 1: case 1:
return r.URL.Path, "", "" return r.URL.Path, "/"
case 2: //nolint: mnd
return pathElements[0], pathElements[1], ""
default: default:
return pathElements[0], pathElements[1], strings.Join(pathElements[2:], "/") return pathElements[0], path.Join("/", path.Join(pathElements[1:]...))
} }
} }