40 lines
1.2 KiB
Go
40 lines
1.2 KiB
Go
//go:build windows
|
|
|
|
package safeio
|
|
|
|
import "golang.org/x/sys/windows"
|
|
|
|
func preflightPrivateDirectory(path string) (bool, error) {
|
|
parents, target, err := openCanonicalWindowsParent(path)
|
|
if err != nil || parents == nil || len(parents.handles) == 0 {
|
|
if parents != nil {
|
|
parents.Close()
|
|
}
|
|
return false, ErrUnsafeFile
|
|
}
|
|
defer parents.Close()
|
|
handle, err := openWindowsRelativeComponent(parents.handles[len(parents.handles)-1], target, true, windows.GENERIC_READ)
|
|
if err != nil {
|
|
if isWindowsRelativeNotFound(err) {
|
|
// A read-only retained handle cannot be upgraded. Re-traverse with the
|
|
// directory FILE_ADD_SUBDIRECTORY right, still using RootDirectory-relative
|
|
// opens for every component rather than reopening parents by absolute path.
|
|
writableParents, _, accessErr := openCanonicalWindowsParentWithFinalAccess(
|
|
path,
|
|
windows.FILE_APPEND_DATA, // FILE_ADD_SUBDIRECTORY for a directory handle
|
|
)
|
|
if accessErr != nil || writableParents == nil {
|
|
return false, ErrUnsafeFile
|
|
}
|
|
writableParents.Close()
|
|
return false, nil
|
|
}
|
|
return false, ErrUnsafeFile
|
|
}
|
|
defer windows.CloseHandle(handle)
|
|
if err := validateOwnerOnlyDACL(handle); err != nil {
|
|
return false, ErrUnsafeFile
|
|
}
|
|
return true, nil
|
|
}
|