You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
7.5 KiB
214 lines
7.5 KiB
// 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;
|
|
}
|
|
|
|
|