867 lines
25 KiB
C++
867 lines
25 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1998.
|
|
//
|
|
// File: imprsnat.hxx
|
|
//
|
|
// Contents: Classes used to control the security context.
|
|
// When called from the "WWW service", the thread is
|
|
// impersonated as the authenticated client, often the
|
|
// "Internet Anonymous User". This user has few privileges
|
|
// and cannot access the content index data needed to
|
|
// resolve the queries. However, for enumerated queries, we
|
|
// need to stay in the context of the client so that normal
|
|
// access controls will work correctly.
|
|
//
|
|
// To assume the system context, we use the fact that before
|
|
// impersonating as the client, the thread was in fact had
|
|
// "local system" privileges.
|
|
// We save the TOKEN of the current thread, revert to the system
|
|
// privileges and on the way out, we restore the TOKEN of the
|
|
// anonymous user.
|
|
//
|
|
// Impersonating a client involves just calling
|
|
// ImpersonateLoggedOnUser with the supplied client token,
|
|
// then calling RevertToSelf when done.
|
|
//
|
|
// Classes: CImpersonateSystem - Become the "system" context
|
|
// CImpersonateClient - Impersonate to a client
|
|
//
|
|
// History: 2-16-96 srikants Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
#include <smatch.hxx>
|
|
#include <filterr.h>
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CImpersonateSystem
|
|
//
|
|
// Purpose: An unwindable class to impersonate system and revert back
|
|
// to what it was before.
|
|
//
|
|
// History: 4-01-96 srikants Added header
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CImpersonateSystem
|
|
{
|
|
public:
|
|
|
|
CImpersonateSystem( BOOL fShouldImpersonate = IsRunningAsSystem() ) :
|
|
_fRevertedToSystem( FALSE ),
|
|
_hClientToken( INVALID_HANDLE_VALUE )
|
|
{
|
|
if ( fShouldImpersonate )
|
|
MakePrivileged();
|
|
}
|
|
|
|
~CImpersonateSystem();
|
|
|
|
// in SYSTEM context
|
|
static BOOL IsImpersonated();
|
|
|
|
static BOOL IsRunningAsSystem();
|
|
|
|
static void SetRunningAsSystem();
|
|
|
|
private:
|
|
|
|
void MakePrivileged();
|
|
|
|
static BOOL _fIsRunningAsSystem; // TRUE if query.dll came up initially
|
|
|
|
BOOL _fRevertedToSystem; // Set to TRUE if we are running in
|
|
// "SYSTEM" context.
|
|
HANDLE _hClientToken; // Handle of the client token
|
|
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CImpersonateClient
|
|
//
|
|
// Purpose: An unwindable class to impersonate a user whose token is given
|
|
// and to revert back to system later.
|
|
//
|
|
// History: 4-01-96 srikants Added Header
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CImpersonateClient
|
|
{
|
|
public:
|
|
|
|
CImpersonateClient( HANDLE hToken ) :
|
|
_hClientToken( hToken )
|
|
{
|
|
if ( INVALID_HANDLE_VALUE != hToken )
|
|
Impersonate();
|
|
}
|
|
|
|
~CImpersonateClient();
|
|
|
|
private:
|
|
void Impersonate();
|
|
|
|
HANDLE _hClientToken; // Handle of the client token
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CLogonInfo
|
|
//
|
|
// Purpose: A linked list element that keeps logon information for a
|
|
// user.
|
|
//
|
|
// History: 4-05-96 srikants Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CLogonInfo : public CDoubleLink
|
|
{
|
|
|
|
public:
|
|
|
|
CLogonInfo()
|
|
{
|
|
CDoubleLink::Close();
|
|
_pwszUser = _pwszDomain = _pwszPassword = 0;
|
|
_ccUser = _ccDomain = _ccPassword = FALSE;
|
|
|
|
_cRef = 0; _fZombie = FALSE;
|
|
_hToken = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
~CLogonInfo();
|
|
|
|
DWORD Logon( WCHAR const * pwszUser, WCHAR const * pwszDomain,
|
|
WCHAR const * pwszPassword );
|
|
|
|
BOOL IsSameUser( WCHAR const * pwszUser, WCHAR const * pwszDomain ) const;
|
|
BOOL IsSamePassword( WCHAR const * pwszPassword ) const;
|
|
|
|
void Addref() { _cRef++; }
|
|
void Release()
|
|
{
|
|
Win4Assert( _cRef > 0 );
|
|
_cRef--;
|
|
}
|
|
|
|
BOOL IsInUse() const { return _cRef > 0; }
|
|
|
|
void Zombify() { _fZombie = TRUE; }
|
|
BOOL IsZombie() const { return _fZombie; }
|
|
|
|
HANDLE GetHandle() const { return _hToken; }
|
|
|
|
static WCHAR * AllocAndCopy( WCHAR const * pwszSrc, ULONG & cc );
|
|
|
|
WCHAR * GetUser() { return _pwszUser; }
|
|
WCHAR * GetDomain() { return _pwszDomain; }
|
|
WCHAR * GetPassword() { return _pwszPassword; }
|
|
|
|
private:
|
|
|
|
WCHAR * _pwszUser; // User Name
|
|
ULONG _ccUser; // Length of user name
|
|
|
|
WCHAR * _pwszDomain; // Domain Name
|
|
ULONG _ccDomain;
|
|
|
|
WCHAR * _pwszPassword; // Password to logon domain\user
|
|
ULONG _ccPassword;
|
|
|
|
LONG _cRef; // Refcount
|
|
BOOL _fZombie; // Set to TRUE if this has been
|
|
// zombified
|
|
|
|
HANDLE _hToken; // "Logged on" token for the account
|
|
|
|
};
|
|
|
|
class CLogonInfoList : public TDoubleList<CLogonInfo>
|
|
{
|
|
public:
|
|
CLogonInfoList() {}
|
|
void Empty();
|
|
~CLogonInfoList() { Empty(); }
|
|
};
|
|
|
|
typedef class TFwdListIter<CLogonInfo, CLogonInfoList> CFwdLogonInfoIter;
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CImprsObjInfo
|
|
//
|
|
// Purpose: A class that encapsulates the object that a user is trying
|
|
// to access.
|
|
//
|
|
// History: 7-12-96 srikants Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
class CImprsObjInfo
|
|
{
|
|
|
|
public:
|
|
|
|
CImprsObjInfo( WCHAR const * const pwszPath,
|
|
WCHAR const * const pwszVPath )
|
|
: _pwszPath( pwszPath ),
|
|
_pwszVPath( pwszVPath )
|
|
{
|
|
|
|
}
|
|
|
|
WCHAR const * GetPhysicalPath() const { return _pwszPath; }
|
|
WCHAR const * GetVPath() const { return _pwszVPath; }
|
|
|
|
private:
|
|
|
|
WCHAR const * const _pwszPath; // physical path
|
|
WCHAR const * const _pwszVPath; // Virtual path, can be 0
|
|
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CPhyDirLogonInfo
|
|
//
|
|
// Purpose: Logon information for a physical directory
|
|
//
|
|
// History: 4-01-96 srikants Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CPhyDirLogonInfo : public CDoubleLink
|
|
{
|
|
friend class CImpersonationTokenCache;
|
|
|
|
public:
|
|
|
|
static ULONG IpAddressFromWStr( WCHAR const * ipAddress );
|
|
|
|
CPhyDirLogonInfo( CImpersonationTokenCache & cache,
|
|
CImprsObjInfo const & obj,
|
|
CLogonInfo * pLogonInfo
|
|
);
|
|
|
|
BOOL IsInScope( WCHAR const * pwszPath, ULONG len ) const
|
|
{
|
|
return _phyScope.IsInScope( pwszPath, len );
|
|
}
|
|
|
|
BOOL IsInScope( WCHAR const * pwszPath ) const
|
|
{
|
|
return _phyScope.IsInScope( pwszPath, wcslen(pwszPath) );
|
|
}
|
|
|
|
BOOL IsInVirtualScope( WCHAR const * pwszVPath ) const
|
|
{
|
|
return pwszVPath ?
|
|
_virtualScope.IsInScope( pwszVPath, wcslen(pwszVPath) ) : TRUE;
|
|
}
|
|
|
|
BOOL IsMatch( CImprsObjInfo const & info ) const;
|
|
|
|
int Compare( CPhyDirLogonInfo const & rhs ) const;
|
|
|
|
HANDLE GetHandle() const
|
|
{
|
|
return _pLogonInfo ? _pLogonInfo->GetHandle()
|
|
: INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
BOOL IsZombie() const { return _fIsZombie; }
|
|
|
|
BOOL IsInUse() const { return _cRef > 0; }
|
|
|
|
ULONG GetVirtualRootLen() const { return _ccVirtual; }
|
|
|
|
BOOL IsSame( CImprsObjInfo const & info ) const;
|
|
|
|
BOOL IsSameVPath( WCHAR const * pwszVPath ) const
|
|
{
|
|
Win4Assert( (0 == _pwszVirtualRoot && 0 == _ccVirtual) ||
|
|
(0 != _pwszVirtualRoot && 0 != _ccVirtual) );
|
|
|
|
ULONG ccVirtual = pwszVPath ? wcslen( pwszVPath ) : 0;
|
|
|
|
if ( 0 == _ccVirtual && 0 == ccVirtual )
|
|
return TRUE;
|
|
else if ( ccVirtual != _ccVirtual )
|
|
return FALSE;
|
|
|
|
return RtlEqualMemory( pwszVPath, _pwszVirtualRoot, ccVirtual * sizeof(WCHAR) );
|
|
}
|
|
|
|
BOOL IsSamePhysicalPath( WCHAR const * pwszPath ) const
|
|
{
|
|
ULONG cc = pwszPath ? wcslen( pwszPath ) : 0;
|
|
|
|
if ( cc != _cc )
|
|
return FALSE;
|
|
|
|
Win4Assert( 0 != _cc );
|
|
return RtlEqualMemory( pwszPath, _pwszDirName, cc * sizeof(WCHAR) );
|
|
}
|
|
|
|
~CPhyDirLogonInfo();
|
|
|
|
CLogonInfo * GetLogonInfo()
|
|
{
|
|
return _pLogonInfo;
|
|
}
|
|
|
|
private:
|
|
|
|
WCHAR const * GetDirName() const { return _pwszDirName; }
|
|
ULONG GetNameLen() const { return _cc; }
|
|
|
|
|
|
void AddRef() { _cRef++; }
|
|
void Release()
|
|
{
|
|
Win4Assert( _cRef > 0 );
|
|
_cRef--;
|
|
}
|
|
|
|
void Zombify() { _fIsZombie = TRUE; }
|
|
|
|
CImpersonationTokenCache & _cache; // token cache
|
|
WCHAR * _pwszDirName; // Physical directory
|
|
ULONG _cc; // Length of the physical dir
|
|
|
|
WCHAR * _pwszVirtualRoot; // Virtual root.
|
|
ULONG _ccVirtual; // Length of the virtual root
|
|
|
|
CLogonInfo * _pLogonInfo; // LogonInformation for this share
|
|
// The impersonation token to use
|
|
BOOL _fIsZombie; // Set to TRUE if this is a zombie
|
|
|
|
long _cRef; // Refcount
|
|
CScopeMatch _phyScope; // For physical scope testing
|
|
CScopeMatch _virtualScope; // For virtula scope testing
|
|
|
|
};
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPhyDirLogonInfo::IsMatch
|
|
//
|
|
// Synopsis: Tests if the given path and the vroot are valid
|
|
// for access using this logon info.
|
|
//
|
|
// Arguments: [info] -- object to be compared
|
|
//
|
|
// Returns: TRUE if the logon info is valid for this vroot.
|
|
//
|
|
// History: 7-12-96 srikants Created
|
|
//
|
|
// Notes: It is assumed that the default server entries are at the end
|
|
// in the list. For the default server, there will be no check
|
|
// done on the ip-address for match.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline
|
|
BOOL CPhyDirLogonInfo::IsMatch( CImprsObjInfo const & info ) const
|
|
|
|
{
|
|
return IsInVirtualScope(info.GetVPath() ) &&
|
|
IsInScope( info.GetPhysicalPath() );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPhyDirLogonInfo::IsSame
|
|
//
|
|
// Synopsis: Tests if the information contained for a path here is exactly
|
|
// the same as the given info.
|
|
//
|
|
// Arguments: [info] -
|
|
//
|
|
// History: 7-12-96 srikants Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline
|
|
BOOL CPhyDirLogonInfo::IsSame( CImprsObjInfo const & info ) const
|
|
|
|
{
|
|
return IsSameVPath( info.GetVPath() ) &&
|
|
IsSamePhysicalPath( info.GetPhysicalPath() );
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPhyDirLogonInfo::Compare
|
|
//
|
|
// Synopsis: Compares this logon information for precedence calculation with
|
|
// the given rhs.
|
|
//
|
|
// Arguments: [rhs] -
|
|
//
|
|
// Returns: 0 if they are equal
|
|
// -1 if this is < than rhs
|
|
// +1 if this is > rhs
|
|
//
|
|
// History: 7-12-96 srikants Created
|
|
//
|
|
// Notes: The nodes in the list are ordered by .
|
|
//
|
|
// Increasing order of ip addresses,
|
|
// Decreasing order of vpath lengths,
|
|
// Decreasing order of phy.path lengths
|
|
//
|
|
// This causes the default ip address nodes to be at the end
|
|
// of the list.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline
|
|
int CPhyDirLogonInfo::Compare( CPhyDirLogonInfo const & rhs ) const
|
|
{
|
|
if ( _ccVirtual == rhs._ccVirtual )
|
|
{
|
|
if ( _cc == rhs._cc )
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return _cc < rhs._cc ? -1 : 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return _ccVirtual < rhs._ccVirtual ? -1 : 1;
|
|
}
|
|
}
|
|
|
|
|
|
typedef class TDoubleList<CPhyDirLogonInfo> CPhyDirLogonList;
|
|
typedef class TFwdListIter<CPhyDirLogonInfo, CPhyDirLogonList> CFwdPhyDirLogonIter;
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CImpersonationTokenCache
|
|
//
|
|
// Purpose: A cache of impersonation tokens for use in accessing remote
|
|
// shares.
|
|
//
|
|
// History: 4-01-96 srikants Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
typedef struct _INET_INFO_VIRTUAL_ROOT_LIST INET_INFO_VIRTUAL_ROOT_LIST;
|
|
typedef struct _INET_INFO_VIRTUAL_ROOT_ENTRY INET_INFO_VIRTUAL_ROOT_ENTRY;
|
|
|
|
class CIISVirtualDirectories;
|
|
|
|
class CImpersonationTokenCache
|
|
{
|
|
friend class CRegistryScopesCallBackImp;
|
|
friend class CIISCallBackImp;
|
|
|
|
enum { CI_MAX_DRIVES = 26 };
|
|
enum EDriveType { eUnknown, eLocal, eRemote };
|
|
|
|
public:
|
|
|
|
CImpersonationTokenCache( WCHAR const * pwcCatName );
|
|
~CImpersonationTokenCache();
|
|
|
|
CPhyDirLogonInfo * Find( CImprsObjInfo & info, ULONG cSkip );
|
|
|
|
CPhyDirLogonInfo * Find( WCHAR const * pwszPath, ULONG cc );
|
|
|
|
void Release( CPhyDirLogonInfo * pInfo )
|
|
{
|
|
CLock lock(_mutex);
|
|
|
|
pInfo->Release();
|
|
if ( pInfo->IsZombie() && !pInfo->IsInUse() )
|
|
{
|
|
Win4Assert( pInfo->IsSingle() );
|
|
delete pInfo;
|
|
}
|
|
}
|
|
|
|
void Release( CLogonInfo * pInfo )
|
|
{
|
|
CLock lock(_mutex);
|
|
|
|
pInfo->Release();
|
|
if ( pInfo->IsZombie() && !pInfo->IsInUse() )
|
|
{
|
|
Win4Assert( pInfo->IsSingle() );
|
|
delete pInfo;
|
|
}
|
|
}
|
|
|
|
BOOL IsNetworkDrive( WCHAR const * pwszPath );
|
|
|
|
BOOL IsIndexingW3Roots() const { return _fIndexW3Roots; }
|
|
BOOL IsIndexingNNTPRoots() const { return _fIndexNNTPRoots; }
|
|
BOOL IsIndexingIMAPRoots() const { return _fIndexIMAPRoots; }
|
|
|
|
ULONG GetW3Instance() const { return _W3SvcInstance; }
|
|
ULONG GetNNTPInstance() const { return _NNTPSvcInstance; }
|
|
ULONG GetIMAPInstance() const { return _IMAPSvcInstance; }
|
|
|
|
BOOL AreRemoteSharesPresent() const { return _fRemoteSharesPresent; }
|
|
|
|
void Initialize( WCHAR const * pwszComponent,
|
|
BOOL fIndexW3Roots,
|
|
BOOL fIndexNNTPRoots,
|
|
BOOL fIndexIMAPRoots,
|
|
ULONG W3SvcInstance,
|
|
ULONG NNTPSvcInstance,
|
|
ULONG IMAPSvcInstance );
|
|
|
|
void ReInitializeIISScopes();
|
|
void ReInitializeIISScopes( CIISVirtualDirectories * pW3Dirs,
|
|
CIISVirtualDirectories * pNNTPDirs,
|
|
CIISVirtualDirectories * pIMAPDirs );
|
|
void ReInitializeScopes();
|
|
|
|
WCHAR const * GetCatalog() { return _awcCatalogName; }
|
|
|
|
private:
|
|
|
|
CPhyDirLogonInfo * _FindExact( CImprsObjInfo const & info );
|
|
|
|
CLogonInfo * _LokFindLogonEntry( WCHAR const * pwszUser,
|
|
WCHAR const * pwszDomain );
|
|
|
|
DWORD _LokValidateOrAddLogonEntry( WCHAR const * pwszUser,
|
|
WCHAR const * pwszDomain,
|
|
WCHAR const * pwszPassword );
|
|
|
|
void _LokAddLogonEntry( WCHAR const * pwszUser, WCHAR const * pwszDomain,
|
|
WCHAR const * pwszPassword );
|
|
|
|
void _LokValidateOrAddDirEntry( CImprsObjInfo const & info,
|
|
WCHAR const * pwszAccount );
|
|
|
|
void _LokAddDirEntry( CImprsObjInfo const & info,
|
|
WCHAR const * pwszAccountName );
|
|
|
|
void _LokSyncUp( INET_INFO_VIRTUAL_ROOT_ENTRY * aEntries,
|
|
ULONG cEntries );
|
|
|
|
unsigned _GetDriveIndex( WCHAR wcDriveLetter )
|
|
{
|
|
return towlower(wcDriveLetter) - L'a';
|
|
}
|
|
|
|
void _WriteLogonFailure( WCHAR const * pwszUser, DWORD dwError );
|
|
|
|
BOOL _fIndexW3Roots; // Set to TRUE if indexing w3svc roots
|
|
BOOL _fIndexNNTPRoots; // Set to TRUE if NNTP is enabled
|
|
BOOL _fIndexIMAPRoots; // Set to TRUE if IMAP is enabled
|
|
|
|
ULONG _W3SvcInstance; // server instance #
|
|
ULONG _NNTPSvcInstance; // server instance #
|
|
ULONG _IMAPSvcInstance; // server instance #
|
|
|
|
BOOL _fRemoteSharesPresent;
|
|
// Optimization - don't do any
|
|
// checks if there are no remote
|
|
// shares.
|
|
|
|
WCHAR * _pwszComponentName; // Name of the component for event log
|
|
// messages
|
|
|
|
CMutexSem _mutex; // Serialization Mutex
|
|
|
|
EDriveType _aDriveInfo[CI_MAX_DRIVES];
|
|
// Array of information on drive
|
|
// letters.
|
|
CPhyDirLogonList _phyDirList; // list of remote directories
|
|
|
|
WCHAR _awcCatalogName[MAX_PATH]; // name of the catalog
|
|
};
|
|
|
|
extern CLogonInfoList g_LogonList; // List of logon information
|
|
|
|
#define CI_DAEMON_NAME L"CiDaemon"
|
|
#define CI_ACTIVEX_NAME L"Indexing Service"
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CImpersonateRemoteAccess
|
|
//
|
|
// Purpose: An unwindable object to impersonate for access to remote
|
|
// shares.
|
|
//
|
|
// History: 4-01-96 srikants Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CImpersonateRemoteAccess
|
|
{
|
|
public:
|
|
|
|
CImpersonateRemoteAccess( CImpersonationTokenCache * pCache );
|
|
|
|
~CImpersonateRemoteAccess()
|
|
{
|
|
Release();
|
|
}
|
|
|
|
void SetTokenCache( CImpersonationTokenCache * pCache )
|
|
{
|
|
_pCache = pCache;
|
|
}
|
|
|
|
static BOOL IsNetPath( WCHAR const * pwszPath )
|
|
{
|
|
//
|
|
// WWW server and CI don't allow remote drive letters.
|
|
// This allows us to do the check significantly cheaper.
|
|
//
|
|
|
|
return L'\\' == pwszPath[0] &&
|
|
L'\\' == pwszPath[1] &&
|
|
L'.' != pwszPath[2];
|
|
}
|
|
|
|
BOOL ImpersonateIfNoThrow( WCHAR const * pwszPath,
|
|
WCHAR const * pwszVirtualPath )
|
|
{
|
|
Win4Assert( 0 != pwszPath );
|
|
|
|
if ( IsNetPath( pwszPath ) )
|
|
{
|
|
if ( !_ImpersonateIf( pwszPath, pwszVirtualPath ) )
|
|
return FALSE;
|
|
}
|
|
else if ( IsImpersonated() )
|
|
{
|
|
//
|
|
// This thread was impersonated for some network access. Revert back to
|
|
// what it was before impersonation.
|
|
//
|
|
Release();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void ImpersonateIf( WCHAR const * pwszPath,
|
|
WCHAR const * pwszVirtualPath )
|
|
{
|
|
if ( !ImpersonateIfNoThrow( pwszPath, pwszVirtualPath ) )
|
|
{
|
|
THROW( CException(STATUS_LOGON_FAILURE) );
|
|
}
|
|
}
|
|
|
|
BOOL ImpersonateIf( WCHAR const * pwszPath,
|
|
ULONG cSkip,
|
|
BOOL fDummy
|
|
)
|
|
{
|
|
Win4Assert( 0 != pwszPath );
|
|
|
|
if ( IsNetPath( pwszPath ) )
|
|
{
|
|
return _ImpersonateIf( pwszPath, 0, cSkip );
|
|
}
|
|
else if ( IsImpersonated() )
|
|
{
|
|
//
|
|
// This thread was impersonated for some network access. Revert back to
|
|
// what it was before impersonation.
|
|
//
|
|
Release();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void Release();
|
|
|
|
BOOL IsImpersonated() const { return _fMustRevert; }
|
|
|
|
BOOL IsTokenFound() const { return 0 != _pTokenInfo; }
|
|
|
|
private:
|
|
|
|
|
|
BOOL _ImpersonateIf( WCHAR const * pwszPath,
|
|
WCHAR const * pwszVirtualPath,
|
|
ULONG cSkip = 0 );
|
|
|
|
CImpersonationTokenCache * _pCache;
|
|
CPhyDirLogonInfo * _pTokenInfo; // Impersonation information
|
|
HANDLE _hTokenPrev; // If valid, the token of the
|
|
// thread before impersonation
|
|
BOOL _fMustRevert; // Set to TRUE if we have to
|
|
// revert to previous state
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: PImpersonatedWorkItem
|
|
//
|
|
// Purpose: Abstract base class that allows the caller to impersonate
|
|
// until success or no more options.
|
|
//
|
|
// History: 7-15-96 srikants Created
|
|
//
|
|
// Notes: This class defines the framework by which threads that need
|
|
// maximum impersonation level allowed by the user to do a
|
|
// particular work. For example, if /vroot1 and /vroot2 point to
|
|
// the same physical remote root, but have different user-id and
|
|
// levels of permission, we have to use whatever id allows the
|
|
// required level of access.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class PImpersonatedWorkItem
|
|
{
|
|
|
|
public:
|
|
|
|
PImpersonatedWorkItem( WCHAR const * pwszPath )
|
|
: _pwszPath(pwszPath),
|
|
_fDontUseDefault(FALSE)
|
|
{
|
|
_fNetPath = CImpersonateRemoteAccess::IsNetPath( _pwszPath );
|
|
}
|
|
|
|
|
|
virtual BOOL DoIt() = 0;
|
|
|
|
static BOOL IsRetryableError( NTSTATUS status )
|
|
{
|
|
return STATUS_ACCESS_DENIED == status ||
|
|
ERROR_ACCESS_DENIED == status ||
|
|
FILTER_E_ACCESS == status ||
|
|
HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == status;
|
|
}
|
|
|
|
protected:
|
|
|
|
void ImpersonateAndDoWork( CImpersonateRemoteAccess & remoteAccess );
|
|
|
|
WCHAR const * const _pwszPath; // Phy. Path to impersonate for
|
|
BOOL _fNetPath; // Set to TRUE if this is a network path
|
|
|
|
private:
|
|
|
|
BOOL _fDontUseDefault; // Set to TRUE if default vroot must not
|
|
// be used for impersonation
|
|
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CImpersonatedGetAttr
|
|
//
|
|
// Purpose: A class that is capable of repeatedly trying to do
|
|
// GetAttributesEx() until there is a success or there are no
|
|
// more impersonation contexts to try.
|
|
//
|
|
// History: 7-18-96 srikants Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CImpersonatedGetAttr: public PImpersonatedWorkItem
|
|
{
|
|
|
|
public:
|
|
|
|
CImpersonatedGetAttr( const CFunnyPath & funnyPath ) :
|
|
PImpersonatedWorkItem( funnyPath.GetActualPath() ),
|
|
_funnyPath( funnyPath )
|
|
{
|
|
}
|
|
|
|
// THROWS if it cannot get attributes in any context
|
|
void DoWork( CImpersonateRemoteAccess & remoteAccess )
|
|
{
|
|
ImpersonateAndDoWork( remoteAccess );
|
|
}
|
|
|
|
BOOL DoIt(); // virtual
|
|
|
|
WIN32_FIND_DATA const & GetAttrEx() const { return _ffData; }
|
|
|
|
|
|
private:
|
|
|
|
WIN32_FIND_DATA _ffData;
|
|
|
|
const CFunnyPath & _funnyPath;
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CImpersonatedGetFileAttr
|
|
//
|
|
// Purpose: A class that is capable of repeatedly trying to do
|
|
// GetAttributesEx() until there is a success or there are no
|
|
// more impersonation contexts to try.
|
|
//
|
|
// History: 7-18-96 srikants Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CImpersonatedGetFileAttr: public PImpersonatedWorkItem
|
|
{
|
|
|
|
public:
|
|
|
|
CImpersonatedGetFileAttr( const CFunnyPath & funnyPath ) :
|
|
PImpersonatedWorkItem( funnyPath.GetActualPath() ),
|
|
_ulAttr( INVALID_FILE_ATTRIBUTES ),
|
|
_funnyPath( funnyPath )
|
|
{
|
|
}
|
|
|
|
// THROWS if it cannot get attributes in any context
|
|
|
|
void DoWork( CImpersonateRemoteAccess & remoteAccess )
|
|
{
|
|
ImpersonateAndDoWork( remoteAccess );
|
|
}
|
|
|
|
BOOL DoIt(); // virtual
|
|
|
|
ULONG GetAttr() const { return _ulAttr; }
|
|
|
|
|
|
private:
|
|
|
|
ULONG _ulAttr;
|
|
|
|
const CFunnyPath & _funnyPath;
|
|
};
|
|
|
|
//
|
|
// This function throws if the caller doesn't have admin priv
|
|
//
|
|
|
|
void VerifyThreadHasAdminPrivilege( void );
|
|
|