Discussion:
Logon Failure: Impersonation Succeeds But CreateFile Fails
(too old to reply)
Sonic..
2008-09-08 09:49:27 UTC
Permalink
Hello,

I am trying to access a network file and edit that file using
impersonation from an local service.
i use the pid of explorer.exe and obtains it's handle to pass to
OpenProcessToken.
Then i use the token obtained, to pass to ImpersonateLoggedOnUser().

Once impersonated i use CreateFile to open an existting network file.
The call fails with error Logon Failure: unknown username or
password.

This is happening only in Vista. In 2000, XP and 2003 the code is
working fine.

Below is the code that i've used. Please tell me why is the above
happening in Vista

DWORD ImpersonateClientX()
{
HANDLE hClient = NULL;
HANDLE hToken = NULL;
LUID LookupUID;
DWORD dwRet = 0;
BOOL bReturn;
DWORD dwProcId = GetExplorerProcessId();

hClient = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcId);
if (hClient == NULL || hClient == INVALID_HANDLE_VALUE)
{
dwRet = GetLastError();
goto Exit;
}

//if (!OpenProcessToken(hClient, TOKEN_ALL_ACCESS, &hToken))
if (!OpenProcessToken(hClient,
TOKEN_ALL_ACCESS,
&hToken))
{
dwRet = GetLastError();
goto Exit;
}

// Look If The Process Has The "SeLoadDriverPrivilege" Privilege
bReturn = LookupPrivilegeValue(NULL, "SeTcbPrivilege", &LookupUID);
if (bReturn == FALSE)
{
dwRet = GetLastError();
goto Exit;
}

LUID_AND_ATTRIBUTES NewPrivileges;
TOKEN_PRIVILEGES TokPrivileges;

NewPrivileges.Attributes = SE_PRIVILEGE_ENABLED;
NewPrivileges.Luid = LookupUID;

TokPrivileges.PrivilegeCount = 1;
TokPrivileges.Privileges[0] = NewPrivileges;

// Set The Process Token The Privileges We Require
bReturn = AdjustTokenPrivileges(hToken,
FALSE,
&TokPrivileges,
0,
NULL,
NULL);

if (bReturn == FALSE)
{
dwRet = GetLastError();
goto Exit;
}

if (!ImpersonateLoggedOnUser(hToken))
{
dwRet = GetLastError();
}

HANDLE fileHandle = CreateFile(szFileName, GENERIC_READ |
GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);

Exit:
if (hClient)
{
CloseHandle(hClient);
hClient = NULL;
}

if (hToken)
{
CloseHandle(hToken);
hToken = NULL;
}

return dwRet;
}
Kerem Gümrükcü
2008-09-08 10:19:12 UTC
Permalink
Hi Sonic,

do not work on the original handles/tokens, instead
dulicate them and use the duplicates,...

http://msdn.microsoft.com/en-us/library/aa446616%28VS.85%29.aspx

http://msdn.microsoft.com/en-us/library/ms724251(VS.85).aspx

Another Problem could be the higher process isolation
and more security checks in the vista shell/user/kernelcode,
for sure thats obvious in your case,...

Regards

Kerem
--
-----------------------
Beste Grüsse / Best regards / Votre bien devoue
Kerem Gümrükcü
Latest Project: http://www.codeplex.com/restarts
Latest Open-Source Projects: http://entwicklung.junetz.de
-----------------------
"This reply is provided as is, without warranty express or implied."
Post by Sonic..
Hello,
I am trying to access a network file and edit that file using
impersonation from an local service.
i use the pid of explorer.exe and obtains it's handle to pass to
OpenProcessToken.
Then i use the token obtained, to pass to ImpersonateLoggedOnUser().
Once impersonated i use CreateFile to open an existting network file.
The call fails with error Logon Failure: unknown username or
password.
This is happening only in Vista. In 2000, XP and 2003 the code is
working fine.
Below is the code that i've used. Please tell me why is the above
happening in Vista
DWORD ImpersonateClientX()
{
HANDLE hClient = NULL;
HANDLE hToken = NULL;
LUID LookupUID;
DWORD dwRet = 0;
BOOL bReturn;
DWORD dwProcId = GetExplorerProcessId();
hClient = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcId);
if (hClient == NULL || hClient == INVALID_HANDLE_VALUE)
{
dwRet = GetLastError();
goto Exit;
}
//if (!OpenProcessToken(hClient, TOKEN_ALL_ACCESS, &hToken))
if (!OpenProcessToken(hClient,
TOKEN_ALL_ACCESS,
&hToken))
{
dwRet = GetLastError();
goto Exit;
}
// Look If The Process Has The "SeLoadDriverPrivilege" Privilege
bReturn = LookupPrivilegeValue(NULL, "SeTcbPrivilege", &LookupUID);
if (bReturn == FALSE)
{
dwRet = GetLastError();
goto Exit;
}
LUID_AND_ATTRIBUTES NewPrivileges;
TOKEN_PRIVILEGES TokPrivileges;
NewPrivileges.Attributes = SE_PRIVILEGE_ENABLED;
NewPrivileges.Luid = LookupUID;
TokPrivileges.PrivilegeCount = 1;
TokPrivileges.Privileges[0] = NewPrivileges;
// Set The Process Token The Privileges We Require
bReturn = AdjustTokenPrivileges(hToken,
FALSE,
&TokPrivileges,
0,
NULL,
NULL);
if (bReturn == FALSE)
{
dwRet = GetLastError();
goto Exit;
}
if (!ImpersonateLoggedOnUser(hToken))
{
dwRet = GetLastError();
}
HANDLE fileHandle = CreateFile(szFileName, GENERIC_READ |
GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if (hClient)
{
CloseHandle(hClient);
hClient = NULL;
}
if (hToken)
{
CloseHandle(hToken);
hToken = NULL;
}
return dwRet;
}
Sonic..
2008-09-08 10:42:07 UTC
Permalink
Thanx, i'll try to use duplicate handles and tokens. but my problem
still persists.

