fix: check path for OoS symlinks
parent
094ee331d6
commit
592606a00d
|
@ -65,21 +65,6 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) {
|
||||||
return nil, os.ErrPermission
|
return nil, os.ErrPermission
|
||||||
}
|
}
|
||||||
|
|
||||||
isSymlink := false
|
|
||||||
symlink := ""
|
|
||||||
if lst, ok := opts.Fs.(afero.Lstater); ok {
|
|
||||||
info, _, err := lst.LstatIfPossible(opts.Path)
|
|
||||||
if err == nil {
|
|
||||||
isSymlink = IsSymlink(info.Mode())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if isSymlink {
|
|
||||||
if lsf, ok := opts.Fs.(afero.LinkReader); ok {
|
|
||||||
symlink, _ = lsf.ReadlinkIfPossible(opts.Path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
info, err := opts.Fs.Stat(opts.Path)
|
info, err := opts.Fs.Stat(opts.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -92,8 +77,6 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) {
|
||||||
ModTime: info.ModTime(),
|
ModTime: info.ModTime(),
|
||||||
Mode: info.Mode(),
|
Mode: info.Mode(),
|
||||||
IsDir: info.IsDir(),
|
IsDir: info.IsDir(),
|
||||||
IsSymlink: isSymlink,
|
|
||||||
Link: symlink,
|
|
||||||
Size: info.Size(),
|
Size: info.Size(),
|
||||||
Extension: filepath.Ext(info.Name()),
|
Extension: filepath.Ext(info.Name()),
|
||||||
Token: opts.Token,
|
Token: opts.Token,
|
||||||
|
|
|
@ -37,16 +37,10 @@ var resourceGetHandler = withUser(func(w http.ResponseWriter, r *http.Request, d
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if symlink's target is within base path
|
err = checkOutOfScopeSymlink(d, file.Path)
|
||||||
if file.IsSymlink {
|
if err != nil {
|
||||||
parentDir := filepath.Dir(filepath.Clean(file.Path))
|
|
||||||
fullLinkTarget := filepath.Join(d.user.FullPath(parentDir), file.Link)
|
|
||||||
scopedLinkTarget := d.user.FullPath(filepath.Join(parentDir, file.Link))
|
|
||||||
if fullLinkTarget != scopedLinkTarget {
|
|
||||||
err = errors.ErrNotExist
|
|
||||||
return errToStatus(err), err
|
return errToStatus(err), err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if r.URL.Query().Get("disk_usage") == "true" {
|
if r.URL.Query().Get("disk_usage") == "true" {
|
||||||
du, inodes, err := fileutils.DiskUsage(file.Fs, file.Path, 100)
|
du, inodes, err := fileutils.DiskUsage(file.Fs, file.Path, 100)
|
||||||
|
@ -322,6 +316,38 @@ func checkParent(src, dst string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks if path contains symlink to out-of-scope targets.
|
||||||
|
// Returns error ErrNotExist if it does.
|
||||||
|
func checkOutOfScopeSymlink(d *data, path string) error {
|
||||||
|
lsf, ok := d.user.Fs.(afero.LinkReader)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var parts []string
|
||||||
|
for _, part := range strings.Split(path, string(os.PathSeparator)) {
|
||||||
|
if part != "" {
|
||||||
|
parts = append(parts, part)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evalPath := string(os.PathSeparator)
|
||||||
|
for _, part := range parts {
|
||||||
|
evalPath = filepath.Join(evalPath, filepath.Clean(part))
|
||||||
|
symlink, err := lsf.ReadlinkIfPossible(evalPath)
|
||||||
|
if err == nil {
|
||||||
|
parentDir := filepath.Dir(evalPath)
|
||||||
|
fullLinkTarget := filepath.Join(d.user.FullPath(parentDir), symlink)
|
||||||
|
scopedLinkTarget := d.user.FullPath(filepath.Join(parentDir, symlink))
|
||||||
|
if fullLinkTarget != scopedLinkTarget {
|
||||||
|
return errors.ErrNotExist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func addVersionSuffix(source string, fs afero.Fs) string {
|
func addVersionSuffix(source string, fs afero.Fs) string {
|
||||||
counter := 1
|
counter := 1
|
||||||
dir, name := path.Split(source)
|
dir, name := path.Split(source)
|
||||||
|
|
Loading…
Reference in New Issue