1
2
3
4 package security
5
6 import (
7 "fmt"
8 "os"
9 "syscall"
10 "unsafe"
11 )
12
13 type (
14 accessMask uint32
15 accessMode uint32
16 desiredAccess uint32
17 inheritMode uint32
18 objectType uint32
19 shareMode uint32
20 securityInformation uint32
21 trusteeForm uint32
22 trusteeType uint32
23
24 explicitAccess struct {
25 accessPermissions accessMask
26 accessMode accessMode
27 inheritance inheritMode
28 trustee trustee
29 }
30
31 trustee struct {
32 multipleTrustee *trustee
33 multipleTrusteeOperation int32
34 trusteeForm trusteeForm
35 trusteeType trusteeType
36 name uintptr
37 }
38 )
39
40 const (
41 accessMaskDesiredPermission accessMask = 1 << 31
42
43 accessModeGrant accessMode = 1
44
45 desiredAccessReadControl desiredAccess = 0x20000
46 desiredAccessWriteDac desiredAccess = 0x40000
47
48
49 gvmga = "GrantVmGroupAccess:"
50
51 inheritModeNoInheritance inheritMode = 0x0
52 inheritModeSubContainersAndObjectsInherit inheritMode = 0x3
53
54 objectTypeFileObject objectType = 0x1
55
56 securityInformationDACL securityInformation = 0x4
57
58 shareModeRead shareMode = 0x1
59 shareModeWrite shareMode = 0x2
60
61 sidVMGroup = "S-1-5-83-0"
62
63 trusteeFormIsSID trusteeForm = 0
64
65 trusteeTypeWellKnownGroup trusteeType = 5
66 )
67
68
69
70
71
72
73
74 func GrantVmGroupAccess(name string) error {
75
76 s, err := os.Stat(name)
77 if err != nil {
78 return fmt.Errorf("%s os.Stat %s: %w", gvmga, name, err)
79 }
80
81
82 fd, err := createFile(name, s.IsDir())
83 if err != nil {
84 return err
85 }
86 defer syscall.CloseHandle(fd)
87
88
89 ot := objectTypeFileObject
90 si := securityInformationDACL
91 sd := uintptr(0)
92 origDACL := uintptr(0)
93 if err := getSecurityInfo(fd, uint32(ot), uint32(si), nil, nil, &origDACL, nil, &sd); err != nil {
94 return fmt.Errorf("%s GetSecurityInfo %s: %w", gvmga, name, err)
95 }
96 defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd)))
97
98
99
100 newDACL, err := generateDACLWithAcesAdded(name, s.IsDir(), origDACL)
101 if err != nil {
102 return err
103 }
104 defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL)))
105
106
107 if err := setSecurityInfo(fd, uint32(ot), uint32(si), uintptr(0), uintptr(0), newDACL, uintptr(0)); err != nil {
108 return fmt.Errorf("%s SetSecurityInfo %s: %w", gvmga, name, err)
109 }
110
111 return nil
112 }
113
114
115
116 func createFile(name string, isDir bool) (syscall.Handle, error) {
117 namep, err := syscall.UTF16FromString(name)
118 if err != nil {
119 return syscall.InvalidHandle, fmt.Errorf("could not convernt name to UTF-16: %w", err)
120 }
121 da := uint32(desiredAccessReadControl | desiredAccessWriteDac)
122 sm := uint32(shareModeRead | shareModeWrite)
123 fa := uint32(syscall.FILE_ATTRIBUTE_NORMAL)
124 if isDir {
125 fa |= syscall.FILE_FLAG_BACKUP_SEMANTICS
126 }
127 fd, err := syscall.CreateFile(&namep[0], da, sm, nil, syscall.OPEN_EXISTING, fa, 0)
128 if err != nil {
129 return syscall.InvalidHandle, fmt.Errorf("%s syscall.CreateFile %s: %w", gvmga, name, err)
130 }
131 return fd, nil
132 }
133
134
135
136 func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintptr, error) {
137
138 sid, err := syscall.StringToSid(sidVMGroup)
139 if err != nil {
140 return 0, fmt.Errorf("%s syscall.StringToSid %s %s: %w", gvmga, name, sidVMGroup, err)
141 }
142
143 inheritance := inheritModeNoInheritance
144 if isDir {
145 inheritance = inheritModeSubContainersAndObjectsInherit
146 }
147
148 eaArray := []explicitAccess{
149 {
150 accessPermissions: accessMaskDesiredPermission,
151 accessMode: accessModeGrant,
152 inheritance: inheritance,
153 trustee: trustee{
154 trusteeForm: trusteeFormIsSID,
155 trusteeType: trusteeTypeWellKnownGroup,
156 name: uintptr(unsafe.Pointer(sid)),
157 },
158 },
159 }
160
161 modifiedDACL := uintptr(0)
162 if err := setEntriesInAcl(uintptr(uint32(1)), uintptr(unsafe.Pointer(&eaArray[0])), origDACL, &modifiedDACL); err != nil {
163 return 0, fmt.Errorf("%s SetEntriesInAcl %s: %w", gvmga, name, err)
164 }
165
166 return modifiedDACL, nil
167 }
168
View as plain text