mirror of
				https://github.com/PowerShell/Win32-OpenSSH.git
				synced 2025-10-31 11:44:38 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			796 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			796 lines
		
	
	
		
			17 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 "win32auth.h"
 | |
| 
 | |
| /*
 | |
|  * Retrieve Security ID (SID) from username.
 | |
|  *
 | |
|  * psid   - output SID (OUT)
 | |
|  * user   - username string (IN)
 | |
|  *
 | |
|  * RETURNS: 0 if OK.
 | |
|  */
 | |
| 
 | |
| static int GetSidW(PSID *psid, const wchar_t *user)
 | |
| {
 | |
|   wchar_t *refDomain = NULL;
 | |
| 
 | |
|   DWORD refDomainSize = 0;
 | |
| 
 | |
|   DWORD sidSize = 0;
 | |
| 
 | |
|   SID_NAME_USE peUse;
 | |
|     
 | |
|   int exitCode = 1;
 | |
| 
 | |
|   /*
 | |
|    * Retrieve SID's size
 | |
|    */
 | |
| 
 | |
|   LookupAccountNameW(NULL, user, NULL, &sidSize, NULL, &refDomainSize, &peUse);
 | |
| 
 | |
|   FAIL(GetLastError() != ERROR_INSUFFICIENT_BUFFER);
 | |
| 
 | |
|   /*
 | |
|    * Allocate buffer and retrieve SID
 | |
|    */
 | |
|   
 | |
|   *psid = (PSID) LocalAlloc(LPTR, sidSize);
 | |
| 
 | |
|   refDomain = (wchar_t *) LocalAlloc(LPTR, refDomainSize * sizeof(wchar_t));
 | |
| 
 | |
|   FAIL(LookupAccountNameW(NULL, user, *psid, &sidSize, 
 | |
|                              refDomain, &refDomainSize, &peUse) == FALSE);
 | |
|   
 | |
|   exitCode = 0;
 | |
|   
 | |
| fail:
 | |
|   
 | |
|   /*
 | |
|    * We don't need reference domain.
 | |
|    */
 | |
|   
 | |
|   if (refDomain)
 | |
|   {
 | |
|     LocalFree(refDomain);
 | |
|   }
 | |
|   
 | |
|   if (exitCode != 0)
 | |
|   {
 | |
|     debug("ERROR. Cannot retrieve SID (%u).", GetLastError());
 | |
|   }
 | |
|   
 | |
|   return exitCode;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Enable or disable privilege for current running process
 | |
|  *
 | |
|  * privName - privilege name (IN)
 | |
|  * enabled  - 1 for enabling, 0 for disabling (IN)
 | |
|  *
 | |
|  * RETURNS: 0 if OK.
 | |
|  */
 | |
| 
 | |
| int EnablePrivilege(const char *privName, int enabled)
 | |
| {
 | |
|   TOKEN_PRIVILEGES tp;
 | |
|   
 | |
|   HANDLE hProcToken = NULL;
 | |
|   
 | |
|   LUID luid;
 | |
| 
 | |
|   int exitCode = 1;
 | |
| 
 | |
|   /*
 | |
|    * Retrievie LUID from privilege name
 | |
|    */
 | |
|   
 | |
|   FAIL(LookupPrivilegeValue(NULL, privName, &luid) == FALSE);
 | |
|   
 | |
|   /*
 | |
|    * Retrievie token for current running process
 | |
|    */
 | |
| 
 | |
|   FAIL(OpenProcessToken(GetCurrentProcess(), 
 | |
|                             TOKEN_ADJUST_PRIVILEGES, &hProcToken) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * Adjust privilege to current running process
 | |
|    */
 | |
|   
 | |
|   tp.PrivilegeCount           = 1;
 | |
|   tp.Privileges[0].Luid       = luid;
 | |
|   tp.Privileges[0].Attributes = enabled ? SE_PRIVILEGE_ENABLED : 0;
 | |
| 
 | |
|   FAIL(AdjustTokenPrivileges(hProcToken, FALSE, &tp, 
 | |
|                                  sizeof(TOKEN_PRIVILEGES), NULL, NULL) == FALSE);
 | |
| 
 | |
|   exitCode = 0;
 | |
|   
 | |
| fail:
 | |
| 
 | |
|   /*
 | |
|    * Free allocated memory if needed.
 | |
|    */
 | |
|   
 | |
|   if (hProcToken)
 | |
|   {
 | |
|     CloseHandle(hProcToken);
 | |
|   }  
 | |
| 
 | |
|   if (exitCode)
 | |
|   {
 | |
|     DWORD err = GetLastError();
 | |
|     
 | |
|     debug("ERROR. Cannot enable privilege to current process (%u).", err);
 | |
|   }
 | |
|   
 | |
|   return exitCode;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * This functions allocate and initialize some 'well known' SIDs.
 | |
|  * This SIDs are global uniqualy, i.e. they are the same on all
 | |
|  * machines.
 | |
|  */
 | |
| 
 | |
| static PSID LocalSID()
 | |
| {
 | |
|   PSID psid = NULL;
 | |
| 
 | |
|   SID_IDENTIFIER_AUTHORITY nt = SECURITY_LOCAL_SID_AUTHORITY;
 | |
|   
 | |
|   AllocateAndInitializeSid(&nt, 1, 0, 0, 0, 0, 0, 0, 0, 0, &psid);
 | |
|   
 | |
|   return psid;
 | |
| }
 | |
| 
 | |
| static PSID EveryoneSID()
 | |
| {
 | |
|   PSID psid = NULL;
 | |
|   
 | |
|   SID_IDENTIFIER_AUTHORITY nt = SECURITY_WORLD_SID_AUTHORITY;
 | |
| 
 | |
|   AllocateAndInitializeSid(&nt, 1, 0, 0, 0, 0, 0, 0, 0, 0, &psid);
 | |
|   
 | |
|   return psid;
 | |
| }
 | |
| 
 | |
| static PSID AuthenticatedUsersSID()
 | |
| {
 | |
|   PSID psid = NULL;
 | |
| 
 | |
|   SID_IDENTIFIER_AUTHORITY nt = SECURITY_NT_AUTHORITY;
 | |
|   
 | |
|   AllocateAndInitializeSid(&nt, 1, SECURITY_AUTHENTICATED_USER_RID, 
 | |
|                                0, 0, 0, 0, 0, 0, 0, &psid);
 | |
|   
 | |
|   return psid;
 | |
| }
 | |
| 
 | |
| static PSID InteractiveSID()
 | |
| {
 | |
|   PSID psid = NULL;
 | |
|   
 | |
|   SID_IDENTIFIER_AUTHORITY nt = SECURITY_NT_AUTHORITY;
 | |
|   
 | |
|   AllocateAndInitializeSid(&nt, 1, SECURITY_INTERACTIVE_RID,
 | |
|                                0, 0, 0, 0, 0, 0, 0, &psid);
 | |
|   
 | |
|   return psid;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Allocate new TOKEN_PRIVILEGES structure and fill it with privileges
 | |
|  * from given user account.
 | |
|  *
 | |
|  * pPrivToken - new, allocated structure (OUT)
 | |
|  * userSid    - SID of user (IN)
 | |
|  *
 | |
|  * RETURNS: 0 if OK.
 | |
|  */
 | |
| 
 | |
| int SetupTokenPrivileges(PTOKEN_PRIVILEGES *pPrivToken, PSID userSid)
 | |
| {
 | |
|   DWORD ntStat = 0;
 | |
|   
 | |
|   int exitCode = 1;
 | |
|   
 | |
|   LSA_OBJECT_ATTRIBUTES lsaOA = {0};
 | |
| 
 | |
|   PLSA_UNICODE_STRING userRights = NULL;
 | |
|   
 | |
|   ULONG nRights = 0;
 | |
|   
 | |
|   DWORD size;
 | |
|   
 | |
|   int i, j;
 | |
|   
 | |
|   /*
 | |
|    * Open local policy.
 | |
|    */
 | |
| 
 | |
|   LSA_HANDLE hPolicy;
 | |
|   
 | |
|   lsaOA.Length = sizeof(lsaOA);
 | |
|   
 | |
|   ACCESS_MASK mask = POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES;
 | |
|   
 | |
|   debug("Opening local policy...");
 | |
|   
 | |
|   ntStat = LsaOpenPolicy(NULL, &lsaOA, mask, &hPolicy);
 | |
|   
 | |
|   FAIL(ntStat);
 | |
|   
 | |
|   /*
 | |
|    * Retrieve user's privileges.
 | |
|    */
 | |
|   
 | |
|   debug("Retrieving user's privileges list...");
 | |
|   
 | |
|   ntStat = LsaEnumerateAccountRights(hPolicy, userSid, &userRights, &nRights);
 | |
| 
 | |
|   /*
 | |
|    * This error code means there is no any rights.
 | |
|    * In this case, we should create empty list.
 | |
|    */
 | |
|   
 | |
|   if (ntStat == STATUS_OBJECT_NAME_NOT_FOUND)
 | |
|   {
 | |
|     nRights = 0;
 | |
|     ntStat  = 0;
 | |
|   }
 | |
|   
 | |
|   FAIL(ntStat);
 | |
|   
 | |
|   /*
 | |
|    * FIXME. Now if some privilege name is not recognized by
 | |
|    * LookupPrivilegeName() part of pPrivToken buffer will be
 | |
|    * unused.
 | |
|    */
 | |
|    
 | |
|   /*
 | |
|    * Allocate buffer for TOKEN_PRIVILEGES.
 | |
|    */
 | |
|   
 | |
|   debug("Allocating buffer for TOKEN_PRIVILEGES [%u]...", nRights);
 | |
|   
 | |
|   size = sizeof(DWORD) + nRights * sizeof(LUID_AND_ATTRIBUTES);
 | |
|   
 | |
|   (*pPrivToken) = LocalAlloc(LPTR, size);
 | |
|   
 | |
|   FAIL(pPrivToken == NULL);
 | |
|   
 | |
|   /*
 | |
|    * Fill TOKEN_PRIVILEGES with LUIDs of retrieved privileges.
 | |
|    */
 | |
|   
 | |
|   j = 0;
 | |
|   
 | |
|   for (i = 0; i < nRights; i++)
 | |
|   {
 | |
|     /*
 | |
|      * Retrieve unicode name of privilege.
 | |
|      * Make sure there is a zero word at the end.
 | |
|      */
 | |
|     
 | |
|     wchar_t privName[128];
 | |
|     
 | |
|     int len = userRights[i].Length;
 | |
|     
 | |
|     memcpy(privName, userRights[i].Buffer, len * sizeof(wchar_t));
 | |
|     
 | |
|     privName[len] = 0;
 | |
|     
 | |
|     debug("Adding %ls... ", privName);
 | |
| 
 | |
|     /*
 | |
|      * Retrieve LUID for given privilege name.
 | |
|      */
 | |
|     
 | |
|     if(LookupPrivilegeValueW(NULL, privName,
 | |
|                                    &(*pPrivToken) -> Privileges[i].Luid) == FALSE)
 | |
|     {
 | |
|       debug("WARNING. Cannot add privilege to token (%u).", GetLastError());
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       (*pPrivToken) -> Privileges[j].Attributes = SE_PRIVILEGE_ENABLED;
 | |
| 
 | |
|       j++;
 | |
|     }  
 | |
|   }
 | |
|   
 | |
|   /*
 | |
|    * j = number of privileges, which were recognized by
 | |
|    * LookupPrivilegesValue().
 | |
|    */
 | |
|   
 | |
|   (*pPrivToken) -> PrivilegeCount = j;
 | |
|   
 | |
|   exitCode = 0;
 | |
| 
 | |
| fail:
 | |
| 
 | |
|   /*
 | |
|    * Clenup.
 | |
|    */
 | |
|   
 | |
|   if (userRights)
 | |
|   {
 | |
|     LsaFreeMemory(userRights);
 | |
|   }
 | |
|   
 | |
|   if (hPolicy)
 | |
|   {
 | |
|     CloseHandle(hPolicy);
 | |
|   }  
 | |
|   
 | |
|   if (exitCode)
 | |
|   {
 | |
|     debug("ERROR. Cannot setup TOKEN_PRIVILEGES (err=%u, ntStat=%x).",
 | |
|               GetLastError(), ntStat);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Allocate new TOKEN_GROUPS structure and fill it with groups, which
 | |
|  * given user belong to.
 | |
|  *
 | |
|  * pGroupsToken - new, allocated TOKEN_GROUPS structure (OUT)
 | |
|  * userNameW    - wide string with username (IN)
 | |
|  *
 | |
|  * RETURNS: 0 if OK.
 | |
|  */
 | |
| 
 | |
| int SetupTokenGroups(PTOKEN_GROUPS *groupsToken, wchar_t *userNameW)
 | |
| {
 | |
|   wchar_t **localGroups  = NULL;
 | |
|   wchar_t **globalGroups = NULL;
 | |
|   
 | |
|   DWORD nLocalGroups     = 0;
 | |
|   DWORD nLocalGroupsTot  = 0;
 | |
|   
 | |
|   DWORD nGlobalGroups    = 0;
 | |
|   DWORD nGlobalGroupsTot = 0;
 | |
|   
 | |
|   DWORD nGroupsTotal     = 0;
 | |
|   
 | |
|   DWORD size;
 | |
|   
 | |
|   int i;
 | |
|   
 | |
|   int exitCode = 1;
 | |
| 
 | |
|   /*
 | |
|    * Retrieve local groups, which user belong to.
 | |
|    */
 | |
|   
 | |
|   debug("Retrieving local groups list...");
 | |
|   
 | |
|   FAIL(NetUserGetLocalGroups(NULL, userNameW, 0, 
 | |
|                                 LG_INCLUDE_INDIRECT, 
 | |
|                                     (LPBYTE *) &localGroups,
 | |
|                                          MAX_PREFERRED_LENGTH,
 | |
|                                              &nLocalGroups, 
 | |
|                                                  &nLocalGroupsTot));
 | |
| 
 | |
|   debug("Retrieving global groups list...");
 | |
|   
 | |
|   /*
 | |
|    * Retrieve global groups, which user belong to.
 | |
|    */
 | |
| 
 | |
|   FAIL(NetUserGetGroups(NULL, userNameW, 0, (LPBYTE *) 
 | |
|                             &globalGroups, MAX_PREFERRED_LENGTH, 
 | |
|                                 &nGlobalGroups, &nGlobalGroupsTot));
 | |
|   
 | |
| 
 | |
|   /*
 | |
|    * Allocate buffer for TOKEN_GROUPS struct.
 | |
|    *
 | |
|    * We assume user belong to Everyone, AuthenticatedUsers, Local, Interactive
 | |
|    * and groups retrievied from NetUserGetLocalGroups() and NetUserGetGroups()
 | |
|    * for given user.
 | |
|    */
 | |
|   
 | |
|   nGroupsTotal = nLocalGroups + nGlobalGroups + 4;
 | |
| 
 | |
|   size = (nGroupsTotal + 1) * sizeof(SID_AND_ATTRIBUTES) + sizeof(DWORD);
 | |
|   
 | |
|   *groupsToken = (TOKEN_GROUPS *) LocalAlloc(LPTR, size);
 | |
|   
 | |
|   (*groupsToken) -> GroupCount = nGroupsTotal;
 | |
| 
 | |
|   /*
 | |
|    * Write SIDs of local groups into TOKEN_GROUPS struct.
 | |
|    */
 | |
|   
 | |
|   #define INSIDE_GROUP_FLAG SE_GROUP_ENABLED\
 | |
|                             | SE_GROUP_ENABLED_BY_DEFAULT\
 | |
|                             | SE_GROUP_MANDATORY
 | |
| 
 | |
|   int delta = 4;
 | |
| 
 | |
|   for (i = 0; i < nLocalGroups; i++)
 | |
|   {
 | |
|     FAIL(GetSidW(&(*groupsToken) -> Groups[i + delta].Sid, localGroups[i]));
 | |
| 
 | |
|     (*groupsToken) -> Groups[i + delta].Attributes = INSIDE_GROUP_FLAG;
 | |
|   }
 | |
|   
 | |
|   /*
 | |
|    * Write SIDs of global groups into TOKEN_GROUPS struct.
 | |
|    */
 | |
| 
 | |
|   delta = 4 + nLocalGroups;
 | |
| 
 | |
|   for (i = 0; i < nGlobalGroups; i++)
 | |
|   {
 | |
|     FAIL(GetSidW(&(*groupsToken) -> Groups[delta + i].Sid, globalGroups[i]));
 | |
| 
 | |
|     (*groupsToken) -> Groups[delta + i].Attributes = INSIDE_GROUP_FLAG;
 | |
|   }
 | |
|   
 | |
|   /*
 | |
|    * Write SIDs of Everyone, AuthenticatedUsers, Local and Interactive
 | |
|    * groups into TOKEN_GROUPS struct.
 | |
|    */
 | |
|   
 | |
|   (*groupsToken) -> Groups[0].Sid = EveryoneSID();
 | |
|   (*groupsToken) -> Groups[0].Attributes = INSIDE_GROUP_FLAG;
 | |
|   
 | |
|   (*groupsToken) -> Groups[1].Sid = AuthenticatedUsersSID();
 | |
|   (*groupsToken) -> Groups[1].Attributes = INSIDE_GROUP_FLAG;
 | |
|   
 | |
|   (*groupsToken) -> Groups[2].Sid = LocalSID();
 | |
|   (*groupsToken) -> Groups[2].Attributes = INSIDE_GROUP_FLAG;
 | |
|   
 | |
|   (*groupsToken) -> Groups[3].Sid = InteractiveSID();
 | |
|   (*groupsToken) -> Groups[3].Attributes = INSIDE_GROUP_FLAG;
 | |
| 
 | |
|   exitCode = 0;
 | |
| 
 | |
| fail:
 | |
| 
 | |
|   /*
 | |
|    * Clean up.
 | |
|    */
 | |
|   
 | |
|   NetApiBufferFree(localGroups);
 | |
|   NetApiBufferFree(globalGroups);
 | |
| 
 | |
|   if (exitCode)
 | |
|   {
 | |
|     debug("ERROR. Failed to setup TOKEN_GROUPS (%u).", GetLastError());
 | |
|   }
 | |
|   
 | |
|   return exitCode;
 | |
| }
 | |
| 
 | |
| #ifdef USE_NTCREATETOKEN
 | |
| 
 | |
| /*
 | |
|  * Creates new user's access token using NtCreateToken() function.
 | |
|  *
 | |
|  * userName   - user name string (IN)
 | |
|  * domainName - domain name (IN) (UNUSED)
 | |
|  * sourceName - ?? (IN)
 | |
|  *
 | |
|  * RETURNS: Handle to created token or INVALID_HANDLE_VALUE if fails.
 | |
|  */
 | |
| 
 | |
| HANDLE CreateUserToken(const char *userName, 
 | |
|                            const char *domainName, const char *sourceName)
 | |
| {
 | |
|   debug2("-> CreateUserToken()...");
 | |
|   
 | |
|   HMODULE hNtDll = NULL;
 | |
|   
 | |
|   NtCreateTokenPtr NtCreateToken = NULL;
 | |
|   
 | |
|   HANDLE token = INVALID_HANDLE_VALUE;
 | |
|   
 | |
|   /*
 | |
|    * These are compounds of user's access token structure.
 | |
|    * The goal is setup these strutures and combine them
 | |
|    * into one access token using NtCreateToken() WINAPI function.
 | |
|    */
 | |
|   
 | |
|   LUID authId = SYSTEM_LUID;
 | |
|   
 | |
|   TOKEN_USER userToken;
 | |
| 
 | |
|   PTOKEN_GROUPS groupsToken = NULL;
 | |
|   
 | |
|   PTOKEN_PRIVILEGES pPrivToken = NULL;
 | |
|   
 | |
|   TOKEN_OWNER ownerToken;
 | |
|   
 | |
|   TOKEN_PRIMARY_GROUP primaryGroupToken;
 | |
| 
 | |
|   TOKEN_SOURCE sourceToken;  
 | |
|   
 | |
|   PTOKEN_DEFAULT_DACL pDaclToken = NULL;
 | |
|   
 | |
|   LARGE_INTEGER expirationTime = {0xFFFFFFFF, 0x7FFFFFFF};
 | |
|   
 | |
|   OBJECT_ATTRIBUTES oa;
 | |
|   
 | |
|   /*
 | |
|    * Temporary variables
 | |
|    */
 | |
|   
 | |
|   SECURITY_QUALITY_OF_SERVICE sqos = 
 | |
|   {
 | |
|     sizeof(sqos), 
 | |
|     SecurityAnonymous, 
 | |
|     SECURITY_STATIC_TRACKING,
 | |
|     FALSE
 | |
|   };
 | |
|     
 | |
|   int i;
 | |
|   
 | |
|   size_t size = 0;
 | |
|   
 | |
|   wchar_t *userNameW = NULL;
 | |
|   
 | |
|   DWORD cbSize;
 | |
|   
 | |
|   HANDLE hProcToken = NULL;
 | |
|   
 | |
|   /*
 | |
|    * Variables to handle error codes.
 | |
|    */
 | |
|   
 | |
|   int exitCode = 1;
 | |
|   int ntStat   = 0;
 | |
|   
 | |
|   /*
 | |
|    * Make wide char version of user's name.
 | |
|    */
 | |
|   
 | |
|   size = (strlen(userName) + 1) * sizeof(wchar_t);
 | |
|   
 | |
|   userNameW = (wchar_t *) LocalAlloc(LPTR, size);;
 | |
| 
 | |
|   swprintf(userNameW, L"%hs", userName);
 | |
|   
 | |
|   /*
 | |
|    * Give needed privilege to current running process
 | |
|    */
 | |
|   
 | |
|   debug("Enabling privilege to current running process...");
 | |
| 
 | |
|   EnablePrivilege("SeTcbPrivilege", 1);
 | |
|   EnablePrivilege("SeChangeNotifyPrivilege", 1);
 | |
|   EnablePrivilege("SeIncreaseQuotaPrivilege", 1);
 | |
|   EnablePrivilege("SeAssignPrimaryTokenPrivilege", 1);
 | |
|   EnablePrivilege("SeCreateTokenPrivilege", 1);
 | |
|   
 | |
|   /*
 | |
|    * Create TOKEN_USER part
 | |
|    */
 | |
|       
 | |
|   debug("Setting up TOKEN_USER...");
 | |
|   
 | |
|   FAIL(GetSidW(&userToken.User.Sid, userNameW));
 | |
| 
 | |
|   userToken.User.Attributes = 0;
 | |
|   
 | |
|   /*
 | |
|    * Create TOKEN_OWNER part. We assume Owner = User.
 | |
|    */
 | |
|   
 | |
|   debug("Setting up TOKEN_OWNER...");
 | |
|   
 | |
|   FAIL(GetSidW(&ownerToken.Owner, userNameW));
 | |
|   
 | |
|   /*
 | |
|    * Create TOKEN_SOURCE part
 | |
|    */
 | |
|   
 | |
|   debug("Setting up TOKEN_SOURCE...");
 | |
|   
 | |
|   FAIL(AllocateLocallyUniqueId(&sourceToken.SourceIdentifier) == FALSE);
 | |
|   
 | |
|   size = min(strlen(sourceName), 8);
 | |
|       
 | |
|   memcpy(sourceToken.SourceName, "********", 8);
 | |
|   memcpy(sourceToken.SourceName, sourceName, size);
 | |
| 
 | |
|   /*
 | |
|    * Create TOKEN_GROUPS part
 | |
|    */
 | |
|   
 | |
|   debug("Setting up TOKEN_GROUPS...");
 | |
|   
 | |
|   FAIL(SetupTokenGroups(&groupsToken, userNameW));
 | |
|   
 | |
|   /*
 | |
|    * Create TOKEN_PRIVILEGES part
 | |
|    */
 | |
|   
 | |
|   debug("Setting up TOKEN_PRIVILEGES...");
 | |
|   
 | |
|   FAIL(SetupTokenPrivileges(&pPrivToken, userToken.User.Sid));
 | |
|   
 | |
|   /*
 | |
|    * Create TOKEN_PRIMARY_GROUP part
 | |
|    */
 | |
|   
 | |
|   debug("Setting up TOKEN_PRIMARY GROUP...");
 | |
|   
 | |
|   primaryGroupToken.PrimaryGroup = EveryoneSID();
 | |
|   
 | |
|   /*
 | |
|    * Setup object attributes
 | |
|    */
 | |
|   
 | |
|   memset(&oa, 0, sizeof(oa));
 | |
| 
 | |
|   oa.Length = sizeof(oa);
 | |
|   
 | |
|   oa.SecurityQualityOfService = &sqos;
 | |
| 
 | |
|   /*
 | |
|    * Setup TOKEN_DEFAULT_DACL part.
 | |
|    */
 | |
|   
 | |
|   debug("Setting up TOKEN_DEFAULT_DACL...");
 | |
|   
 | |
|   debug("Opening current process's token...");
 | |
| 
 | |
|   FAIL(OpenProcessToken(GetCurrentProcess(),
 | |
|                             TOKEN_QUERY | TOKEN_QUERY_SOURCE, 
 | |
|                                 &hProcToken) == FALSE);
 | |
| 
 | |
|   debug("Retrieving TOKEN_DEFAULT_DACL...");
 | |
| 
 | |
|   GetTokenInformation(hProcToken, TokenDefaultDacl, NULL, 0, &cbSize);
 | |
|   
 | |
|   pDaclToken = LocalAlloc(LPTR, cbSize);
 | |
| 
 | |
|   FAIL(GetTokenInformation(hProcToken, TokenDefaultDacl,
 | |
|                                pDaclToken, cbSize, &cbSize) == FALSE);
 | |
| 
 | |
|   /*
 | |
|    * Print debug info about parts
 | |
|    */
 | |
|   
 | |
|   //PrintPartsInfo(&token, TOKEN_ALL_ACCESS, &oa, 
 | |
|   //                            TokenPrimary, &authId, &expirationTime,
 | |
|   //                                &userToken, groupsToken, pPrivToken,
 | |
|   //                                    &ownerToken, &primaryGroupToken, 
 | |
|   //                                        pDaclToken, &sourceToken);
 | |
| 
 | |
|   /*
 | |
|    * Retrieve address of NtCreateToken() function.
 | |
|    */
 | |
| 
 | |
|   debug("Retrieving NtCreateToken() address...");
 | |
|   
 | |
|   hNtDll = GetModuleHandle("ntdll.dll");
 | |
|   
 | |
|   FAIL(hNtDll == NULL);
 | |
| 
 | |
|   NtCreateToken = (NtCreateTokenPtr) GetProcAddress(hNtDll, "NtCreateToken");
 | |
| 
 | |
|   FAIL(NtCreateToken == NULL);
 | |
| 
 | |
|   /*
 | |
|    * Create new user acces token from parts setted up above.
 | |
|    */
 | |
| 
 | |
|   debug("Creating token from parts...");
 | |
|   
 | |
|   ntStat = NtCreateToken(&token, TOKEN_ALL_ACCESS, &oa,
 | |
|                               TokenPrimary, &authId, &expirationTime,
 | |
|                                   &userToken, groupsToken, pPrivToken,
 | |
|                                       &ownerToken, &primaryGroupToken,
 | |
|                                           pDaclToken, &sourceToken);                         
 | |
|   FAIL(ntStat);
 | |
| 
 | |
|   /*
 | |
|    * Add rights to use 'default' desktop and WinStation0.
 | |
|    */
 | |
| 
 | |
|   if (AddRightsToDesktopBySid(userToken.User.Sid))
 | |
|   {
 | |
|     debug("WARNING. Cannot add rights to 'winsta0\\default'!");
 | |
|   }
 | |
| 
 | |
|   exitCode = 0;
 | |
|   
 | |
| fail:
 | |
| 
 | |
|   /*
 | |
|    * Free allocated memory
 | |
|    */
 | |
|   
 | |
|   debug2("Freeing groupsToken...");
 | |
|   
 | |
|   if (groupsToken)
 | |
|   {
 | |
|     /*
 | |
|      * We don't need to test were SIDs allocated correctly,
 | |
|      * becouse FreeSid() do it.
 | |
|      */
 | |
|     
 | |
|     for (i = 0; i < groupsToken -> GroupCount; i++)
 | |
|     {
 | |
|       FreeSid(groupsToken -> Groups[i].Sid);
 | |
|     }
 | |
| 
 | |
|     LocalFree(groupsToken);
 | |
|   }
 | |
|   
 | |
|   debug2("Freeing local buffers...");
 | |
|   
 | |
|   LocalFree(userNameW);
 | |
|   LocalFree(pDaclToken);
 | |
|   LocalFree(pPrivToken);
 | |
|   
 | |
|   debug2("Freeing SIDs...");
 | |
|   
 | |
|   FreeSid(userToken.User.Sid);
 | |
|   FreeSid(ownerToken.Owner);
 | |
|   FreeSid(primaryGroupToken.PrimaryGroup);
 | |
|   
 | |
|   debug2("Closing hProcToken...");
 | |
|   
 | |
|   CloseHandle(hProcToken);
 | |
| 
 | |
|   debug2("Closing hNtDll...");
 | |
|   
 | |
|   CloseHandle(hNtDll);
 | |
|   
 | |
|   /*
 | |
|    * Something was wrong.
 | |
|    */
 | |
|   
 | |
|   if (exitCode)
 | |
|   {
 | |
|     debug("ERROR. Cannot create user's acces token. (err = %u, ntStat = %x)",
 | |
|               GetLastError(), ntStat);
 | |
|   }
 | |
| 
 | |
|   debug2("<- CreateUserToken()...");
 | |
|   
 | |
|   return token;
 | |
| }
 | |
| 
 | |
| #endif
 |