bastion 0.54.0
ci / personal-data (push) Successful in 4s
ci / fuzz (push) Successful in 2m44s
ci / test (push) Successful in 2m11s

This commit is contained in:
Privatae
2026-10-21 22:29:10 +00:00
parent e4c9b69b46
commit d62da8adb4
58 changed files with 6944 additions and 124 deletions
+122
View File
@@ -0,0 +1,122 @@
//go:build windows
package main
import (
"os"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
)
// The decisions are in mcpconfig_winopen.go; this file makes the calls.
// The values mcpconfig_winopen.go spells out must be Windows' own: each line
// fails to compile if one differs.
var (
_ = [1]struct{}{}[mcpWinFileTypeDisk^windows.FILE_TYPE_DISK]
_ = [1]struct{}{}[mcpWinAttrDirectory^windows.FILE_ATTRIBUTE_DIRECTORY]
_ = [1]struct{}{}[mcpWinAttrDevice^windows.FILE_ATTRIBUTE_DEVICE]
_ = [1]struct{}{}[mcpWinAttrReparse^windows.FILE_ATTRIBUTE_REPARSE_POINT]
)
var mcpAdminOwners = mcpWinAdminOwners
// mcpOpenRegular opens path with CreateFile and keeps it only when the
// handle is a regular file on disk (mcpWinOpenWith). It shares read, write
// and delete with everyone else: the agent client that owns the file must be
// able to save it, including by replacing it, while this reads it.
func mcpOpenRegular(path string) (*os.File, string, error) {
return mcpWinOpenWith(mcpWinSystemOps, path)
}
var mcpWinSystemOps = mcpWinOps{
openPath: mcpWinCreateFile,
handleInfo: mcpWinHandleFacts,
closeHandle: func(h uintptr) { windows.CloseHandle(windows.Handle(h)) },
asFile: func(h uintptr, path string) *os.File { return os.NewFile(h, path) },
}
func mcpWinCreateFile(path string) (uintptr, error) {
p, err := windows.UTF16PtrFromString(path)
if err != nil {
return 0, &os.PathError{Op: "open", Path: path, Err: err}
}
h, err := windows.CreateFile(p, windows.GENERIC_READ,
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE, nil,
windows.OPEN_EXISTING, windows.FILE_FLAG_OPEN_REPARSE_POINT, 0)
if err != nil {
return 0, &os.PathError{Op: "open", Path: path, Err: err}
}
return uintptr(h), nil
}
// mcpWinHandleFacts reads the type, the attributes and the owner from the
// handle. GENERIC_READ carries READ_CONTROL, which GetSecurityInfo needs for
// the owner; an owner that cannot be read is left "" and the file is then
// read only where no owner check applies.
func mcpWinHandleFacts(h uintptr) (mcpWinHandleInfo, error) {
wh := windows.Handle(h)
var i mcpWinHandleInfo
t, err := windows.GetFileType(wh)
if err != nil {
return i, err
}
i.FileType = t
if t != windows.FILE_TYPE_DISK {
return i, nil // refused by mcpWinRegular; nothing more to ask it
}
var bi windows.ByHandleFileInformation
if err := windows.GetFileInformationByHandle(wh, &bi); err != nil {
return i, err
}
i.Attributes = bi.FileAttributes
if sd, err := windows.GetSecurityInfo(wh, windows.SE_FILE_OBJECT, windows.OWNER_SECURITY_INFORMATION); err == nil {
if o, _, err := sd.Owner(); err == nil && o != nil {
i.Owner = o.String()
}
}
return i, nil
}
// mcpPathOwner is the SID whose profile dir is, from the ProfileList the
// User Profile Service keeps
// (HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\<SID>,
// value ProfileImagePath). A directory it does not name, or names twice,
// gives mcpOwnerUnknown, so only SYSTEM's and the Administrators group's
// files are read there.
func mcpPathOwner(dir string) string {
return mcpWinProfileSID(dir, mcpWinProfiles())
}
func mcpWinProfiles() map[string]string {
out := map[string]string{}
k, err := registry.OpenKey(registry.LOCAL_MACHINE,
`SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList`, registry.ENUMERATE_SUB_KEYS)
if err != nil {
return out
}
defer k.Close()
sids, err := k.ReadSubKeyNames(-1)
if err != nil {
return out
}
for _, sid := range sids {
sk, err := registry.OpenKey(k, sid, registry.QUERY_VALUE)
if err != nil {
continue
}
p, typ, err := sk.GetStringValue("ProfileImagePath")
sk.Close()
if err != nil {
continue
}
if typ == registry.EXPAND_SZ {
if x, err := registry.ExpandString(p); err == nil {
p = x
}
}
out[sid] = p
}
return out
}