PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/class/referencesource/mscorlib/system/security/principal/win32.cs

https://github.com/pruiz/mono
C# | 457 lines | 298 code | 77 blank | 82 comment | 41 complexity | 6702503de16dbd6f099b73bbbc4ae85f MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. // ==++==
  2. //
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. //
  5. // ==--==
  6. // <OWNER>Microsoft</OWNER>
  7. //
  8. using Microsoft.Win32;
  9. using Microsoft.Win32.SafeHandles;
  10. using System;
  11. using System.Runtime.CompilerServices;
  12. using System.Runtime.InteropServices;
  13. using System.Security.Permissions;
  14. using System.Text;
  15. using System.Runtime.Versioning;
  16. namespace System.Security.Principal
  17. {
  18. using BOOL = System.Int32;
  19. using DWORD = System.UInt32;
  20. using System.Globalization;
  21. using System.Diagnostics.Contracts;
  22. [Flags]
  23. internal enum PolicyRights
  24. {
  25. POLICY_VIEW_LOCAL_INFORMATION = 0x00000001,
  26. POLICY_VIEW_AUDIT_INFORMATION = 0x00000002,
  27. POLICY_GET_PRIVATE_INFORMATION = 0x00000004,
  28. POLICY_TRUST_ADMIN = 0x00000008,
  29. POLICY_CREATE_ACCOUNT = 0x00000010,
  30. POLICY_CREATE_SECRET = 0x00000020,
  31. POLICY_CREATE_PRIVILEGE = 0x00000040,
  32. POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080,
  33. POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100,
  34. POLICY_AUDIT_LOG_ADMIN = 0x00000200,
  35. POLICY_SERVER_ADMIN = 0x00000400,
  36. POLICY_LOOKUP_NAMES = 0x00000800,
  37. POLICY_NOTIFICATION = 0x00001000,
  38. }
  39. internal static class Win32
  40. {
  41. internal const BOOL FALSE = 0;
  42. internal const BOOL TRUE = 1;
  43. private static bool _LsaLookupNames2Supported;
  44. private static bool _WellKnownSidApisSupported;
  45. [System.Security.SecuritySafeCritical] // auto-generated
  46. static Win32()
  47. {
  48. Win32Native.OSVERSIONINFO osvi = new Win32Native.OSVERSIONINFO();
  49. bool r = Environment.GetVersion(osvi);
  50. if ( !r )
  51. {
  52. Contract.Assert( r, "OSVersion native call failed." );
  53. throw new SystemException( Environment.GetResourceString( "InvalidOperation_GetVersion" ));
  54. }
  55. if (osvi.MajorVersion > 5 || osvi.MinorVersion > 0 ) // Windows XP/2003 and above
  56. {
  57. //
  58. // LsaLookupNames2 supported only on XP and Windows 2003 and above
  59. //
  60. _LsaLookupNames2Supported = true;
  61. _WellKnownSidApisSupported = true;
  62. }
  63. else
  64. {
  65. // Win2000
  66. _LsaLookupNames2Supported = false;
  67. //
  68. // WellKnownSid apis are only supported on Windows 2000 SP3 and above
  69. // (so we need sp info)
  70. //
  71. Win32Native.OSVERSIONINFOEX osviex = new Win32Native.OSVERSIONINFOEX();
  72. r = Environment.GetVersionEx(osviex);
  73. if ( !r )
  74. {
  75. Contract.Assert( r, "OSVersion native call failed");
  76. throw new SystemException( Environment.GetResourceString( "InvalidOperation_GetVersion" ));
  77. }
  78. if (osviex.ServicePackMajor < 3)
  79. {
  80. _WellKnownSidApisSupported = false;
  81. }
  82. else
  83. {
  84. _WellKnownSidApisSupported = true;
  85. }
  86. }
  87. }
  88. internal static bool LsaLookupNames2Supported
  89. {
  90. get {
  91. return _LsaLookupNames2Supported;
  92. }
  93. }
  94. internal static bool WellKnownSidApisSupported
  95. {
  96. get {
  97. return _WellKnownSidApisSupported;
  98. }
  99. }
  100. //
  101. // Wrapper around advapi32.LsaOpenPolicy
  102. //
  103. [System.Security.SecurityCritical] // auto-generated
  104. internal static SafeLsaPolicyHandle LsaOpenPolicy(
  105. string systemName,
  106. PolicyRights rights )
  107. {
  108. uint ReturnCode;
  109. SafeLsaPolicyHandle Result;
  110. Win32Native.LSA_OBJECT_ATTRIBUTES Loa;
  111. Loa.Length = Marshal.SizeOf( typeof( Win32Native.LSA_OBJECT_ATTRIBUTES ));
  112. Loa.RootDirectory = IntPtr.Zero;
  113. Loa.ObjectName = IntPtr.Zero;
  114. Loa.Attributes = 0;
  115. Loa.SecurityDescriptor = IntPtr.Zero;
  116. Loa.SecurityQualityOfService = IntPtr.Zero;
  117. if ( 0 == ( ReturnCode = Win32Native.LsaOpenPolicy( systemName, ref Loa, ( int )rights, out Result )))
  118. {
  119. return Result;
  120. }
  121. else if ( ReturnCode == Win32Native.STATUS_ACCESS_DENIED )
  122. {
  123. throw new UnauthorizedAccessException();
  124. }
  125. else if ( ReturnCode == Win32Native.STATUS_INSUFFICIENT_RESOURCES ||
  126. ReturnCode == Win32Native.STATUS_NO_MEMORY )
  127. {
  128. throw new OutOfMemoryException();
  129. }
  130. else
  131. {
  132. int win32ErrorCode = Win32Native.LsaNtStatusToWinError(unchecked((int) ReturnCode));
  133. throw new SystemException(Win32Native.GetMessage(win32ErrorCode));
  134. }
  135. }
  136. [System.Security.SecurityCritical] // auto-generated
  137. internal static byte[] ConvertIntPtrSidToByteArraySid( IntPtr binaryForm )
  138. {
  139. byte[] ResultSid;
  140. //
  141. // Verify the revision (just sanity, should never fail to be 1)
  142. //
  143. byte Revision = Marshal.ReadByte( binaryForm, 0 );
  144. if ( Revision != SecurityIdentifier.Revision )
  145. {
  146. throw new ArgumentException(Environment.GetResourceString( "IdentityReference_InvalidSidRevision" ), "binaryForm");
  147. }
  148. //
  149. // Need the subauthority count in order to figure out how many bytes to read
  150. //
  151. byte SubAuthorityCount = Marshal.ReadByte( binaryForm, 1 );
  152. if ( SubAuthorityCount < 0 ||
  153. SubAuthorityCount > SecurityIdentifier.MaxSubAuthorities )
  154. {
  155. throw new ArgumentException(Environment.GetResourceString( "IdentityReference_InvalidNumberOfSubauthorities", SecurityIdentifier.MaxSubAuthorities), "binaryForm");
  156. }
  157. //
  158. // Compute the size of the binary form of this SID and allocate the memory
  159. //
  160. int BinaryLength = 1 + 1 + 6 + SubAuthorityCount * 4;
  161. ResultSid = new byte[ BinaryLength ];
  162. //
  163. // Extract the data from the returned pointer
  164. //
  165. Marshal.Copy( binaryForm, ResultSid, 0, BinaryLength );
  166. return ResultSid;
  167. }
  168. //
  169. // Wrapper around advapi32.ConvertStringSidToSidW
  170. //
  171. [System.Security.SecurityCritical] // auto-generated
  172. internal static int CreateSidFromString(
  173. string stringSid,
  174. out byte[] resultSid
  175. )
  176. {
  177. int ErrorCode;
  178. IntPtr ByteArray = IntPtr.Zero;
  179. try
  180. {
  181. if ( TRUE != Win32Native.ConvertStringSidToSid( stringSid, out ByteArray ))
  182. {
  183. ErrorCode = Marshal.GetLastWin32Error();
  184. goto Error;
  185. }
  186. resultSid = ConvertIntPtrSidToByteArraySid( ByteArray );
  187. }
  188. finally
  189. {
  190. //
  191. // Now is a good time to get rid of the returned pointer
  192. //
  193. Win32Native.LocalFree( ByteArray );
  194. }
  195. //
  196. // Now invoke the SecurityIdentifier factory method to create the result
  197. //
  198. return Win32Native.ERROR_SUCCESS;
  199. Error:
  200. resultSid = null;
  201. return ErrorCode;
  202. }
  203. //
  204. // Wrapper around advapi32.CreateWellKnownSid
  205. //
  206. [System.Security.SecurityCritical] // auto-generated
  207. internal static int CreateWellKnownSid(
  208. WellKnownSidType sidType,
  209. SecurityIdentifier domainSid,
  210. out byte[] resultSid
  211. )
  212. {
  213. //
  214. // Check if the api is supported
  215. //
  216. if (!WellKnownSidApisSupported) {
  217. throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
  218. }
  219. //
  220. // Passing an array as big as it can ever be is a small price to pay for
  221. // not having to P/Invoke twice (once to get the buffer, once to get the data)
  222. //
  223. uint length = ( uint )SecurityIdentifier.MaxBinaryLength;
  224. resultSid = new byte[ length ];
  225. if ( FALSE != Win32Native.CreateWellKnownSid(( int )sidType, domainSid == null ? null : domainSid.BinaryForm, resultSid, ref length ))
  226. {
  227. return Win32Native.ERROR_SUCCESS;
  228. }
  229. else
  230. {
  231. resultSid = null;
  232. return Marshal.GetLastWin32Error();
  233. }
  234. }
  235. //
  236. // Wrapper around advapi32.EqualDomainSid
  237. //
  238. [System.Security.SecurityCritical] // auto-generated
  239. internal static bool IsEqualDomainSid( SecurityIdentifier sid1, SecurityIdentifier sid2 )
  240. {
  241. //
  242. // Check if the api is supported
  243. //
  244. if (!WellKnownSidApisSupported) {
  245. throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
  246. }
  247. if ( sid1 == null || sid2 == null )
  248. {
  249. return false;
  250. }
  251. else
  252. {
  253. bool result;
  254. byte[] BinaryForm1 = new Byte[sid1.BinaryLength];
  255. sid1.GetBinaryForm( BinaryForm1, 0 );
  256. byte[] BinaryForm2 = new Byte[sid2.BinaryLength];
  257. sid2.GetBinaryForm( BinaryForm2, 0 );
  258. return ( Win32Native.IsEqualDomainSid( BinaryForm1, BinaryForm2, out result ) == FALSE ? false : result );
  259. }
  260. }
  261. /// <summary>
  262. /// Setup the size of the buffer Windows provides for an LSA_REFERENCED_DOMAIN_LIST
  263. /// </summary>
  264. [System.Security.SecurityCritical] // auto-generated
  265. internal static void InitializeReferencedDomainsPointer(SafeLsaMemoryHandle referencedDomains)
  266. {
  267. Contract.Assert(referencedDomains != null, "referencedDomains != null");
  268. // We don't know the real size of the referenced domains yet, so we need to set an initial
  269. // size based on the LSA_REFERENCED_DOMAIN_LIST structure, then resize it to include all of
  270. // the domains.
  271. referencedDomains.Initialize((uint)Marshal.SizeOf(typeof(Win32Native.LSA_REFERENCED_DOMAIN_LIST)));
  272. Win32Native.LSA_REFERENCED_DOMAIN_LIST domainList = referencedDomains.Read<Win32Native.LSA_REFERENCED_DOMAIN_LIST>(0);
  273. unsafe
  274. {
  275. byte* pRdl = null;
  276. RuntimeHelpers.PrepareConstrainedRegions();
  277. try
  278. {
  279. referencedDomains.AcquirePointer(ref pRdl);
  280. // If there is a trust information list, then the buffer size is the end of that list minus
  281. // the beginning of the domain list. Otherwise, then the buffer is just the size of the
  282. // referenced domain list structure, which is what we defaulted to.
  283. if (!domainList.Domains.IsNull())
  284. {
  285. Win32Native.LSA_TRUST_INFORMATION* pTrustInformation = (Win32Native.LSA_TRUST_INFORMATION*)domainList.Domains;
  286. pTrustInformation = pTrustInformation + domainList.Entries;
  287. long bufferSize = (byte*)pTrustInformation - pRdl;
  288. Contract.Assert(bufferSize > 0, "bufferSize > 0");
  289. referencedDomains.Initialize((ulong)bufferSize);
  290. }
  291. }
  292. finally
  293. {
  294. if (pRdl != null)
  295. referencedDomains.ReleasePointer();
  296. }
  297. }
  298. }
  299. //
  300. // Wrapper around avdapi32.GetWindowsAccountDomainSid
  301. //
  302. [System.Security.SecurityCritical] // auto-generated
  303. internal static int GetWindowsAccountDomainSid(
  304. SecurityIdentifier sid,
  305. out SecurityIdentifier resultSid
  306. )
  307. {
  308. //
  309. // Check if the api is supported
  310. //
  311. if (!WellKnownSidApisSupported) {
  312. throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
  313. }
  314. //
  315. // Passing an array as big as it can ever be is a small price to pay for
  316. // not having to P/Invoke twice (once to get the buffer, once to get the data)
  317. //
  318. byte[] BinaryForm = new Byte[sid.BinaryLength];
  319. sid.GetBinaryForm( BinaryForm, 0 );
  320. uint sidLength = ( uint )SecurityIdentifier.MaxBinaryLength;
  321. byte[] resultSidBinary = new byte[ sidLength ];
  322. if ( FALSE != Win32Native.GetWindowsAccountDomainSid( BinaryForm, resultSidBinary, ref sidLength ))
  323. {
  324. resultSid = new SecurityIdentifier( resultSidBinary, 0 );
  325. return Win32Native.ERROR_SUCCESS;
  326. }
  327. else
  328. {
  329. resultSid = null;
  330. return Marshal.GetLastWin32Error();
  331. }
  332. }
  333. //
  334. // Wrapper around advapi32.IsWellKnownSid
  335. //
  336. [System.Security.SecurityCritical] // auto-generated
  337. internal static bool IsWellKnownSid(
  338. SecurityIdentifier sid,
  339. WellKnownSidType type
  340. )
  341. {
  342. //
  343. // Check if the api is supported
  344. //
  345. if (!WellKnownSidApisSupported) {
  346. throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
  347. }
  348. byte[] BinaryForm = new byte[sid.BinaryLength];
  349. sid.GetBinaryForm( BinaryForm, 0 );
  350. if ( FALSE == Win32Native.IsWellKnownSid( BinaryForm, ( int )type ))
  351. {
  352. return false;
  353. }
  354. else
  355. {
  356. return true;
  357. }
  358. }
  359. // When the CLR is hosted, the host gets to implement these calls,
  360. // otherwise, we call down into the Win32 APIs.
  361. #if FEATURE_IMPERSONATION
  362. [System.Security.SecurityCritical] // auto-generated
  363. [ResourceExposure(ResourceScope.Process)]
  364. [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
  365. internal static extern int ImpersonateLoggedOnUser (SafeAccessTokenHandle hToken);
  366. [System.Security.SecurityCritical] // auto-generated
  367. [ResourceExposure(ResourceScope.Process)]
  368. [MethodImplAttribute(MethodImplOptions.InternalCall)]
  369. internal static extern int OpenThreadToken (TokenAccessLevels dwDesiredAccess, WinSecurityContext OpenAs, out SafeAccessTokenHandle phThreadToken);
  370. [System.Security.SecurityCritical] // auto-generated
  371. [ResourceExposure(ResourceScope.None)]
  372. [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
  373. internal static extern int RevertToSelf ();
  374. [System.Security.SecurityCritical] // auto-generated
  375. [ResourceExposure(ResourceScope.None)]
  376. [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
  377. internal static extern int SetThreadToken(SafeAccessTokenHandle hToken);
  378. #endif
  379. }
  380. }