Reputation: 23226
Using ANCI C, and the Windows API:
I am calling the function CreateProcessAsUser(,,,) from a Windows 7 service application (running in session 0) to launch an application as the user logged into session 1.
This works well. All behavior exhibited by the application after being launched by the service in this manner is normal EXCEPT that the network locations normally accessible to the user (i.e. as if the application were launched from session 1) are no longer available
So my questions are:
If I have duplicated the token for the user logged into session 1 correctly, why, when the application is started using this token, does it not have access to data in the network locations normally accessible to that user?
Is there an additional step I am missing to restore network accessibility in addition to using the CreateProcessAsUser function?
NOTE: I specifically chose CreateProcessAsUser (as opposed to other choices such as CreateProcessWithLogonW) to avoid having to maintain and pass user credentials within the source code.
any suggestions?
Here is the source code I am using to launch an application from a Windows service as a session 1 user:
BOOL LaunchAppIntoDifferentSession(char *AtsAppPathName)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL bResult = FALSE;
DWORD dwSessionId;
DWORD winlogonPid = 0;
HANDLE hUserToken,hUserTokenDup,hPToken,hProcess;
DWORD dwCreationFlags;
// Log the client on to the local computer.
dwSessionId = WTSGetActiveConsoleSessionId();
// Find the winlogon process
PROCESSENTRY32 procEntry;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
{
return 1 ;
}
procEntry.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hSnap, &procEntry))
{
CloseHandle(hSnap);
return 1 ;
}
do
{
if (stricmp(procEntry.szExeFile, "winlogon.exe") == 0)
{
// found a winlogon process...make sure it's running in the console session
DWORD winlogonSessId = 0;
if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId) && winlogonSessId == dwSessionId)
{
winlogonPid = procEntry.th32ProcessID;
break;
}
}
} while (Process32Next(hSnap, &procEntry));
WTSQueryUserToken(dwSessionId,&hUserToken);
dwCreationFlags = NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = "winsta0\\default";
ZeroMemory(&pi, sizeof(pi));
TOKEN_PRIVILEGES tp;
LUID luid;
hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,winlogonPid);
if(!OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY
|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID
|TOKEN_READ|TOKEN_WRITE,&hPToken))
{
sprintf(gTempBuf, "Process token open Error: %u",GetLastError());
if(LOG_ERR==1) WriteToLog("gTempBuf");
}
if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))
{
sprintf(gTempBuf, "Lookup Privilege value Error: %u",GetLastError());
if(LOG_ERR==1) WriteToLog("gTempBuf");
}
tp.PrivilegeCount =1;
tp.Privileges[0].Luid =luid;
tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;
if(!DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityImpersonation,TokenPrimary,&hUserTokenDup))
{
sprintf(gTempBuf, "DuplicateTokenEx return Error: %u",GetLastError());
if(LOG_ERR==1) WriteToLog("gTempBuf");
}
//Adjust Token privilege
SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)dwSessionId,sizeof(DWORD));
if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,NULL))
{
sprintf(gTempBuf, "Adjust Privilege value Error: %u",GetLastError());
if(LOG_ERR==1) WriteToLog("gTempBuf");
}
if (GetLastError()== ERROR_NOT_ALL_ASSIGNED)
{
sprintf(gTempBuf, "Token does not have the privilege");
if(LOG_ERR==1) WriteToLog("gTempBuf");
}
LPVOID pEnv =NULL;
if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
{
dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
}
else
pEnv=NULL;
// Launch the process in the client's logon session.
bResult = CreateProcessAsUser(
hUserTokenDup, // client's access token
AtsAppPathName, // file to execute
NULL, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
dwCreationFlags, // creation flags
pEnv, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
// End impersonation of client.
//Perform All the Close Handles task
CloseHandle(hProcess);
CloseHandle(hUserToken);
CloseHandle(hUserTokenDup);
CloseHandle(hPToken);
CloseHandle(hSnap);
//return iResultOfCreateProcessAsUser;
return 0;
}
Upvotes: 0
Views: 676
Reputation: 36348
The problem is that you're getting a copy of the administrative (elevated) token. This is presumably intentional since you enable debug privilege. Unfortunately, the user's elevated token is not in the same logon session as the filtered token, and hence does not have any of the user's mapped drives.
More information, including various workarounds, can be found in the MSDN article "Copying files from a mapped drive to a local directory fails with error “Location is not available” if UAC is enabled". Typically the simplest solution is to use UNC paths or to remap the drives as needed.
Upvotes: 0
Reputation: 256991
Are you accessing these network locations using mapped drives?
Mapped drives are stored with a login session. Since the user's profile is not loaded, they will not have access to their "mapped drives".
You can use full UNC paths instead.
Upvotes: 0