3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // <OWNER>Microsoft</OWNER>
10 using Microsoft.Win32.SafeHandles;
12 using System.Runtime.CompilerServices;
13 using System.Runtime.InteropServices;
14 using System.Security.Permissions;
16 using System.Runtime.Versioning;
18 namespace System.Security.Principal
20 using BOOL = System.Int32;
21 using DWORD = System.UInt32;
22 using System.Globalization;
23 using System.Diagnostics.Contracts;
26 internal enum PolicyRights
28 POLICY_VIEW_LOCAL_INFORMATION = 0x00000001,
29 POLICY_VIEW_AUDIT_INFORMATION = 0x00000002,
30 POLICY_GET_PRIVATE_INFORMATION = 0x00000004,
31 POLICY_TRUST_ADMIN = 0x00000008,
32 POLICY_CREATE_ACCOUNT = 0x00000010,
33 POLICY_CREATE_SECRET = 0x00000020,
34 POLICY_CREATE_PRIVILEGE = 0x00000040,
35 POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080,
36 POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100,
37 POLICY_AUDIT_LOG_ADMIN = 0x00000200,
38 POLICY_SERVER_ADMIN = 0x00000400,
39 POLICY_LOOKUP_NAMES = 0x00000800,
40 POLICY_NOTIFICATION = 0x00001000,
43 internal static class Win32
45 internal const BOOL FALSE = 0;
46 internal const BOOL TRUE = 1;
48 private static bool _LsaLookupNames2Supported;
49 private static bool _WellKnownSidApisSupported;
51 [System.Security.SecuritySafeCritical] // auto-generated
55 Win32Native.OSVERSIONINFO osvi = new Win32Native.OSVERSIONINFO();
57 bool r = Environment.GetVersion(osvi);
60 Contract.Assert( r, "OSVersion native call failed." );
61 throw new SystemException( Environment.GetResourceString( "InvalidOperation_GetVersion" ));
63 if (osvi.MajorVersion > 5 || osvi.MinorVersion > 0 ) // Windows XP/2003 and above
67 // LsaLookupNames2 supported only on XP and Windows 2003 and above
69 _LsaLookupNames2Supported = true;
70 _WellKnownSidApisSupported = true;
75 _LsaLookupNames2Supported = false;
79 // WellKnownSid apis are only supported on Windows 2000 SP3 and above
80 // (so we need sp info)
82 Win32Native.OSVERSIONINFOEX osviex = new Win32Native.OSVERSIONINFOEX();
84 r = Environment.GetVersionEx(osviex);
87 Contract.Assert( r, "OSVersion native call failed");
88 throw new SystemException( Environment.GetResourceString( "InvalidOperation_GetVersion" ));
91 if (osviex.ServicePackMajor < 3)
93 _WellKnownSidApisSupported = false;
97 _WellKnownSidApisSupported = true;
102 internal static bool LsaLookupNames2Supported
105 return _LsaLookupNames2Supported;
109 internal static bool WellKnownSidApisSupported
112 return _WellKnownSidApisSupported;
117 // Wrapper around advapi32.LsaOpenPolicy
120 [System.Security.SecurityCritical] // auto-generated
121 internal static SafeLsaPolicyHandle LsaOpenPolicy(
123 PolicyRights rights )
126 SafeLsaPolicyHandle Result;
127 Win32Native.LSA_OBJECT_ATTRIBUTES Loa;
129 Loa.Length = Marshal.SizeOf( typeof( Win32Native.LSA_OBJECT_ATTRIBUTES ));
130 Loa.RootDirectory = IntPtr.Zero;
131 Loa.ObjectName = IntPtr.Zero;
133 Loa.SecurityDescriptor = IntPtr.Zero;
134 Loa.SecurityQualityOfService = IntPtr.Zero;
136 if ( 0 == ( ReturnCode = Win32Native.LsaOpenPolicy( systemName, ref Loa, ( int )rights, out Result )))
140 else if ( ReturnCode == Win32Native.STATUS_ACCESS_DENIED )
142 throw new UnauthorizedAccessException();
144 else if ( ReturnCode == Win32Native.STATUS_INSUFFICIENT_RESOURCES ||
145 ReturnCode == Win32Native.STATUS_NO_MEMORY )
147 throw new OutOfMemoryException();
151 int win32ErrorCode = Win32Native.LsaNtStatusToWinError(unchecked((int) ReturnCode));
153 throw new SystemException(Win32Native.GetMessage(win32ErrorCode));
157 [System.Security.SecurityCritical] // auto-generated
158 internal static byte[] ConvertIntPtrSidToByteArraySid( IntPtr binaryForm )
163 // Verify the revision (just sanity, should never fail to be 1)
166 byte Revision = Marshal.ReadByte( binaryForm, 0 );
168 if ( Revision != SecurityIdentifier.Revision )
170 throw new ArgumentException(Environment.GetResourceString( "IdentityReference_InvalidSidRevision" ), "binaryForm");
174 // Need the subauthority count in order to figure out how many bytes to read
177 byte SubAuthorityCount = Marshal.ReadByte( binaryForm, 1 );
179 if ( SubAuthorityCount < 0 ||
180 SubAuthorityCount > SecurityIdentifier.MaxSubAuthorities )
182 throw new ArgumentException(Environment.GetResourceString( "IdentityReference_InvalidNumberOfSubauthorities", SecurityIdentifier.MaxSubAuthorities), "binaryForm");
186 // Compute the size of the binary form of this SID and allocate the memory
189 int BinaryLength = 1 + 1 + 6 + SubAuthorityCount * 4;
190 ResultSid = new byte[ BinaryLength ];
193 // Extract the data from the returned pointer
196 Marshal.Copy( binaryForm, ResultSid, 0, BinaryLength );
202 // Wrapper around advapi32.ConvertStringSidToSidW
205 [System.Security.SecurityCritical] // auto-generated
206 internal static int CreateSidFromString(
212 IntPtr ByteArray = IntPtr.Zero;
216 if ( TRUE != Win32Native.ConvertStringSidToSid( stringSid, out ByteArray ))
218 ErrorCode = Marshal.GetLastWin32Error();
222 resultSid = ConvertIntPtrSidToByteArraySid( ByteArray );
227 // Now is a good time to get rid of the returned pointer
230 Win32Native.LocalFree( ByteArray );
234 // Now invoke the SecurityIdentifier factory method to create the result
237 return Win32Native.ERROR_SUCCESS;
246 // Wrapper around advapi32.CreateWellKnownSid
249 [System.Security.SecurityCritical] // auto-generated
250 internal static int CreateWellKnownSid(
251 WellKnownSidType sidType,
252 SecurityIdentifier domainSid,
258 // Check if the api is supported
260 if (!WellKnownSidApisSupported) {
261 throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
265 // Passing an array as big as it can ever be is a small price to pay for
266 // not having to P/Invoke twice (once to get the buffer, once to get the data)
269 uint length = ( uint )SecurityIdentifier.MaxBinaryLength;
270 resultSid = new byte[ length ];
272 if ( FALSE != Win32Native.CreateWellKnownSid(( int )sidType, domainSid == null ? null : domainSid.BinaryForm, resultSid, ref length ))
274 return Win32Native.ERROR_SUCCESS;
280 return Marshal.GetLastWin32Error();
285 // Wrapper around advapi32.EqualDomainSid
288 [System.Security.SecurityCritical] // auto-generated
289 internal static bool IsEqualDomainSid( SecurityIdentifier sid1, SecurityIdentifier sid2 )
292 // Check if the api is supported
294 if (!WellKnownSidApisSupported) {
295 throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
298 if ( sid1 == null || sid2 == null )
306 byte[] BinaryForm1 = new Byte[sid1.BinaryLength];
307 sid1.GetBinaryForm( BinaryForm1, 0 );
309 byte[] BinaryForm2 = new Byte[sid2.BinaryLength];
310 sid2.GetBinaryForm( BinaryForm2, 0 );
312 return ( Win32Native.IsEqualDomainSid( BinaryForm1, BinaryForm2, out result ) == FALSE ? false : result );
317 /// Setup the size of the buffer Windows provides for an LSA_REFERENCED_DOMAIN_LIST
319 [System.Security.SecurityCritical] // auto-generated
320 internal static void InitializeReferencedDomainsPointer(SafeLsaMemoryHandle referencedDomains)
322 Contract.Assert(referencedDomains != null, "referencedDomains != null");
324 // We don't know the real size of the referenced domains yet, so we need to set an initial
325 // size based on the LSA_REFERENCED_DOMAIN_LIST structure, then resize it to include all of
327 referencedDomains.Initialize((uint)Marshal.SizeOf(typeof(Win32Native.LSA_REFERENCED_DOMAIN_LIST)));
328 Win32Native.LSA_REFERENCED_DOMAIN_LIST domainList = referencedDomains.Read<Win32Native.LSA_REFERENCED_DOMAIN_LIST>(0);
333 RuntimeHelpers.PrepareConstrainedRegions();
336 referencedDomains.AcquirePointer(ref pRdl);
338 // If there is a trust information list, then the buffer size is the end of that list minus
339 // the beginning of the domain list. Otherwise, then the buffer is just the size of the
340 // referenced domain list structure, which is what we defaulted to.
341 if (!domainList.Domains.IsNull())
343 Win32Native.LSA_TRUST_INFORMATION* pTrustInformation = (Win32Native.LSA_TRUST_INFORMATION*)domainList.Domains;
344 pTrustInformation = pTrustInformation + domainList.Entries;
346 long bufferSize = (byte*)pTrustInformation - pRdl;
347 Contract.Assert(bufferSize > 0, "bufferSize > 0");
348 referencedDomains.Initialize((ulong)bufferSize);
354 referencedDomains.ReleasePointer();
360 // Wrapper around avdapi32.GetWindowsAccountDomainSid
363 [System.Security.SecurityCritical] // auto-generated
364 internal static int GetWindowsAccountDomainSid(
365 SecurityIdentifier sid,
366 out SecurityIdentifier resultSid
371 // Check if the api is supported
373 if (!WellKnownSidApisSupported) {
374 throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
378 // Passing an array as big as it can ever be is a small price to pay for
379 // not having to P/Invoke twice (once to get the buffer, once to get the data)
382 byte[] BinaryForm = new Byte[sid.BinaryLength];
383 sid.GetBinaryForm( BinaryForm, 0 );
384 uint sidLength = ( uint )SecurityIdentifier.MaxBinaryLength;
385 byte[] resultSidBinary = new byte[ sidLength ];
387 if ( FALSE != Win32Native.GetWindowsAccountDomainSid( BinaryForm, resultSidBinary, ref sidLength ))
389 resultSid = new SecurityIdentifier( resultSidBinary, 0 );
391 return Win32Native.ERROR_SUCCESS;
397 return Marshal.GetLastWin32Error();
402 // Wrapper around advapi32.IsWellKnownSid
405 [System.Security.SecurityCritical] // auto-generated
406 internal static bool IsWellKnownSid(
407 SecurityIdentifier sid,
408 WellKnownSidType type
412 // Check if the api is supported
414 if (!WellKnownSidApisSupported) {
415 throw new PlatformNotSupportedException( Environment.GetResourceString( "PlatformNotSupported_RequiresW2kSP3" ));
418 byte[] BinaryForm = new byte[sid.BinaryLength];
419 sid.GetBinaryForm( BinaryForm, 0 );
421 if ( FALSE == Win32Native.IsWellKnownSid( BinaryForm, ( int )type ))
432 // When the CLR is hosted, the host gets to implement these calls,
433 // otherwise, we call down into the Win32 APIs.
435 #if FEATURE_IMPERSONATION
436 [System.Security.SecurityCritical] // auto-generated
437 [ResourceExposure(ResourceScope.Process)]
438 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
439 internal static extern int ImpersonateLoggedOnUser (SafeAccessTokenHandle hToken);
441 [System.Security.SecurityCritical] // auto-generated
442 [ResourceExposure(ResourceScope.Process)]
443 [MethodImplAttribute(MethodImplOptions.InternalCall)]
444 internal static extern int OpenThreadToken (TokenAccessLevels dwDesiredAccess, WinSecurityContext OpenAs, out SafeAccessTokenHandle phThreadToken);
446 [System.Security.SecurityCritical] // auto-generated
447 [ResourceExposure(ResourceScope.None)]
448 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
449 internal static extern int RevertToSelf ();
451 [System.Security.SecurityCritical] // auto-generated
452 [ResourceExposure(ResourceScope.None)]
453 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
454 internal static extern int SetThreadToken(SafeAccessTokenHandle hToken);