You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

499 lines
16 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Security.AccessControl;
  4. using Microsoft.Win32;
  5. using System.Runtime.InteropServices;
  6. using System.Security.Principal;
  7. namespace Security2
  8. {
  9. //#region FileSecurity2
  10. //public class FileSecurity2 : ICast<FileSecurity>, IDisposable
  11. //{
  12. // protected FileSecurity securityDescriptor;
  13. // public string FullName { get; set; }
  14. // public string Name { get { return System.IO.Path.GetFileName(FullName); } }
  15. // public FileSecurity2() { }
  16. // public FileSecurity2(FileSecurity SecurityDescriptor)
  17. // {
  18. // this.securityDescriptor = SecurityDescriptor;
  19. // }
  20. // #region conversion
  21. // public static implicit operator FileSecurity(FileSecurity2 V)
  22. // {
  23. // return V.securityDescriptor;
  24. // }
  25. // public static implicit operator FileSecurity2(FileSecurity n)
  26. // {
  27. // return new FileSecurity2(n);
  28. // }
  29. // //REQUIRED BECAUSE OF CONVERSION OPERATORS
  30. // public override bool Equals(object obj)
  31. // {
  32. // return this.securityDescriptor == (FileSecurity)obj;
  33. // }
  34. // public override int GetHashCode()
  35. // {
  36. // return this.securityDescriptor.GetHashCode();
  37. // }
  38. // #endregion
  39. // #region ICast<FileSecurity> Members
  40. // public FileSecurity Cast
  41. // {
  42. // get { return this.securityDescriptor; }
  43. // }
  44. // #endregion
  45. // #region IDisposable Members
  46. // public void Dispose()
  47. // { }
  48. // #endregion
  49. //}
  50. //#endregion
  51. //#region DirectorySecurity2
  52. //public class DirectorySecurity2 : ICast<DirectorySecurity>, IDisposable
  53. //{
  54. // protected DirectorySecurity securityDescriptor;
  55. // public string FullName { get; set; }
  56. // public string Name { get { return System.IO.Path.GetFileName(FullName); } }
  57. // public DirectorySecurity2() { }
  58. // public DirectorySecurity2(DirectorySecurity SecurityDescriptor)
  59. // {
  60. // this.securityDescriptor = SecurityDescriptor;
  61. // }
  62. // #region conversion
  63. // public static implicit operator DirectorySecurity(DirectorySecurity2 V)
  64. // {
  65. // return V.securityDescriptor;
  66. // }
  67. // public static implicit operator DirectorySecurity2(DirectorySecurity n)
  68. // {
  69. // return new DirectorySecurity2(n);
  70. // }
  71. // //REQUIRED BECAUSE OF CONVERSION OPERATORS
  72. // public override bool Equals(object obj)
  73. // {
  74. // return this.securityDescriptor == (DirectorySecurity)obj;
  75. // }
  76. // public override int GetHashCode()
  77. // {
  78. // return this.securityDescriptor.GetHashCode();
  79. // }
  80. // #endregion
  81. // #region ICast<DirectorySecurity> Members
  82. // public DirectorySecurity Cast
  83. // {
  84. // get { return this.securityDescriptor; }
  85. // }
  86. // #endregion
  87. // #region IDisposable Members
  88. // public void Dispose()
  89. // { }
  90. // #endregion
  91. //}
  92. //#endregion
  93. #region RegistryAccessRule2
  94. public class RegistryAccessRule2 : IDisposable
  95. {
  96. protected RegistryAccessRule registryAccessRule;
  97. public string Name
  98. {
  99. get
  100. {
  101. if (!string.IsNullOrEmpty(FullName))
  102. {
  103. if (FullName.Contains("\\"))
  104. {
  105. var elements = FullName.Split('\\');
  106. return elements[elements.Length - 1];
  107. }
  108. else
  109. {
  110. return FullName;
  111. }
  112. }
  113. else
  114. {
  115. return null;
  116. }
  117. }
  118. }
  119. public string FullName { get; set; }
  120. public bool InheritanceEnabled { get; set; }
  121. public RegistryAccessRule2(RegistryAccessRule registryAccessRule)
  122. {
  123. this.registryAccessRule = registryAccessRule;
  124. }
  125. #region Properties
  126. public AccessControlType AccessControlType { get { return registryAccessRule.AccessControlType; } }
  127. public RegistryRights RegistryRights { get { return registryAccessRule.RegistryRights; } }
  128. public IdentityReference2 IdentityReference { get { return (IdentityReference2)registryAccessRule.IdentityReference; } }
  129. public InheritanceFlags InheritanceFlags { get { return registryAccessRule.InheritanceFlags; } }
  130. public bool IsInherited { get { return registryAccessRule.IsInherited; } }
  131. public PropagationFlags PropagationFlags { get { return registryAccessRule.PropagationFlags; } }
  132. #endregion
  133. #region conversion
  134. public static implicit operator RegistryAccessRule(RegistryAccessRule2 V)
  135. {
  136. return V.registryAccessRule;
  137. }
  138. public static implicit operator RegistryAccessRule2(RegistryAccessRule n)
  139. {
  140. return new RegistryAccessRule2(n);
  141. }
  142. //REQUIRED BECAUSE OF CONVERSION OPERATORS
  143. public override bool Equals(object obj)
  144. {
  145. return this.registryAccessRule == (RegistryAccessRule)obj;
  146. }
  147. public override int GetHashCode()
  148. {
  149. return this.registryAccessRule.GetHashCode();
  150. }
  151. public override string ToString()
  152. {
  153. return registryAccessRule.ToString();
  154. }
  155. #endregion
  156. #region IDisposable Members
  157. public void Dispose()
  158. { }
  159. #endregion
  160. }
  161. #endregion
  162. #region RegistryInheritanceInfo
  163. public class RegistryInheritanceInfo
  164. {
  165. public RegistryKey Item { get; set; }
  166. public bool InheritanceEnabled { get; set; }
  167. public string FullName { get { return Item.Name; } }
  168. public string Name
  169. {
  170. get
  171. {
  172. if (!string.IsNullOrEmpty(FullName))
  173. {
  174. if (FullName.Contains("\\"))
  175. {
  176. var elements = FullName.Split('\\');
  177. return elements[elements.Length - 1];
  178. }
  179. else
  180. {
  181. return FullName;
  182. }
  183. }
  184. else
  185. {
  186. return null;
  187. }
  188. }
  189. }
  190. }
  191. #endregion
  192. #region RegistryEffectivePermissionEntry
  193. public class RegistryEffectivePermissionEntry
  194. {
  195. private IdentityReference2 account;
  196. public IdentityReference2 Account { get { return account; } }
  197. private uint accessMask;
  198. public uint AccessMask { get { return accessMask; } }
  199. private string objectPath;
  200. public string FullName { get { return objectPath; } }
  201. public string Name { get
  202. {
  203. if (!string.IsNullOrEmpty(FullName))
  204. {
  205. if (FullName.Contains("\\"))
  206. {
  207. var elements = FullName.Split('\\');
  208. return elements[elements.Length - 1];
  209. }
  210. else
  211. {
  212. return FullName;
  213. }
  214. }
  215. else
  216. {
  217. return null;
  218. }
  219. }
  220. }
  221. private List<string> accessAsString;
  222. public List<string> AccessAsString { get { return accessAsString; } }
  223. public RegistryEffectivePermissionEntry(IdentityReference2 id, uint AccessMask, string FullName)
  224. {
  225. this.account = id;
  226. this.accessMask = AccessMask;
  227. this.objectPath = FullName;
  228. this.accessAsString = new List<string>();
  229. if (accessMask == 0)
  230. {
  231. accessAsString.Add("None");
  232. }
  233. else
  234. {
  235. string tempString = ((RegistryRights)this.accessMask).ToString();
  236. foreach (var s in tempString.Split(','))
  237. {
  238. this.accessAsString.Add(s);
  239. }
  240. }
  241. }
  242. }
  243. #endregion
  244. #region RegistryOwner
  245. public class RegistryOwner
  246. {
  247. public RegistryKey Item { get; set; }
  248. public Security2.IdentityReference2 Account { get; set; }
  249. }
  250. #endregion
  251. #region Win32
  252. #region Win32Enums
  253. /// <summary>
  254. /// enum used by RegOpenKeyEx
  255. /// </summary>
  256. public enum SAM_DESIRED : long
  257. {
  258. KEY_QUERY_VALUE = 0x1,
  259. KEY_SET_VALUE = 0x2,
  260. KEY_ALL_ACCESS = 0xf003f,
  261. KEY_CREATE_SUB_KEY = 0x4,
  262. KEY_ENUMERATE_SUB_KEYS = 0x8,
  263. KEY_NOTIFY = 0x10,
  264. KEY_CREATE_LINK = 0x20,
  265. READ_CONTROL = 0x20000,
  266. WRITE_DAC = 0x40000,
  267. WRITE_OWNER = 0x80000,
  268. SYNCHRONIZE = 0x100000,
  269. STANDARD_RIGHTS_REQUIRED = 0xf0000,
  270. STANDARD_RIGHTS_READ = READ_CONTROL,
  271. STANDARD_RIGHTS_WRITE = READ_CONTROL,
  272. STANDARD_RIGHTS_EXECUTE = READ_CONTROL,
  273. KEY_READ = STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY,
  274. KEY_WRITE = STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY,
  275. KEY_EXECUTE = KEY_READ
  276. }
  277. /// <summary>
  278. /// constant enum for registry roots
  279. /// </summary>
  280. public enum REGISTRY_ROOT : long
  281. {
  282. HKEY_CLASSES_ROOT = 0x80000000,
  283. HKEY_CURRENT_USER = 0x80000001,
  284. HKEY_LOCAL_MACHINE = 0x80000002,
  285. HKEY_USERS = 0x80000003
  286. }
  287. #endregion
  288. public class RegistryKeyOpenException : System.Exception
  289. {
  290. private long win32ErrorCode;
  291. public long Win32ErrorCode { get { return win32ErrorCode; } }
  292. public RegistryKeyOpenException()
  293. : base("Cannot open Registry Key")
  294. { }
  295. public RegistryKeyOpenException(Exception innerException)
  296. : base("Cannot open Registry Key", innerException)
  297. { }
  298. public RegistryKeyOpenException(long Win32ErrorCode)
  299. : base("Cannot open Registry Key")
  300. {
  301. this.win32ErrorCode = Win32ErrorCode;
  302. }
  303. public RegistryKeyOpenException(Exception innerException, long Win32ErrorCode)
  304. : base("Cannot open Registry Key", innerException)
  305. {
  306. this.win32ErrorCode = Win32ErrorCode;
  307. }
  308. }
  309. public class RegistryKeySetSecurityException : System.Exception
  310. {
  311. private long win32ErrorCode;
  312. public long Win32ErrorCode { get { return win32ErrorCode; } }
  313. public RegistryKeySetSecurityException()
  314. : base("Cannot set security descriptor on registry key")
  315. { }
  316. public RegistryKeySetSecurityException(Exception innerException)
  317. : base("Cannot set security descriptor on registry key", innerException)
  318. { }
  319. public RegistryKeySetSecurityException(long Win32ErrorCode)
  320. : base("Cannot set security descriptor on registry key")
  321. {
  322. this.win32ErrorCode = Win32ErrorCode;
  323. }
  324. public RegistryKeySetSecurityException(Exception innerException, long Win32ErrorCode)
  325. : base("Cannot set security descriptor on registry key", innerException)
  326. {
  327. this.win32ErrorCode = Win32ErrorCode;
  328. }
  329. }
  330. public class Win32RegistrySecurity
  331. {
  332. #region DllImports
  333. [DllImport("kernel32.dll")]
  334. private static extern long CloseHandle(IntPtr hHandle);
  335. [DllImport("advapi32.dll")]
  336. private static extern long InitializeSecurityDescriptor(ref SECURITY_DESCRIPTOR pSecurityDescriptor, long dwRevision);
  337. [DllImport("advapi32.dll")]
  338. private static extern long SetSecurityDescriptorOwner(ref SECURITY_DESCRIPTOR pSecurityDescriptor, byte[] pOwner, long bOwnerDefaulted);
  339. [DllImport("advapi32.dll")]
  340. private static extern long RegSetKeySecurity(IntPtr ptrKey, SECURITY_INFORMATION SecurityInformation, SECURITY_DESCRIPTOR pSecurityDescriptor);
  341. [DllImport("advapi32.dll", EntryPoint = "RegOpenKeyExA")]
  342. private static extern long RegOpenKeyEx(REGISTRY_ROOT hKey, string lpSubKey, long ulOptions, SAM_DESIRED samDesired, ref IntPtr ptrKey);
  343. [DllImport("advapi32.dll")]
  344. private static extern long RegCloseKey(IntPtr ptrKey);
  345. private struct SECURITY_DESCRIPTOR
  346. {
  347. public byte Revision;
  348. public byte Sbz1;
  349. public long Control;
  350. public long Owner;
  351. public long Group;
  352. public ACL Sacl;
  353. public ACL Dacl;
  354. }
  355. private struct ACL
  356. {
  357. public byte AclRevision;
  358. public byte Sbz1;
  359. public int AclSize;
  360. public int AceCount;
  361. public int Sbz2;
  362. }
  363. #endregion
  364. private RegistryKey GetRegistryKey(REGISTRY_ROOT Root, string KeyPath, RegistryRights Desired)
  365. {
  366. try
  367. {
  368. switch (Root)
  369. {
  370. case REGISTRY_ROOT.HKEY_CLASSES_ROOT:
  371. return Registry.ClassesRoot.OpenSubKey(KeyPath, RegistryKeyPermissionCheck.ReadWriteSubTree, Desired);
  372. case REGISTRY_ROOT.HKEY_LOCAL_MACHINE:
  373. return Registry.LocalMachine.OpenSubKey(KeyPath, RegistryKeyPermissionCheck.ReadWriteSubTree, Desired);
  374. case REGISTRY_ROOT.HKEY_USERS:
  375. return Registry.Users.OpenSubKey(KeyPath, RegistryKeyPermissionCheck.ReadWriteSubTree, Desired);
  376. case REGISTRY_ROOT.HKEY_CURRENT_USER:
  377. return Registry.CurrentUser.OpenSubKey(KeyPath, RegistryKeyPermissionCheck.ReadWriteSubTree, Desired);
  378. default:
  379. return null;
  380. }
  381. }
  382. catch (Exception)
  383. {
  384. return null;
  385. }
  386. }
  387. public void SetRegistryOwner(REGISTRY_ROOT Root, string KeyPath, SecurityIdentifier sid)
  388. {
  389. long win32ErrorCode = 0;
  390. SECURITY_DESCRIPTOR sd = new SECURITY_DESCRIPTOR();
  391. byte[] byteSid = new byte[sid.BinaryLength];
  392. sid.GetBinaryForm(byteSid, 0);
  393. IntPtr pRegKey = IntPtr.Zero;
  394. try
  395. {
  396. win32ErrorCode = RegOpenKeyEx(Root, KeyPath, 0, SAM_DESIRED.WRITE_OWNER, ref pRegKey);
  397. if (win32ErrorCode != 0)
  398. {
  399. throw new RegistryKeyOpenException(win32ErrorCode);
  400. }
  401. }
  402. catch (RegistryKeyOpenException)
  403. {
  404. throw;
  405. }
  406. catch (Exception ex)
  407. {
  408. throw new RegistryKeyOpenException(ex);
  409. }
  410. InitializeSecurityDescriptor(ref sd, 1);
  411. SetSecurityDescriptorOwner(ref sd, byteSid, 0);
  412. try
  413. {
  414. win32ErrorCode = RegSetKeySecurity(pRegKey, SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION, sd);
  415. if (win32ErrorCode != 0)
  416. {
  417. throw new RegistryKeySetSecurityException(win32ErrorCode);
  418. }
  419. }
  420. catch (RegistryKeySetSecurityException)
  421. {
  422. throw;
  423. }
  424. catch (Exception ex)
  425. {
  426. throw new RegistryKeyOpenException(ex);
  427. }
  428. finally
  429. {
  430. RegCloseKey(pRegKey);
  431. }
  432. }
  433. }
  434. #endregion
  435. }