Search code examples
c#dllimportimpersonation

Impersonate local user on another machine


I need to log on my controller to another machine and copy a file on it; I have to use a local user on the remote machine.

Currently I'm using this code:

    private Impersonate(bool active, string domain, string username, string password, LogonType logonType)
    {
        if (active)
        {
            IntPtr handle;
            var ok = NativeMethods.LogonUser(username, domain, password, (int)logonType, 0, out handle);
            if (!ok)
            {
                var errorCode = Marshal.GetLastWin32Error();
                throw new ApplicationException(string.Format("Could not impersonate the elevated user.  LogonUser returned error code {0}.", errorCode));
            }

            _handle = new SafeTokenHandle(handle);
            _context = WindowsIdentity.Impersonate(_handle.DangerousGetHandle());
        }
    }

passing these args:

    using (Impersonate.LogonUser(true,
        ".",
        "todev1.domain.com\admin",
        "Test123_",
        LogonType.Interactive))
    {

    }  

and this win API:

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

I checked this Q/A Using advapi32.dll:LogonUserA() to impersonate a remote machine's local user but the solution provided is not working.

I tried to pass multiple values to the method as domain, user and so on, but I can't find the rigth solution. I tried using NewCredentials but it returns always ok even if not logged.


Solution

  • I finally solved this issue, without the need to add the user to each machine that will impersonate to the remote machine.

    It's correct to use NewCredential, but using the WINNT50 LogonProvider.

    So my impersonate method now is like:

     private Impersonate(bool active, string domain, string username, string password, LogonType logonType, LogonProvider logonProvider)
            {
                if (active)
                {
                    IntPtr handle;
                    var ok = NativeMethods.LogonUser(username, domain, password, (int)logonType, (int)logonProvider, out handle);
                    if (!ok)
                    {
                        var errorCode = Marshal.GetLastWin32Error();
                        throw new ApplicationException(string.Format("Could not impersonate the elevated user.  LogonUser returned error code {0}.", errorCode));
                    }
    
                    _handle = new SafeTokenHandle(handle);
                    _context = WindowsIdentity.Impersonate(_handle.DangerousGetHandle());
                }
            }
    

    Then I call the Impersonate method using the code:

    using (Impersonate.LogonUser(true,
        "todev1.domain.com",
        "admin",
        "Test123_",
        LogonType.NewCredentials,
        LogonProvider.WinNT50))
    {
    
    }