I need to access a remote file on Vista through my service, and i was
only aware of Impersonation method,
what could be the other approach.

Regards
Abhishek
Uwe Sieber
2008-09-08 10:31:36 UTC
Permalink
Post by Sonic..
Hello,
I am trying to access a network file and edit that file using
impersonation from an local service.
i use the pid of explorer.exe and obtains it's handle to pass to
OpenProcessToken.
Then i use the token obtained, to pass to ImpersonateLoggedOnUser().
Once impersonated i use CreateFile to open an existting network file.
The call fails with error Logon Failure: unknown username or
password.
This is happening only in Vista. In 2000, XP and 2003 the code is
working fine.
Below is the code that i've used. Please tell me why is the above
happening in Vista
Stealing the Explorer's token is required under W2K only.
Since XP the terminal API has some new functions:

DWORD id = WTSGetActiveConsoleSessionId();
WTSQueryUserToken(id, &hToken);

Remember that the functions are not aviallable under W2K,
so load them at runtime.


Uwe
Uwe Sieber
2008-09-08 10:34:55 UTC
Permalink
Post by Uwe Sieber
Post by Sonic..
Hello,
I am trying to access a network file and edit that file using
impersonation from an local service.
i use the pid of explorer.exe and obtains it's handle to pass to
OpenProcessToken.
Then i use the token obtained, to pass to ImpersonateLoggedOnUser().
Once impersonated i use CreateFile to open an existting network file.
The call fails with error Logon Failure: unknown username or
password.
This is happening only in Vista. In 2000, XP and 2003 the code is
working fine.
Below is the code that i've used. Please tell me why is the above
happening in Vista
Stealing the Explorer's token is required under W2K only.
DWORD id = WTSGetActiveConsoleSessionId();
WTSQueryUserToken(id, &hToken);
Remember that the functions are not aviallable under W2K,
so load them at runtime.
And under Vista you might deal with UAC, so there are two
tokens, maybe only the elveated one has access to your
network ressource. WTSQueryUserToken returns the non elevated.
Get the elevated by GetTokenInformation called with
TokenLinkedToken.


Uwe
Sonic..
2008-09-15 11:24:09 UTC
Permalink
Thanks Uwe,

Your trick worked, i was successfully able to impersonate on all
operating systems.

In Vista, it was the token of the non elevated process i was
receiving. and i did found the API's WTSGetActiveConsoleSessionId and
WTSQueryUserToken useful.

Thank you
Post by Uwe Sieber
Post by Uwe Sieber
Post by Sonic..
Hello,
I am trying to access a network file and edit that file using
impersonation from an local service.
i use the pid of explorer.exe and obtains it's handle to pass to
OpenProcessToken.
Then i use the token obtained, to pass to ImpersonateLoggedOnUser().
Once impersonated i use CreateFile to open an existting network file.
The call fails with error Logon Failure: unknown username or
password.
This is happening only in Vista. In 2000, XP and 2003 the code is
working fine.
Below is the code that i've used. Please tell me why is the above
happening in Vista
Stealing the Explorer's token is required under W2K only.
DWORD id = WTSGetActiveConsoleSessionId();
WTSQueryUserToken(id, &hToken);
Remember that the functions are not aviallable under W2K,
so load them at runtime.
And under Vista you might deal with UAC, so there are two
tokens, maybe only the elveated one has access to your
network ressource. WTSQueryUserToken returns the non elevated.
Get the elevated by GetTokenInformation called with
TokenLinkedToken.
Uwe
Loading...