Files
ThothII/tools/tht/internal/safeio/claim_windows.go
T

113 lines
3.4 KiB
Go

//go:build windows
package safeio
import (
"path/filepath"
"golang.org/x/sys/windows"
)
type windowsPrivateRegular struct {
parents *windowsParentHandles
handle windows.Handle
info windows.ByHandleFileInformation
}
func (value *windowsPrivateRegular) Close() {
if value.handle != 0 {
_ = windows.CloseHandle(value.handle)
value.handle = 0
}
if value.parents != nil {
value.parents.Close()
value.parents = nil
}
}
func openWindowsPrivateRegular(path string, links uint32) (*windowsPrivateRegular, error) {
parents, target, err := openCanonicalWindowsParent(path)
if err != nil || parents == nil || len(parents.handles) == 0 || validateOwnerOnlyDACL(parents.handles[len(parents.handles)-1]) != nil {
if parents != nil {
parents.Close()
}
return nil, ErrUnsafeFile
}
value, err := openWindowsPrivateRegularAt(parents.handles[len(parents.handles)-1], target, windows.GENERIC_READ, links)
if err != nil {
parents.Close()
return nil, err
}
handle := value.handle
value.handle = 0
return &windowsPrivateRegular{
parents: parents,
handle: handle,
info: value.info,
}, nil
}
func claimCanonicalPrivateRegular(source, claim string) (claimed bool, resultErr error) {
directory, sourceName, claimName, err := openWindowsPrivateClaimDirectory(source, claim)
if err != nil {
return false, ErrUnsafeFile
}
defer func() {
if closeErr := directory.Close(); closeErr != nil && resultErr == nil {
claimed = false
resultErr = ErrUnsafeFile
}
}()
return directory.ClaimRegular(sourceName, claimName)
}
func readCanonicalPrivateClaim(source, claim string, maximum int64) (contents []byte, found bool, resultErr error) {
directory, sourceName, claimName, err := openWindowsPrivateClaimDirectory(source, claim)
if err != nil {
return nil, false, ErrUnsafeFile
}
defer func() {
if closeErr := directory.Close(); closeErr != nil && resultErr == nil {
contents = nil
found = false
resultErr = ErrUnsafeFile
}
}()
return directory.ReadClaim(sourceName, claimName, maximum)
}
func openWindowsPrivateClaimDirectory(source, claim string) (PrivateDirectoryHandle, string, string, error) {
parentPath := filepath.Dir(source)
sourceName := filepath.Base(source)
claimName := filepath.Base(claim)
if parentPath != filepath.Dir(claim) || !validPrivateLeafName(sourceName) || !validPrivateLeafName(claimName) {
return nil, "", "", ErrUnsafeFile
}
directory, found, err := OpenPrivateDirectory(parentPath, false)
if err != nil || !found {
if directory != nil {
_ = directory.Close()
}
return nil, "", "", ErrUnsafeFile
}
return directory, sourceName, claimName, nil
}
func removeCanonicalPrivateClaim(source, claim string) (removed bool, resultErr error) {
directory, sourceName, claimName, err := openWindowsPrivateClaimDirectory(source, claim)
if err != nil {
return false, ErrUnsafeFile
}
defer func() {
if closeErr := directory.Close(); closeErr != nil && resultErr == nil {
resultErr = ErrUnsafeFile
}
}()
NotifyPrivateDirectoryTestHookForTest("after-canonical-private-claim-parent-open")
return directory.RemoveClaim(sourceName, claimName)
}
func sameWindowsPrivateFile(left, right windows.ByHandleFileInformation) bool {
return left.VolumeSerialNumber == right.VolumeSerialNumber && left.FileIndexHigh == right.FileIndexHigh && left.FileIndexLow == right.FileIndexLow && left.FileSizeHigh == right.FileSizeHigh && left.FileSizeLow == right.FileSizeLow && left.LastWriteTime == right.LastWriteTime
}