Advertisement
uwekeim

Impersonator.cs

Mar 18th, 2024 (edited)
799
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.59 KB | None | 0 0
  1. namespace Tools;
  2.  
  3. using Microsoft.Win32.SafeHandles;
  4. using System.Runtime.InteropServices;
  5. using System.Security.Principal;
  6.  
  7. /// <summary>
  8. /// Impersonation of a user. Allows to execute code under another
  9. /// user context.
  10. /// The account that instantiates the Impersonator class
  11. /// needs to have the 'Act as part of operating system' privilege set.
  12. /// </summary>
  13. /// <remarks>
  14. /// This class is based on the information in the Microsoft knowledge base
  15. /// article http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158
  16. /// Encapsulate an instance into a using-directive like e.g.:
  17. /// ...
  18. /// new Impersonator( "myUsername", "myDomainname", "myPassword" ).RunImpersonated(
  19. ///     true,
  20. ///     () => {
  21. ///         ...
  22. ///         [code that executes under the new context]
  23. ///         ...
  24. ///     });
  25. /// ...
  26. /// </remarks>
  27. [PublicAPI]
  28. public sealed class Impersonator(
  29.     string? userName,
  30.     string? domainName,
  31.     string? password)
  32. {
  33.     // https://docs.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.runimpersonated
  34.  
  35.     private const int LOGON32_PROVIDER_DEFAULT = 0;
  36.     private const int LOGON32_LOGON_INTERACTIVE = 2;
  37.  
  38.     public T RunImpersonated<T>(bool active, Func<T> func)
  39.     {
  40.         if (active)
  41.         {
  42.             var r = LogonUser(
  43.                 userName ?? string.Empty,
  44.                 domainName ?? string.Empty,
  45.                 password ?? string.Empty,
  46.                 LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
  47.                 out var safeAccessTokenHandle);
  48.  
  49.             if (r && safeAccessTokenHandle != null)
  50.             {
  51.                 try
  52.                 {
  53. #pragma warning disable CA1416 // Validate platform compatibility
  54.                     return WindowsIdentity.RunImpersonated(safeAccessTokenHandle, func);
  55. #pragma warning restore CA1416 // Validate platform compatibility
  56.                 }
  57.                 finally
  58.                 {
  59.                     safeAccessTokenHandle.Dispose();
  60.                 }
  61.             }
  62.             else
  63.             {
  64.                 var ret = Marshal.GetLastWin32Error();
  65.                 throw new Win32Exception(ret);
  66.             }
  67.         }
  68.         else
  69.         {
  70.             return func();
  71.         }
  72.     }
  73.  
  74.     public async Task<T> RunImpersonatedAsync<T>(bool active, Func<Task<T>> func)
  75.     {
  76.         if (active)
  77.         {
  78.             var r = LogonUser(
  79.                 userName ?? string.Empty, domainName ?? string.Empty, password ?? string.Empty,
  80.                 LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
  81.                 out var safeAccessTokenHandle);
  82.  
  83.             if (r && safeAccessTokenHandle != null)
  84.             {
  85.                 try
  86.                 {
  87. #pragma warning disable CA1416 // Validate platform compatibility
  88.                     return await WindowsIdentity.RunImpersonatedAsync(safeAccessTokenHandle, func);
  89. #pragma warning restore CA1416 // Validate platform compatibility
  90.                 }
  91.                 finally
  92.                 {
  93.                     safeAccessTokenHandle.Dispose();
  94.                 }
  95.             }
  96.             else
  97.             {
  98.                 var ret = Marshal.GetLastWin32Error();
  99.                 throw new Win32Exception(ret);
  100.             }
  101.         }
  102.         else
  103.         {
  104.             return await func();
  105.         }
  106.     }
  107.  
  108.     public void RunImpersonated(bool active, Action action)
  109.     {
  110.         if (active)
  111.         {
  112.             var r = LogonUser(
  113.                 userName ?? string.Empty,
  114.                 domainName ?? string.Empty,
  115.                 password ?? string.Empty,
  116.                 LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
  117.                 out var safeAccessTokenHandle);
  118.  
  119.             if (r && safeAccessTokenHandle != null)
  120.             {
  121.                 try
  122.                 {
  123. #pragma warning disable CA1416 // Validate platform compatibility
  124.                     WindowsIdentity.RunImpersonated(safeAccessTokenHandle, action);
  125. #pragma warning restore CA1416 // Validate platform compatibility
  126.                 }
  127.                 finally
  128.                 {
  129.                     safeAccessTokenHandle.Dispose();
  130.                 }
  131.             }
  132.             else
  133.             {
  134.                 var ret = Marshal.GetLastWin32Error();
  135.                 throw new Win32Exception(ret);
  136.             }
  137.         }
  138.         else
  139.         {
  140.             action();
  141.         }
  142.     }
  143.  
  144.     public async Task RunImpersonatedAsync(bool active, Func<Task> action)
  145.     {
  146.         if (active)
  147.         {
  148.             var r = LogonUser(
  149.                 userName ?? string.Empty,
  150.                 domainName ?? string.Empty,
  151.                 password ?? string.Empty,
  152.                 LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
  153.                 out var safeAccessTokenHandle);
  154.  
  155.             if (r && safeAccessTokenHandle != null)
  156.             {
  157.                 try
  158.                 {
  159. #pragma warning disable CA1416 // Validate platform compatibility
  160.                     await WindowsIdentity.RunImpersonatedAsync(safeAccessTokenHandle, action);
  161. #pragma warning restore CA1416 // Validate platform compatibility
  162.                 }
  163.                 finally
  164.                 {
  165.                     safeAccessTokenHandle.Dispose();
  166.                 }
  167.             }
  168.             else
  169.             {
  170.                 var ret = Marshal.GetLastWin32Error();
  171.                 throw new Win32Exception(ret);
  172.             }
  173.         }
  174.         else
  175.         {
  176.             await action();
  177.         }
  178.     }
  179.  
  180.     [DllImport(@"advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  181.     public static extern bool LogonUser(
  182.         string lpszUsername,
  183.         string lpszDomain,
  184.         string lpszPassword,
  185.         int dwLogonType,
  186.         int dwLogonProvider,
  187.         out SafeAccessTokenHandle? phToken);
  188. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement