diff --git a/base/database/storage/fstree/fstree.go b/base/database/storage/fstree/fstree.go index 44cf384f..7965439a 100644 --- a/base/database/storage/fstree/fstree.go +++ b/base/database/storage/fstree/fstree.go @@ -15,6 +15,7 @@ import ( "strings" "time" + "github.com/hectane/go-acl" "github.com/safing/portmaster/base/database/iterator" "github.com/safing/portmaster/base/database/query" "github.com/safing/portmaster/base/database/record" @@ -288,10 +289,13 @@ func writeFile(filename string, data []byte, perm os.FileMode) error { defer t.Cleanup() //nolint:errcheck // Set permissions before writing data, in case the data is sensitive. - if !onWindows { - if err := t.Chmod(perm); err != nil { - return err - } + if onWindows { + err = acl.Chmod(filename, perm) + } else { + err = t.Chmod(perm) + } + if err != nil { + return err } if _, err := t.Write(data); err != nil { diff --git a/base/utils/fs.go b/base/utils/fs.go index b612a069..bb59960f 100644 --- a/base/utils/fs.go +++ b/base/utils/fs.go @@ -6,6 +6,8 @@ import ( "io/fs" "os" "runtime" + + "github.com/hectane/go-acl" ) const isWindows = runtime.GOOS == "windows" @@ -20,8 +22,9 @@ func EnsureDirectory(path string, perm os.FileMode) error { if f.IsDir() { // directory exists, check permissions if isWindows { - // TODO: set correct permission on windows - // acl.Chmod(path, perm) + // Ignore windows permission error. For none admin users it will always fail. + acl.Chmod(path, perm) + return nil } else if f.Mode().Perm() != perm { return os.Chmod(path, perm) } @@ -38,7 +41,13 @@ func EnsureDirectory(path string, perm os.FileMode) error { if err != nil { return fmt.Errorf("could not create dir %s: %w", path, err) } - return os.Chmod(path, perm) + if isWindows { + // Ignore windows permission error. For none admin users it will always fail. + acl.Chmod(path, perm) + return nil + } else { + return os.Chmod(path, perm) + } } // other error opening path return fmt.Errorf("failed to access %s: %w", path, err) diff --git a/base/utils/renameio/writefile.go b/base/utils/renameio/writefile.go index 21153025..073a1e1b 100644 --- a/base/utils/renameio/writefile.go +++ b/base/utils/renameio/writefile.go @@ -1,6 +1,11 @@ package renameio -import "os" +import ( + "os" + "runtime" + + "github.com/hectane/go-acl" +) // WriteFile mirrors os.WriteFile, replacing an existing file with the same // name atomically. @@ -14,7 +19,12 @@ func WriteFile(filename string, data []byte, perm os.FileMode) error { }() // Set permissions before writing data, in case the data is sensitive. - if err := t.Chmod(perm); err != nil { + if runtime.GOOS == "windows" { + err = acl.Chmod(t.path, perm) + } else { + err = t.Chmod(perm) + } + if err != nil { return err } diff --git a/go.mod b/go.mod index 8ffd3e37..f3d7a43e 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( github.com/gorilla/websocket v1.5.3 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-version v1.7.0 + github.com/hectane/go-acl v0.0.0-20230122075934-ca0b05cb1adb github.com/jackc/puddle/v2 v2.2.2 github.com/lmittmann/tint v1.0.5 github.com/maruel/panicparse/v2 v2.3.1 diff --git a/go.sum b/go.sum index 6f47c5af..f644b0d2 100644 --- a/go.sum +++ b/go.sum @@ -129,6 +129,8 @@ github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKe github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/hcl v0.0.0-20170914154624-68e816d1c783/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hectane/go-acl v0.0.0-20230122075934-ca0b05cb1adb h1:PGufWXXDq9yaev6xX1YQauaO1MV90e6Mpoq1I7Lz/VM= +github.com/hectane/go-acl v0.0.0-20230122075934-ca0b05cb1adb/go.mod h1:QiyDdbZLaJ/mZP4Zwc9g2QsfaEA4o7XvvgZegSci5/E= github.com/inconshreveable/log15 v0.0.0-20170622235902-74a0988b5f80/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -377,6 +379,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=