Skip to content

Commit

Permalink
Fix copyFileInfo on Windows
Browse files Browse the repository at this point in the history
The c.chowner function was being ignored. This change makes use of the
supplied chowner and calls Chown() on the file. If no chowner is
specified, we copy over the DACL and owner information from the source.
  • Loading branch information
gabriel-samfira committed Nov 18, 2022
1 parent 47cb68b commit 9b2fff1
Showing 1 changed file with 42 additions and 27 deletions.
69 changes: 42 additions & 27 deletions copy/copy_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,61 @@ func getUIDGID(fi os.FileInfo) (uid, gid int) {
return 0, 0
}

func (c *copier) copyFileInfo(fi os.FileInfo, src, name string) error {
if err := os.Chmod(name, fi.Mode()); err != nil {
return errors.Wrapf(err, "failed to chmod %s", name)
}

// Copy file ownership and ACL
// We need SeRestorePrivilege and SeTakeOwnershipPrivilege in order
// to restore security info on a file, especially if we're trying to
// apply security info which includes SIDs not necessarily present on
// the host.
privileges := []string{winio.SeRestorePrivilege, seTakeOwnershipPrivilege}
if err := winio.EnableProcessPrivileges(privileges); err != nil {
return err
}
defer winio.DisableProcessPrivileges(privileges)

func getFileSecurityInfo(name string) (*windows.SID, *windows.ACL, error) {
secInfo, err := windows.GetNamedSecurityInfo(
src, windows.SE_FILE_OBJECT,
name, windows.SE_FILE_OBJECT,
windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION)

if err != nil {
return err
return nil, nil, errors.Wrap(err, "fetching security info")
}
sid, _, err := secInfo.Owner()
if err != nil {
return nil, nil, errors.Wrap(err, "fetching owner SID")
}

dacl, _, err := secInfo.DACL()
if err != nil {
return err
return nil, nil, errors.Wrap(err, "fetching dacl")
}
return sid, dacl, nil
}

sid, _, err := secInfo.Owner()
func (c *copier) copyFileInfo(fi os.FileInfo, src, name string) error {
if err := os.Chmod(name, fi.Mode()); err != nil {
return errors.Wrapf(err, "failed to chmod %s", name)
}

sid, dacl, err := getFileSecurityInfo(src)
if err != nil {
return err
return errors.Wrap(err, "getting file info")
}

if err := windows.SetNamedSecurityInfo(
name, windows.SE_FILE_OBJECT,
windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION,
sid, nil, dacl, nil); err != nil {
if c.chown != nil {
// Use the defined chowner.
usr := &User{SID: sid.String()}
if err := Chown(name, usr, c.chown); err != nil {
return errors.Wrapf(err, "failed to chown %s", name)
}
return nil
} else {
// Copy file ownership and ACL from the source file.
// We need SeRestorePrivilege and SeTakeOwnershipPrivilege in order
// to restore security info on a file, especially if we're trying to
// apply security info which includes SIDs not necessarily present on
// the host.
privileges := []string{winio.SeRestorePrivilege, seTakeOwnershipPrivilege}
if err := winio.EnableProcessPrivileges(privileges); err != nil {
return err
}
defer winio.DisableProcessPrivileges(privileges)

return err
if err := windows.SetNamedSecurityInfo(
name, windows.SE_FILE_OBJECT,
windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION,
sid, nil, dacl, nil); err != nil {

return err
}
}

if err := c.copyFileTimestamp(fi, name); err != nil {
Expand Down

0 comments on commit 9b2fff1

Please sign in to comment.