3

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.

Community
  • 1
  • 1
Irvin Dominin
  • 30,819
  • 9
  • 77
  • 111

2 Answers2

7

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))
{

}
Irvin Dominin
  • 30,819
  • 9
  • 77
  • 111
  • LOGON32_PROVIDER_WINNT50 alone does not work for me. I even tried several logon types. I still get "The user or password is incorrect" when trying to access a remote folder with a user that is local on the remote machine. LOGON32_PROVIDER_WINNT50 does the same as LOGON32_PROVIDER_DEFAULT anyway if a domain is passed (according to the documentation). If your code really works, there must be something else that is not visible in the code you shared. Could you please share the whole code and the invocation? – Jürgen Bayer Aug 24 '17 at 18:11
  • @JürgenBayer added the code to use the impersonate method, with that code is working fine – Irvin Dominin Aug 25 '17 at 08:06
0

You can try to make a local user on your local machine with the same username and password as the local user on the remote server.

Ryan Dale
  • 1
  • 1
  • Thanks, but I can't replicate the user to each machine in the farm; if you look at my answer I found a solution avoiding it. – Irvin Dominin May 06 '17 at 13:00