diff --git a/internal/articles/thresholds.go b/internal/articles/thresholds.go index d49ccbb..dd0c8f3 100644 --- a/internal/articles/thresholds.go +++ b/internal/articles/thresholds.go @@ -8,7 +8,8 @@ import ( "io" "io/fs" "os" - "syscall" + + "github.com/pilot-protocol/cosift/internal/fileowner" ) const DefaultThresholdsPath = "/etc/cosift/articles.json" @@ -49,11 +50,11 @@ func LoadThresholds(path string) (Thresholds, error) { if err != nil { return Thresholds{}, err } - st, ok := fi.Sys().(*syscall.Stat_t) + owner, ok := fileowner.UID(fi) switch { case !fi.Mode().IsRegular(): return Thresholds{}, errors.New("not a regular file") - case !ok || st.Uid != thresholdsOwner: + case !ok || owner != thresholdsOwner: return Thresholds{}, fmt.Errorf("owner must be uid %d", thresholdsOwner) case fi.Mode().Perm()&0o027 != 0: return Thresholds{}, errors.New("mode must not grant group write or any other access") diff --git a/internal/fileowner/owner_other.go b/internal/fileowner/owner_other.go new file mode 100644 index 0000000..b570b3f --- /dev/null +++ b/internal/fileowner/owner_other.go @@ -0,0 +1,9 @@ +//go:build !unix + +// Package fileowner reads a file's owning uid where the platform has one. +package fileowner + +import "os" + +// UID reports no owner here, so every owner check refuses. +func UID(os.FileInfo) (uint32, bool) { return 0, false } diff --git a/internal/fileowner/owner_unix.go b/internal/fileowner/owner_unix.go new file mode 100644 index 0000000..8fbdc67 --- /dev/null +++ b/internal/fileowner/owner_unix.go @@ -0,0 +1,18 @@ +//go:build unix + +// Package fileowner reads a file's owning uid where the platform has one. +package fileowner + +import ( + "os" + "syscall" +) + +// UID returns the file's owner uid; ok is false when it cannot be read. +func UID(fi os.FileInfo) (uid uint32, ok bool) { + st, ok := fi.Sys().(*syscall.Stat_t) + if !ok { + return 0, false + } + return st.Uid, true +} diff --git a/internal/svcauth/config.go b/internal/svcauth/config.go index e403857..24fe008 100644 --- a/internal/svcauth/config.go +++ b/internal/svcauth/config.go @@ -15,9 +15,9 @@ import ( "slices" "strconv" "strings" - "syscall" "time" + "github.com/pilot-protocol/cosift/internal/fileowner" v1 "github.com/pilot-protocol/cosift/internal/v1" ) @@ -149,8 +149,8 @@ func ReadFile(path string, uid uint32) ([]byte, error) { if !st.Mode().IsRegular() { return nil, errors.New("not a regular file") } - sys, ok := st.Sys().(*syscall.Stat_t) - if !ok || sys.Uid != uid { + owner, ok := fileowner.UID(st) + if !ok || owner != uid { return nil, fmt.Errorf("owner must be uid %d", uid) } if st.Mode().Perm()&0o027 != 0 {