I'm trying to use CreateFile()
to access a remote system. NetUseAdd()
is used to establish the connection with the remote system so that CreateFile()
can execute successfully.
I've passed the correct username and password on the domain, but error 1326 (The user name or password is incorrect) is returned.
After examining the network traffic, I noticed it passes the username of the executor, instead of the username of the remote system (the passed username):
Session Setup Request, NTLMSSP_AUTH, User: .\localhost
But here is the passed arguments (and the code, of course):
net::Establish(L"\\\\192.168.1.10", L"user", L"password");
bool net::Establish(const wchar_t* domain, const wchar_t* user, const wchar_t* password) {
HANDLE remotebin;
DWORD ret;
char RemoteBinPath[MAX_PATH];
// Establish the connection with the remote domain
USER_INFO_1 userinfo;
userinfo.usri1_name = (LPWSTR)user;
userinfo.usri1_password = (LPWSTR)password;
userinfo.usri1_priv = USER_PRIV_USER;
userinfo.usri1_home_dir = NULL;
userinfo.usri1_comment = NULL;
userinfo.usri1_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT;
userinfo.usri1_script_path = NULL;
ret = NetUseAdd((LPTSTR)domain, 1, (LPBYTE)&userinfo, MB_OK);
if (ret != NERR_Success) {
#ifdef DEBUG
printf("Erorr: NetUseAdd: %d\n", ret);
#endif
return false;
}
Pay attention that you are calling NetUseAdd()
(USE) instead of NetUserAdd()
(USER). By setting the LevelFlags
parameter to 1
, you are telling NetUseAdd()
(USE) to expect a pointer to a USE_INFO_1
(USE) struct, however you are actually passing in a pointer to a USER_INFO_1
(USER) struct instead. The two structs are very different. Since you are not passing in a proper USE_INFO_1
(USE) struct, you end up with the ERROR_LOGON_FAILURE
error.
That being said, NetUseAdd()
(USE) at level 1 does not take in a username, only a password. To pass in a username (and domain), you need to use level 2 (USE_INFO_2
) instead. However, to use either level, you will have to also pass in a UNC share path, too.
Try this:
net::Establish(L"\\\\192.168.1.10", L"\\\\192.168.1.10\\share", L"domain", L"user", L"password");
bool net::Establish(const wchar_t* server, const wchar_t* share, const wchar_t* domain, const wchar_t* user, const wchar_t* password) {
// Establish the connection with the remote domain
USE_INFO_2 useinfo = {};
useinfo.ui2_remote = (LPWSTR)share;
useinfo.ui2_password = (LPWSTR)password;
useinfo.ui2_asg_type = USE_WILDCARD;
useinfo.ui2_username = (LPWSTR)user;
useinfo.ui2_domainname = (LPWSTR)domain;
DWORD ret = NetUseAdd((LPTSTR)server, 2, (LPBYTE)&useinfo, NULL);
if (ret != NERR_Success) {
#ifdef DEBUG
printf("Error: NetUseAdd: %d\n", ret);
#endif
return false;
}
On a side note:
The (LPTSTR)server
type-cast is questionable. It will work fine if you are compiling with UNICODE
defined, but it will not work at all if you are not compiling with UNICODE
defined. Since you are dealing with wchar_t
strings exclusively, not TCHAR
strings, you really should just avoid the typecast altogether since NetUseAdd()
takes only wchar_t
strings on Windows anyway, not TCHAR
strings.
Also, when casting your const wchar_t*
pointers to LPWSTR
(wchar_t*
), you should be using const_cast
instead of a C-style cast.
Also, use reinterpret_cast
instead of a C-style cast when passing in the USE_INFO_...
pointer to `NetUseAdd().
Try this:
net::Establish(L"\\\\192.168.1.10", L"\\\\192.168.1.10\\share", L"domain", L"user", L"password");
bool net::Establish(const wchar_t* server, const wchar_t* share, const wchar_t* domain, const wchar_t* user, const wchar_t* password) {
// Establish the connection with the remote domain
USE_INFO_2 useinfo = {};
useinfo.ui2_remote = const_cast<LPWSTR>(share);
useinfo.ui2_password = const_cast<LPWSTR>(password);
useinfo.ui2_asg_type = USE_WILDCARD;
useinfo.ui2_username = const_cast<LPWSTR>(user);
useinfo.ui2_domainname = const_cast<LPWSTR>(domain);
DWORD ret = NetUseAdd(server, 2, reinterpret_cast<LPBYTE>(&useinfo), NULL);
if (ret != NERR_Success) {
#ifdef DEBUG
printf("Error: NetUseAdd: %d\n", ret);
#endif
return false;
}