mirror of
				https://github.com/PowerShell/Win32-OpenSSH.git
				synced 2025-10-31 19:53:55 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			828 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			828 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Author: NoMachine <developers@nomachine.com>
 | |
|  *
 | |
|  * Copyright (c) 2009, 2011 NoMachine
 | |
|  * All rights reserved
 | |
|  *
 | |
|  * Support functions and system calls' replacements needed to let the
 | |
|  * software run on Win32 based operating systems.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions
 | |
|  * are met:
 | |
|  *
 | |
|  * 1. Redistributions of source code must retain the above copyright
 | |
|  * notice, this list of conditions and the following disclaimer.
 | |
|  * 2. Redistributions in binary form must reproduce the above copyright
 | |
|  * notice, this list of conditions and the following disclaimer in the
 | |
|  * documentation and/or other materials provided with the distribution.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 | |
|  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 | |
|  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | |
|  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 | |
|  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | |
|  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
|  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
|  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 | |
|  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| #include "deskright.h"
 | |
| 
 | |
| /*
 | |
|  * Retrieve SID from access token.
 | |
|  *
 | |
|  * hToken - access token (IN)
 | |
|  * psid   - user's SID (OUT)
 | |
|  *
 | |
|  * RETURNS: TRUE if OK.
 | |
|  */
 | |
| 
 | |
| BOOL ObtainSid(HANDLE hToken, PSID *psid)
 | |
