From 70cf8e37887cd574c055337f37427eca94d54052 Mon Sep 17 00:00:00 2001 From: Aneesh Nireshwalia <99904+aneesh-n@users.noreply.github.com> Date: Sat, 24 Feb 2024 13:25:28 -0700 Subject: [PATCH] Add support for backup/restore of security descriptors --- internal/restic/node.go | 4 +++- internal/restic/node_windows.go | 21 ++++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/internal/restic/node.go b/internal/restic/node.go index 8fc06df79..a0e658b9b 100644 --- a/internal/restic/node.go +++ b/internal/restic/node.go @@ -48,13 +48,15 @@ const ( TypeCreationTime GenericAttributeType = "windows.creation_time" // TypeFileAttributes is the GenericAttributeType used for storing file attributes for windows files within the generic attributes map. TypeFileAttributes GenericAttributeType = "windows.file_attributes" + // TypeSecurityDescriptor is the GenericAttributeType used for storing security descriptors including owner, group, discretionary access control list (DACL), system access control list (SACL)) for windows files within the generic attributes map. + TypeSecurityDescriptor GenericAttributeType = "windows.security_descriptor" // Generic Attributes for other OS types should be defined here. ) // init is called when the package is initialized. Any new GenericAttributeTypes being created must be added here as well. func init() { - storeGenericAttributeType(TypeCreationTime, TypeFileAttributes) + storeGenericAttributeType(TypeCreationTime, TypeFileAttributes, TypeSecurityDescriptor) } // genericAttributesForOS maintains a map of known genericAttributesForOS to the OSType diff --git a/internal/restic/node_windows.go b/internal/restic/node_windows.go index 5875c3ccd..f4797c0d7 100644 --- a/internal/restic/node_windows.go +++ b/internal/restic/node_windows.go @@ -23,6 +23,9 @@ type WindowsAttributes struct { CreationTime *syscall.Filetime `generic:"creation_time"` // FileAttributes is used for storing file attributes for windows files. FileAttributes *uint32 `generic:"file_attributes"` + // SecurityDescriptor is used for storing security descriptors which includes + // owner, group, discretionary access control list (DACL), system access control list (SACL)) + SecurityDescriptor *[]byte `generic:"security_descriptor"` } var ( @@ -114,7 +117,7 @@ func (s statT) mtim() syscall.Timespec { func (s statT) ctim() syscall.Timespec { // Windows does not have the concept of a "change time" in the sense Unix uses it, so we're using the LastWriteTime here. - return syscall.NsecToTimespec(s.LastWriteTime.Nanoseconds()) + return s.mtim() } // restoreGenericAttributes restores generic attributes for Windows @@ -137,6 +140,11 @@ func (node Node) restoreGenericAttributes(path string, warn func(msg string)) (e errs = append(errs, fmt.Errorf("error restoring file attributes for: %s : %v", path, err)) } } + if windowsAttributes.SecurityDescriptor != nil { + if err := fs.SetSecurityDescriptor(path, windowsAttributes.SecurityDescriptor); err != nil { + errs = append(errs, fmt.Errorf("error restoring security descriptor for: %s : %v", path, err)) + } + } HandleUnknownGenericAttributesFound(unknownAttribs, warn) return errors.CombineErrors(errs...) @@ -270,11 +278,18 @@ func (node *Node) fillGenericAttributes(path string, fi os.FileInfo, stat *statT // Do not process file attributes and created time for windows directories like // C:, D: // Filepath.Clean(path) ends with '\' for Windows root drives only. + var sd *[]byte + if node.Type == "file" || node.Type == "dir" { + if sd, err = fs.GetSecurityDescriptor(path); err != nil { + return true, err + } + } // Add Windows attributes node.GenericAttributes, err = WindowsAttrsToGenericAttributes(WindowsAttributes{ - CreationTime: getCreationTime(fi, path), - FileAttributes: &stat.FileAttributes, + CreationTime: getCreationTime(fi, path), + FileAttributes: &stat.FileAttributes, + SecurityDescriptor: sd, }) } return true, err