diff --git a/tools/tht/internal/safeio/private_windows_test.go b/tools/tht/internal/safeio/private_windows_test.go index e124b72c..a8dbf2b3 100644 --- a/tools/tht/internal/safeio/private_windows_test.go +++ b/tools/tht/internal/safeio/private_windows_test.go @@ -40,33 +40,82 @@ func TestPrivateWindowsDACLRejectsPermissiveDirectoryAndRegularFile(t *testing.T for name, path := range map[string]string{"directory": directory, "regular file": path} { t.Run(name, func(t *testing.T) { + parents, target, err := openCanonicalWindowsParent(path) + if err != nil { + t.Fatal(err) + } + handle, err := openWindowsRelativeComponent( + parents.handles[len(parents.handles)-1], + target, + name == "directory", + windows.GENERIC_READ|windows.WRITE_DAC|windows.WRITE_OWNER, + ) + if err != nil { + parents.Close() + t.Fatal(err) + } t.Cleanup(func() { - var restoreErr error - if name == "directory" { - restoreErr = ProtectPrivateDirectory(path) - } else { - restoreErr = ProtectPrivateRegular(path) - } - if restoreErr != nil { + if restoreErr := setOwnerOnlyDACL(handle); restoreErr != nil { t.Errorf("restore owner-only DACL: %v", restoreErr) } + _ = windows.CloseHandle(handle) + parents.Close() }) if err := setPermissiveDACL(path); err != nil { t.Fatal(err) } - var err error + var validationErr error if name == "directory" { - err = ValidatePrivateDirectory(path) + validationErr = ValidatePrivateDirectory(path) } else { - err = ValidatePrivateRegular(path) + validationErr = ValidatePrivateRegular(path) } - if !errors.Is(err, ErrUnsafeFile) { - t.Fatalf("private validation error = %v, want ErrUnsafeFile", err) + if !errors.Is(validationErr, ErrUnsafeFile) { + t.Fatalf("private validation error = %v, want ErrUnsafeFile", validationErr) } }) } } +func TestOwnerOnlySecurityDescriptorNativeCreate(t *testing.T) { + directory := filepath.Join(t.TempDir(), "auth") + if err := os.Mkdir(directory, 0o700); err != nil { + t.Fatal(err) + } + if err := ProtectPrivateDirectory(directory); err != nil { + t.Fatal(err) + } + path := filepath.Join(directory, "created.env") + parents, target, err := openCanonicalWindowsParent(path) + if err != nil { + t.Fatal(err) + } + defer parents.Close() + security, err := newOwnerOnlySecurityDescriptor() + if err != nil { + t.Fatalf("newOwnerOnlySecurityDescriptor() error = %T %v", err, err) + } + defer security.Close() + handle, err := openWindowsRelativeObject( + parents.handles[len(parents.handles)-1], + target, + windows.FILE_GENERIC_READ|windows.FILE_GENERIC_WRITE|windows.DELETE, + windows.FILE_CREATE, + windows.FILE_NON_DIRECTORY_FILE|windows.FILE_SYNCHRONOUS_IO_NONALERT|windows.FILE_OPEN_REPARSE_POINT, + security, + ) + if err != nil { + t.Fatalf("NtCreateFile() private regular error = %T %v", err, err) + } + defer windows.CloseHandle(handle) + if err := windows.GetFileInformationByHandle(handle, new(windows.ByHandleFileInformation)); err != nil { + t.Fatalf("GetFileInformationByHandle() after private create = %T %v", err, err) + } + if err := validateOwnerOnlyDACL(handle); err != nil { + t.Fatalf("validateOwnerOnlyDACL() after private create = %T %v", err, err) + } +} + func TestOwnerOnlyDACLCanProtectInheritedRegularFile(t *testing.T) { directory := filepath.Join(t.TempDir(), "auth") if err := os.Mkdir(directory, 0o700); err != nil {