ryyker
ryyker

Reputation: 23226

After using CreateProcessAsUser to restore user to session 1, user's path's are no longer accessible

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:

  1. 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?

  2. 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

Answers (2)

Harry Johnston
Harry Johnston

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

Ian Boyd
Ian Boyd

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

Related Questions