Starting an Interactive Client Process in C++

简介:

The following example uses the  LogonUser  function to start a new  logon session  for a client. The example gets the  logon SID  from the client's  access token , and uses it to add  access control entries  (ACEs) to the  discretionary access control list  (DACL) of the interactive window station and desktop. The ACEs allow the client access to the interactive desktop for the duration of the logon session. Next, the example calls the ImpersonateLoggedOnUserfunction to ensure that it has access to the client's executable file. A call to the  CreateProcessAsUser  function creates the client's  process , specifying that it run in the interactive desktop. Note that your process must have the SE_ASSIGNPRIMARYTOKEN_NAME and SE_INCREASE_QUOTA_NAME privileges for successful execution of CreateProcessAsUser. Before the function returns, it calls the RevertToSelf function to end the caller's impersonation of the client.

This example calls the GetLogonSID and FreeLogonSID functions described in Getting the Logon SID in C++.

  #define  DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \ 
DESKTOP_CREATEMENU  |  DESKTOP_HOOKCONTROL  |  DESKTOP_JOURNALRECORD  |  \
DESKTOP_JOURNALPLAYBACK  |  DESKTOP_ENUMERATE  |  DESKTOP_WRITEOBJECTS  |  \
DESKTOP_SWITCHDESKTOP  |  STANDARD_RIGHTS_REQUIRED)

  #define  WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \ 
WINSTA_ACCESSCLIPBOARD  |  WINSTA_CREATEDESKTOP  |  WINSTA_WRITEATTRIBUTES  |  \
WINSTA_ACCESSGLOBALATOMS  |  WINSTA_EXITWINDOWS  |  WINSTA_ENUMERATE  |  \
WINSTA_READSCREEN  |  STANDARD_RIGHTS_REQUIRED)

  #define  GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | \ 
GENERIC_ALL)

BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid);

BOOL AddAceToDesktop(HDESK hdesk, PSID psid);

