diff --git a/pkg/storage/fs/owncloud/owncloud.go b/pkg/storage/fs/owncloud/owncloud.go index bad1b6d53c9..76be9061aaf 100644 --- a/pkg/storage/fs/owncloud/owncloud.go +++ b/pkg/storage/fs/owncloud/owncloud.go @@ -263,7 +263,9 @@ func (fs *ocfs) toInternalPath(ctx context.Context, sp string) (ip string) { if fs.c.EnableHome { u := user.ContextMustGetUser(ctx) layout := templates.WithUser(u, fs.c.UserLayout) - ip = filepath.Join(fs.c.DataDirectory, layout, "files", sp) + // The inner filepath.Join prevents the path from breaking out of + // //files/ + ip = filepath.Join(fs.c.DataDirectory, layout, "files", filepath.Join("/", sp)) } else { // trim all / sp = strings.Trim(sp, "/") @@ -290,7 +292,7 @@ func (fs *ocfs) toInternalPath(ctx context.Context, sp string) (ip string) { ip = filepath.Join(fs.c.DataDirectory, layout, "files") } else { // parts = "", "foo/bar.txt" - ip = filepath.Join(fs.c.DataDirectory, layout, "files", segments[1]) + ip = filepath.Join(fs.c.DataDirectory, layout, "files", filepath.Join(segments[1])) } } @@ -362,7 +364,7 @@ func (fs *ocfs) getVersionsPath(ctx context.Context, ip string) string { return filepath.Join(fs.c.DataDirectory, layout, "files_versions") case 4: // parts = "", "", "foo/bar.txt" - return filepath.Join(fs.c.DataDirectory, layout, "files_versions", parts[3]) + return filepath.Join(fs.c.DataDirectory, layout, "files_versions", filepath.Join("/", parts[3])) default: return "" // TODO Must not happen? } @@ -799,7 +801,7 @@ func (fs *ocfs) resolve(ctx context.Context, ref *provider.Reference) (string, e if err != nil { return "", err } - filepath.Join("/", ip, ref.Path) + filepath.Join("/", ip, filepath.Join("/", ref.Path)) return ip, nil } diff --git a/pkg/storage/fs/owncloud/upload.go b/pkg/storage/fs/owncloud/upload.go index e48f1c74943..181f86e643f 100644 --- a/pkg/storage/fs/owncloud/upload.go +++ b/pkg/storage/fs/owncloud/upload.go @@ -263,7 +263,7 @@ func (fs *ocfs) getUploadPath(ctx context.Context, uploadID string) (string, err // GetUpload returns the Upload for the given upload id func (fs *ocfs) GetUpload(ctx context.Context, id string) (tusd.Upload, error) { - infoPath := filepath.Join(fs.c.UploadInfoDir, id+".info") + infoPath := filepath.Join(fs.c.UploadInfoDir, filepath.Join("/", id+".info")) info := tusd.FileInfo{} data, err := ioutil.ReadFile(infoPath) diff --git a/pkg/storage/utils/chunking/chunking.go b/pkg/storage/utils/chunking/chunking.go index 5130d88772b..656ec14fe91 100644 --- a/pkg/storage/utils/chunking/chunking.go +++ b/pkg/storage/utils/chunking/chunking.go @@ -96,7 +96,7 @@ func (c *ChunkHandler) createChunkTempFile() (string, *os.File, error) { } func (c *ChunkHandler) getChunkFolderName(i *ChunkBLOBInfo) (string, error) { - path := "/" + c.ChunkFolder + filepath.Clean("/"+i.uploadID()) + path := filepath.Join("/", c.ChunkFolder, filepath.Join("/", i.uploadID())) if err := os.MkdirAll(path, 0755); err != nil { return "", err } @@ -132,7 +132,7 @@ func (c *ChunkHandler) saveChunk(path string, r io.ReadCloser) (bool, string, er } // c.logger.Info().Log("chunkfolder", chunksFolderName) - chunkTarget := chunksFolderName + "/" + fmt.Sprintf("%d", chunkInfo.CurrentChunk) + chunkTarget := filepath.Join(chunksFolderName, strconv.Itoa(chunkInfo.CurrentChunk)) if err = os.Rename(chunkTempFilename, chunkTarget); err != nil { return false, "", err } @@ -171,7 +171,7 @@ func (c *ChunkHandler) saveChunk(path string, r io.ReadCloser) (bool, string, er // walk all chunks and append to assembled file for i := range chunks { - target := chunksFolderName + "/" + fmt.Sprintf("%d", i) + target := filepath.Join(chunksFolderName, strconv.Itoa(i)) chunk, err := os.Open(target) if err != nil { diff --git a/pkg/storage/utils/decomposedfs/node/node.go b/pkg/storage/utils/decomposedfs/node/node.go index 55af74eb5c4..660165ef322 100644 --- a/pkg/storage/utils/decomposedfs/node/node.go +++ b/pkg/storage/utils/decomposedfs/node/node.go @@ -200,7 +200,7 @@ func isNotDir(err error) bool { // Child returns the child node with the given name func (n *Node) Child(ctx context.Context, name string) (*Node, error) { - link, err := os.Readlink(filepath.Join(n.InternalPath(), name)) + link, err := os.Readlink(filepath.Join(n.InternalPath(), filepath.Join("/", name))) if err != nil { if os.IsNotExist(err) || isNotDir(err) { c := &Node{ diff --git a/pkg/storage/utils/localfs/localfs.go b/pkg/storage/utils/localfs/localfs.go index c8d5cc2fbc2..e0c6464fe14 100644 --- a/pkg/storage/utils/localfs/localfs.go +++ b/pkg/storage/utils/localfs/localfs.go @@ -161,6 +161,9 @@ func getUser(ctx context.Context) (*userpb.User, error) { } func (fs *localfs) wrap(ctx context.Context, p string) string { + // This is to prevent path traversal. + // With this p can't break out of its parent folder + p = path.Join("/", p) var internal string if !fs.conf.DisableHome { layout, err := fs.GetHome(ctx) @@ -203,6 +206,7 @@ func (fs *localfs) wrapRecycleBin(ctx context.Context, p string) string { } func (fs *localfs) wrapVersions(ctx context.Context, p string) string { + p = path.Join("/", p) var internal string if !fs.conf.DisableHome { layout, err := fs.GetHome(ctx)