277 lines
7.8 KiB
C++
277 lines
7.8 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 2000.
|
||
|
//
|
||
|
// File: imprsnat.cxx
|
||
|
//
|
||
|
// Contents:
|
||
|
//
|
||
|
// Classes:
|
||
|
//
|
||
|
// Functions:
|
||
|
//
|
||
|
// History: 2-16-96 srikants Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include <pch.cxx>
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <imprsnat.hxx>
|
||
|
#include <ciregkey.hxx>
|
||
|
|
||
|
BOOL CImpersonateSystem::_fIsRunningAsSystem = TRUE;
|
||
|
|
||
|
BOOL CImpersonateSystem::IsRunningAsSystem()
|
||
|
{
|
||
|
return CImpersonateSystem::_fIsRunningAsSystem;
|
||
|
}
|
||
|
|
||
|
void CImpersonateSystem::SetRunningAsSystem()
|
||
|
{
|
||
|
CImpersonateSystem::_fIsRunningAsSystem = TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CImpersonateSystem::MakePrivileged
|
||
|
//
|
||
|
// Synopsis: This call makes the caller a "privileged" user by reverting
|
||
|
// to the "original" context.
|
||
|
//
|
||
|
// History: 2-19-96 srikants Created
|
||
|
//
|
||
|
// Notes: We are assuming that the "original" context of the thread
|
||
|
// is a "privileged" context.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CImpersonateSystem::MakePrivileged()
|
||
|
{
|
||
|
Win4Assert( !_fRevertedToSystem );
|
||
|
|
||
|
//
|
||
|
// The typical path here is failure, and it's expensive for NT to
|
||
|
// convert the NTSTATUS to a Win32 error. So call NT.
|
||
|
//
|
||
|
|
||
|
NTSTATUS status = NtOpenThreadToken( GetCurrentThread(),
|
||
|
TOKEN_DUPLICATE | TOKEN_QUERY |
|
||
|
TOKEN_IMPERSONATE,
|
||
|
TRUE, // Access check against the process
|
||
|
&_hClientToken );
|
||
|
|
||
|
if ( NT_ERROR( status ) )
|
||
|
{
|
||
|
if ( STATUS_NO_TOKEN == status )
|
||
|
{
|
||
|
//
|
||
|
// This thread is currently not impersonating anyone. We don't
|
||
|
// have to become system. We should already have the correct
|
||
|
// privileges.
|
||
|
//
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ciDebugOut(( DEB_ERROR,
|
||
|
"NtOpenThreadToken() failed with error %#x\n",
|
||
|
status ));
|
||
|
THROW( CException( status ) );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_fRevertedToSystem = RevertToSelf();
|
||
|
|
||
|
//
|
||
|
// NTRAID#DB-NTBUG9-84492-2000/07/31-dlee Indexing Service assumes in multiple places that RevertToSelf will always succeed
|
||
|
// what should we do if we fail to revert to self?
|
||
|
//
|
||
|
|
||
|
if ( !_fRevertedToSystem )
|
||
|
{
|
||
|
ciDebugOut(( DEB_ERROR,
|
||
|
"RevertToSelf() failed with error %d\n", GetLastError() ));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CImpersonateSystem::~CImpersonateSystem
|
||
|
//
|
||
|
// Synopsis: ~dtor of the CImpersonateSystem class. Will restore the
|
||
|
// context of the thread before making it privileged.
|
||
|
//
|
||
|
// History: 2-19-96 srikants Created
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CImpersonateSystem::~CImpersonateSystem()
|
||
|
{
|
||
|
if ( _fRevertedToSystem )
|
||
|
{
|
||
|
Win4Assert( INVALID_HANDLE_VALUE != _hClientToken );
|
||
|
BOOL fResult = ImpersonateLoggedOnUser( _hClientToken );
|
||
|
if ( !fResult )
|
||
|
{
|
||
|
DWORD dwError = GetLastError();
|
||
|
ciDebugOut(( DEB_ERROR, "ImpersonateLoggedOnUser failed with error code %d\n",
|
||
|
dwError ));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( INVALID_HANDLE_VALUE != _hClientToken )
|
||
|
{
|
||
|
CloseHandle( _hClientToken );
|
||
|
}
|
||
|
}
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: IsImpersonated
|
||
|
//
|
||
|
// Synopsis: Tests if the caller is impersonated.
|
||
|
//
|
||
|
// Returns: TRUE if impersonated; FALSE if not.
|
||
|
//
|
||
|
// History: 12-31-96 srikants Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
BOOL CImpersonateSystem::IsImpersonated()
|
||
|
{
|
||
|
BOOL fImpersonated = FALSE;
|
||
|
|
||
|
HANDLE hThreadToken;
|
||
|
|
||
|
NTSTATUS status = NtOpenThreadToken( GetCurrentThread(),
|
||
|
TOKEN_QUERY,
|
||
|
TRUE, // Access check against the process
|
||
|
&hThreadToken );
|
||
|
|
||
|
if ( NT_SUCCESS( status ) )
|
||
|
{
|
||
|
CloseHandle( hThreadToken );
|
||
|
fImpersonated = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( STATUS_NO_TOKEN != status )
|
||
|
{
|
||
|
ciDebugOut(( DEB_ERROR,
|
||
|
"NtOpenThreadToken() failed with error %#x\n",
|
||
|
status ));
|
||
|
fImpersonated = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fImpersonated;
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CImpersonateClient::Impersonate
|
||
|
//
|
||
|
// Synopsis: Assume a client context.
|
||
|
//
|
||
|
// History: 19 Mar 96 AlanW Created
|
||
|
//
|
||
|
// Notes: We are assuming that the "original" context of the thread
|
||
|
// is a "privileged" context.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CImpersonateClient::Impersonate()
|
||
|
{
|
||
|
if ( INVALID_HANDLE_VALUE != _hClientToken )
|
||
|
{
|
||
|
BOOL fResult = ImpersonateLoggedOnUser( _hClientToken );
|
||
|
if ( !fResult )
|
||
|
{
|
||
|
ciDebugOut(( DEB_ERROR,
|
||
|
"ImpersonateLoggedOnUser failed with error code %d\n",
|
||
|
GetLastError() ));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CImpersonateClient::~CImpersonateClient
|
||
|
//
|
||
|
// Synopsis: ~dtor of the CImpersonateClient class. Will restore the
|
||
|
// context of the thread before impersonating (assumed to be
|
||
|
// running as "system" previously).
|
||
|
//
|
||
|
// History: 19 Mar 96 AlanW Created
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CImpersonateClient::~CImpersonateClient()
|
||
|
{
|
||
|
if ( INVALID_HANDLE_VALUE != _hClientToken )
|
||
|
{
|
||
|
BOOL fRevertedToSystem = RevertToSelf();
|
||
|
|
||
|
if ( !fRevertedToSystem )
|
||
|
{
|
||
|
ciDebugOut(( DEB_ERROR,
|
||
|
"RevertToSelf() failed with error %d\n",
|
||
|
GetLastError() ));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: VerifyThreadHasAdminPrivilege, public
|
||
|
//
|
||
|
// Synopsis: Checks to see if the client has administrative access.
|
||
|
//
|
||
|
// Arguments: - NONE -
|
||
|
//
|
||
|
// Returns: Nothing, throws if access is denied.
|
||
|
//
|
||
|
// Notes: The ACL on the HKEY_CURRENT_MACHINE\system\CurrentControlSet\
|
||
|
// Control\ContentIndex registry key is used to determine if
|
||
|
// access is permitted.
|
||
|
//
|
||
|
// History: 26 Jun 96 AlanW Created.
|
||
|
// History: 1 Oct 96 dlee Stole from idq and renamed
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void VerifyThreadHasAdminPrivilege()
|
||
|
{
|
||
|
HKEY hNewKey = (HKEY) INVALID_HANDLE_VALUE;
|
||
|
LONG dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
||
|
wcsRegAdminSubKey,
|
||
|
0,
|
||
|
KEY_WRITE,
|
||
|
&hNewKey );
|
||
|
|
||
|
if ( ERROR_SUCCESS == dwError )
|
||
|
{
|
||
|
RegCloseKey( hNewKey );
|
||
|
}
|
||
|
else if ( ERROR_ACCESS_DENIED == dwError )
|
||
|
{
|
||
|
THROW( CException( STATUS_ACCESS_DENIED ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ciDebugOut(( DEB_ERROR,
|
||
|
"Can't open reg key %ws, error %d\n",
|
||
|
wcsRegAdminSubKey, dwError ));
|
||
|
THROW( CException( HRESULT_FROM_WIN32( dwError ) ) );
|
||
|
}
|
||
|
} //VerifyThreadHasAdminPrivilege
|
||
|
|
||
|
|