// Security.cpp: implementation of the CSecurity class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "amisafe.h" #include "Security.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif #define TESTPERM_READ 1 #define TESTPERM_WRITE 2 ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CSecurity::CSecurity() { } CSecurity::~CSecurity() { } BOOL CSecurity::IsAdministrator() { BOOL fAdmin = FALSE; HANDLE hToken = NULL; DWORD dwStatus; DWORD dwACLSize; DWORD cbps = sizeof(PRIVILEGE_SET); PACL pACL = NULL; PSID psidAdmin = NULL; PSECURITY_DESCRIPTOR psdAdmin = NULL; PRIVILEGE_SET ps; GENERIC_MAPPING gm; SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY; // Prepare some memory ZeroMemory(&ps, sizeof(ps)); ZeroMemory(&gm, sizeof(gm)); // Get the Administrators SID if (AllocateAndInitializeSid(&sia, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin) ) { // Get the Asministrators Security Descriptor (SD) psdAdmin = LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH); if(InitializeSecurityDescriptor(psdAdmin,SECURITY_DESCRIPTOR_REVISION)) { // Compute size needed for the ACL then allocate the // memory for it dwACLSize = sizeof(ACCESS_ALLOWED_ACE) + 8 + GetLengthSid(psidAdmin) - sizeof(DWORD); pACL = (PACL)LocalAlloc(LPTR, dwACLSize); // Initialize the new ACL if(InitializeAcl(pACL, dwACLSize, ACL_REVISION2)) { // Add the access-allowed ACE to the DACL if(AddAccessAllowedAce(pACL,ACL_REVISION2, (TESTPERM_READ | TESTPERM_WRITE),psidAdmin)) { // Set our DACL to the Administrator's SD if (SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE)) { // AccessCheck is downright picky about what is in the SD, // so set the group and owner SetSecurityDescriptorGroup(psdAdmin,psidAdmin,FALSE); SetSecurityDescriptorOwner(psdAdmin,psidAdmin,FALSE); // Initialize GenericMapping structure even though we // won't be using generic rights gm.GenericRead = TESTPERM_READ; gm.GenericWrite = TESTPERM_WRITE; gm.GenericExecute = 0; gm.GenericAll = TESTPERM_READ | TESTPERM_WRITE; // AccessCheck requires an impersonation token, so lets // indulge it ImpersonateSelf(SecurityImpersonation); if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken)) { if (!AccessCheck(psdAdmin, hToken, TESTPERM_READ, &gm, &ps,&cbps,&dwStatus,&fAdmin)) fAdmin = FALSE; CloseHandle(hToken); } } } } LocalFree(pACL); } LocalFree(psdAdmin); FreeSid(psidAdmin); } RevertToSelf(); return(fAdmin); } BOOL CSecurity::IsUntrusted(void) { BOOL fResult = FALSE; HANDLE hToken; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) { fResult = IsTokenUntrusted(hToken); CloseHandle(hToken); } return fResult; } // Return TRUE if the token does is not able to access a DACL against the // Token User SID. This is typically the case in these situations: // - the User SID is disabled (for deny-use only) // - there are Restricting SIDs and the User SID is not one of them. // // If an error occurs during the evaluation of this check, the result // returned will be TRUE (assumed untrusted). // // The passed token handle must have been opened for TOKEN_QUERY and // TOKEN_DUPLICATE access or else the evaluation will fail. BOOL CSecurity::IsTokenUntrusted(HANDLE hToken) { BOOL fTrusted = FALSE; DWORD dwStatus; DWORD dwACLSize; DWORD cbps = sizeof(PRIVILEGE_SET); PACL pACL = NULL; DWORD dwUserSidSize; PTOKEN_USER psidUser = NULL; PSECURITY_DESCRIPTOR psdUser = NULL; PRIVILEGE_SET ps; GENERIC_MAPPING gm; SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY; HANDLE hImpToken; // Prepare some memory ZeroMemory(&ps, sizeof(ps)); ZeroMemory(&gm, sizeof(gm)); // Get the User's SID. if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwUserSidSize)) { psidUser = (PTOKEN_USER) LocalAlloc(LPTR, dwUserSidSize); if (psidUser != NULL) { if (GetTokenInformation(hToken, TokenUser, psidUser, dwUserSidSize, &dwUserSidSize)) { // Create the Security Descriptor (SD) psdUser = LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH); if(InitializeSecurityDescriptor(psdUser,SECURITY_DESCRIPTOR_REVISION)) { // Compute size needed for the ACL then allocate the // memory for it dwACLSize = sizeof(ACCESS_ALLOWED_ACE) + 8 + GetLengthSid(psidUser->User.Sid) - sizeof(DWORD); pACL = (PACL)LocalAlloc(LPTR, dwACLSize); // Initialize the new ACL if(InitializeAcl(pACL, dwACLSize, ACL_REVISION2)) { // Add the access-allowed ACE to the DACL if(AddAccessAllowedAce(pACL,ACL_REVISION2, (TESTPERM_READ | TESTPERM_WRITE),psidUser->User.Sid)) { // Set our DACL to the Administrator's SD if (SetSecurityDescriptorDacl(psdUser, TRUE, pACL, FALSE)) { // AccessCheck is downright picky about what is in the SD, // so set the group and owner SetSecurityDescriptorGroup(psdUser,psidUser->User.Sid,FALSE); SetSecurityDescriptorOwner(psdUser,psidUser->User.Sid,FALSE); // Initialize GenericMapping structure even though we // won't be using generic rights gm.GenericRead = TESTPERM_READ; gm.GenericWrite = TESTPERM_WRITE; gm.GenericExecute = 0; gm.GenericAll = TESTPERM_READ | TESTPERM_WRITE; if (ImpersonateLoggedOnUser(hToken) && OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hImpToken)) { if (!AccessCheck(psdUser, hImpToken, TESTPERM_READ, &gm, &ps,&cbps,&dwStatus,&fTrusted)) fTrusted = FALSE; CloseHandle(hImpToken); } } } } LocalFree(pACL); } LocalFree(psdUser); } LocalFree(psidUser); } } RevertToSelf(); return(!fTrusted); } BOOL CSecurity::GetLoggedInUsername(LPTSTR szInBuffer, DWORD dwInBufferSize) { DWORD dwUserSidSize; PTOKEN_USER psidUser = NULL; HANDLE hToken; // Get the current process token. if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) { // Get the User's SID. if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dwUserSidSize)) { psidUser = (PTOKEN_USER) LocalAlloc(LPTR, dwUserSidSize); if (psidUser != NULL) { if (GetTokenInformation(hToken, TokenUser, psidUser, dwUserSidSize, &dwUserSidSize)) { TCHAR szDomain[200]; DWORD dwDomainSize = sizeof(szDomain) / sizeof(TCHAR); SID_NAME_USE eSidUse; if (LookupAccountSid( NULL, psidUser->User.Sid, szInBuffer, &dwInBufferSize, szDomain, &dwDomainSize, &eSidUse)) { LocalFree((HLOCAL) psidUser); CloseHandle(hToken); return TRUE; } } LocalFree((HLOCAL) psidUser); } } CloseHandle(hToken); } return NULL; }