|
|
// AdjustTokenPrivileges.cpp: implementation of the CAdjustTokenPrivileges class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "AdjustTokenPrivileges.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CAdjustTokenPrivileges::CAdjustTokenPrivileges() : m_dwAttributesPrev(0), m_bImpersonation(false), m_hToken(INVALID_HANDLE_VALUE), m_hTokenDuplicate(INVALID_HANDLE_VALUE) { } CAdjustTokenPrivileges::~CAdjustTokenPrivileges() { if ( m_bImpersonation ) RevertToSelf(); // Deletes the thread token so there is no need to reset the TokenPrivilege
else if ( INVALID_HANDLE_VALUE != m_hToken ) { TOKEN_PRIVILEGES TokenPrivileges; DWORD dwRC = GetLastError();
TokenPrivileges.PrivilegeCount = 1; TokenPrivileges.Privileges[0].Luid = m_luid; TokenPrivileges.Privileges[0].Attributes = m_dwAttributesPrev; //adjust the privlige to this new privilege
AdjustTokenPrivileges( m_hToken, FALSE, &TokenPrivileges, sizeof( TOKEN_PRIVILEGES ), NULL, NULL ); CloseHandle( m_hToken ); if ( ERROR_SUCCESS != dwRC ) // Preserve any error code
SetLastError( dwRC ); } if ( INVALID_HANDLE_VALUE != m_hTokenDuplicate ) CloseHandle( m_hTokenDuplicate ); }
//////////////////////////////////////////////////////////////////////
// Implementation : public
//////////////////////////////////////////////////////////////////////
DWORD CAdjustTokenPrivileges::AdjustPrivileges( LPCTSTR lpPrivelegeName, DWORD dwAttributes ) { //local variables
TOKEN_PRIVILEGES TokenPrivileges, TokenPrivilegesOld; DWORD dwRC = ERROR_SUCCESS, dwSize = sizeof( TokenPrivilegesOld );
if ( !LookupPrivilegeValue( NULL, lpPrivelegeName, &m_luid )) dwRC = GetLastError(); if ( ERROR_SUCCESS == dwRC ) { // open the token of the current process
if ( !OpenThreadToken( GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &m_hToken )) { dwRC = GetLastError(); if ( ERROR_NO_TOKEN == dwRC ) {// There's no impersonation let's impersonate self so we can make this work
if ( ImpersonateSelf( SecurityImpersonation )) { if ( OpenThreadToken( GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &m_hToken )) { dwRC = ERROR_SUCCESS; m_bImpersonation = true; } else { dwRC = GetLastError(); RevertToSelf(); // Already have an error, don't want to overwrite if this fails
} } else dwRC = GetLastError(); } } } if ( ERROR_SUCCESS == dwRC ) { // Set up the privilege set we will need
TokenPrivileges.PrivilegeCount = 1; TokenPrivileges.Privileges[0].Luid = m_luid; TokenPrivileges.Privileges[0].Attributes = dwAttributes; //adjust the privlige to this new privilege
if ( AdjustTokenPrivileges( m_hToken, FALSE, &TokenPrivileges, sizeof( TOKEN_PRIVILEGES ), &TokenPrivilegesOld, &dwSize )) m_dwAttributesPrev = TokenPrivilegesOld.Privileges[0].Attributes; dwRC = GetLastError(); // We need to check the return code regardless of what AdjustTokenPrivileges returns
// AdjustTokenPrivileges set last error to ERROR_SUCCESS if it set all specified privileges!
} if ( dwRC != ERROR_SUCCESS ) { CloseHandle( m_hToken ); m_hToken = INVALID_HANDLE_VALUE; } return dwRC; }
DWORD CAdjustTokenPrivileges::DuplicateProcessToken( LPCTSTR lpPrivelegeName, DWORD dwAttributes ) { DWORD dwRC = ERROR_SUCCESS; HANDLE hToken; HANDLE hTokenThread = INVALID_HANDLE_VALUE; if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_DUPLICATE, &hToken )) dwRC = GetLastError(); if ( ERROR_SUCCESS == dwRC ) { if ( !DuplicateToken( hToken, SecurityImpersonation, &m_hTokenDuplicate )) dwRC = GetLastError(); CloseHandle( hToken ); } if ( ERROR_SUCCESS == dwRC ) { if ( !OpenThreadToken( GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hTokenThread )) { dwRC = GetLastError(); if ( ERROR_NO_TOKEN == dwRC ) { dwRC = ERROR_SUCCESS; hTokenThread = INVALID_HANDLE_VALUE; } } } if ( ERROR_SUCCESS == dwRC ) { if ( SetThreadToken( NULL, m_hTokenDuplicate )) { dwRC = AdjustPrivileges( SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED ); m_hToken = INVALID_HANDLE_VALUE; // This is really the m_hTokenDuplicate, don't want to Close in the destructor
if ( !SetThreadToken( NULL, NULL )) { if ( ERROR_SUCCESS == dwRC ) // Don't overwrite existing error code
dwRC = GetLastError(); } } else dwRC = GetLastError(); } if ( INVALID_HANDLE_VALUE != hTokenThread ) { if ( !SetThreadToken( NULL, hTokenThread )) dwRC = GetLastError(); CloseHandle( hTokenThread ); } return dwRC; }
/////////////////////////////////////////////////////////////////////////////
// ResetThreadToken, public
//
// Purpose:
// Use the Duplicate process token to enable privileges for the thread.
// If the Thread already has a token (unexpected) then adjust the privileges.
//
// Arguments:
//
// Returns: TRUE on success, FALSE otherwise
DWORD CAdjustTokenPrivileges::ResetToken() { DWORD dwRC = ERROR_SUCCESS; HANDLE hToken; if ( INVALID_HANDLE_VALUE != m_hTokenDuplicate && INVALID_HANDLE_VALUE == m_hToken ) { if ( !SetThreadToken( NULL, NULL )) dwRC = GetLastError(); } else dwRC = ERROR_NO_TOKEN; return dwRC; }
/////////////////////////////////////////////////////////////////////////////
// SetThreadToken, public
//
// Purpose:
// Use the Duplicated process token to enable privileges for the thread.
// If the Thread already has a token (unexpected) then adjust the privileges.
//
// Arguments:
//
// Returns: TRUE on success, FALSE otherwise
DWORD CAdjustTokenPrivileges::SetToken() { DWORD dwRC = ERROR_SUCCESS; HANDLE hToken; if ( INVALID_HANDLE_VALUE != m_hTokenDuplicate ) { if ( OpenThreadToken( GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken )) { // The thread already has a token, let's work with it
CloseHandle( hToken ); dwRC = AdjustPrivileges( SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED ); } else { // Let's use are duplicate token
if ( ERROR_NO_TOKEN == GetLastError() ) { if ( !SetThreadToken( NULL, m_hTokenDuplicate )) dwRC = GetLastError(); } else dwRC = GetLastError(); } } else dwRC = ERROR_NO_TOKEN; return dwRC; }
|