Example #1
0
 internal static extern bool AdjustTokenPrivileges(
     [In]     SafeTokenHandle TokenHandle,
     [In]     bool DisableAllPrivileges,
     [In]     ref TOKEN_PRIVILEGE NewState,
     [In]     uint BufferLength,
     [In, Out] ref TOKEN_PRIVILEGE PreviousState,
     [In, Out] ref uint ReturnLength);
Example #2
0
        public void Revert()
        {
            var error = 0;

            //
            // All privilege operations must take place on the same thread
            //

            if (!this.currentThread.Equals(Thread.CurrentThread))
            {
                throw new InvalidOperationException("Operation must take place on the thread that created the object");
            }

            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 {
                var 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))
                    {
                        var newState = new TOKEN_PRIVILEGE {
                            PrivilegeCount = 1,
                            Privilege      =
                            {
                                Luid = this.luid, Attributes = this.initialState ? NativeMethods.SE_PRIVILEGE_ENABLED : NativeMethods.SE_PRIVILEGE_DISABLED
                            }
                        };

                        var    previousState = new TOKEN_PRIVILEGE();
                        UInt32 previousSize  = 0;

                        if (!NativeMethods.AdjustTokenPrivileges(this.tlsContents.ThreadHandle, false, ref newState, ( UInt32 )Marshal.SizeOf(previousState),
                                                                 ref previousState, ref previousSize))
                        {
                            error   = Marshal.GetLastWin32Error();
                            success = false;
                        }
                    }
                }
                finally {
                    if (success)
                    {
                        this.Reset();
                    }
                }
            }

            switch (error)
            {
            case NativeMethods.ERROR_NOT_ENOUGH_MEMORY: throw new OutOfMemoryException();

            case NativeMethods.ERROR_ACCESS_DENIED: throw new UnauthorizedAccessException("Caller does not have the permission to change the privilege");
            }

            if (error != 0)
            {
                throw new Win32Exception(error);
            }
        }
Example #3
0
 public static extern Boolean AdjustTokenPrivileges([In] SafeTokenHandle TokenHandle, [In] Boolean DisableAllPrivileges, [In] ref TOKEN_PRIVILEGE NewState,
                                                    [In] DWORD BufferLength, [In][Out] ref TOKEN_PRIVILEGE PreviousState, [In][Out] ref DWORD ReturnLength);
Example #4
0
        private void ToggleState(Boolean enable)
        {
            var error = 0;

            //
            // All privilege operations must take place on the same thread
            //

            if (!this.currentThread.Equals(Thread.CurrentThread))
            {
                throw new InvalidOperationException("Operation must take place on the thread that created the object");
            }

            //
            // This privilege was already altered and needs to be reverted before it can be altered again
            //

            if (this.NeedToRevert)
            {
                throw new InvalidOperationException("Must revert the privilege prior to attempting this operation");
            }

            //
            // 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();
                    }

                    var newState = new TOKEN_PRIVILEGE {
                        PrivilegeCount = 1,
                        Privilege      =
                        {
                            Luid = this.luid, Attributes = enable ? NativeMethods.SE_PRIVILEGE_ENABLED : NativeMethods.SE_PRIVILEGE_DISABLED
                        }
                    };

                    var    previousState = new TOKEN_PRIVILEGE();
                    UInt32 previousSize  = 0;

                    //
                    // Place the new privilege on the thread token and remember the previous state.
                    //

                    if (!NativeMethods.AdjustTokenPrivileges(this.tlsContents.ThreadHandle, false, ref newState, ( UInt32 )Marshal.SizeOf(previousState),
                                                             ref previousState, ref previousSize))
                    {
                        error = Marshal.GetLastWin32Error();
                    }
                    else if (NativeMethods.ERROR_NOT_ALL_ASSIGNED == Marshal.GetLastWin32Error())
                    {
                        error = NativeMethods.ERROR_NOT_ALL_ASSIGNED;
                    }
                    else
                    {
                        //
                        // This is the initial state that revert will have to go back to
                        //

                        this.initialState = (previousState.Privilege.Attributes & NativeMethods.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();
                    }
                }
            }

            switch (error)
            {
            case NativeMethods.ERROR_NOT_ALL_ASSIGNED: throw new PrivilegeNotHeldException(privileges[this.luid] as String);

            case NativeMethods.ERROR_NOT_ENOUGH_MEMORY: throw new OutOfMemoryException();

            case NativeMethods.ERROR_ACCESS_DENIED:
            case NativeMethods.ERROR_CANT_OPEN_ANONYMOUS:
                throw new UnauthorizedAccessException("The caller does not have the right to change the privilege");
            }

            if (error != 0)
            {
                throw new Win32Exception(error);
            }
        }