| {
 | |
|   debug3("-> ObtainSid()...");
 | |
|   
 | |
|   BOOL bSuccess = FALSE;
 | |
|   
 | |
|   DWORD dwIndex;
 | |
|   
 | |
|   DWORD dwLength = 0;
 | |
| 
 | |
|   TOKEN_INFORMATION_CLASS tic = TokenGroups;
 | |
| 
 | |
|   PTOKEN_GROUPS ptg = NULL;
 | |
| 
 | |
|   /* 
 | |
|    * determine the size of the buffer
 | |
|    */
 | |
|   
 | |
|   if (!GetTokenInformation(hToken, tic, (LPVOID) ptg, 0, &dwLength))
 | |
|   {
 | |
|     FAIL(GetLastError() != ERROR_INSUFFICIENT_BUFFER);
 | |
| 
 | |
|     ptg = (PTOKEN_GROUPS) HeapAlloc(GetProcessHeap(), 
 | |
|                                         HEAP_ZERO_MEMORY, dwLength);
 | |
| 
 | |
|     FAIL(ptg == NULL);  
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * obtain the groups the access token belongs to
 | |
|    */
 | |
| 
 | |
|   FAIL(GetTokenInformation(hToken, tic, (LPVOID) ptg, 
 | |
|                                dwLength, &dwLength) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * determine which group is the logon sid
 | |
|    */
 | |
| 
 | |
|   for (dwIndex = 0; dwIndex < ptg -> GroupCount; dwIndex++)
 | |
|   {
 | |
|     if ((ptg -> Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) ==  SE_GROUP_LOGON_ID)
 | |
|     {
 | |
|       /*
 | |
|        * determine the length of the sid
 | |
|        */
 | |
|       
 | |
|       dwLength = GetLengthSid(ptg -> Groups[dwIndex].Sid);
 | |
| 
 | |
|       /*
 | |
|        * allocate a buffer for the logon sid
 | |
|        */
 | |
|   
 | |
|       *psid = (PSID) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
 | |
|       
 | |
|        FAIL(*psid == NULL);
 | |
| 
 | |
|        /*
 | |
|         * obtain a copy of the logon sid
 | |
|         */
 | |
|   
 | |
|        FAIL(CopySid(dwLength, *psid, ptg -> Groups[dwIndex].Sid) == FALSE);
 | |
| 
 | |
|        /*
 | |
|         * Break out of the loop because the logon sid has been
 | |
|         * found.
 | |
|         */
 | |
|   
 | |
|        break;
 | |
|      }
 | |
|    }
 | |
| 
 | |
|    /*
 | |
|     * Indicate success.
 | |
|     */
 | |
|    
 | |
|    bSuccess = TRUE;
 | |
| 
 | |
|  fail:
 | |
| 
 | |
|  /*
 | |
|   * Free the buffer for the token group.
 | |
|   */
 | |
|  
 | |
|  if (ptg != NULL)
 | |
|  {
 | |
|    HeapFree(GetProcessHeap(), 0, (LPVOID)ptg);
 | |
|  }
 | |
| 
 | |
|   debug3("<- ObtainSid()...");
 | |
|   
 | |
|   return bSuccess;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Gives or removes user rights to use given WinStation object.
 | |
|  *
 | |
|  * WARNING. This rights is given only for login session, i.e,
 | |
|  *          acount's properties are not be changed.
 | |
|  *
 | |
|  * hwinsta - handle to WindowsStation object (IN)
 | |
|  * psid    - pointer to user's SID (IN)
 | |
|  * mode    - 1 for add, 0 for remove right (IN)
 | |
|  *
 | |
|  * RETURNS: TRUE if OK.
 | |
|  */
 | |
|    
 | |
| BOOL ModifyTheAceWindowStation(HWINSTA hwinsta, PSID psid, int mode)
 | |
| {
 | |
|   debug2("-> ModifyTheAceWindowStation(mode = %d)...", mode);
 | |
|   
 | |
|   ACCESS_ALLOWED_ACE *pace = NULL;
 | |
|   
 | |
|   ACL_SIZE_INFORMATION aclSizeInfo;
 | |
|   
 | |
|   BOOL bDaclExist;
 | |
|   BOOL bDaclPresent;
 | |
|   BOOL bSuccess = FALSE;
 | |
|                         
 | |
|   DWORD dwNewAclSize;
 | |
|   DWORD dwSidSize = 0;
 | |
|   DWORD dwSdSizeNeeded;
 | |
|   
 | |
|   PACL pacl;
 | |
|   PACL pNewAcl = NULL;
 | |
|   
 | |
|   PSECURITY_DESCRIPTOR psd    = NULL;
 | |
|   PSECURITY_DESCRIPTOR psdNew = NULL;
 | |
|   
 | |
|   ACCESS_ALLOWED_ACE *pTempAce;
 | |
|   
 | |
|   SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
 | |
|   
 | |
|   unsigned int i;
 | |
|   
 | |
|   /*
 | |
|    * is input SID valid?
 | |
|    */
 | |
|   
 | |
|   debug3("Testing is SID valid...");
 | |
| 
 | |
|   FAIL(psid == NULL);
 | |
|   
 | |
|   FAIL(IsValidSid(psid) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * obtain the dacl for the windowstation
 | |
|    */
 | |
| 
 | |
|   debug3("GetUserObjectSecurity()...");
 | |
|   
 | |
|   if (!GetUserObjectSecurity(hwinsta, &si, psd, dwSidSize, &dwSdSizeNeeded))
 | |
|   {
 | |
|     FAIL(GetLastError() != ERROR_INSUFFICIENT_BUFFER);
 | |
| 
 | |
|     psd = (PSECURITY_DESCRIPTOR) HeapAlloc(GetProcessHeap(), 
 | |
|                                                HEAP_ZERO_MEMORY, 
 | |
|                                                    dwSdSizeNeeded);
 | |
| 
 | |
|     FAIL(psd == NULL);
 | |
| 
 | |
|     psdNew = (PSECURITY_DESCRIPTOR) HeapAlloc(GetProcessHeap(), 
 | |
|                                                   HEAP_ZERO_MEMORY, 
 | |
|                                                       dwSdSizeNeeded);
 | |
|       
 | |
|     FAIL(psdNew == NULL);
 | |
| 
 | |
|     dwSidSize = dwSdSizeNeeded;
 | |
| 
 | |
|     FAIL(GetUserObjectSecurity(hwinsta, &si, psd, 
 | |
|                                    dwSidSize, &dwSdSizeNeeded) == FALSE);
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Create a new dacl.
 | |
|    */
 | |
|   
 | |
|   debug3("InitializeSecurityDescriptor()...");
 | |
|   
 | |
|   FAIL(InitializeSecurityDescriptor(psdNew, SECURITY_DESCRIPTOR_REVISION) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * get dacl from the security descriptor.
 | |
|    */
 | |
|  
 | |
|   debug3("GetSecurityDescriptorDacl()...");
 | |
|   
 | |
|   FAIL(GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl, &bDaclExist) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * Initialize.
 | |
|    */
 | |
|  
 | |
|   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.
 | |
|      */
 | |
|  
 | |
|     debug3("GetAclInformation()...");
 | |
|     
 | |
|     FAIL(GetAclInformation(pacl, (LPVOID) &aclSizeInfo,
 | |
|                                sizeof(ACL_SIZE_INFORMATION), 
 | |
|                                    AclSizeInformation) == FALSE);
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Compute the size of the new acl.
 | |
|    */
 | |
|   
 | |
|   debug3("Calculating dwNewAclSize...");
 | |
|     
 | |
|   dwNewAclSize = aclSizeInfo.AclBytesInUse;
 | |
|                
 | |
|   if (mode == ADD_RIGHT)
 | |
|   {
 | |
|     dwNewAclSize = dwNewAclSize + (2 * GetLengthSid(psid)) 
 | |
|                  + (2 * sizeof(ACCESS_ALLOWED_ACE))
 | |
|                  - (2 * sizeof(DWORD));
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     dwNewAclSize = dwNewAclSize + (2 * GetLengthSid(psid)) 
 | |
|                  - (2 * sizeof(ACCESS_ALLOWED_ACE))
 | |
|                  + (2 * sizeof(DWORD));
 | |
|   }
 | |
| 
 | |
|   debug3("dwNewAclSize = %d", dwNewAclSize);
 | |
| 
 | |
|   /*
 | |
|    * Allocate memory for the new acl.
 | |
|    */
 | |
| 
 | |
|   debug3("HeapAlloc()...");
 | |
|   
 | |
|   pNewAcl = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNewAclSize);
 | |
| 
 | |
|   FAIL(pNewAcl == NULL);
 | |
| 
 | |
|   /*
 | |
|    * Initialize the new dacl.
 | |
|    */
 | |
| 
 | |
|   debug3("InitializeAcl()...");
 | |
|   
 | |
|   FAIL(InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * If DACL is present, copy it to a new DACL.
 | |
|    */
 | |
|  
 | |
|   if (bDaclPresent) 
 | |
|   {
 | |
|     /*
 | |
|      * Copy the ACEs from old to new ACL.
 | |
|      */
 | |
|     
 | |
|     if (aclSizeInfo.AceCount)
 | |
|     {
 | |
| 
 | |
|       debug3("aclSizeInfo.AceCount = %d", aclSizeInfo.AceCount);
 | |
|        
 | |
|       for (i = 0; i < aclSizeInfo.AceCount; i++)
 | |
|       {
 | |
|         /*
 | |
|          * Get next ACE from old ACL.
 | |
|          */
 | |
|   
 | |
|         FAIL(GetAce(pacl, i, &pTempAce) == FALSE);
 | |
| 
 | |
|         /*
 | |
|          * Add the ACE to the new ACL.
 | |
|          *
 | |
|          * We copy all original list for RIGHT_ADD mode and
 | |
|          * skip ACE with given input SID in RIGHT_REMOVE mode.
 | |
|          */
 | |
| 
 | |
|         if (mode == ADD_RIGHT || EqualSid(psid, &pTempAce -> SidStart) == 0)
 | |
|         {        
 | |
|           FAIL(AddAce(pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, 
 | |
|                           ((PACE_HEADER) pTempAce) -> AceSize) == FALSE);
 | |
|         }                  
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (mode == ADD_RIGHT)
 | |
|   {
 | |
|     /*
 | |
|      * Add the first ACE to the windowstation.
 | |
|      */
 | |
|   
 | |
|     pace = (ACCESS_ALLOWED_ACE *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
 | |
|                                                 sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) - sizeof(DWORD));
 | |
|   
 | |
|     FAIL(pace == NULL);
 | |
| 
 | |
|     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;
 | |
| 
 | |
|     debug3("CopySid()...");
 | |
|       
 | |
|     FAIL(CopySid(GetLengthSid(psid), &pace -> SidStart, psid) == FALSE);
 | |
| 
 | |
|     debug3("AddAce()...");
 | |
|   
 | |
|     FAIL(AddAce(pNewAcl, ACL_REVISION, MAXDWORD, 
 | |
|                     (LPVOID)pace, pace -> Header.AceSize) == FALSE);
 | |
| 
 | |
|     /*
 | |
|      * Add the second ACE to the windowstation.
 | |
|      */
 | |
|  
 | |
|     pace -> Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;
 | |
|     pace -> Mask = WINSTA_ALL;
 | |
| 
 | |
|     debug3("AddAce()...");
 | |
|   
 | |
|     FAIL(AddAce(pNewAcl, ACL_REVISION, MAXDWORD, 
 | |
|                     (LPVOID) pace, pace -> Header.AceSize) == FALSE);
 | |
|   }
 | |
|   
 | |
|   /*
 | |
|    * Set new dacl for the security descriptor.
 | |
|    */
 | |
|  
 | |
|   debug3("SetSecurityDescriptorDacl()...");
 | |
|   
 | |
|   FAIL(SetSecurityDescriptorDacl(psdNew, TRUE, pNewAcl, FALSE) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * Set the new security descriptor for the windowstation.
 | |
|    */
 | |
|   
 | |
|   debug3("SetUserObjectSecurity()...");
 | |
|   
 | |
|   FAIL(SetUserObjectSecurity(hwinsta, &si, psdNew) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * Indicate success.
 | |
|    */
 | |
|  
 | |
|   bSuccess = TRUE;
 | |
| 
 | |
| fail:
 | |
| 
 | |
|   /*
 | |
|    * 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;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Gives ore removes user right to use given desktop.
 | |
|  *
 | |
|  * WARNING. This right is given only for login session, i.e,
 | |
|  *          account's properties are not be changed.
 | |
|  *
 | |
|  * hdesk - handle to desktop (IN)
 | |
|  * psid  - pointer to user's SID (IN)
 | |
|  * mode  - 1 for add, 0 for remove (IN)
 | |
|  *
 | |
|  * RETURNS: TRUE if OK.
 | |
|  */
 | |
| 
 | |
| BOOL ModifyTheAceDesktop(HDESK hdesk, PSID psid, int mode)
 | |
| {
 | |
|   debug2("-> ModifyTheAceDesktop(mode = %d)...", mode);
 | |
|   
 | |
|   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;
 | |
|   
 | |
|   HANDLE procHeap = NULL;
 | |
|   
 | |
|   ACCESS_ALLOWED_ACE *pTempAce;
 | |
| 
 | |
|   SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
 | |
| 
 | |
|   unsigned int i;
 | |
| 
 | |
|   /*
 | |
|    * is input SID valid?
 | |
|    */
 | |
|   
 | |
|   debug3("Testing is SID valid...");
 | |
| 
 | |
|   FAIL(psid == NULL);
 | |
|   
 | |
|   FAIL(IsValidSid(psid) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * Obtain process heap. 
 | |
|    */
 | |
|   
 | |
|   procHeap = GetProcessHeap();
 | |
|   
 | |
|   /*
 | |
|    * Obtain the security descriptor for the desktop object.
 | |
|    */
 | |
| 
 | |
|   debug3("GetUserObjectSecurity()...");
 | |
|   
 | |
|   if (!GetUserObjectSecurity(hdesk, &si, psd, 
 | |
|                                  dwSidSize, &dwSdSizeNeeded))
 | |
|   {
 | |
|     FAIL(GetLastError() != ERROR_INSUFFICIENT_BUFFER);
 | |
| 
 | |
|     psd = (PSECURITY_DESCRIPTOR) HeapAlloc(procHeap,
 | |
|                                                HEAP_ZERO_MEMORY, 
 | |
|                                                    dwSdSizeNeeded);
 | |
|       
 | |
|     FAIL(psd == NULL); 
 | |
|      
 | |
|     psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(procHeap, 
 | |
|                                                  HEAP_ZERO_MEMORY, 
 | |
|                                                      dwSdSizeNeeded);
 | |
| 
 | |
|     FAIL(psdNew == NULL);
 | |
|       
 | |
|     dwSidSize = dwSdSizeNeeded;
 | |
| 
 | |
|     FAIL(GetUserObjectSecurity(hdesk, &si, psd, dwSidSize, 
 | |
|                                    &dwSdSizeNeeded) == FALSE);
 | |
|   }
 | |
|   
 | |
|   /*
 | |
|    * create a new security descriptor.
 | |
|    */
 | |
| 
 | |
|   debug3("InitializeSecurityDescriptor()...");
 | |
|   
 | |
|   FAIL(InitializeSecurityDescriptor(psdNew, 
 | |
|                                         SECURITY_DESCRIPTOR_REVISION) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * obtain the dacl from the security descriptor.
 | |
|    */
 | |
| 
 | |
|   debug3("GetSecurityDescriptorDacl()...");
 | |
|   
 | |
|   FAIL(GetSecurityDescriptorDacl(psd, &bDaclPresent, 
 | |
|                                      &pacl, &bDaclExist) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * 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 info.
 | |
|      */
 | |
| 
 | |
|     debug3("GetAclInformation()..");
 | |
|   
 | |
|     FAIL(GetAclInformation(pacl, (LPVOID)&aclSizeInfo, 
 | |
|                                sizeof(ACL_SIZE_INFORMATION), 
 | |
|                                    AclSizeInformation) == FALSE);
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Compute the size of the new acl.
 | |
|    */
 | |
|  
 | |
|   dwNewAclSize = aclSizeInfo.AclBytesInUse;
 | |
|   
 | |
|   if (mode == ADD_RIGHT)
 | |
|   {
 | |
|     dwNewAclSize = dwNewAclSize + sizeof(ACCESS_ALLOWED_ACE) 
 | |
|                  + GetLengthSid(psid) - sizeof(DWORD);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     dwNewAclSize = dwNewAclSize - sizeof(ACCESS_ALLOWED_ACE) 
 | |
|                  - GetLengthSid(psid) + sizeof(DWORD);
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Allocate buffer for the new acl.
 | |
|    */
 | |
| 
 | |
|   pNewAcl = (PACL) HeapAlloc(procHeap, 
 | |
|                                  HEAP_ZERO_MEMORY, dwNewAclSize);
 | |
| 
 | |
|   FAIL(pNewAcl == NULL);
 | |
| 
 | |
|   /*
 | |
|    * Initialize the new acl.
 | |
|    */
 | |
|  
 | |
|   debug3("InitializeAcl()..");
 | |
|     
 | |
|   FAIL(InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * If DACL is present, copy it to a new DACL.
 | |
|    */
 | |
| 
 | |
|   if (bDaclPresent) // only copy if DACL was present
 | |
|   {
 | |
|     /*
 | |
|      * Copy the ACEs to our new ACL.
 | |
|      */
 | |
|       
 | |
|     if (aclSizeInfo.AceCount)
 | |
|     {
 | |
| 
 | |
|       for (i=0; i < aclSizeInfo.AceCount; i++)
 | |
|       {
 | |
|         /*
 | |
|          * Get next ACE from old ACL.
 | |
|          */
 | |
|   
 | |
|         FAIL(GetAce(pacl, i, &pTempAce) == FALSE);
 | |
| 
 | |
|         /*
 | |
|          * Add the ACE to the new ACL.
 | |
|          *
 | |
|          * We copy all original list for RIGHT_ADD mode and
 | |
|          * skip ACE with given input SID in RIGHT_REMOVE mode.
 | |
|          */
 | |
| 
 | |
|         if (mode == ADD_RIGHT || EqualSid(psid, &pTempAce -> SidStart) == 0)
 | |
|         {        
 | |
|           FAIL(AddAce(pNewAcl, ACL_REVISION, MAXDWORD, pTempAce, 
 | |
|                           ((PACE_HEADER) pTempAce) -> AceSize) == FALSE);
 | |
|         }                  
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (mode == ADD_RIGHT)
 | |
|   {
 | |
|     /*
 | |
|      * Add one additional ace to the dacl.
 | |
|      */
 | |
|   
 | |
|     debug3("AccessAllowedAce()...");
 | |
|   
 | |
|     FAIL(AddAccessAllowedAce(pNewAcl, ACL_REVISION, 
 | |
|                                  DESKTOP_ALL, psid) == FALSE);
 | |
|   } 
 | |
| 
 | |
|   /*
 | |
|    * Set new dacl to the new security descriptor.
 | |
|    */
 | |
| 
 | |
|   debug3("AddSecurityDescriptiorDacl()..");
 | |
|   
 | |
|   FAIL(SetSecurityDescriptorDacl(psdNew, TRUE, pNewAcl, FALSE) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * Set the new security descriptor for the desktop object.
 | |
|    */
 | |
|    
 | |
|   debug3("SetUserObjectSecurity()..");
 | |
|   
 | |
|   FAIL(SetUserObjectSecurity(hdesk, &si, psdNew) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * Indicate success.
 | |
|    */
 | |
| 
 | |
|   bSuccess = TRUE;
 | |
| 
 | |
| fail:
 | |
| 
 | |
|   /*
 | |
|    * Free buffers.
 | |
|    */
 | |
| 
 | |
|   debug3("Freeing buffers...");
 | |
|   
 | |
|   if (pNewAcl != NULL)
 | |
|   {
 | |
|     HeapFree(procHeap, 0, (LPVOID) pNewAcl);
 | |
|   }
 | |
| 
 | |
|   if (psd != NULL)
 | |
|   {
 | |
|     HeapFree(procHeap, 0, (LPVOID) psd);
 | |
|   }
 | |
| 
 | |
|   if (psdNew != NULL)
 | |
|   {
 | |
|     HeapFree(procHeap, 0, (LPVOID) psdNew);
 | |
|   }
 | |
| 
 | |
|   debug3("<- AddTheAceDesktop()...");
 | |
|   
 | |
|   return bSuccess;
 | |
| }
 | |
| 
 | |
| void RemoveSid(PSID *psid)
 | |
| {
 | |
|   HeapFree(GetProcessHeap(), 0, (LPVOID) *psid);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Gives user rights to use 'WinStation0' and 'default' desktop.
 | |
|  *
 | |
|  * psid - pointer to SID for acount SID (IN)
 | |
|  * mode - 1 for add, 0 for remove (IN)
 | |
|  *
 | |
|  * RETURNS: 0 if OK.
 | |
|  */
 | |
| 
 | |
| int ModifyRightsToDesktopBySid(PSID psid, int mode)
 | |
| {
 | |
|   debug3("-> ModifyRightsToDesktopBySid(mode = %d)...", mode);
 | |
|   
 | |
|   HDESK hdesk = NULL;
 | |
| 
 | |
|   HWINSTA hwinsta = NULL;
 | |
|   
 | |
|   int exitCode = -1;
 | |
|     
 | |
|   /*
 | |
|    * obtain a handle to the interactive windowstation.
 | |
|    */
 | |
|   
 | |
|   debug3("OpenWindowStation()...");
 | |
|   
 | |
|   hwinsta = OpenWindowStation("winsta0", FALSE, READ_CONTROL | WRITE_DAC);
 | |
|   
 | |
|   FAIL(hwinsta == NULL);
 | |
| 
 | |
|   debug3("GetProcessWindowStation()...");
 | |
|   
 | |
|   HWINSTA hwinstaold = GetProcessWindowStation();
 | |
| 
 | |
|   /*
 | |
|    * Set the windowstation to winsta0 so that you obtain the
 | |
|    * correct default desktop.
 | |
|    */
 | |
|   
 | |
|   debug3("SetProcessWindowStation()...");
 | |
|   
 | |
|   FAIL(!SetProcessWindowStation(hwinsta));
 | |
| 
 | |
|   /*
 | |
|    * Obtain a handle to the "default" desktop.
 | |
|    */
 | |
| 
 | |
|   debug3("OpenDesktop()...");
 | |
|   
 | |
|   hdesk = OpenDesktop("default", 0, FALSE, READ_CONTROL | WRITE_DAC |
 | |
|                           DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS);
 | |
|   
 | |
|   FAIL(hdesk == NULL);
 | |
| 
 | |
|   /*
 | |
|    * Add the user to interactive windowstation.
 | |
|    */
 | |
|   
 | |
|   debug3("ModifyTheAceWindowStation()...");
 | |
|   
 | |
|   FAIL(!ModifyTheAceWindowStation(hwinsta, psid, mode));
 | |
| 
 | |
|   /*
 | |
|    * Add user to "default" desktop.
 | |
|    */
 | |
|   
 | |
|   debug3("AddTheAceDesktop()...");
 | |
|   
 | |
|   FAIL(!ModifyTheAceDesktop(hdesk, psid, mode));
 | |
| 
 | |
|   exitCode = 0;
 | |
| 
 | |
| fail:
 | |
| 
 | |
|   /*
 | |
|    * Close the handles to the interactive windowstation and desktop.
 | |
|    */
 | |
|   
 | |
|   debug3("CloseWindowStation()...");
 | |
|   
 | |
|   if (hwinsta)
 | |
|   {
 | |
|     CloseWindowStation(hwinsta);
 | |
|   }  
 | |
| 
 | |
|   debug3("CloseDesktop()...");
 | |
|   
 | |
|   if (hdesk)
 | |
|   {
 | |
|     CloseDesktop(hdesk);
 | |
|   }
 | |
|   
 | |
|   debug3("<- ModifyRightsToDesktopBySid()...");
 | |
|   
 | |
|   return exitCode;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Gives or removes user rights to use 'WinStation0' and 'default' desktop.
 | |
|  *
 | |
|  * hToken - logged user's token (IN)
 | |
|  * mode   - 1 for add, 0 for remove (IN)
 | |
|  *
 | |
|  * RETURNS: 0 if OK.
 | |
|  */
 | |
| 
 | |
| int ModifyRightsToDesktop(HANDLE hToken, int mode)
 | |
| {
 | |
|   debug2("-> ModifyRightsToDesktop(mode = %d)...", mode);
 | |
|   
 | |
|   PSID psid = NULL;
 | |
|   
 | |
|   int exitCode = -1;
 | |
|   
 | |
|   /*
 | |
|    * Obtain the logon sid of the user fester.
 | |
|    */
 | |
|   
 | |
|   debug3("ObtainSid()...");
 | |
|   
 | |
|   FAIL(!ObtainSid(hToken, &psid));
 | |
|   
 | |
|   FAIL(ModifyRightsToDesktopBySid(psid, mode));
 | |
|   
 | |
|   if (psid)
 | |
|   {
 | |
|     RemoveSid(&psid);
 | |
|   }
 | |
|   
 | |
|   exitCode = 0;
 | |
|   
 | |
| fail:
 | |
| 
 | |
|   debug2("<- ModifyRightsToDesktop()...");
 | |
| 
 | |
|   return exitCode;
 | |
| }
 |