From 11724a77be0a9b5c9aa61126e70b1acbcc5fc3d7 Mon Sep 17 00:00:00 2001 From: Alex Hughes Date: Wed, 6 Mar 2024 14:32:04 -0800 Subject: [PATCH] Apply ACLs for CREATOR_OWNER to the newly created windows files We encountered an issue in testing where the new owner of the file had no permissions of any of the downloaded files. It appears that this was due to the s5cmd process running as a SYSTEM service and executing --preserve-ownership to set the owner to "Ahuge". --- storage/fs_windows.go | 75 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/storage/fs_windows.go b/storage/fs_windows.go index 3d34efb5a..8074fcb47 100644 --- a/storage/fs_windows.go +++ b/storage/fs_windows.go @@ -9,6 +9,13 @@ import ( "strings" "syscall" "time" + "unsafe" +) + +// Load the SetEntriesInAclW Win API function +var ( + modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") + procSetEntriesInAclW = modadvapi32.NewProc("SetEntriesInAclW") ) func GetFileTime(filename string) (time.Time, time.Time, time.Time, error) { @@ -118,6 +125,11 @@ func SetFileUserGroup(filename, userId, groupId string) error { return err } + err = addCreatorOwnerAclToFile(filename) + if err != nil { + return err + } + return nil } @@ -147,3 +159,66 @@ func StringSidAsName(strSID string) (name string, err error) { } return name, nil } + +// addCreatorOwnerAclToFile is required because on Windows systems, a new file doesn +func addCreatorOwnerAclToFile(filename string) error { + // Get the DACL security descriptor from the filename + sd, err := windows.GetNamedSecurityInfo(filename, windows.SE_FILE_OBJECT, windows.DACL_SECURITY_INFORMATION) + if err != nil { + return err + } + + // Get the DACL from the security descriptor + dacl, _, err := sd.DACL() + if err != nil { + return err + } + + // Create a SID for the CREATOR_OWNER + sid, err := windows.StringToSid("S-1-3-0") + if err != nil { + return err + } + + // Create an access control entry (ACE) for the CREATOR_OWNER SID + ace := windows.EXPLICIT_ACCESS{ + AccessPermissions: windows.GENERIC_ALL, + AccessMode: windows.GRANT_ACCESS, + Trustee: windows.TRUSTEE{ + TrusteeForm: windows.TRUSTEE_IS_SID, + TrusteeType: windows.TRUSTEE_IS_USER, + TrusteeValue: windows.TrusteeValueFromSID(sid), + }, + } + + newAcl := new(windows.ACL) + newAclH := windows.Handle(unsafe.Pointer(newAcl)) + entries := []windows.EXPLICIT_ACCESS{ace} + if err := SetEntriesInAcl( + entries, + windows.Handle(unsafe.Pointer(dacl)), + &newAclH, + ); err != nil { + return err + } + + // Set the updated security descriptor of the file + err = windows.SetNamedSecurityInfo(filename, windows.SE_FILE_OBJECT, windows.DACL_SECURITY_INFORMATION|windows.UNPROTECTED_DACL_SECURITY_INFORMATION, nil, nil, newAcl, nil) + if err != nil { + return err + } + return nil +} + +func SetEntriesInAcl(entries []windows.EXPLICIT_ACCESS, oldAcl windows.Handle, newAcl *windows.Handle) error { + ret, _, _ := procSetEntriesInAclW.Call( + uintptr(len(entries)), + uintptr(unsafe.Pointer(&entries[0])), + uintptr(oldAcl), + uintptr(unsafe.Pointer(newAcl)), + ) + if ret != 0 { + return windows.Errno(ret) + } + return nil +}