filesystem/windows_sec.go (78 lines of code) (raw):
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT
//go:build windows
package filesystem
import (
"unsafe"
"golang.org/x/sys/windows"
)
// https://docs.microsoft.com/en-us/windows/win32/api/accctrl/ne-accctrl-se_object_type
const (
SE_UNKNOWN_OBJECT_TYPE = iota
SE_FILE_OBJECT
)
// https://github.com/mhammond/pywin32/blob/70ddf693927fa1635f15e9ef41eb1aea37fdf32a/win32/Lib/ntsecuritycon.py
const (
ACCESS_ALLOWED_ACE_TYPE = 0
ACCESS_DENIED_ACE_TYPE = 1
FILE_ALL_ACCESS = (windows.STANDARD_RIGHTS_ALL | 0x1FF)
)
const (
AclSizeInformationEnum = 2
DACL_SECURITY_INFORMATION = 0x00004
)
var (
advapi32 = windows.NewLazyDLL("advapi32.dll")
procGetAclInformation = advapi32.NewProc("GetAclInformation")
procGetNamedSecurityInfo = advapi32.NewProc("GetNamedSecurityInfoW")
procGetAce = advapi32.NewProc("GetAce")
)
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-acl_size_information
type AclSizeInformation struct {
AceCount uint32
AclBytesInUse uint32
AclBytesFree uint32
}
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-acl
type Acl struct {
AclRevision uint8
Sbz1 uint8
AclSize uint16
AceCount uint16
Sbz2 uint16
}
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_access_allowed_ace
type AccessAllowedAce struct {
AceType uint8
AceFlags uint8
AceSize uint16
AccessMask uint32
SidStart uint32
}
// Retrieve a copy of security descriptor for an object specified by name (e.g a file)
// For more information: https://docs.microsoft.com/en-us/windows/win32/api/aclapi/nf-aclapi-getnamedsecurityinfoa
func GetNamedSecurityInfo(objectName string, objectType int32, secInfo uint32, owner, group **windows.SID, dacl, sacl **Acl, secDesc *windows.Handle) error {
ret, _, err := procGetNamedSecurityInfo.Call(
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(objectName))),
uintptr(objectType),
uintptr(secInfo),
uintptr(unsafe.Pointer(owner)),
uintptr(unsafe.Pointer(group)),
uintptr(unsafe.Pointer(dacl)),
uintptr(unsafe.Pointer(sacl)),
uintptr(unsafe.Pointer(secDesc)),
)
if ret != 0 {
return err
}
return nil
}
// Retrieve information about access control list (e.g a file)
// For more information: https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-getaclinformation
func GetAclInformation(acl *Acl, info *AclSizeInformation, class uint32) error {
length := unsafe.Sizeof(*info)
ret, _, _ := procGetAclInformation.Call(
uintptr(unsafe.Pointer(acl)),
uintptr(unsafe.Pointer(info)),
uintptr(length),
uintptr(class))
if int(ret) == 0 {
return windows.GetLastError()
}
return nil
}
// Obtain a pointer to an access control entry (ACE) in an access control list (ACL).
// For more information: https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-getace
func GetAce(acl *Acl, index uint32, ace **AccessAllowedAce) error {
ret, _, _ := procGetAce.Call(uintptr(unsafe.Pointer(acl)), uintptr(index), uintptr(unsafe.Pointer(ace)))
if int(ret) != 0 {
return windows.GetLastError()
}
return nil
}