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:
@@ -1,16 +1,18 @@
|
||||
package filesystem
|
||||
|
||||
import (
|
||||
"os"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gabriel-vasile/mimetype"
|
||||
"github.com/goccy/go-json"
|
||||
|
||||
"github.com/pterodactyl/wings/internal/ufs"
|
||||
)
|
||||
|
||||
type Stat struct {
|
||||
os.FileInfo
|
||||
ufs.FileInfo
|
||||
Mimetype string
|
||||
}
|
||||
|
||||
@@ -31,40 +33,31 @@ func (s *Stat) MarshalJSON() ([]byte, error) {
|
||||
Created: s.CTime().Format(time.RFC3339),
|
||||
Modified: s.ModTime().Format(time.RFC3339),
|
||||
Mode: s.Mode().String(),
|
||||
// Using `&os.ModePerm` on the file's mode will cause the mode to only have the permission values, and nothing else.
|
||||
ModeBits: strconv.FormatUint(uint64(s.Mode()&os.ModePerm), 8),
|
||||
// Using `&ModePerm` on the file's mode will cause the mode to only have the permission values, and nothing else.
|
||||
ModeBits: strconv.FormatUint(uint64(s.Mode()&ufs.ModePerm), 8),
|
||||
Size: s.Size(),
|
||||
Directory: s.IsDir(),
|
||||
File: !s.IsDir(),
|
||||
Symlink: s.Mode().Perm()&os.ModeSymlink != 0,
|
||||
Symlink: s.Mode().Perm()&ufs.ModeSymlink != 0,
|
||||
Mime: s.Mimetype,
|
||||
})
|
||||
}
|
||||
|
||||
// Stat stats a file or folder and returns the base stat object from go along
|
||||
// with the MIME data that can be used for editing files.
|
||||
func (fs *Filesystem) Stat(p string) (Stat, error) {
|
||||
cleaned, err := fs.SafePath(p)
|
||||
func statFromFile(f ufs.File) (Stat, error) {
|
||||
s, err := f.Stat()
|
||||
if err != nil {
|
||||
return Stat{}, err
|
||||
}
|
||||
return fs.unsafeStat(cleaned)
|
||||
}
|
||||
|
||||
func (fs *Filesystem) unsafeStat(p string) (Stat, error) {
|
||||
s, err := os.Stat(p)
|
||||
if err != nil {
|
||||
return Stat{}, err
|
||||
}
|
||||
|
||||
var m *mimetype.MIME
|
||||
if !s.IsDir() {
|
||||
m, err = mimetype.DetectFile(p)
|
||||
m, err = mimetype.DetectReader(f)
|
||||
if err != nil {
|
||||
return Stat{}, err
|
||||
}
|
||||
if _, err := f.Seek(0, io.SeekStart); err != nil {
|
||||
return Stat{}, err
|
||||
}
|
||||
}
|
||||
|
||||
st := Stat{
|
||||
FileInfo: s,
|
||||
Mimetype: "inode/directory",
|
||||
@@ -72,6 +65,20 @@ func (fs *Filesystem) unsafeStat(p string) (Stat, error) {
|
||||
if m != nil {
|
||||
st.Mimetype = m.String()
|
||||
}
|
||||
|
||||
return st, nil
|
||||
}
|
||||
|
||||
// Stat stats a file or folder and returns the base stat object from go along
|
||||
// with the MIME data that can be used for editing files.
|
||||
func (fs *Filesystem) Stat(p string) (Stat, error) {
|
||||
f, err := fs.unixFS.Open(p)
|
||||
if err != nil {
|
||||
return Stat{}, err
|
||||
}
|
||||
defer f.Close()
|
||||
st, err := statFromFile(f)
|
||||
if err != nil {
|
||||
return Stat{}, err
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user