Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Security / AccessControl / Privilege.cs / 1305376 / Privilege.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** Class: Privilege ** ** Purpose: Managed wrapper for NT privileges. ** ** Date: July 1, 2004 ** ===========================================================*/ using Microsoft.Win32; using Microsoft.Win32.SafeHandles; using System.Collections; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; using System.Security.Permissions; using System.Security.Principal; using System.Threading; using System.Runtime.Versioning; using System.Diagnostics.Contracts; namespace System.Security.AccessControl { using CultureInfo = System.Globalization.CultureInfo; using FCall = System.Security.Principal.Win32; using Luid = Microsoft.Win32.Win32Native.LUID; #if false internal delegate void PrivilegedHelper(); #endif internal sealed class Privilege { private static LocalDataStoreSlot tlsSlot = Thread.AllocateDataSlot(); private static Hashtable privileges = new Hashtable(); private static Hashtable luids = new Hashtable(); private static ReaderWriterLock privilegeLock = new ReaderWriterLock(); private bool needToRevert = false; private bool initialState = false; private bool stateWasChanged = false; [System.Security.SecurityCritical /*auto-generated*/] private Luid luid; private readonly Thread currentThread = Thread.CurrentThread; private TlsContents tlsContents = null; public const string CreateToken = "SeCreateTokenPrivilege"; public const string AssignPrimaryToken = "SeAssignPrimaryTokenPrivilege"; public const string LockMemory = "SeLockMemoryPrivilege"; public const string IncreaseQuota = "SeIncreaseQuotaPrivilege"; public const string UnsolicitedInput = "SeUnsolicitedInputPrivilege"; public const string MachineAccount = "SeMachineAccountPrivilege"; public const string TrustedComputingBase = "SeTcbPrivilege"; public const string Security = "SeSecurityPrivilege"; public const string TakeOwnership = "SeTakeOwnershipPrivilege"; public const string LoadDriver = "SeLoadDriverPrivilege"; public const string SystemProfile = "SeSystemProfilePrivilege"; public const string SystemTime = "SeSystemtimePrivilege"; public const string ProfileSingleProcess = "SeProfileSingleProcessPrivilege"; public const string IncreaseBasePriority = "SeIncreaseBasePriorityPrivilege"; public const string CreatePageFile = "SeCreatePagefilePrivilege"; public const string CreatePermanent = "SeCreatePermanentPrivilege"; public const string Backup = "SeBackupPrivilege"; public const string Restore = "SeRestorePrivilege"; public const string Shutdown = "SeShutdownPrivilege"; public const string Debug = "SeDebugPrivilege"; public const string Audit = "SeAuditPrivilege"; public const string SystemEnvironment = "SeSystemEnvironmentPrivilege"; public const string ChangeNotify = "SeChangeNotifyPrivilege"; public const string RemoteShutdown = "SeRemoteShutdownPrivilege"; public const string Undock = "SeUndockPrivilege"; public const string SyncAgent = "SeSyncAgentPrivilege"; public const string EnableDelegation = "SeEnableDelegationPrivilege"; public const string ManageVolume = "SeManageVolumePrivilege"; public const string Impersonate = "SeImpersonatePrivilege"; public const string CreateGlobal = "SeCreateGlobalPrivilege"; public const string TrustedCredentialManagerAccess = "SeTrustedCredManAccessPrivilege"; public const string ReserveProcessor = "SeReserveProcessorPrivilege"; // // This routine is a wrapper around a hashtable containing mappings // of privilege names to LUIDs // [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] private static Luid LuidFromPrivilege( string privilege ) { Luid luid; luid.LowPart = 0; luid.HighPart = 0; // // Look up the privilege LUID inside the cache // RuntimeHelpers.PrepareConstrainedRegions(); try { privilegeLock.AcquireReaderLock( -1 ); if ( luids.Contains( privilege )) { luid = ( Luid )luids[ privilege ]; privilegeLock.ReleaseReaderLock(); } else { privilegeLock.ReleaseReaderLock(); if ( false == Win32Native.LookupPrivilegeValue( null, privilege, ref luid )) { int error = Marshal.GetLastWin32Error(); if ( error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) { throw new OutOfMemoryException(); } else if ( error == Win32Native.ERROR_ACCESS_DENIED ) { throw new UnauthorizedAccessException(); } else if ( error == Win32Native.ERROR_NO_SUCH_PRIVILEGE ) { throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidPrivilegeName", privilege )); } else { Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "LookupPrivilegeValue() failed with unrecognized error code {0}", error )); throw new InvalidOperationException(); } } privilegeLock.AcquireWriterLock( -1 ); } } finally { if ( privilegeLock.IsReaderLockHeld ) { privilegeLock.ReleaseReaderLock(); } if ( privilegeLock.IsWriterLockHeld ) { if ( !luids.Contains( privilege )) { luids[ privilege ] = luid; privileges[ luid ] = privilege; } privilegeLock.ReleaseWriterLock(); } } return luid; } private sealed class TlsContents : IDisposable { private bool disposed = false; private int referenceCount = 1; [System.Security.SecurityCritical /*auto-generated*/] private SafeTokenHandle threadHandle = new SafeTokenHandle( IntPtr.Zero ); private bool isImpersonating = false; [System.Security.SecurityCritical /*auto-generated*/] private static SafeTokenHandle processHandle = new SafeTokenHandle( IntPtr.Zero ); private static readonly object syncRoot = new object(); #region Constructor and Finalizer [System.Security.SecuritySafeCritical] // auto-generated static TlsContents() { } [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] public TlsContents() { int error = 0; int cachingError = 0; bool success = true; if ( processHandle.IsInvalid) { lock( syncRoot ) { if ( processHandle.IsInvalid) { SafeTokenHandle localProcessHandle; if ( false == Win32Native.OpenProcessToken( Win32Native.GetCurrentProcess(), TokenAccessLevels.Duplicate, out localProcessHandle)) { cachingError = Marshal.GetLastWin32Error(); success = false; } processHandle = localProcessHandle; } } } RuntimeHelpers.PrepareConstrainedRegions(); try { // Make the sequence non-interruptible } finally { try { // // Open the thread token; if there is no thread token, get one from // the process token by impersonating self. // SafeTokenHandle threadHandleBefore = this.threadHandle; error = FCall.OpenThreadToken( TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges, WinSecurityContext.Process, out this.threadHandle ); unchecked { error &= ~(int)0x80070000; } if ( error != 0 ) { if ( success == true ) { this.threadHandle = threadHandleBefore; if ( error != Win32Native.ERROR_NO_TOKEN ) { success = false; } Contract.Assert( this.isImpersonating == false, "Incorrect isImpersonating state" ); if ( success == true ) { error = 0; if ( false == Win32Native.DuplicateTokenEx( processHandle, TokenAccessLevels.Impersonate | TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges, IntPtr.Zero, Win32Native.SECURITY_IMPERSONATION_LEVEL.Impersonation, System.Security.Principal.TokenType.TokenImpersonation, ref this.threadHandle )) { error = Marshal.GetLastWin32Error(); success = false; } } if ( success == true ) { error = FCall.SetThreadToken( this.threadHandle ); unchecked { error &= ~(int)0x80070000; } if ( error != 0 ) { success = false; } } if ( success == true ) { this.isImpersonating = true; } } else { error = cachingError; } } else { success = true; } } finally { if ( !success ) { Dispose(); } } } if ( error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) { throw new OutOfMemoryException(); } else if ( error == Win32Native.ERROR_ACCESS_DENIED || error == Win32Native.ERROR_CANT_OPEN_ANONYMOUS ) { throw new UnauthorizedAccessException(); } else if ( error != 0 ) { Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "WindowsIdentity.GetCurrentThreadToken() failed with unrecognized error code {0}", error )); throw new InvalidOperationException(); } } [System.Security.SecuritySafeCritical] ~TlsContents() { if ( !this.disposed ) { Dispose( false ); } } #endregion #region IDisposable implementation [System.Security.SecuritySafeCritical] // overrides public transparent member public void Dispose() { Dispose( true ); GC.SuppressFinalize( this ); } [System.Security.SecurityCritical] // auto-generated private void Dispose( bool disposing ) { if ( this.disposed ) return; if ( disposing ) { if ( this.threadHandle != null ) { this.threadHandle.Dispose(); this.threadHandle = null; } } if ( this.isImpersonating ) { FCall.RevertToSelf(); } this.disposed = true; } #endregion #region Reference Counting public void IncrementReferenceCount() { this.referenceCount++; } [System.Security.SecurityCritical] // auto-generated public int DecrementReferenceCount() { int result = --this.referenceCount; if ( result == 0 ) { Dispose(); } return result; } public int ReferenceCountValue { get { return this.referenceCount; } } #endregion #region Properties public SafeTokenHandle ThreadHandle { [System.Security.SecurityCritical] // auto-generated get { return this.threadHandle; } } public bool IsImpersonating { get { return this.isImpersonating; } } #endregion } #region Constructors [System.Security.SecurityCritical] // auto-generated public Privilege( string privilegeName ) { if ( privilegeName == null ) { throw new ArgumentNullException( "privilegeName" ); } Contract.EndContractBlock(); this.luid = LuidFromPrivilege( privilegeName ); } #endregion // // Finalizer simply ensures that the privilege was not leaked // [System.Security.SecuritySafeCritical] ~Privilege() { Contract.Assert( !this.needToRevert, "Must revert privileges that you alter!" ); if ( this.needToRevert ) { Revert(); } } #region Public interface [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] public void Enable() { this.ToggleState( true ); } public bool NeedToRevert { get { return this.needToRevert; } } #endregion // [SecurityPermission( SecurityAction.Demand, TogglePrivileges=true )] [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.AppDomain, ResourceScope.AppDomain | ResourceScope.Assembly)] private void ToggleState( bool enable ) { int error = 0; // // All privilege operations must take place on the same thread // if ( !this.currentThread.Equals( Thread.CurrentThread )) { throw new InvalidOperationException( Environment.GetResourceString( "InvalidOperation_MustBeSameThread" )); } // // This privilege was already altered and needs to be reverted before it can be altered again // if ( this.needToRevert ) { throw new InvalidOperationException( Environment.GetResourceString( "InvalidOperation_MustRevertPrivilege" )); } // // Need to make this block of code non-interruptible so that it would preserve // consistency of thread oken state even in the face of catastrophic exceptions // RuntimeHelpers.PrepareConstrainedRegions(); try { // // The payload is entirely in the finally block // This is how we ensure that the code will not be // interrupted by catastrophic exceptions // } finally { try { // // Retrieve TLS state // this.tlsContents = Thread.GetData( tlsSlot ) as TlsContents; if ( this.tlsContents == null ) { this.tlsContents = new TlsContents(); Thread.SetData( tlsSlot, this.tlsContents ); } else { this.tlsContents.IncrementReferenceCount(); } Win32Native.TOKEN_PRIVILEGE newState = new Win32Native.TOKEN_PRIVILEGE(); newState.PrivilegeCount = 1; newState.Privilege.Luid = this.luid; newState.Privilege.Attributes = enable ? Win32Native.SE_PRIVILEGE_ENABLED : Win32Native.SE_PRIVILEGE_DISABLED; Win32Native.TOKEN_PRIVILEGE previousState = new Win32Native.TOKEN_PRIVILEGE(); uint previousSize = 0; // // Place the new privilege on the thread token and remember the previous state. // if ( false == Win32Native.AdjustTokenPrivileges( this.tlsContents.ThreadHandle, false, ref newState, ( uint )Marshal.SizeOf( previousState ), ref previousState, ref previousSize )) { error = Marshal.GetLastWin32Error(); } else if ( Win32Native.ERROR_NOT_ALL_ASSIGNED == Marshal.GetLastWin32Error()) { error = Win32Native.ERROR_NOT_ALL_ASSIGNED; } else { // // This is the initial state that revert will have to go back to // this.initialState = (( previousState.Privilege.Attributes & Win32Native.SE_PRIVILEGE_ENABLED ) != 0 ); // // Remember whether state has changed at all // this.stateWasChanged = ( this.initialState != enable ); // // If we had to impersonate, or if the privilege state changed we'll need to revert // this.needToRevert = this.tlsContents.IsImpersonating || this.stateWasChanged; } } finally { if ( !this.needToRevert ) { this.Reset(); } } } if ( error == Win32Native.ERROR_NOT_ALL_ASSIGNED ) { throw new PrivilegeNotHeldException( privileges[this.luid] as string ); } if ( error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) { throw new OutOfMemoryException(); } else if ( error == Win32Native.ERROR_ACCESS_DENIED || error == Win32Native.ERROR_CANT_OPEN_ANONYMOUS ) { throw new UnauthorizedAccessException(); } else if ( error != 0 ) { Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "AdjustTokenPrivileges() failed with unrecognized error code {0}", error )); throw new InvalidOperationException(); } } // [SecurityPermission( SecurityAction.Demand, TogglePrivileges=true )] [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] public void Revert() { int error = 0; if ( !this.currentThread.Equals( Thread.CurrentThread )) { throw new InvalidOperationException( Environment.GetResourceString( "InvalidOperation_MustBeSameThread" )); } if ( !this.NeedToRevert ) { return; } // // This code must be eagerly prepared and non-interruptible. // RuntimeHelpers.PrepareConstrainedRegions(); try { // // The payload is entirely in the finally block // This is how we ensure that the code will not be // interrupted by catastrophic exceptions // } finally { bool success = true; try { // // Only call AdjustTokenPrivileges if we're not going to be reverting to self, // on this Revert, since doing the latter obliterates the thread token anyway // if ( this.stateWasChanged && ( this.tlsContents.ReferenceCountValue > 1 || !this.tlsContents.IsImpersonating )) { Win32Native.TOKEN_PRIVILEGE newState = new Win32Native.TOKEN_PRIVILEGE(); newState.PrivilegeCount = 1; newState.Privilege.Luid = this.luid; newState.Privilege.Attributes = ( this.initialState ? Win32Native.SE_PRIVILEGE_ENABLED : Win32Native.SE_PRIVILEGE_DISABLED ); Win32Native.TOKEN_PRIVILEGE previousState = new Win32Native.TOKEN_PRIVILEGE(); uint previousSize = 0; if ( false == Win32Native.AdjustTokenPrivileges( this.tlsContents.ThreadHandle, false, ref newState, ( uint )Marshal.SizeOf( previousState ), ref previousState, ref previousSize )) { error = Marshal.GetLastWin32Error(); success = false; } } } finally { if ( success ) { this.Reset(); } } } if ( error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) { throw new OutOfMemoryException(); } else if ( error == Win32Native.ERROR_ACCESS_DENIED ) { throw new UnauthorizedAccessException(); } else if ( error != 0 ) { Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "AdjustTokenPrivileges() failed with unrecognized error code {0}", error )); throw new InvalidOperationException(); } } #if false [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] public static void RunWithPrivilege( string privilege, bool enabled, PrivilegedHelper helper ) { if ( helper == null ) { throw new ArgumentNullException( "helper" ); } Contract.EndContractBlock(); Privilege p = new Privilege( privilege ); RuntimeHelpers.PrepareConstrainedRegions(); try { if (enabled) { p.Enable(); } else { p.Disable(); } helper(); } finally { p.Revert(); } } #endif [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.AppDomain, ResourceScope.AppDomain)] private void Reset() { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { this.stateWasChanged = false; this.initialState = false; this.needToRevert = false; if ( this.tlsContents != null ) { if ( 0 == this.tlsContents.DecrementReferenceCount()) { this.tlsContents = null; Thread.SetData( tlsSlot, null ); } } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** Class: Privilege ** ** Purpose: Managed wrapper for NT privileges. ** ** Date: July 1, 2004 ** ===========================================================*/ using Microsoft.Win32; using Microsoft.Win32.SafeHandles; using System.Collections; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.ConstrainedExecution; using System.Security.Permissions; using System.Security.Principal; using System.Threading; using System.Runtime.Versioning; using System.Diagnostics.Contracts; namespace System.Security.AccessControl { using CultureInfo = System.Globalization.CultureInfo; using FCall = System.Security.Principal.Win32; using Luid = Microsoft.Win32.Win32Native.LUID; #if false internal delegate void PrivilegedHelper(); #endif internal sealed class Privilege { private static LocalDataStoreSlot tlsSlot = Thread.AllocateDataSlot(); private static Hashtable privileges = new Hashtable(); private static Hashtable luids = new Hashtable(); private static ReaderWriterLock privilegeLock = new ReaderWriterLock(); private bool needToRevert = false; private bool initialState = false; private bool stateWasChanged = false; [System.Security.SecurityCritical /*auto-generated*/] private Luid luid; private readonly Thread currentThread = Thread.CurrentThread; private TlsContents tlsContents = null; public const string CreateToken = "SeCreateTokenPrivilege"; public const string AssignPrimaryToken = "SeAssignPrimaryTokenPrivilege"; public const string LockMemory = "SeLockMemoryPrivilege"; public const string IncreaseQuota = "SeIncreaseQuotaPrivilege"; public const string UnsolicitedInput = "SeUnsolicitedInputPrivilege"; public const string MachineAccount = "SeMachineAccountPrivilege"; public const string TrustedComputingBase = "SeTcbPrivilege"; public const string Security = "SeSecurityPrivilege"; public const string TakeOwnership = "SeTakeOwnershipPrivilege"; public const string LoadDriver = "SeLoadDriverPrivilege"; public const string SystemProfile = "SeSystemProfilePrivilege"; public const string SystemTime = "SeSystemtimePrivilege"; public const string ProfileSingleProcess = "SeProfileSingleProcessPrivilege"; public const string IncreaseBasePriority = "SeIncreaseBasePriorityPrivilege"; public const string CreatePageFile = "SeCreatePagefilePrivilege"; public const string CreatePermanent = "SeCreatePermanentPrivilege"; public const string Backup = "SeBackupPrivilege"; public const string Restore = "SeRestorePrivilege"; public const string Shutdown = "SeShutdownPrivilege"; public const string Debug = "SeDebugPrivilege"; public const string Audit = "SeAuditPrivilege"; public const string SystemEnvironment = "SeSystemEnvironmentPrivilege"; public const string ChangeNotify = "SeChangeNotifyPrivilege"; public const string RemoteShutdown = "SeRemoteShutdownPrivilege"; public const string Undock = "SeUndockPrivilege"; public const string SyncAgent = "SeSyncAgentPrivilege"; public const string EnableDelegation = "SeEnableDelegationPrivilege"; public const string ManageVolume = "SeManageVolumePrivilege"; public const string Impersonate = "SeImpersonatePrivilege"; public const string CreateGlobal = "SeCreateGlobalPrivilege"; public const string TrustedCredentialManagerAccess = "SeTrustedCredManAccessPrivilege"; public const string ReserveProcessor = "SeReserveProcessorPrivilege"; // // This routine is a wrapper around a hashtable containing mappings // of privilege names to LUIDs // [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] private static Luid LuidFromPrivilege( string privilege ) { Luid luid; luid.LowPart = 0; luid.HighPart = 0; // // Look up the privilege LUID inside the cache // RuntimeHelpers.PrepareConstrainedRegions(); try { privilegeLock.AcquireReaderLock( -1 ); if ( luids.Contains( privilege )) { luid = ( Luid )luids[ privilege ]; privilegeLock.ReleaseReaderLock(); } else { privilegeLock.ReleaseReaderLock(); if ( false == Win32Native.LookupPrivilegeValue( null, privilege, ref luid )) { int error = Marshal.GetLastWin32Error(); if ( error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) { throw new OutOfMemoryException(); } else if ( error == Win32Native.ERROR_ACCESS_DENIED ) { throw new UnauthorizedAccessException(); } else if ( error == Win32Native.ERROR_NO_SUCH_PRIVILEGE ) { throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidPrivilegeName", privilege )); } else { Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "LookupPrivilegeValue() failed with unrecognized error code {0}", error )); throw new InvalidOperationException(); } } privilegeLock.AcquireWriterLock( -1 ); } } finally { if ( privilegeLock.IsReaderLockHeld ) { privilegeLock.ReleaseReaderLock(); } if ( privilegeLock.IsWriterLockHeld ) { if ( !luids.Contains( privilege )) { luids[ privilege ] = luid; privileges[ luid ] = privilege; } privilegeLock.ReleaseWriterLock(); } } return luid; } private sealed class TlsContents : IDisposable { private bool disposed = false; private int referenceCount = 1; [System.Security.SecurityCritical /*auto-generated*/] private SafeTokenHandle threadHandle = new SafeTokenHandle( IntPtr.Zero ); private bool isImpersonating = false; [System.Security.SecurityCritical /*auto-generated*/] private static SafeTokenHandle processHandle = new SafeTokenHandle( IntPtr.Zero ); private static readonly object syncRoot = new object(); #region Constructor and Finalizer [System.Security.SecuritySafeCritical] // auto-generated static TlsContents() { } [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] public TlsContents() { int error = 0; int cachingError = 0; bool success = true; if ( processHandle.IsInvalid) { lock( syncRoot ) { if ( processHandle.IsInvalid) { SafeTokenHandle localProcessHandle; if ( false == Win32Native.OpenProcessToken( Win32Native.GetCurrentProcess(), TokenAccessLevels.Duplicate, out localProcessHandle)) { cachingError = Marshal.GetLastWin32Error(); success = false; } processHandle = localProcessHandle; } } } RuntimeHelpers.PrepareConstrainedRegions(); try { // Make the sequence non-interruptible } finally { try { // // Open the thread token; if there is no thread token, get one from // the process token by impersonating self. // SafeTokenHandle threadHandleBefore = this.threadHandle; error = FCall.OpenThreadToken( TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges, WinSecurityContext.Process, out this.threadHandle ); unchecked { error &= ~(int)0x80070000; } if ( error != 0 ) { if ( success == true ) { this.threadHandle = threadHandleBefore; if ( error != Win32Native.ERROR_NO_TOKEN ) { success = false; } Contract.Assert( this.isImpersonating == false, "Incorrect isImpersonating state" ); if ( success == true ) { error = 0; if ( false == Win32Native.DuplicateTokenEx( processHandle, TokenAccessLevels.Impersonate | TokenAccessLevels.Query | TokenAccessLevels.AdjustPrivileges, IntPtr.Zero, Win32Native.SECURITY_IMPERSONATION_LEVEL.Impersonation, System.Security.Principal.TokenType.TokenImpersonation, ref this.threadHandle )) { error = Marshal.GetLastWin32Error(); success = false; } } if ( success == true ) { error = FCall.SetThreadToken( this.threadHandle ); unchecked { error &= ~(int)0x80070000; } if ( error != 0 ) { success = false; } } if ( success == true ) { this.isImpersonating = true; } } else { error = cachingError; } } else { success = true; } } finally { if ( !success ) { Dispose(); } } } if ( error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) { throw new OutOfMemoryException(); } else if ( error == Win32Native.ERROR_ACCESS_DENIED || error == Win32Native.ERROR_CANT_OPEN_ANONYMOUS ) { throw new UnauthorizedAccessException(); } else if ( error != 0 ) { Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "WindowsIdentity.GetCurrentThreadToken() failed with unrecognized error code {0}", error )); throw new InvalidOperationException(); } } [System.Security.SecuritySafeCritical] ~TlsContents() { if ( !this.disposed ) { Dispose( false ); } } #endregion #region IDisposable implementation [System.Security.SecuritySafeCritical] // overrides public transparent member public void Dispose() { Dispose( true ); GC.SuppressFinalize( this ); } [System.Security.SecurityCritical] // auto-generated private void Dispose( bool disposing ) { if ( this.disposed ) return; if ( disposing ) { if ( this.threadHandle != null ) { this.threadHandle.Dispose(); this.threadHandle = null; } } if ( this.isImpersonating ) { FCall.RevertToSelf(); } this.disposed = true; } #endregion #region Reference Counting public void IncrementReferenceCount() { this.referenceCount++; } [System.Security.SecurityCritical] // auto-generated public int DecrementReferenceCount() { int result = --this.referenceCount; if ( result == 0 ) { Dispose(); } return result; } public int ReferenceCountValue { get { return this.referenceCount; } } #endregion #region Properties public SafeTokenHandle ThreadHandle { [System.Security.SecurityCritical] // auto-generated get { return this.threadHandle; } } public bool IsImpersonating { get { return this.isImpersonating; } } #endregion } #region Constructors [System.Security.SecurityCritical] // auto-generated public Privilege( string privilegeName ) { if ( privilegeName == null ) { throw new ArgumentNullException( "privilegeName" ); } Contract.EndContractBlock(); this.luid = LuidFromPrivilege( privilegeName ); } #endregion // // Finalizer simply ensures that the privilege was not leaked // [System.Security.SecuritySafeCritical] ~Privilege() { Contract.Assert( !this.needToRevert, "Must revert privileges that you alter!" ); if ( this.needToRevert ) { Revert(); } } #region Public interface [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] public void Enable() { this.ToggleState( true ); } public bool NeedToRevert { get { return this.needToRevert; } } #endregion // [SecurityPermission( SecurityAction.Demand, TogglePrivileges=true )] [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.AppDomain, ResourceScope.AppDomain | ResourceScope.Assembly)] private void ToggleState( bool enable ) { int error = 0; // // All privilege operations must take place on the same thread // if ( !this.currentThread.Equals( Thread.CurrentThread )) { throw new InvalidOperationException( Environment.GetResourceString( "InvalidOperation_MustBeSameThread" )); } // // This privilege was already altered and needs to be reverted before it can be altered again // if ( this.needToRevert ) { throw new InvalidOperationException( Environment.GetResourceString( "InvalidOperation_MustRevertPrivilege" )); } // // Need to make this block of code non-interruptible so that it would preserve // consistency of thread oken state even in the face of catastrophic exceptions // RuntimeHelpers.PrepareConstrainedRegions(); try { // // The payload is entirely in the finally block // This is how we ensure that the code will not be // interrupted by catastrophic exceptions // } finally { try { // // Retrieve TLS state // this.tlsContents = Thread.GetData( tlsSlot ) as TlsContents; if ( this.tlsContents == null ) { this.tlsContents = new TlsContents(); Thread.SetData( tlsSlot, this.tlsContents ); } else { this.tlsContents.IncrementReferenceCount(); } Win32Native.TOKEN_PRIVILEGE newState = new Win32Native.TOKEN_PRIVILEGE(); newState.PrivilegeCount = 1; newState.Privilege.Luid = this.luid; newState.Privilege.Attributes = enable ? Win32Native.SE_PRIVILEGE_ENABLED : Win32Native.SE_PRIVILEGE_DISABLED; Win32Native.TOKEN_PRIVILEGE previousState = new Win32Native.TOKEN_PRIVILEGE(); uint previousSize = 0; // // Place the new privilege on the thread token and remember the previous state. // if ( false == Win32Native.AdjustTokenPrivileges( this.tlsContents.ThreadHandle, false, ref newState, ( uint )Marshal.SizeOf( previousState ), ref previousState, ref previousSize )) { error = Marshal.GetLastWin32Error(); } else if ( Win32Native.ERROR_NOT_ALL_ASSIGNED == Marshal.GetLastWin32Error()) { error = Win32Native.ERROR_NOT_ALL_ASSIGNED; } else { // // This is the initial state that revert will have to go back to // this.initialState = (( previousState.Privilege.Attributes & Win32Native.SE_PRIVILEGE_ENABLED ) != 0 ); // // Remember whether state has changed at all // this.stateWasChanged = ( this.initialState != enable ); // // If we had to impersonate, or if the privilege state changed we'll need to revert // this.needToRevert = this.tlsContents.IsImpersonating || this.stateWasChanged; } } finally { if ( !this.needToRevert ) { this.Reset(); } } } if ( error == Win32Native.ERROR_NOT_ALL_ASSIGNED ) { throw new PrivilegeNotHeldException( privileges[this.luid] as string ); } if ( error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) { throw new OutOfMemoryException(); } else if ( error == Win32Native.ERROR_ACCESS_DENIED || error == Win32Native.ERROR_CANT_OPEN_ANONYMOUS ) { throw new UnauthorizedAccessException(); } else if ( error != 0 ) { Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "AdjustTokenPrivileges() failed with unrecognized error code {0}", error )); throw new InvalidOperationException(); } } // [SecurityPermission( SecurityAction.Demand, TogglePrivileges=true )] [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] public void Revert() { int error = 0; if ( !this.currentThread.Equals( Thread.CurrentThread )) { throw new InvalidOperationException( Environment.GetResourceString( "InvalidOperation_MustBeSameThread" )); } if ( !this.NeedToRevert ) { return; } // // This code must be eagerly prepared and non-interruptible. // RuntimeHelpers.PrepareConstrainedRegions(); try { // // The payload is entirely in the finally block // This is how we ensure that the code will not be // interrupted by catastrophic exceptions // } finally { bool success = true; try { // // Only call AdjustTokenPrivileges if we're not going to be reverting to self, // on this Revert, since doing the latter obliterates the thread token anyway // if ( this.stateWasChanged && ( this.tlsContents.ReferenceCountValue > 1 || !this.tlsContents.IsImpersonating )) { Win32Native.TOKEN_PRIVILEGE newState = new Win32Native.TOKEN_PRIVILEGE(); newState.PrivilegeCount = 1; newState.Privilege.Luid = this.luid; newState.Privilege.Attributes = ( this.initialState ? Win32Native.SE_PRIVILEGE_ENABLED : Win32Native.SE_PRIVILEGE_DISABLED ); Win32Native.TOKEN_PRIVILEGE previousState = new Win32Native.TOKEN_PRIVILEGE(); uint previousSize = 0; if ( false == Win32Native.AdjustTokenPrivileges( this.tlsContents.ThreadHandle, false, ref newState, ( uint )Marshal.SizeOf( previousState ), ref previousState, ref previousSize )) { error = Marshal.GetLastWin32Error(); success = false; } } } finally { if ( success ) { this.Reset(); } } } if ( error == Win32Native.ERROR_NOT_ENOUGH_MEMORY ) { throw new OutOfMemoryException(); } else if ( error == Win32Native.ERROR_ACCESS_DENIED ) { throw new UnauthorizedAccessException(); } else if ( error != 0 ) { Contract.Assert( false, string.Format( CultureInfo.InvariantCulture, "AdjustTokenPrivileges() failed with unrecognized error code {0}", error )); throw new InvalidOperationException(); } } #if false [ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )] public static void RunWithPrivilege( string privilege, bool enabled, PrivilegedHelper helper ) { if ( helper == null ) { throw new ArgumentNullException( "helper" ); } Contract.EndContractBlock(); Privilege p = new Privilege( privilege ); RuntimeHelpers.PrepareConstrainedRegions(); try { if (enabled) { p.Enable(); } else { p.Disable(); } helper(); } finally { p.Revert(); } } #endif [System.Security.SecurityCritical] // auto-generated [ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )] [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.AppDomain, ResourceScope.AppDomain)] private void Reset() { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { this.stateWasChanged = false; this.initialState = false; this.needToRevert = false; if ( this.tlsContents != null ) { if ( 0 == this.tlsContents.DecrementReferenceCount()) { this.tlsContents = null; Thread.SetData( tlsSlot, null ); } } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- QuotedPrintableStream.cs
- FieldToken.cs
- SystemException.cs
- ComponentManagerBroker.cs
- FormViewInsertedEventArgs.cs
- ItemsControlAutomationPeer.cs
- Context.cs
- Viewport3DAutomationPeer.cs
- ResetableIterator.cs
- FrameworkReadOnlyPropertyMetadata.cs
- StyleSelector.cs
- Substitution.cs
- PriorityChain.cs
- HotSpotCollection.cs
- TextElement.cs
- WebDescriptionAttribute.cs
- DTCTransactionManager.cs
- BitmapEffectGroup.cs
- XamlInt32CollectionSerializer.cs
- TraceLevelHelper.cs
- Bezier.cs
- ColorTransformHelper.cs
- SplitterPanel.cs
- DragStartedEventArgs.cs
- RectAnimationClockResource.cs
- OpenFileDialog.cs
- QueryInterceptorAttribute.cs
- EventDriven.cs
- ActivityExecutionContextCollection.cs
- ApplyImportsAction.cs
- BasePattern.cs
- CorrelationRequestContext.cs
- NetworkInformationException.cs
- GACIdentityPermission.cs
- UnaryQueryOperator.cs
- ReverseComparer.cs
- MatrixKeyFrameCollection.cs
- ShadowGlyph.cs
- TimeSpanMinutesOrInfiniteConverter.cs
- HtmlContainerControl.cs
- Compiler.cs
- SecurityContext.cs
- TypeExtensionConverter.cs
- NamespaceEmitter.cs
- WindowsFormsEditorServiceHelper.cs
- WsdlInspector.cs
- HatchBrush.cs
- HuffCodec.cs
- DeferredReference.cs
- DataGridHelper.cs
- _UncName.cs
- Fx.cs
- MouseGestureConverter.cs
- TextBox.cs
- DeviceSpecificChoiceCollection.cs
- IndexerHelper.cs
- RegexFCD.cs
- IndexedSelectQueryOperator.cs
- NativeMethods.cs
- ZoneIdentityPermission.cs
- MissingManifestResourceException.cs
- Panel.cs
- XPathSelectionIterator.cs
- LinkTarget.cs
- RecordBuilder.cs
- LabelLiteral.cs
- Ops.cs
- BaseTemplateCodeDomTreeGenerator.cs
- IteratorFilter.cs
- XmlBinaryWriterSession.cs
- AspNetSynchronizationContext.cs
- CodeMethodInvokeExpression.cs
- ExternalCalls.cs
- Object.cs
- ClusterSafeNativeMethods.cs
- CodeGeneratorOptions.cs
- HostedImpersonationContext.cs
- HttpException.cs
- CodeLabeledStatement.cs
- RoleManagerModule.cs
- BamlStream.cs
- UriExt.cs
- HTMLTextWriter.cs
- Table.cs
- ToolStripStatusLabel.cs
- ParseNumbers.cs
- CacheHelper.cs
- TypeLibConverter.cs
- TransformPatternIdentifiers.cs
- DriveNotFoundException.cs
- ListViewAutomationPeer.cs
- IdentifierService.cs
- UserPreferenceChangedEventArgs.cs
- ResourceSet.cs
- CommandID.cs
- DrawingContextWalker.cs
- datacache.cs
- DataGridCellsPanel.cs
- OperationAbortedException.cs
- HashJoinQueryOperatorEnumerator.cs