LogonUser using LOGON32_LOGON_NEW_CREDENTIALS work

2019-04-01 00:00发布

问题:

So between the two machines, there is no trust - they are in different domains.

I've successfully connected to the remote machine using LogonUser API using logon type, LOGON32_LOGON_NEW_CREDENTIALS. I am able to retrieve the content of a directory using the UNC share, and create a file stream to "download" the file. So far so good.

The only issue is that it seems, LogonUser fails unless there is an already open session. Let me clarify that.

I found that the ASP.NET MVC page was not working this morning, specifically the page that retrieves the file list from this remote machine using LogonUser. I look at the log and I see in the stacktrace, System.IO.__Error.WinIOError above Directory.GetFiles call. I then remoted into the web server and tried to open the remote folder in the explorer using the same login/password used by the web site. It went through and I could see the files. I opened up the command prompt, type in net use, and I see that there is an open connection to the remote machine. Then I went back to the page and suddenly the page is working again.

So, at this point, I am not exactly sure if the LogonUser is working as expected or not. If the call requires that a network connection opened first by other means, then this is certainly not satisfactory.

Does anyone know what may be happening or suggest a workaround?

回答1:

I am not sure that I understand why you use LogonUser. This function help you if you want to do some job on the local machine with another user credentials, but it helps not to establish a remote connection to another computer.

If you want to get some information from the remote computer independent on existing trust between to the computer you should use WNet or Net (Network Management) functions to establish a new connection to the remote computer. So you should use WNetAddConnection2 (see http://msdn.microsoft.com/en-us/library/aa385413%28VS.85%29.aspx) or NetUseAdd (http://msdn.microsoft.com/en-us/library/aa370645%28VS.85%29.aspx) functions. This function will makes remote login on the destination computer and establish a new session (exact what net use \\computer\share /u:domain\user password do). You can don't map a new connection to a local drive. To do so you should fill lpLocalName with NULL in the struct NETRESOURCE. As a lpUsername and lpPassword you should give any values which understand the destination computer. You can also use ipc$ as a destination share name, then you just establish a session to the computer and nothing more. After that you can use any other functions to access the remote share, directory or files. To close the session you should use WNetCancelConnection2 or NetUseDel.



回答2:

This is how you LogonUser to a remote computer. Make sure that you're using LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50. Then impersonate the token. You should be able to do a lot of remote things this way without WNetAddConnection2. WNetAddConnection2 is not very good because the connection can be destroyed by a lot of things. LogonUser will also make the appropriate connection when needed by several api calls.

PXERR impersonate_user(LPCWSTR lpszUserName, LPCWSTR lpszDomain, LPCWSTR lpszPassword)
{
    HANDLE token;

    if(!LogonUserW(lpszUserName, lpszDomain, lpszPassword, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, &token))
    {
        return PXERR_IMPERSONATION_FAILURE;
    }

    if(!ImpersonateLoggedOnUser(token))
    {
        CloseHandle(token);
        RevertToSelf();
        return PXERR_IMPERSONATION_FAILURE;
    }

    CloseHandle(token);

    return PXERR_SUCCESS;
}