server(filesystem): rebuild everything imaginable

This wonderfully large commit replaces basically everything under the
`server/filesystem` package, re-implementing essentially everything.

This is related to
https://github.com/pterodactyl/wings/security/advisories/GHSA-494h-9924-xww9

If any vulnerabilities related to symlinks persist after this commit, I
will be very upset.

Signed-off-by: Matthew Penner <me@matthewp.io>
This commit is contained in:
Matthew Penner
2024-03-12 21:44:55 -06:00
parent 27f3e76c77
commit d1c0ca5260
51 changed files with 3694 additions and 1225 deletions

View File

@@ -2,7 +2,6 @@ package sftp
import (
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
@@ -122,7 +121,7 @@ func (h *Handler) Filewrite(request *sftp.Request) (io.WriterAt, error) {
if !h.can(permission) {
return nil, sftp.ErrSSHFxPermissionDenied
}
f, err := h.fs.Touch(request.Filepath, os.O_RDWR|os.O_CREATE|os.O_TRUNC)
f, err := h.fs.Touch(request.Filepath, os.O_RDWR|os.O_TRUNC)
if err != nil {
l.WithField("flags", request.Flags).WithField("error", err).Error("failed to open existing file on system")
return nil, sftp.ErrSSHFxFailure
@@ -220,16 +219,8 @@ func (h *Handler) Filecmd(request *sftp.Request) error {
if !h.can(PermissionFileCreate) {
return sftp.ErrSSHFxPermissionDenied
}
source, err := h.fs.SafePath(request.Filepath)
if err != nil {
return sftp.ErrSSHFxNoSuchFile
}
target, err := h.fs.SafePath(request.Target)
if err != nil {
return sftp.ErrSSHFxNoSuchFile
}
if err := os.Symlink(source, target); err != nil {
l.WithField("target", target).WithField("error", err).Error("failed to create symlink")
if err := h.fs.Symlink(request.Filepath, request.Target); err != nil {
l.WithField("target", request.Target).WithField("error", err).Error("failed to create symlink")
return sftp.ErrSSHFxFailure
}
break
@@ -274,16 +265,12 @@ func (h *Handler) Filelist(request *sftp.Request) (sftp.ListerAt, error) {
switch request.Method {
case "List":
p, err := h.fs.SafePath(request.Filepath)
if err != nil {
return nil, sftp.ErrSSHFxNoSuchFile
}
files, err := ioutil.ReadDir(p)
entries, err := h.fs.ReadDirStat(request.Filepath)
if err != nil {
h.logger.WithField("source", request.Filepath).WithField("error", err).Error("error while listing directory")
return nil, sftp.ErrSSHFxFailure
}
return ListerAt(files), nil
return ListerAt(entries), nil
case "Stat":
st, err := h.fs.Stat(request.Filepath)
if err != nil {