//go:build windows package authconfig import ( "errors" "path/filepath" "runtime" "testing" "github.com/aritmolab/thothii/tools/tht/internal/safeio" "golang.org/x/sys/windows" ) func TestLoadRejectsPermissiveWindowsDirectoryAuthAndUsersDACLs(t *testing.T) { for name, makePermissive := range map[string]func(t *testing.T, directory string){ "directory": func(t *testing.T, directory string) { setPermissiveAuthDACL(t, directory) }, "auth file": func(t *testing.T, directory string) { setPermissiveAuthDACL(t, filepath.Join(directory, "auth.yaml")) }, "users file": func(t *testing.T, directory string) { setPermissiveAuthDACL(t, filepath.Join(directory, "users.yaml")) }, } { t.Run(name, func(t *testing.T) { directory := writePrivateWindowsAuthFiles(t) makePermissive(t, directory) if _, _, err := Load(directory); !errors.Is(err, safeio.ErrUnsafeFile) { t.Fatalf("Load() error = %v, want ErrUnsafeFile", err) } }) } } func TestMutateUsersCreatesAndRejectsPermissiveWindowsLockDACL(t *testing.T) { directory := writePrivateWindowsAuthFiles(t) if err := MutateUsers(directory, func(*Registry) error { return nil }); err != nil { t.Fatal(err) } lockPath := filepath.Join(directory, lockFileName) if err := safeio.ValidatePrivateRegular(lockPath); err != nil { t.Fatalf("lock privacy error = %v", err) } setPermissiveAuthDACL(t, lockPath) if err := MutateUsers(directory, func(*Registry) error { return nil }); !errors.Is(err, safeio.ErrUnsafeFile) { t.Fatalf("MutateUsers() error = %v, want ErrUnsafeFile", err) } } func writePrivateWindowsAuthFiles(t *testing.T) string { t.Helper() directory := writeAuthFiles(t, defaultAuthYAML, registryYAML(adminUserYAML("admin", "Admin", true, "admin"))) if err := safeio.ProtectPrivateDirectory(directory); err != nil { t.Fatal(err) } for _, name := range []string{"auth.yaml", "users.yaml"} { if err := safeio.ProtectPrivateRegular(filepath.Join(directory, name)); err != nil { t.Fatal(err) } } return directory } func setPermissiveAuthDACL(t *testing.T, path string) { t.Helper() world, err := windows.StringToSid("S-1-1-0") if err != nil { t.Fatal(err) } var pinner runtime.Pinner pinner.Pin(world) defer pinner.Unpin() acl, err := windows.ACLFromEntries([]windows.EXPLICIT_ACCESS{{ AccessPermissions: windows.GENERIC_READ | windows.GENERIC_WRITE, AccessMode: windows.GRANT_ACCESS, Trustee: windows.TRUSTEE{ TrusteeForm: windows.TRUSTEE_IS_SID, TrusteeType: windows.TRUSTEE_IS_GROUP, TrusteeValue: windows.TrusteeValueFromSID(world), }, }}, nil) if err != nil { t.Fatal(err) } if err := windows.SetNamedSecurityInfo(path, windows.SE_FILE_OBJECT, windows.DACL_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION, nil, nil, acl, nil); err != nil { t.Fatal(err) } }