Security: Create new files without execution permission #2809

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer 2022-10-31 15:01:48 +01:00
parent 6ae5c5e4a6
commit 91774c4068
29 changed files with 77 additions and 69 deletions

View file

@ -91,14 +91,14 @@ func SaveConfigOptions(router *gin.RouterGroup) {
}
// Make sure directory exists.
if err := os.MkdirAll(filepath.Dir(fileName), os.ModePerm); err != nil {
if err := os.MkdirAll(filepath.Dir(fileName), fs.ModeDir); err != nil {
log.Errorf("config: failed creating config path %s (%s)", filepath.Dir(fileName), err)
c.AbortWithStatusJSON(http.StatusInternalServerError, err)
return
}
// Write YAML data to file.
if err := os.WriteFile(fileName, yamlData, os.ModePerm); err != nil {
if err := os.WriteFile(fileName, yamlData, fs.ModeFile); err != nil {
log.Errorf("config: failed writing values to %s (%s)", clean.Log(fileName), err)
c.AbortWithStatusJSON(http.StatusInternalServerError, err)
return

View file

@ -42,7 +42,7 @@ func SharePreview(router *gin.RouterGroup) {
thumbPath := path.Join(conf.ThumbCachePath(), "share")
if err := os.MkdirAll(thumbPath, os.ModePerm); err != nil {
if err := os.MkdirAll(thumbPath, fs.ModeDir); err != nil {
log.Error(err)
c.Redirect(http.StatusTemporaryRedirect, conf.SitePreview())
return

View file

@ -110,7 +110,7 @@ func backupAction(ctx *cli.Context) error {
// Create backup directory if not exists.
if dir := filepath.Dir(indexFileName); dir != "." {
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
if err := os.MkdirAll(dir, fs.ModeDir); err != nil {
return err
}
}
@ -162,7 +162,7 @@ func backupAction(ctx *cli.Context) error {
fmt.Println(out.String())
} else {
// Write output to file.
if err := os.WriteFile(indexFileName, []byte(out.String()), os.ModePerm); err != nil {
if err := os.WriteFile(indexFileName, []byte(out.String()), fs.ModeFile); err != nil {
return err
}
}

View file

@ -284,11 +284,11 @@ func (c *Config) initSerial() (err error) {
storageName := filepath.Join(c.StoragePath(), serialName)
backupName := filepath.Join(c.BackupPath(), serialName)
if err = os.WriteFile(storageName, []byte(c.serial), os.ModePerm); err != nil {
if err = os.WriteFile(storageName, []byte(c.serial), fs.ModeFile); err != nil {
return fmt.Errorf("could not create %s: %s", storageName, err)
}
if err = os.WriteFile(backupName, []byte(c.serial), os.ModePerm); err != nil {
if err = os.WriteFile(backupName, []byte(c.serial), fs.ModeFile); err != nil {
return fmt.Errorf("could not create %s: %s", backupName, err)
}

View file

@ -79,109 +79,109 @@ func (c *Config) CreateDirectories() error {
if c.AssetsPath() == "" {
return notFoundError("assets")
} else if err := os.MkdirAll(c.AssetsPath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.AssetsPath(), fs.ModeDir); err != nil {
return createError(c.AssetsPath(), err)
}
if c.StoragePath() == "" {
return notFoundError("storage")
} else if err := os.MkdirAll(c.StoragePath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.StoragePath(), fs.ModeDir); err != nil {
return createError(c.StoragePath(), err)
}
if c.UsersPath() == "" {
return notFoundError("users")
} else if err := os.MkdirAll(c.UsersPath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.UsersPath(), fs.ModeDir); err != nil {
return createError(c.UsersPath(), err)
}
if c.CmdCachePath() == "" {
return notFoundError("cmd cache")
} else if err := os.MkdirAll(c.CmdCachePath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.CmdCachePath(), fs.ModeDir); err != nil {
return createError(c.CmdCachePath(), err)
}
if c.BackupPath() == "" {
return notFoundError("backup")
} else if err := os.MkdirAll(c.BackupPath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.BackupPath(), fs.ModeDir); err != nil {
return createError(c.BackupPath(), err)
}
if c.OriginalsPath() == "" {
return notFoundError("originals")
} else if err := os.MkdirAll(c.OriginalsPath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.OriginalsPath(), fs.ModeDir); err != nil {
return createError(c.OriginalsPath(), err)
}
if c.ImportPath() == "" {
return notFoundError("import")
} else if err := os.MkdirAll(c.ImportPath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.ImportPath(), fs.ModeDir); err != nil {
return createError(c.ImportPath(), err)
}
if filepath.IsAbs(c.SidecarPath()) {
if err := os.MkdirAll(c.SidecarPath(), os.ModePerm); err != nil {
if err := os.MkdirAll(c.SidecarPath(), fs.ModeDir); err != nil {
return createError(c.SidecarPath(), err)
}
}
if c.CachePath() == "" {
return notFoundError("cache")
} else if err := os.MkdirAll(c.CachePath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.CachePath(), fs.ModeDir); err != nil {
return createError(c.CachePath(), err)
}
if c.ThumbCachePath() == "" {
return notFoundError("thumbs")
} else if err := os.MkdirAll(c.ThumbCachePath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.ThumbCachePath(), fs.ModeDir); err != nil {
return createError(c.ThumbCachePath(), err)
}
if c.ConfigPath() == "" {
return notFoundError("config")
} else if err := os.MkdirAll(c.ConfigPath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.ConfigPath(), fs.ModeDir); err != nil {
return createError(c.ConfigPath(), err)
}
if c.CertificatesPath() == "" {
return notFoundError("certificates")
} else if err := os.MkdirAll(c.CertificatesPath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.CertificatesPath(), fs.ModeDir); err != nil {
return createError(c.CertificatesPath(), err)
}
if c.TempPath() == "" {
return notFoundError("temp")
} else if err := os.MkdirAll(c.TempPath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.TempPath(), fs.ModeDir); err != nil {
return createError(c.TempPath(), err)
}
if c.AlbumsPath() == "" {
return notFoundError("albums")
} else if err := os.MkdirAll(c.AlbumsPath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.AlbumsPath(), fs.ModeDir); err != nil {
return createError(c.AlbumsPath(), err)
}
if c.TensorFlowModelPath() == "" {
return notFoundError("tensorflow model")
} else if err := os.MkdirAll(c.TensorFlowModelPath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.TensorFlowModelPath(), fs.ModeDir); err != nil {
return createError(c.TensorFlowModelPath(), err)
}
if c.BuildPath() == "" {
return notFoundError("build")
} else if err := os.MkdirAll(c.BuildPath(), os.ModePerm); err != nil {
} else if err := os.MkdirAll(c.BuildPath(), fs.ModeDir); err != nil {
return createError(c.BuildPath(), err)
}
if filepath.Dir(c.PIDFilename()) == "" {
return notFoundError("pid file")
} else if err := os.MkdirAll(filepath.Dir(c.PIDFilename()), os.ModePerm); err != nil {
} else if err := os.MkdirAll(filepath.Dir(c.PIDFilename()), fs.ModeDir); err != nil {
return createError(filepath.Dir(c.PIDFilename()), err)
}
if filepath.Dir(c.LogFilename()) == "" {
return notFoundError("log file")
} else if err := os.MkdirAll(filepath.Dir(c.LogFilename()), os.ModePerm); err != nil {
} else if err := os.MkdirAll(filepath.Dir(c.LogFilename()), fs.ModeDir); err != nil {
return createError(filepath.Dir(c.LogFilename()), err)
}
@ -323,7 +323,7 @@ func (c *Config) UserPath(userUid string) string {
dir := filepath.Join(c.UsersPath(), userUid)
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
if err := os.MkdirAll(dir, fs.ModeDir); err != nil {
return ""
}
@ -338,7 +338,7 @@ func (c *Config) UserUploadPath(userUid, token string) (string, error) {
dir := filepath.Join(c.UserPath(userUid), "upload", clean.Token(token))
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
if err := os.MkdirAll(dir, fs.ModeDir); err != nil {
return "", err
}
@ -377,7 +377,7 @@ func (c *Config) tempPath() string {
if c.options.TempPath != "" {
if dir := fs.Abs(c.options.TempPath); dir == "" {
// Ignore.
} else if err := os.MkdirAll(dir, os.ModePerm); err != nil {
} else if err := os.MkdirAll(dir, fs.ModeDir); err != nil {
// Ignore.
} else if fs.PathWritable(dir) {
return dir
@ -387,7 +387,7 @@ func (c *Config) tempPath() string {
// Find alternative temp path based on storage serial checksum.
if dir := filepath.Join(osTempDir, "photoprism_"+c.SerialChecksum()); dir == "" {
// Ignore.
} else if err := os.MkdirAll(dir, os.ModePerm); err != nil {
} else if err := os.MkdirAll(dir, fs.ModeDir); err != nil {
// Ignore.
} else if fs.PathWritable(dir) {
return dir
@ -396,7 +396,7 @@ func (c *Config) tempPath() string {
// Find alternative temp path based on built-in TempDir() function.
if dir, err := ioutil.TempDir(osTempDir, "photoprism_"); err != nil || dir == "" {
// Ignore.
} else if err = os.MkdirAll(dir, os.ModePerm); err != nil {
} else if err = os.MkdirAll(dir, fs.ModeDir); err != nil {
// Ignore.
} else if fs.PathWritable(dir) {
return dir

View file

@ -42,7 +42,7 @@ func (c *Config) CreateDarktableCachePath() (string, error) {
if cachePath == "" {
return "", nil
} else if err := os.MkdirAll(cachePath, os.ModePerm); err != nil {
} else if err := os.MkdirAll(cachePath, fs.ModeDir); err != nil {
return cachePath, err
} else {
c.options.DarktableCachePath = cachePath
@ -57,7 +57,7 @@ func (c *Config) CreateDarktableConfigPath() (string, error) {
if configPath == "" {
return "", nil
} else if err := os.MkdirAll(configPath, os.ModePerm); err != nil {
} else if err := os.MkdirAll(configPath, fs.ModeDir); err != nil {
return configPath, err
} else {
c.options.DarktableConfigPath = configPath

View file

@ -165,7 +165,7 @@ func NewTestConfig(pkg string) *Config {
s := customize.NewSettings(c.DefaultTheme(), c.DefaultLocale())
if err := os.MkdirAll(c.ConfigPath(), os.ModePerm); err != nil {
if err := os.MkdirAll(c.ConfigPath(), fs.ModeDir); err != nil {
log.Fatalf("config: %s", err.Error())
}

View file

@ -154,7 +154,7 @@ func (s *Settings) Save(fileName string) error {
s.Propagate()
if err := os.WriteFile(fileName, data, os.ModePerm); err != nil {
if err := os.WriteFile(fileName, data, fs.ModeFile); err != nil {
return err
}

View file

@ -8,7 +8,7 @@ Search:
BatchSize: 0
Maps:
Animate: 0
Style: streets
Style: ""
Features:
Account: true
Advanced: false

View file

@ -30,7 +30,7 @@ func (m *Album) SaveAsYaml(fileName string) error {
}
// Make sure directory exists.
if err := os.MkdirAll(filepath.Dir(fileName), os.ModePerm); err != nil {
if err := os.MkdirAll(filepath.Dir(fileName), fs.ModeDir); err != nil {
return err
}
@ -38,7 +38,7 @@ func (m *Album) SaveAsYaml(fileName string) error {
defer albumYamlMutex.Unlock()
// Write YAML data to file.
if err := os.WriteFile(fileName, data, os.ModePerm); err != nil {
if err := os.WriteFile(fileName, data, fs.ModeFile); err != nil {
return err
}

View file

@ -34,7 +34,7 @@ func (m *Photo) SaveAsYaml(fileName string) error {
}
// Make sure directory exists.
if err := os.MkdirAll(filepath.Dir(fileName), os.ModePerm); err != nil {
if err := os.MkdirAll(filepath.Dir(fileName), fs.ModeDir); err != nil {
return err
}
@ -42,7 +42,7 @@ func (m *Photo) SaveAsYaml(fileName string) error {
defer photoYamlMutex.Unlock()
// Write YAML data to file.
if err := os.WriteFile(fileName, data, os.ModePerm); err != nil {
if err := os.WriteFile(fileName, data, fs.ModeFile); err != nil {
return err
}

View file

@ -153,7 +153,7 @@ func (c *Config) Resync(token string) (err error) {
mutex.Lock()
defer mutex.Unlock()
if err := os.MkdirAll(filepath.Dir(c.FileName), os.ModePerm); err != nil {
if err := os.MkdirAll(filepath.Dir(c.FileName), fs.ModeDir); err != nil {
return err
}
@ -275,11 +275,11 @@ func (c *Config) Save() error {
c.Propagate()
if err := os.MkdirAll(filepath.Dir(c.FileName), os.ModePerm); err != nil {
if err := os.MkdirAll(filepath.Dir(c.FileName), fs.ModeDir); err != nil {
return err
}
if err := os.WriteFile(c.FileName, data, os.ModePerm); err != nil {
if err := os.WriteFile(c.FileName, data, fs.ModeFile); err != nil {
return err
}

View file

@ -133,7 +133,7 @@ func (c *Convert) ToJpeg(f *MediaFile, force bool) (*MediaFile, error) {
break
} else if res := out.Bytes(); len(res) < 512 || !mimetype.Detect(res).Is(fs.MimeTypeJpeg) {
continue
} else if err = os.WriteFile(jpegName, res, os.ModePerm); err != nil {
} else if err = os.WriteFile(jpegName, res, fs.ModeFile); err != nil {
log.Tracef("convert: %s (%s)", err, filepath.Base(cmd.Path))
continue
} else {

View file

@ -52,7 +52,7 @@ func (c *Convert) ToJson(f *MediaFile) (jsonName string, err error) {
}
// Write output to file.
if err := os.WriteFile(jsonName, []byte(out.String()), os.ModePerm); err != nil {
if err := os.WriteFile(jsonName, []byte(out.String()), fs.ModeFile); err != nil {
return "", err
}

View file

@ -70,7 +70,7 @@ func ImportWorker(jobs <-chan ImportJob) {
if fs.PathExists(destDir) {
// Do nothing.
} else if err := os.MkdirAll(destDir, os.ModePerm); err != nil {
} else if err := os.MkdirAll(destDir, fs.ModeDir); err != nil {
log.Errorf("import: failed creating folder for %s (%s)", clean.Log(f.BaseName()), err.Error())
} else {
destDirRel := fs.RelName(destDir, imp.originalsPath())

View file

@ -641,7 +641,7 @@ func (m *MediaFile) HasSameName(f *MediaFile) bool {
// Move file to a new destination with the filename provided in parameter.
func (m *MediaFile) Move(dest string) error {
if err := os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil {
if err := os.MkdirAll(filepath.Dir(dest), fs.ModeDir); err != nil {
return err
}
@ -668,7 +668,7 @@ func (m *MediaFile) Move(dest string) error {
// Copy a MediaFile to another file by destinationFilename.
func (m *MediaFile) Copy(dest string) error {
if err := os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil {
if err := os.MkdirAll(filepath.Dir(dest), fs.ModeDir); err != nil {
return err
}
@ -684,7 +684,7 @@ func (m *MediaFile) Copy(dest string) error {
defer thisFile.Close()
destFile, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE, os.ModePerm)
destFile, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE, fs.ModeFile)
if err != nil {
log.Error(err.Error())

View file

@ -970,7 +970,7 @@ func TestMediaFile_Move(t *testing.T) {
origName := tmpPath + "/original.jpg"
destName := tmpPath + "/destination.jpg"
if err := os.MkdirAll(tmpPath, os.ModePerm); err != nil {
if err := os.MkdirAll(tmpPath, fs.ModeDir); err != nil {
t.Fatal(err)
}
@ -1006,7 +1006,7 @@ func TestMediaFile_Copy(t *testing.T) {
tmpPath := conf.CachePath() + "/_tmp/TestMediaFile_Copy"
if err := os.MkdirAll(tmpPath, os.ModePerm); err != nil {
if err := os.MkdirAll(tmpPath, fs.ModeDir); err != nil {
t.Fatal(err)
}
@ -2359,7 +2359,7 @@ func TestMediaFile_RenameSidecarFiles(t *testing.T) {
t.Fatal(err)
}
if err := os.MkdirAll(filepath.Join(conf.SidecarPath(), "foo"), os.ModePerm); err != nil {
if err := os.MkdirAll(filepath.Join(conf.SidecarPath(), "foo"), fs.ModeDir); err != nil {
t.Fatal(err)
}

View file

@ -193,7 +193,7 @@ func (c Client) Download(from, to string, force bool) (err error) {
if err != nil {
// Create local storage path.
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
if err := os.MkdirAll(dir, fs.ModeDir); err != nil {
return fmt.Errorf("webdav: cannot create folder %s (%s)", clean.Log(dir), err)
}
} else if !dirInfo.IsDir() {
@ -212,7 +212,7 @@ func (c Client) Download(from, to string, force bool) (err error) {
}
// Write data to file and return.
return os.WriteFile(to, bytes, os.ModePerm)
return os.WriteFile(to, bytes, fs.ModeFile)
}
// DownloadDir downloads all files from a remote to a local directory.
@ -261,7 +261,7 @@ func (c Client) CreateDir(dir string) error {
return nil
}
return c.client.MkdirAll(dir, os.ModePerm)
return c.client.MkdirAll(dir, fs.ModeDir)
}
// Upload uploads a single file to the remote server.
@ -282,7 +282,7 @@ func (c Client) Upload(from, to string) (err error) {
_ = file.Close()
}(file)
return c.client.WriteStream(to, file, os.ModePerm)
return c.client.WriteStream(to, file, fs.ModeFile)
}
// Delete deletes a single file or directory on a remote server.

View file

@ -129,13 +129,13 @@ func MarkUploadAsFavorite(fileName string) {
}
// Make sure directory exists.
if err := os.MkdirAll(filepath.Dir(yamlName), os.ModePerm); err != nil {
if err := os.MkdirAll(filepath.Dir(yamlName), fs.ModeDir); err != nil {
log.Errorf("webdav: %s", err.Error())
return
}
// Write YAML data to file.
if err := os.WriteFile(yamlName, []byte("Favorite: true\n"), os.ModePerm); err != nil {
if err := os.WriteFile(yamlName, []byte("Favorite: true\n"), fs.ModeFile); err != nil {
log.Errorf("webdav: %s", err.Error())
return
}

View file

@ -45,7 +45,7 @@ func FileName(hash, thumbPath string, width, height int, opts ...ResampleOption)
suffix := Suffix(width, height, opts...)
p := path.Join(thumbPath, hash[0:1], hash[1:2], hash[2:3])
if err := os.MkdirAll(p, os.ModePerm); err != nil {
if err := os.MkdirAll(p, fs.ModeDir); err != nil {
return "", err
}

View file

@ -19,7 +19,7 @@ func CachePath(basePath, fileHash, namespace string, create bool) (cachePath str
cachePath = path.Join(basePath, namespace, fileHash[0:1], fileHash[1:2], fileHash[2:3])
if create {
if err := os.MkdirAll(cachePath, os.ModePerm); err != nil {
if err := os.MkdirAll(cachePath, ModeDir); err != nil {
return "", err
}
}

View file

@ -10,7 +10,7 @@ import (
func CaseInsensitive(storagePath string) (result bool, err error) {
tmpName := filepath.Join(storagePath, ".caseTest.tmp")
if err = os.WriteFile(tmpName, []byte("{}"), os.ModePerm); err != nil {
if err = os.WriteFile(tmpName, []byte("{}"), ModeFile); err != nil {
return false, fmt.Errorf("%s not writable", filepath.Base(storagePath))
}

View file

@ -15,7 +15,7 @@ func Copy(src, dest string) (err error) {
}
}()
if err := os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil {
if err := os.MkdirAll(filepath.Dir(dest), ModeDir); err != nil {
return err
}
@ -27,7 +27,7 @@ func Copy(src, dest string) (err error) {
defer thisFile.Close()
destFile, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE, os.ModePerm)
destFile, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE, ModeFile)
if err != nil {
return err

View file

@ -147,7 +147,7 @@ func copyToFile(f *zip.File, dest string) (fileName string, err error) {
if f.FileInfo().IsDir() {
// Make Folder
return fileName, os.MkdirAll(fileName, os.ModePerm)
return fileName, os.MkdirAll(fileName, ModeDir)
}
// Make File
@ -157,7 +157,7 @@ func copyToFile(f *zip.File, dest string) (fileName string, err error) {
fdir = fileName[:lastIndex]
}
err = os.MkdirAll(fdir, os.ModePerm)
err = os.MkdirAll(fdir, ModeDir)
if err != nil {
return fileName, err
}
@ -179,7 +179,7 @@ func copyToFile(f *zip.File, dest string) (fileName string, err error) {
// Download downloads a file from a URL.
func Download(filepath string, url string) error {
os.MkdirAll("/tmp/photoprism", os.ModePerm)
os.MkdirAll("/tmp/photoprism", ModeDir)
// Create the file
out, err := os.Create(filepath)

8
pkg/fs/mode.go Normal file
View file

@ -0,0 +1,8 @@
package fs
import "os"
var (
ModeDir os.FileMode = 0o777
ModeFile os.FileMode = 0o666
)

View file

@ -14,7 +14,7 @@ func Move(src, dest string) (err error) {
}
}()
if err := os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil {
if err := os.MkdirAll(filepath.Dir(dest), ModeDir); err != nil {
return err
}

View file

@ -21,7 +21,7 @@ func FileName(fileName, dirName, baseDir, fileExt string) string {
}
}
if err := os.MkdirAll(dirName, os.ModePerm); err != nil {
if err := os.MkdirAll(dirName, ModeDir); err != nil {
fmt.Println(err.Error())
return ""
}

View file

@ -23,7 +23,7 @@ func TestResolve(t *testing.T) {
}(linkName, targetName)
// Create empty test target file.
if targetFile, err := os.OpenFile(targetName, os.O_RDONLY|os.O_CREATE, os.ModePerm); err != nil {
if targetFile, err := os.OpenFile(targetName, os.O_RDONLY|os.O_CREATE, ModeFile); err != nil {
t.Fatal(err)
} else if err = targetFile.Close(); err != nil {
t.Fatal(err)

View file

@ -19,7 +19,7 @@ func SymlinksSupported(storagePath string) (bool, error) {
}(linkName, targetName)
// Create empty test target file.
if targetFile, err := os.OpenFile(targetName, os.O_RDONLY|os.O_CREATE, os.ModePerm); err != nil {
if targetFile, err := os.OpenFile(targetName, os.O_RDONLY|os.O_CREATE, ModeFile); err != nil {
return false, err
} else if err = targetFile.Close(); err != nil {
return false, err