uwekeim icon

Impersonator.cs

uwekeim | PRO | 03/18/24 10:18:03 AM UTC (Edited) | 0 ⭐ | 13948 👁️ | Never ⏰ | [windows, Impersonate]
C# |

4.59 KB

|

None

|

0 👍

/

0 👎

namespace Tools;
 
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.Security.Principal;
 
/// <summary>
/// Impersonation of a user. Allows to execute code under another
/// user context.
/// The account that instantiates the Impersonator class
/// needs to have the 'Act as part of operating system' privilege set.
/// </summary>
/// <remarks>
/// This class is based on the information in the Microsoft knowledge base
/// article http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158
/// Encapsulate an instance into a using-directive like e.g.:
/// ...
/// new Impersonator( "myUsername", "myDomainname", "myPassword" ).RunImpersonated(
///     true,
///     () => {
///         ...
///         [code that executes under the new context]
///         ...
///     });
/// ...
/// </remarks>
[PublicAPI]
public sealed class Impersonator(
    string? userName,
    string? domainName,
    string? password)
{
    // https://docs.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.runimpersonated
 
    private const int LOGON32_PROVIDER_DEFAULT = 0;
    private const int LOGON32_LOGON_INTERACTIVE = 2;
 
    public T RunImpersonated<T>(bool active, Func<T> func)
    {
        if (active)
        {
            var r = LogonUser(
                userName ?? string.Empty,
                domainName ?? string.Empty,
                password ?? string.Empty,
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                out var safeAccessTokenHandle);
 
            if (r && safeAccessTokenHandle != null)
            {
                try
                {
#pragma warning disable CA1416 // Validate platform compatibility
                    return WindowsIdentity.RunImpersonated(safeAccessTokenHandle, func);
#pragma warning restore CA1416 // Validate platform compatibility
                }
                finally
                {
                    safeAccessTokenHandle.Dispose();
                }
            }
            else
            {
                var ret = Marshal.GetLastWin32Error();
                throw new Win32Exception(ret);
            }
        }
        else
        {
            return func();
        }
    }
 
    public async Task<T> RunImpersonatedAsync<T>(bool active, Func<Task<T>> func)
    {
        if (active)
        {
            var r = LogonUser(
                userName ?? string.Empty, domainName ?? string.Empty, password ?? string.Empty,
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                out var safeAccessTokenHandle);
 
            if (r && safeAccessTokenHandle != null)
            {
                try
                {
#pragma warning disable CA1416 // Validate platform compatibility
                    return await WindowsIdentity.RunImpersonatedAsync(safeAccessTokenHandle, func);
#pragma warning restore CA1416 // Validate platform compatibility
                }
                finally
                {
                    safeAccessTokenHandle.Dispose();
                }
            }
            else
            {
                var ret = Marshal.GetLastWin32Error();
                throw new Win32Exception(ret);
            }
        }
        else
        {
            return await func();
        }
    }
 
    public void RunImpersonated(bool active, Action action)
    {
        if (active)
        {
            var r = LogonUser(
                userName ?? string.Empty,
                domainName ?? string.Empty,
                password ?? string.Empty,
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                out var safeAccessTokenHandle);
 
            if (r && safeAccessTokenHandle != null)
            {
                try
                {
#pragma warning disable CA1416 // Validate platform compatibility
                    WindowsIdentity.RunImpersonated(safeAccessTokenHandle, action);
#pragma warning restore CA1416 // Validate platform compatibility
                }
                finally
                {
                    safeAccessTokenHandle.Dispose();
                }
            }
            else
            {
                var ret = Marshal.GetLastWin32Error();
                throw new Win32Exception(ret);
            }
        }
        else
        {
            action();
        }
    }
 
    public async Task RunImpersonatedAsync(bool active, Func<Task> action)
    {
        if (active)
        {
            var r = LogonUser(
                userName ?? string.Empty,
                domainName ?? string.Empty,
                password ?? string.Empty,
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                out var safeAccessTokenHandle);
 
            if (r && safeAccessTokenHandle != null)
            {
                try
                {
#pragma warning disable CA1416 // Validate platform compatibility
                    await WindowsIdentity.RunImpersonatedAsync(safeAccessTokenHandle, action);
#pragma warning restore CA1416 // Validate platform compatibility
                }
                finally
                {
                    safeAccessTokenHandle.Dispose();
                }
            }
            else
            {
                var ret = Marshal.GetLastWin32Error();
                throw new Win32Exception(ret);
            }
        }
        else
        {
            await action();
        }
    }
 
    [DllImport(@"advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        out SafeAccessTokenHandle? phToken);
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