BOOL StartInteractiveClientProcess (
    LPTSTR lpszUsername,      //   client to log on 
 
    LPTSTR lpszDomain,        //   domain of client's account 
 
    LPTSTR lpszPassword,      //   client's password 
 
    LPTSTR lpCommandLine      //   command line to execute 
 

  {
   HANDLE      hToken;
   HDESK       hdesk  =  NULL;
   HWINSTA     hwinsta  =  NULL, hwinstaSave  =  NULL;
   PROCESS_INFORMATION pi;
   PSID pSid  =  NULL;
   STARTUPINFO si;
   BOOL bResult  =  FALSE;

 //  Log the client on to the local computer. 
 

    if  ( ! LogonUser(
           lpszUsername,
           lpszDomain,
           lpszPassword,
           LOGON32_LOGON_INTERACTIVE,
           LOGON32_PROVIDER_DEFAULT,
            & hToken) ) 
    {
       goto  Cleanup;
   } 

 
 //  Save a handle to the caller's current window station. 
 

    if  ( (hwinstaSave  =  GetProcessWindowStation() )  ==  NULL)
       goto  Cleanup;

 //  Get a handle to the interactive window station. 
 

   hwinsta  =  OpenWindowStation(
        " winsta0 " ,                    //  the interactive window station  
 
       FALSE,                        //  handle is not inheritable 
 
       READ_CONTROL  |  WRITE_DAC);    //  rights to read/write the DACL 
 

    if  (hwinsta  ==  NULL) 
       goto  Cleanup;

 //  To get the correct default desktop, set the caller's 
 //  window station to the interactive window station. 
 

    if  ( ! SetProcessWindowStation(hwinsta))
       goto  Cleanup;

 //  Get a handle to the interactive desktop. 
 

   hdesk  =  OpenDesktop(
       " default " ,      //  the interactive window station  
 
       0 ,              //  no interaction with other desktop processes 
 
      FALSE,          //  handle is not inheritable 
 
      READ_CONTROL  |   //  request the rights to read and write the DACL 
 
      WRITE_DAC  |  
      DESKTOP_WRITEOBJECTS  |  
      DESKTOP_READOBJECTS);

 //  Restore the caller's window station. 
 

    if  ( ! SetProcessWindowStation(hwinstaSave)) 
       goto  Cleanup;

    if  (hdesk  ==  NULL) 
       goto  Cleanup;

 //  Get the SID for the client's logon session. 
 

    if  ( ! GetLogonSID(hToken,  & pSid)) 
       goto  Cleanup;

 //  Allow logon SID full access to interactive window station. 
 

    if  ( !  AddAceToWindowStation(hwinsta, pSid) ) 
       goto  Cleanup;

 //  Allow logon SID full access to interactive desktop. 
 

    if  ( !  AddAceToDesktop(hdesk, pSid) ) 
       goto  Cleanup;

 //  Impersonate client to ensure access to executable file. 
 

    if  ( !  ImpersonateLoggedOnUser(hToken) ) 
       goto  Cleanup;

 //  Initialize the STARTUPINFO structure.
 //  Specify that the process runs in the interactive desktop. 
 

   ZeroMemory( & si,  sizeof (STARTUPINFO));
   si.cb =   sizeof (STARTUPINFO);
   si.lpDesktop  =  TEXT( " winsta0\\default " );

 //  Launch the process in the client's logon session. 
 

   bResult  =  CreateProcessAsUser(
      hToken,             //  client's access token 
 
      NULL,               //  file to execute 
 
      lpCommandLine,      //  command line 
 
      NULL,               //  pointer to process SECURITY_ATTRIBUTES 
 
      NULL,               //  pointer to thread SECURITY_ATTRIBUTES 
 
      FALSE,              //  handles are not inheritable 
 
      NORMAL_PRIORITY_CLASS  |  CREATE_NEW_CONSOLE,    //  creation flags 
 
      NULL,               //  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. 
 

   RevertToSelf();

    if  (bResult  &&  pi.hProcess  !=  INVALID_HANDLE_VALUE) 
    
      WaitForSingleObject(pi.hProcess, INFINITE); 
      CloseHandle(pi.hProcess); 
   } 
 

    if  (pi.hThread  !=  INVALID_HANDLE_VALUE)
      CloseHandle(pi.hThread);  

Cleanup: 

    if  (hwinstaSave  !=  NULL)
      SetProcessWindowStation (hwinstaSave);

 //  Free the buffer for the logon SID. 
 

    if  (pSid)
      FreeLogonSID( & pSid);

 //  Close the handles to the interactive window station and desktop. 
 

    if  (hwinsta)
      CloseWindowStation(hwinsta);

    if  (hdesk)
      CloseDesktop(hdesk);

 //  Close the handle to the client's access token. 
 

    if  (hToken  !=  INVALID_HANDLE_VALUE)
      CloseHandle(hToken);  

    return  bResult;

 
BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid)
  {
   ACCESS_ALLOWED_ACE    * pace;
   ACL_SIZE_INFORMATION aclSizeInfo;
   BOOL                 bDaclExist;
   BOOL                 bDaclPresent;
   BOOL                 bSuccess  =  FALSE;
   DWORD                dwNewAclSize;
   DWORD                dwSidSize  =   0 ;
   DWORD                dwSdSizeNeeded;
   PACL                 pacl;
   PACL                 pNewAcl;
   PSECURITY_DESCRIPTOR psd  =  NULL;
   PSECURITY_DESCRIPTOR psdNew  =  NULL;
   PVOID                pTempAce;
   SECURITY_INFORMATION si  =  DACL_SECURITY_INFORMATION;
   unsigned  int          i;

   __try
    {
       //  Obtain the DACL for the window station. 
 

       if  ( ! GetUserObjectSecurity(
             hwinsta,
              & si,
             psd,
             dwSidSize,
              & dwSdSizeNeeded)
      )
       if  (GetLastError()  ==  ERROR_INSUFFICIENT_BUFFER)
       {
         psd  =  (PSECURITY_DESCRIPTOR)HeapAlloc(
               GetProcessHeap(),
               HEAP_ZERO_MEMORY,
               dwSdSizeNeeded);

          if  (psd  ==  NULL)
            __leave;

         psdNew  =  (PSECURITY_DESCRIPTOR)HeapAlloc(
               GetProcessHeap(),
               HEAP_ZERO_MEMORY,
               dwSdSizeNeeded);

          if  (psdNew  ==  NULL)
            __leave;

         dwSidSize  =  dwSdSizeNeeded;

          if  ( ! GetUserObjectSecurity(
               hwinsta,
                & si,
               psd,
               dwSidSize,
                & dwSdSizeNeeded)
         )
            __leave;
      } 

       else 
         __leave;

       //  Create a new DACL. 
 

       if  ( ! InitializeSecurityDescriptor(
            psdNew,
            SECURITY_DESCRIPTOR_REVISION)
      )
         __leave;

       //  Get the DACL from the security descriptor. 
 

       if  ( ! GetSecurityDescriptorDacl(
            psd,
             & bDaclPresent,
             & pacl,
             & bDaclExist)
      )
         __leave;

       //  Initialize the ACL. 
 

      ZeroMemory( & aclSizeInfo,  sizeof (ACL_SIZE_INFORMATION));
      aclSizeInfo.AclBytesInUse  =   sizeof (ACL);

       //  Call only if the DACL is not NULL. 
 

       if  (pacl  !=  NULL)
       {
          //  get the file ACL size info 
 
          if  ( ! GetAclInformation(
               pacl,
               (LPVOID) & aclSizeInfo,
                sizeof (ACL_SIZE_INFORMATION),
               AclSizeInformation)
         )
            __leave;
      } 

 
       //  Compute the size of the new ACL. 
 

      dwNewAclSize  =  aclSizeInfo.AclBytesInUse  +  ( 2 * sizeof (ACCESS_ALLOWED_ACE))  +  
( 2 * GetLengthSid(psid))  -  ( 2 * sizeof (DWORD));

       //  Allocate memory for the new ACL. 
 

      pNewAcl  =  (PACL)HeapAlloc(
            GetProcessHeap(),
            HEAP_ZERO_MEMORY,
            dwNewAclSize);

       if  (pNewAcl  ==  NULL)
         __leave;

       //  Initialize the new DACL. 
 

       if  ( ! InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
         __leave;

       //  If DACL is present, copy it to a new DACL. 
 

       if  (bDaclPresent)
       {
          //  Copy the ACEs to the new ACL. 
 
          if  (aclSizeInfo.AceCount)
          {
             for  (i = 0 ; i  <  aclSizeInfo.AceCount; i ++ )
             {
                //  Get an ACE. 
 
                if  ( ! GetAce(pacl, i,  & pTempAce))
                  __leave;

                //  Add the ACE to the new ACL. 
 
                if  ( ! AddAce(
                     pNewAcl,
                     ACL_REVISION,
                     MAXDWORD,
                     pTempAce,
                    ((PACE_HEADER)pTempAce) -> AceSize)
               )
                  __leave;
            } 

         } 

      } 

 
       //  Add the first ACE to the window station. 
 

      pace  =  (ACCESS_ALLOWED_ACE  * )HeapAlloc(
            GetProcessHeap(),
            HEAP_ZERO_MEMORY,
             sizeof (ACCESS_ALLOWED_ACE)  +  GetLengthSid(psid)  - 
                   sizeof (DWORD));

       if  (pace  ==  NULL)
         __leave;

      pace -> Header.AceType   =  ACCESS_ALLOWED_ACE_TYPE;
      pace -> Header.AceFlags  =  CONTAINER_INHERIT_ACE  | 
                   INHERIT_ONLY_ACE  |  OBJECT_INHERIT_ACE;
      pace -> Header.AceSize   =   sizeof (ACCESS_ALLOWED_ACE)  + 
                   GetLengthSid(psid)  -   sizeof (DWORD);
      pace -> Mask             =  GENERIC_ACCESS;

       if  ( ! CopySid(GetLengthSid(psid),  & pace -> SidStart, psid))
         __leave;

       if  ( ! AddAce(
            pNewAcl,
            ACL_REVISION,
            MAXDWORD,
            (LPVOID)pace,
            pace -> Header.AceSize)
      )
         __leave;

       //  Add the second ACE to the window station. 
 

      pace -> Header.AceFlags  =  NO_PROPAGATE_INHERIT_ACE;
      pace -> Mask             =  WINSTA_ALL;

       if  ( ! AddAce(
            pNewAcl,
            ACL_REVISION,
            MAXDWORD,
            (LPVOID)pace,
            pace -> Header.AceSize)
      )
         __leave;

       //  Set a new DACL for the security descriptor. 
 

       if  ( ! SetSecurityDescriptorDacl(
            psdNew,
            TRUE,
            pNewAcl,
            FALSE)
      )
         __leave;

       //  Set the new security descriptor for the window station. 
 

       if  ( ! SetUserObjectSecurity(hwinsta,  & si, psdNew))
         __leave;

       //  Indicate success. 
 

      bSuccess  =  TRUE;
   } 

   __finally
    {
       //  Free the allocated buffers. 
 

       if  (pace  !=  NULL)
         HeapFree(GetProcessHeap(),  0 , (LPVOID)pace);

       if  (pNewAcl  !=  NULL)
         HeapFree(GetProcessHeap(),  0 , (LPVOID)pNewAcl);

       if  (psd  !=  NULL)
         HeapFree(GetProcessHeap(),  0 , (LPVOID)psd);

       if  (psdNew  !=  NULL)
         HeapFree(GetProcessHeap(),  0 , (LPVOID)psdNew);
   } 

 
    return  bSuccess;


 
BOOL AddAceToDesktop(HDESK hdesk, PSID psid)
  {
   ACL_SIZE_INFORMATION aclSizeInfo;
   BOOL                 bDaclExist;
   BOOL                 bDaclPresent;
   BOOL                 bSuccess  =  FALSE;
   DWORD                dwNewAclSize;
   DWORD                dwSidSize  =   0 ;
   DWORD                dwSdSizeNeeded;
   PACL                 pacl;
   PACL                 pNewAcl;
   PSECURITY_DESCRIPTOR psd  =  NULL;
   PSECURITY_DESCRIPTOR psdNew  =  NULL;
   PVOID                pTempAce;
   SECURITY_INFORMATION si  =  DACL_SECURITY_INFORMATION;
   unsigned  int          i;

   __try
    {
       //  Obtain the security descriptor for the desktop object. 
 

       if  ( ! GetUserObjectSecurity(
            hdesk,
             & si,
            psd,
            dwSidSize,
             & dwSdSizeNeeded))
       {
          if  (GetLastError()  ==  ERROR_INSUFFICIENT_BUFFER)
          {
            psd  =  (PSECURITY_DESCRIPTOR)HeapAlloc(
                  GetProcessHeap(),
                  HEAP_ZERO_MEMORY,
                  dwSdSizeNeeded );

             if  (psd  ==  NULL)
               __leave;

            psdNew  =  (PSECURITY_DESCRIPTOR)HeapAlloc(
                  GetProcessHeap(),
                  HEAP_ZERO_MEMORY,
                  dwSdSizeNeeded);

             if  (psdNew  ==  NULL)
               __leave;

            dwSidSize  =  dwSdSizeNeeded;

             if  ( ! GetUserObjectSecurity(
                  hdesk,
                   & si,
                  psd,
                  dwSidSize,
                   & dwSdSizeNeeded)
            )
               __leave;
         } 

          else 
            __leave;
      } 

 
       //  Create a new security descriptor. 
 

       if  ( ! InitializeSecurityDescriptor(
            psdNew,
            SECURITY_DESCRIPTOR_REVISION)
      )
         __leave;

       //  Obtain the DACL from the security descriptor. 
 

       if  ( ! GetSecurityDescriptorDacl(
            psd,
             & bDaclPresent,
             & pacl,
             & bDaclExist)
      )
         __leave;

       //  Initialize. 
 

      ZeroMemory( & aclSizeInfo,  sizeof (ACL_SIZE_INFORMATION));
      aclSizeInfo.AclBytesInUse  =   sizeof (ACL);

       //  Call only if NULL DACL. 
 

       if  (pacl  !=  NULL)
       {
          //  Determine the size of the ACL information. 
 

          if  ( ! GetAclInformation(
               pacl,
               (LPVOID) & aclSizeInfo,
                sizeof (ACL_SIZE_INFORMATION),
               AclSizeInformation)
         )
            __leave;
      } 

 
       //  Compute the size of the new ACL. 
 

      dwNewAclSize  =  aclSizeInfo.AclBytesInUse  + 
             sizeof (ACCESS_ALLOWED_ACE)  + 
            GetLengthSid(psid)  -   sizeof (DWORD);

       //  Allocate buffer for the new ACL. 
 

      pNewAcl  =  (PACL)HeapAlloc(
            GetProcessHeap(),
            HEAP_ZERO_MEMORY,
            dwNewAclSize);

       if  (pNewAcl  ==  NULL)
         __leave;

       //  Initialize the new ACL. 
 

       if  ( ! InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
         __leave;

       //  If DACL is present, copy it to a new DACL. 
 

       if  (bDaclPresent)
       {
          //  Copy the ACEs to the new ACL. 
 
          if  (aclSizeInfo.AceCount)
          {
             for  (i = 0 ; i  <  aclSizeInfo.AceCount; i ++ )
             {
                //  Get an ACE. 
 
                if  ( ! GetAce(pacl, i,  & pTempAce))
                  __leave;

                //  Add the ACE to the new ACL. 
 
                if  ( ! AddAce(
                  pNewAcl,
                  ACL_REVISION,
                  MAXDWORD,
                  pTempAce,
                  ((PACE_HEADER)pTempAce) -> AceSize)
               )
                  __leave;
            } 

         } 

      } 

 
       //  Add ACE to the DACL. 
 

       if  ( ! AddAccessAllowedAce(
            pNewAcl,
            ACL_REVISION,
            DESKTOP_ALL,
            psid)
      )
         __leave;

       //  Set new DACL to the new security descriptor. 
 

       if  ( ! SetSecurityDescriptorDacl(
            psdNew,
            TRUE,
            pNewAcl,
            FALSE)
      )
         __leave;

       //  Set the new security descriptor for the desktop object. 
 

       if  ( ! SetUserObjectSecurity(hdesk,  & si, psdNew))
         __leave;

       //  Indicate success. 
 

      bSuccess  =  TRUE;
   } 

   __finally
    {
       //  Free buffers. 
 

       if  (pNewAcl  !=  NULL)
         HeapFree(GetProcessHeap(),  0 , (LPVOID)pNewAcl);

       if  (psd  !=  NULL)
         HeapFree(GetProcessHeap(),  0 , (LPVOID)psd);

       if  (psdNew  !=  NULL)
         HeapFree(GetProcessHeap(),  0 , (LPVOID)psdNew);
   } 

 
    return  bSuccess;
目录
相关文章
|
6月前
|
机器学习/深度学习 TensorFlow 算法框架/工具
Gaussian Process
【6月更文挑战第14天】
55 4
|
7月前
|
负载均衡 Java 应用服务中间件
Client not connected, current status:STARTING
Client not connected, current status:STARTING
582 1
|
7月前
|
测试技术
Could not proxy command to the remote server. Original error: timeout of 240000ms exceeded 的解决办法
Could not proxy command to the remote server. Original error: timeout of 240000ms exceeded 的解决办法
260 0
|
7月前
|
Java Python
【已解决】RuntimeError Java gateway process exited before sending its port number
【已解决】RuntimeError Java gateway process exited before sending its port number
315 0
|
网络安全 开发工具
【解决方案】A session ended very soon after starting. Check that the command in profile “XXX” is correct.
【解决方案】A session ended very soon after starting. Check that the command in profile “XXX” is correct.
1120 0
【解决方案】A session ended very soon after starting. Check that the command in profile “XXX” is correct.
‘Client‘ is not allowed to run in parallel.Would you like to stop the running one?
‘Client‘ is not allowed to run in parallel.Would you like to stop the running one?
589 0
‘Client‘ is not allowed to run in parallel.Would you like to stop the running one?
|
关系型数据库 Java MySQL