Leaked source code of windows server 2003
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

// 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;
}