-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSecurityEditor.cs
383 lines (308 loc) · 11.5 KB
/
SecurityEditor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
using System;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
namespace HttpConfig
{
public class SecurityEditor :IDisposable
{
#region P/Invoke
[DllImport("aclui", SetLastError=true)]
private static extern bool EditSecurity(
IntPtr hwndOwner,
IntPtr psi); // LPSECURITYINFO
[DllImport("Advapi32", SetLastError=true)]
private static extern bool MakeSelfRelativeSD(
IntPtr pAbsoluteSD,
IntPtr pSelfRelativeSD,
ref uint lpdwBufferLength);
private enum SI_PAGE_TYPE
{
SI_PAGE_PERM=0,
SI_PAGE_ADVPERM=1,
SI_PAGE_AUDIT=2,
SI_PAGE_OWNER=3,
SI_PAGE_EFFECTIVE=4,
}
[StructLayout(LayoutKind.Sequential)]
private struct SI_INHERIT_TYPE
{
public IntPtr pguid; // GUID *
public uint dwFlags;
[MarshalAs(UnmanagedType.LPWStr)]
public string pszName; // may be resource ID
}
[StructLayout(LayoutKind.Sequential)]
private struct SI_OBJECT_INFO
{
public uint dwFlags;
public IntPtr hInstance; // resources (e.g. strings) reside here
[MarshalAs(UnmanagedType.LPWStr)]
public string pszServerName; // must be present
[MarshalAs(UnmanagedType.LPWStr)]
public string pszObjectName; // must be present
[MarshalAs(UnmanagedType.LPWStr)]
public string pszPageTitle; // only valid if SI_PAGE_TITLE is set
public Guid guidObjectType; // only valid if SI_OBJECT_GUID is set
}
[StructLayout(LayoutKind.Sequential)]
private struct SI_ACCESS
{
public IntPtr pguid; // GUID *
public uint mask; // ACCESS_MASK
[MarshalAs(UnmanagedType.LPWStr)]
public string pszName; // may be resource ID
public uint dwFlags;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
private struct SiAccess
{
public SiAccess(IntPtr pguid, uint mask, string name, SiAccessFlags flags)
{
PGuid = pguid;
Mask = mask;
Name = name;
Flags = flags;
}
public IntPtr PGuid; // Guid*
public uint Mask;
public string Name;
public SiAccessFlags Flags;
}
[StructLayout(LayoutKind.Sequential)]
private struct GENERIC_MAPPING
{
public int GenericRead;
public int GenericWrite;
public int GenericExecute;
public int GenericAll;
}
private enum SiAccessFlags
{
Specific = 0x10000,
General = 0x20000,
Container = 0x40000,
Property = 0x80000,
}
private const uint S_OK = 0;
private const uint E_FAIL = 0x80004005;
private const uint E_NOINTERFACE = 0x80004002;
private const uint ERROR_INSUFFICIENT_BUFFER = 122;
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint GENERIC_EXECUTE = 0x20000000;
private const uint GENERIC_ALL = 0x10000000;
private const uint SI_EDIT_PERMS = 0x00000000;
private const uint SI_EDIT_OWNER = 0x00000001;
private const uint SI_EDIT_AUDITS = 0x00000002;
private const uint SI_ADVANCED = 0x00000010;
private const uint SI_EDIT_ALL = (SI_EDIT_PERMS | SI_EDIT_OWNER | SI_EDIT_AUDITS);
#endregion P/Invoke
delegate uint QueryInterfaceDelegate(IntPtr pThis, [In] ref Guid riid, out IntPtr ppvObj);
delegate uint AddRefDelegate(IntPtr pThis);
delegate uint ReleaseDelegate(IntPtr pThis);
delegate uint GetObjectInformationDelegate(IntPtr pThis, ref SI_OBJECT_INFO pObjectInfo);
delegate uint GetSecurityDelegate(IntPtr pThis, [In] uint RequestedInformation, ref IntPtr ppSecurityDescriptor, [In] bool fDefault);
delegate uint SetSecurityDelegate(IntPtr pThis, [In] uint SecurityInformation, [In] IntPtr pSecurityDescriptor);
delegate uint GetInheritTypesDelegate(IntPtr pThis, ref SI_INHERIT_TYPE ppInheritTypes, ref uint pcInheritTypes);
delegate uint PropertySheetPageCallbackDelegate(IntPtr pThis, [In] IntPtr hwnd, [In] uint uMsg, [In] SI_PAGE_TYPE uPage);
unsafe delegate uint GetAccessRightsDelegate(IntPtr pThis, [In] Guid *pguidObjectType, [In] uint dwFlags, ref IntPtr ppAccess, ref uint pcAccesses, ref uint piDefaultAccess);
unsafe delegate uint MapGenericDelegate(IntPtr pThis, [In] Guid *pguidObjectType, [In] ref byte pAceFlags, [In] ref uint pMask);
[StructLayout(LayoutKind.Sequential)]
private struct ISI_Struct
{
public IntPtr pTable;
public IntPtr QueryInterface;
public IntPtr AddRef;
public IntPtr Release;
public IntPtr GetObjectInformation;
public IntPtr GetSecurity;
public IntPtr SetSecurity;
public IntPtr GetAccessRights;
public IntPtr MapGeneric;
public IntPtr GetInheritTypes;
public IntPtr PropertySheetPageCallback;
}
private static readonly SiAccess[] __rights = new SiAccess[] {
new SiAccess(IntPtr.Zero, GENERIC_EXECUTE, "Register", SiAccessFlags.General | SiAccessFlags.Specific), // Default right...must be at index 0
new SiAccess(IntPtr.Zero, GENERIC_WRITE, "Delegate", SiAccessFlags.General | SiAccessFlags.Specific)
};
private static readonly Guid IID_ISecurityInformation = new Guid("965fc360-16ff-11d0-91cb-00aa00bbb723");
private string _sddl;
private string _objectName;
private IntPtr _pSecurityInterface;
private IntPtr _pAccessRights;
private Delegate _queryInterfaceDelegate;
private Delegate _addRefDelegate;
private Delegate _releaseDelegate;
private Delegate _getObjectInformationDelegate;
private Delegate _getSecurityDelegate;
private Delegate _setSecurityDelegate;
private Delegate _getAccessRightsDelegate;
private Delegate _mapGenericDelegate;
private Delegate _getInheritTypesDelegate;
private Delegate _propertySheetPageCallbackDelegate;
private SecurityEditor(string objectName, string sddl)
{
_objectName = objectName;
_sddl = sddl;
_queryInterfaceDelegate = new QueryInterfaceDelegate(QueryInterface);
_addRefDelegate = new AddRefDelegate(AddRef);
_releaseDelegate = new ReleaseDelegate(Release);
_getObjectInformationDelegate = new GetObjectInformationDelegate(GetObjectInformation);
_getSecurityDelegate = new GetSecurityDelegate(GetSecurity);
_setSecurityDelegate = new SetSecurityDelegate(SetSecurity);
_getInheritTypesDelegate = new GetInheritTypesDelegate(GetInheritTypes);
_propertySheetPageCallbackDelegate = new PropertySheetPageCallbackDelegate(PropertySheetPageCallback);
unsafe
{
_getAccessRightsDelegate = new GetAccessRightsDelegate(GetAccessRights);
_mapGenericDelegate = new MapGenericDelegate(MapGeneric);
}
ISI_Struct isi = new ISI_Struct();
_pSecurityInterface = Marshal.AllocHGlobal(Marshal.SizeOf(isi));
isi.pTable = (IntPtr)((long)_pSecurityInterface + (long)Marshal.SizeOf(typeof(IntPtr)));
isi.QueryInterface = Marshal.GetFunctionPointerForDelegate(_queryInterfaceDelegate);
isi.AddRef = Marshal.GetFunctionPointerForDelegate(_addRefDelegate);
isi.Release = Marshal.GetFunctionPointerForDelegate(_releaseDelegate);
isi.GetObjectInformation = Marshal.GetFunctionPointerForDelegate(_getObjectInformationDelegate);
isi.GetSecurity = Marshal.GetFunctionPointerForDelegate(_getSecurityDelegate);
isi.SetSecurity = Marshal.GetFunctionPointerForDelegate(_setSecurityDelegate);
isi.GetAccessRights = Marshal.GetFunctionPointerForDelegate(_getAccessRightsDelegate);
isi.MapGeneric = Marshal.GetFunctionPointerForDelegate(_mapGenericDelegate);
isi.GetInheritTypes = Marshal.GetFunctionPointerForDelegate(_getInheritTypesDelegate);
isi.PropertySheetPageCallback = Marshal.GetFunctionPointerForDelegate(_propertySheetPageCallbackDelegate);
Marshal.StructureToPtr(isi, _pSecurityInterface, false);
}
public static string EditSecurity(IntPtr hwndOwner, string objectName, string sddl)
{
using(SecurityEditor editor = new SecurityEditor(objectName, sddl))
{
if(!EditSecurity(hwndOwner, editor._pSecurityInterface))
{
int err = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(err, "EditSecurity failed. Error = " + err);
}
return editor._sddl;
}
}
public void Dispose()
{
if(_pAccessRights != IntPtr.Zero)
Marshal.FreeHGlobal(_pAccessRights);
if(_pSecurityInterface != IntPtr.Zero)
Marshal.FreeHGlobal(_pSecurityInterface);
}
private uint QueryInterface(IntPtr pThis, ref Guid riid, out IntPtr ppvObj)
{
if(riid == IID_ISecurityInformation)
{
ppvObj = _pSecurityInterface;
return S_OK;
}
else
{
ppvObj = IntPtr.Zero;
return E_NOINTERFACE;
}
}
private uint AddRef(IntPtr pThis)
{
return S_OK;
}
private uint Release(IntPtr pThis)
{
return S_OK;
}
private uint GetObjectInformation(IntPtr pThis, ref SI_OBJECT_INFO pObjectInfo)
{
pObjectInfo.dwFlags = SI_EDIT_ALL | SI_ADVANCED;
pObjectInfo.pszObjectName = _objectName;
return S_OK;
}
private uint GetSecurity(IntPtr pThis, uint RequestedInformation, ref IntPtr ppSecurityDescriptor, bool fDefault)
{
try
{
FileSecurity fs = new FileSecurity();
fs.SetSecurityDescriptorSddlForm(_sddl);
byte[] sd = fs.GetSecurityDescriptorBinaryForm();
ppSecurityDescriptor = Marshal.AllocHGlobal(sd.Length);
Marshal.Copy(sd, 0, ppSecurityDescriptor, sd.Length);
fDefault = false;
return S_OK;
}
catch
{
return E_FAIL;
}
}
private uint SetSecurity(IntPtr pThis, uint SecurityInformation, IntPtr pSecurityDescriptor)
{
IntPtr psd = IntPtr.Zero;
uint len = 0;
try
{
if(!MakeSelfRelativeSD(pSecurityDescriptor, psd, ref len))
{
int err = Marshal.GetLastWin32Error();
if(err != ERROR_INSUFFICIENT_BUFFER)
throw new System.ComponentModel.Win32Exception(err, "MakeSelfRelativeSD failed. Error = " + err);
}
psd = Marshal.AllocHGlobal((int)len);
if(!MakeSelfRelativeSD(pSecurityDescriptor, psd, ref len))
{
int err = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(err, "MakeSelfRelativeSD failed. Error = " + err);
}
byte[] sd = new byte[len];
Marshal.Copy(psd, sd, 0, (int)len);
FileSecurity fs = new FileSecurity();
fs.SetSecurityDescriptorBinaryForm(sd);
_sddl = fs.GetSecurityDescriptorSddlForm(AccessControlSections.All);
return S_OK;
}
catch
{
return E_FAIL;
}
finally
{
if(psd != IntPtr.Zero)
Marshal.FreeHGlobal(psd);
}
}
private unsafe uint GetAccessRights(IntPtr pThis, Guid *pguidObjectType, uint dwFlags, ref IntPtr ppAccess, ref uint pcAccesses, ref uint piDefaultAccess)
{
try
{
if(_pAccessRights == IntPtr.Zero)
{
_pAccessRights = Marshal.AllocHGlobal(__rights.Length * Marshal.SizeOf(__rights[0]));
for(int i = 0; i < __rights.Length; i++)
Marshal.StructureToPtr(__rights[i], (IntPtr)((int)_pAccessRights + (i * Marshal.SizeOf(__rights[0]))), false);
}
ppAccess = _pAccessRights;
pcAccesses = (uint)__rights.Length;
piDefaultAccess = 0;
return S_OK;
}
catch
{
return E_FAIL;
}
}
private unsafe uint MapGeneric(IntPtr pThis, Guid *pguidObjectType, ref byte pAceFlags, ref uint pMask)
{
return S_OK;
}
private uint GetInheritTypes(IntPtr pThis, ref SI_INHERIT_TYPE ppInheritTypes, ref uint pcInheritTypes)
{
pcInheritTypes = 0;
return S_OK;
}
private uint PropertySheetPageCallback(IntPtr pThis, IntPtr hwnd, uint uMsg, SI_PAGE_TYPE uPage)
{
return S_OK;
}
}
}