AnonymousImpersonation.cs 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // Copyright (c) .NET Foundation. All rights reserved.
  2. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  3. #if NET451
  4. using System;
  5. using System.Runtime.ConstrainedExecution;
  6. using System.Runtime.InteropServices;
  7. using Microsoft.AspNetCore.Cryptography;
  8. using Microsoft.Win32.SafeHandles;
  9. namespace Microsoft.AspNetCore.DataProtection
  10. {
  11. /// <summary>
  12. /// Helpers for working with the anonymous Windows identity.
  13. /// </summary>
  14. internal static class AnonymousImpersonation
  15. {
  16. /// <summary>
  17. /// Performs an action while impersonated under the anonymous user (NT AUTHORITY\ANONYMOUS LOGIN).
  18. /// </summary>
  19. public static void Run(Action callback)
  20. {
  21. using (var threadHandle = ThreadHandle.OpenCurrentThreadHandle())
  22. {
  23. bool impersonated = false;
  24. try
  25. {
  26. impersonated = ImpersonateAnonymousToken(threadHandle);
  27. if (!impersonated)
  28. {
  29. Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
  30. }
  31. callback();
  32. }
  33. finally
  34. {
  35. if (impersonated && !RevertToSelf())
  36. {
  37. Environment.FailFast("RevertToSelf() returned false!");
  38. }
  39. }
  40. }
  41. }
  42. [DllImport("advapi32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
  43. private static extern bool ImpersonateAnonymousToken([In] ThreadHandle ThreadHandle);
  44. [DllImport("advapi32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
  45. private static extern bool RevertToSelf();
  46. private sealed class ThreadHandle : SafeHandleZeroOrMinusOneIsInvalid
  47. {
  48. private ThreadHandle()
  49. : base(ownsHandle: true)
  50. {
  51. }
  52. public static ThreadHandle OpenCurrentThreadHandle()
  53. {
  54. const int THREAD_ALL_ACCESS = 0x1FFFFF;
  55. var handle = OpenThread(
  56. dwDesiredAccess: THREAD_ALL_ACCESS,
  57. bInheritHandle: false,
  58. #pragma warning disable CS0618 // Type or member is obsolete
  59. dwThreadId: (uint)AppDomain.GetCurrentThreadId());
  60. #pragma warning restore CS0618 // Type or member is obsolete
  61. CryptoUtil.AssertSafeHandleIsValid(handle);
  62. return handle;
  63. }
  64. protected override bool ReleaseHandle()
  65. {
  66. return CloseHandle(handle);
  67. }
  68. [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  69. [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
  70. private static extern bool CloseHandle(
  71. [In] IntPtr hObject);
  72. [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
  73. private static extern ThreadHandle OpenThread(
  74. [In] uint dwDesiredAccess,
  75. [In] bool bInheritHandle,
  76. [In] uint dwThreadId);
  77. }
  78. }
  79. }
  80. #endif