windows-nt/Source/XPSP1/NT/admin/wmi/wbem/scripting/security.cpp

2117 lines
51 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//***************************************************************************
//
// Copyright (c) 1998-2000 Microsoft Corporation
//
// SECURITY.CPP
//
// alanbos 28-Jun-98 Created.
//
// Defines the implementation of CSWbemSecurity
//
//***************************************************************************
#include "precomp.h"
// Used to protect security calls
extern CRITICAL_SECTION g_csSecurity;
bool CSWbemSecurity::s_bInitialized = false;
bool CSWbemSecurity::s_bIsNT = false;
DWORD CSWbemSecurity::s_dwNTMajorVersion = 0;
HINSTANCE CSWbemSecurity::s_hAdvapi = NULL;
bool CSWbemSecurity::s_bCanRevert = false;
WbemImpersonationLevelEnum CSWbemSecurity::s_dwDefaultImpersonationLevel
= wbemImpersonationLevelIdentify;
// Declarations for function pointers that won't exist on Win9x
BOOL (STDAPICALLTYPE *s_pfnDuplicateTokenEx) (
HANDLE,
DWORD,
LPSECURITY_ATTRIBUTES,
SECURITY_IMPERSONATION_LEVEL,
TOKEN_TYPE,
PHANDLE
) = NULL;
//***************************************************************************
//
// SCODE CSWbemSecurity::Initialize
//
// DESCRIPTION:
//
// This static function is caused on DLL attachment to the process; it
// sets up the function pointers for advanced API privilege functions.
// On Win9x these functions are not supported which is why we need to
// indirect through GetProcAddress.
//
//***************************************************************************
void CSWbemSecurity::Initialize ()
{
EnterCriticalSection (&g_csSecurity);
if (!s_bInitialized)
{
// Get OS info
OSVERSIONINFO osVersionInfo;
osVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx (&osVersionInfo);
s_bIsNT = (VER_PLATFORM_WIN32_NT == osVersionInfo.dwPlatformId);
s_dwNTMajorVersion = osVersionInfo.dwMajorVersion;
if (s_bIsNT)
{
HKEY hKey;
// Security values are relevant for NT only - for Win9x leave as default
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
WBEMS_RK_SCRIPTING, 0, KEY_QUERY_VALUE, &hKey))
{
DWORD dwDummy = 0;
// Get revert flag value from registry - NT 4.0 or less only
if (s_dwNTMajorVersion <= 4)
{
DWORD dwEnableForAsp = 0;
dwDummy = sizeof (dwEnableForAsp);
if (ERROR_SUCCESS == RegQueryValueEx (hKey, WBEMS_RV_ENABLEFORASP,
NULL, NULL, (BYTE *) &dwEnableForAsp, &dwDummy))
s_bCanRevert = (0 != dwEnableForAsp);
}
// Get default impersonation level from registry
DWORD dwImpLevel = 0;
dwDummy = sizeof (dwImpLevel);
if (ERROR_SUCCESS == RegQueryValueEx (hKey, WBEMS_RV_DEFAULTIMPLEVEL,
NULL, NULL, (BYTE *) &dwImpLevel, &dwDummy))
s_dwDefaultImpersonationLevel = (WbemImpersonationLevelEnum) dwImpLevel;
RegCloseKey (hKey);
}
// Set up security function pointers for NT
if (!s_hAdvapi)
{
TCHAR dllName [] = _T("\\advapi32.dll");
LPTSTR pszSysDir = new TCHAR[ MAX_PATH + _tcslen (dllName) + 1];
if (pszSysDir)
{
pszSysDir[0] = NULL;
UINT uSize = GetSystemDirectory(pszSysDir, MAX_PATH);
if(uSize > MAX_PATH) {
delete[] pszSysDir;
pszSysDir = new TCHAR[ uSize + _tcslen (dllName) + 1];
if (pszSysDir)
{
pszSysDir[0] = NULL;
uSize = GetSystemDirectory(pszSysDir, uSize);
}
}
if (pszSysDir)
{
_tcscat (pszSysDir, dllName);
s_hAdvapi = LoadLibraryEx (pszSysDir, NULL, 0);
if (s_hAdvapi)
(FARPROC&) s_pfnDuplicateTokenEx = GetProcAddress(s_hAdvapi, "DuplicateTokenEx");
delete [] pszSysDir;
}
}
}
}
s_bInitialized = true;
}
LeaveCriticalSection (&g_csSecurity);
}
//***************************************************************************
//
// SCODE CSWbemSecurity::Uninitialize
//
// DESCRIPTION:
//
// This static function is caused on DLL detachment to the process; it
// unloads the API loaded by Initialize (above) to obtain function pointers.
//
//***************************************************************************
void CSWbemSecurity::Uninitialize ()
{
EnterCriticalSection (&g_csSecurity);
if (s_hAdvapi)
{
s_pfnDuplicateTokenEx = NULL;
FreeLibrary (s_hAdvapi);
s_hAdvapi = NULL;
}
LeaveCriticalSection (&g_csSecurity);
}
//***************************************************************************
//
// SCODE CSWbemSecurity::LookupPrivilegeValue
//
// DESCRIPTION:
//
// This static function wraps the Win32 LookupPrivilegeValue function,
// allowing us to do some OS-dependent stuff.
//
// PARAMETERS:
//
// lpName the privilege name
// lpLuid holds the LUID on successful return
//
// RETURN VALUES:
//
// true On NT this means we found the privilege. On Win9x we
// always return this.
//
// false On NT this means the privilege is not recognized. This
// is never returned on Win9x.
//
//***************************************************************************
BOOL CSWbemSecurity::LookupPrivilegeValue (
LPCTSTR lpName,
PLUID lpLuid
)
{
// Allows any name to map to 0 LUID on Win9x - this aids script portability
if (IsNT ())
return ::LookupPrivilegeValue(NULL, lpName, lpLuid);
else
return true;
}
//***************************************************************************
//
// SCODE CSWbemSecurity::LookupPrivilegeDisplayName
//
// DESCRIPTION:
//
// This static function wraps the Win32 LookupPrivilegeDisplayName function,
// allowing us to do some OS-dependent stuff.
//
// PARAMETERS:
//
// tName the privilege name
// pDisplayName holds the display name on successful return
//
//***************************************************************************
void CSWbemSecurity::LookupPrivilegeDisplayName (LPCTSTR lpName, BSTR *pDisplayName)
{
if (pDisplayName)
{
// Can't return display name on Win9x (no privilege support)
if (IsNT ())
{
DWORD dwLangID;
DWORD dwSize = 1;
TCHAR dummy [1];
// Get size of required buffer
::LookupPrivilegeDisplayName (NULL, lpName, dummy, &dwSize, &dwLangID);
LPTSTR dname = new TCHAR[dwSize + 1];
if (dname)
{
if (::LookupPrivilegeDisplayName (_T(""), lpName, dname, &dwSize, &dwLangID))
{
// Have a valid name - now copy it to a BSTR
#ifdef _UNICODE
*pDisplayName = SysAllocString (dname);
#else
size_t dnameLen = strlen (dname);
OLECHAR *nameW = new OLECHAR [dnameLen + 1];
if (nameW)
{
mbstowcs (nameW, dname, dnameLen);
nameW [dnameLen] = NULL;
*pDisplayName = SysAllocString (nameW);
delete [] nameW;
}
#endif
}
delete [] dname;
}
}
// If we failed, just set an empty string
if (!(*pDisplayName))
*pDisplayName = SysAllocString (L"");
}
}
//***************************************************************************
//
// CSWbemSecurity::CSWbemSecurity
//
// CONSTRUCTOR
// This form of the constructor is used for securing a new WBEM
// remoted interface where no previous security has been applied.
// It is only used to secure IWbemServices interfaces.
// Note that the Locator may have security settings so these are
// transferred if present.
//
//***************************************************************************
CSWbemSecurity::CSWbemSecurity (
IUnknown *pUnk,
BSTR bsAuthority ,
BSTR bsUser,
BSTR bsPassword,
CWbemLocatorSecurity *pLocatorSecurity) :
m_pPrivilegeSet (NULL),
m_pProxyCache (NULL),
m_pCurProxy (NULL)
{
m_Dispatch.SetObj (this, IID_ISWbemSecurity,
CLSID_SWbemSecurity, L"SWbemSecurity");
m_cRef=1;
m_pProxyCache = new CSWbemProxyCache (pUnk, bsAuthority,
bsUser, bsPassword, pLocatorSecurity);
if (m_pProxyCache)
m_pCurProxy = m_pProxyCache->GetInitialProxy ();
if (pLocatorSecurity)
{
// Clone the privilege set
CSWbemPrivilegeSet *pPrivilegeSet = pLocatorSecurity->GetPrivilegeSet ();
if (pPrivilegeSet)
{
m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet);
pPrivilegeSet->Release ();
}
}
else
{
// Create a new privilege set
m_pPrivilegeSet = new CSWbemPrivilegeSet;
}
InterlockedIncrement(&g_cObj);
}
//***************************************************************************
//
// CSWbemSecurity::CSWbemSecurity
//
// CONSTRUCTOR
// This form of the constructor is used for securing a new WBEM
// remoted interface where no previous security has been applied,
// and where the user credentials are expressed in the form of an
// encrypted COAUTHIDENTITY plus principal and authority.
// It is only used to secure IWbemServices interfaces.
//
//***************************************************************************
CSWbemSecurity::CSWbemSecurity (
IUnknown *pUnk,
COAUTHIDENTITY *pCoAuthIdentity,
BSTR bsPrincipal,
BSTR bsAuthority) :
m_pPrivilegeSet (NULL),
m_pProxyCache (NULL),
m_pCurProxy (NULL)
{
m_Dispatch.SetObj (this, IID_ISWbemSecurity,
CLSID_SWbemSecurity, L"SWbemSecurity");
m_cRef=1;
m_pProxyCache = new CSWbemProxyCache (pUnk, pCoAuthIdentity,
bsPrincipal, bsAuthority);
if (m_pProxyCache)
m_pCurProxy = m_pProxyCache->GetInitialProxy ();
// Create a new privilege set
m_pPrivilegeSet = new CSWbemPrivilegeSet;
InterlockedIncrement(&g_cObj);
}
//***************************************************************************
//
// CSWbemSecurity::CSWbemSecurity
//
// CONSTRUCTOR
// This form of the constructor is used for securing a new WBEM interface
// non-remoted interface using the security attributes attached to another
// (already secured) remoted interface; a non-remoted interface is secured
// by virtue of securing a new proxy on an underlying remoted interface.
// It is used to "secure" an ISWbemObjectEx interface using the security
// settings of an IWbemServices interface.
//
//***************************************************************************
CSWbemSecurity::CSWbemSecurity (
CSWbemSecurity *pSecurity) :
m_pPrivilegeSet (NULL),
m_pProxyCache (NULL),
m_pCurProxy (NULL)
{
m_Dispatch.SetObj (this, IID_ISWbemSecurity,
CLSID_SWbemSecurity, L"SWbemSecurity");
m_cRef=1;
// Clone the privilege set
if (pSecurity)
{
CSWbemPrivilegeSet *pPrivilegeSet = pSecurity->GetPrivilegeSet ();
if (pPrivilegeSet)
{
m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet);
pPrivilegeSet->Release ();
}
else
{
// Create a new one
m_pPrivilegeSet = new CSWbemPrivilegeSet ();
}
m_pProxyCache = pSecurity->GetProxyCache ();
m_pCurProxy = pSecurity->GetProxy ();
}
InterlockedIncrement(&g_cObj);
}
CSWbemSecurity::CSWbemSecurity (
IUnknown *pUnk,
ISWbemInternalSecurity *pISWbemInternalSecurity) :
m_pPrivilegeSet (NULL),
m_pProxyCache (NULL),
m_pCurProxy (NULL)
{
m_Dispatch.SetObj (this, IID_ISWbemSecurity,
CLSID_SWbemSecurity, L"SWbemSecurity");
m_cRef=1;
if (pISWbemInternalSecurity)
{
// Clone the privilege set
ISWbemSecurity *pISWbemSecurity = NULL;
if (SUCCEEDED(pISWbemInternalSecurity->QueryInterface (IID_ISWbemSecurity,
(void**) &pISWbemSecurity)))
{
ISWbemPrivilegeSet *pISWbemPrivilegeSet = NULL;
if (SUCCEEDED(pISWbemSecurity->get_Privileges (&pISWbemPrivilegeSet)))
{
// Build the privilege set
m_pPrivilegeSet = new CSWbemPrivilegeSet (pISWbemPrivilegeSet);
// Build the proxy cache
BSTR bsAuthority = NULL;
BSTR bsPrincipal = NULL;
BSTR bsUser = NULL;
BSTR bsPassword = NULL;
BSTR bsDomain = NULL;
pISWbemInternalSecurity->GetAuthority (&bsAuthority);
pISWbemInternalSecurity->GetPrincipal (&bsPrincipal);
pISWbemInternalSecurity->GetUPD (&bsUser, &bsPassword, &bsDomain);
COAUTHIDENTITY *pCoAuthIdentity = NULL;
// Decide if we need a COAUTHIDENTITY
if ((bsUser && (0 < wcslen (bsUser))) ||
(bsPassword && (0 < wcslen (bsPassword))) ||
(bsDomain && (0 < wcslen (bsDomain))))
WbemAllocAuthIdentity (bsUser, bsPassword, bsDomain, &pCoAuthIdentity);
m_pProxyCache = new CSWbemProxyCache (pUnk, pCoAuthIdentity,
bsPrincipal, bsAuthority);
if (pCoAuthIdentity)
WbemFreeAuthIdentity (pCoAuthIdentity);
if (bsAuthority)
SysFreeString (bsAuthority);
if (bsPrincipal)
SysFreeString (bsPrincipal);
if (bsUser)
SysFreeString (bsUser);
if (bsPassword)
SysFreeString (bsPassword);
if (bsDomain)
SysFreeString (bsDomain);
if (m_pProxyCache)
m_pCurProxy = m_pProxyCache->GetInitialProxy ();
}
pISWbemPrivilegeSet->Release ();
}
pISWbemSecurity->Release ();
}
InterlockedIncrement(&g_cObj);
}
//***************************************************************************
//
// CSWbemSecurity::CSWbemSecurity
//
// CONSTRUCTOR
// This form of the constructor is used for securing a new WBEM remoted
// interface interface using the security attributes attached to another
// (already secured) remoted interface.
// It is used to "secure" an ISWbemObjectSet interface using the security
// settings of an IWbemServices interface.
//
//***************************************************************************
CSWbemSecurity::CSWbemSecurity (
IUnknown *pUnk,
CSWbemSecurity *pSecurity) :
m_pPrivilegeSet (NULL),
m_pProxyCache (NULL),
m_pCurProxy (NULL)
{
m_Dispatch.SetObj (this, IID_ISWbemSecurity,
CLSID_SWbemSecurity, L"SWbemSecurity");
m_cRef=1;
InterlockedIncrement(&g_cObj);
if (pSecurity)
{
// Clone the privilege set
CSWbemPrivilegeSet *pPrivilegeSet = pSecurity->GetPrivilegeSet ();
if (pPrivilegeSet)
{
m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet);
pPrivilegeSet->Release ();
}
m_pProxyCache = new CSWbemProxyCache (pUnk, pSecurity);
if (m_pProxyCache)
m_pCurProxy = m_pProxyCache->GetInitialProxy ();
}
else
{
m_pPrivilegeSet = new CSWbemPrivilegeSet ();
m_pProxyCache = new CSWbemProxyCache (pUnk, NULL);
if (m_pProxyCache)
m_pCurProxy = m_pProxyCache->GetInitialProxy ();
}
}
//***************************************************************************
//
// CSWbemSecurity::~CSWbemSecurity
//
// DESTRUCTOR
//
//***************************************************************************
CSWbemSecurity::~CSWbemSecurity (void)
{
InterlockedDecrement(&g_cObj);
if (m_pCurProxy)
m_pCurProxy->Release ();
if (m_pProxyCache)
m_pProxyCache->Release ();
if (m_pPrivilegeSet)
m_pPrivilegeSet->Release ();
}
//***************************************************************************
// HRESULT CSWbemSecurity::QueryInterface
// long CSWbemSecurity::AddRef
// long CSWbemSecurity::Release
//
// DESCRIPTION:
//
// Standard Com IUNKNOWN functions.
//
//***************************************************************************
STDMETHODIMP CSWbemSecurity::QueryInterface (
IN REFIID riid,
OUT LPVOID *ppv
)
{
*ppv=NULL;
if (IID_IUnknown==riid)
*ppv = reinterpret_cast<IUnknown*>(this);
else if (IID_ISWbemSecurity==riid)
*ppv = (ISWbemSecurity *)this;
else if (IID_IDispatch==riid)
*ppv = (IDispatch *)this;
else if (IID_ISupportErrorInfo==riid)
*ppv = (ISupportErrorInfo *)this;
else if (IID_ISWbemInternalSecurity==riid)
*ppv = (ISWbemInternalSecurity *)this;
else if (IID_IProvideClassInfo==riid)
*ppv = (IProvideClassInfo *)this;
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CSWbemSecurity::AddRef(void)
{
long l = InterlockedIncrement(&m_cRef);
return l;
}
STDMETHODIMP_(ULONG) CSWbemSecurity::Release(void)
{
long l = InterlockedDecrement(&m_cRef);
if (0L!=l)
return l;
delete this;
return 0;
}
//***************************************************************************
// HRESULT CSWbemSecurity::InterfaceSupportsErrorInfo
//
// DESCRIPTION:
//
// Standard Com ISupportErrorInfo functions.
//
//***************************************************************************
STDMETHODIMP CSWbemSecurity::InterfaceSupportsErrorInfo (IN REFIID riid)
{
return (IID_ISWbemSecurity == riid) ? S_OK : S_FALSE;
}
//***************************************************************************
//
// SCODE CSWbemSecurity::get_AuthenticationLevel
//
// DESCRIPTION:
//
// Retrieve the authentication level
//
// PARAMETERS:
//
// pAuthenticationLevel holds the value on return
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CSWbemSecurity::get_AuthenticationLevel (
WbemAuthenticationLevelEnum *pAuthenticationLevel
)
{
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if (NULL == pAuthenticationLevel)
hr = WBEM_E_INVALID_PARAMETER;
else if (m_pCurProxy)
{
DWORD dwAuthnLevel;
DWORD dwImpLevel;
if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
{
*pAuthenticationLevel = (WbemAuthenticationLevelEnum) dwAuthnLevel;
hr = WBEM_S_NO_ERROR;
}
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}
//***************************************************************************
//
// SCODE CSWbemSecurity::put_AuthenticationLevel
//
// DESCRIPTION:
//
// Set the authentication level
//
// PARAMETERS:
//
// authenticationLevel the new value
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CSWbemSecurity::put_AuthenticationLevel (
WbemAuthenticationLevelEnum authenticationLevel
)
{
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if ((WBEMS_MIN_AUTHN_LEVEL > authenticationLevel) ||
(WBEMS_MAX_AUTHN_LEVEL < authenticationLevel))
hr = WBEM_E_INVALID_PARAMETER;
else if (m_pCurProxy && m_pProxyCache)
{
DWORD dwAuthnLevel;
DWORD dwImpLevel;
if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
{
// Only refressh from cache if settings have changed
if (authenticationLevel != (WbemAuthenticationLevelEnum) dwAuthnLevel)
{
m_pCurProxy->Release ();
m_pCurProxy = NULL;
m_pCurProxy = m_pProxyCache->GetProxy
(authenticationLevel, (WbemImpersonationLevelEnum) dwImpLevel);
}
hr = WBEM_S_NO_ERROR;
}
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}
//***************************************************************************
//
// SCODE CSWbemSecurity::get_ImpersonationLevel
//
// DESCRIPTION:
//
// Retrieve the impersonation level
//
// PARAMETERS:
//
// pImpersonationLevel holds the value on return
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CSWbemSecurity::get_ImpersonationLevel (
WbemImpersonationLevelEnum *pImpersonationLevel
)
{
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if (NULL == pImpersonationLevel)
hr = WBEM_E_INVALID_PARAMETER;
else if (m_pCurProxy)
{
DWORD dwAuthnLevel;
DWORD dwImpLevel;
if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
{
*pImpersonationLevel = (WbemImpersonationLevelEnum) dwImpLevel;
hr = WBEM_S_NO_ERROR;
}
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}
//***************************************************************************
//
// SCODE CSWbemSecurity::put_ImpersonationLevel
//
// DESCRIPTION:
//
// Set the impersonation level
//
// PARAMETERS:
//
// impersonationLevel the new value
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CSWbemSecurity::put_ImpersonationLevel (
WbemImpersonationLevelEnum impersonationLevel
)
{
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if ((WBEMS_MIN_IMP_LEVEL > impersonationLevel) || (WBEMS_MAX_IMP_LEVEL < impersonationLevel))
hr = WBEM_E_INVALID_PARAMETER;
else if (m_pCurProxy && m_pProxyCache)
{
DWORD dwAuthnLevel;
DWORD dwImpLevel;
if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
{
// Only refressh from cache if settings have changed
if (impersonationLevel != (WbemImpersonationLevelEnum) dwImpLevel)
{
m_pCurProxy->Release ();
m_pCurProxy = NULL;
m_pCurProxy = m_pProxyCache->GetProxy
((WbemAuthenticationLevelEnum) dwAuthnLevel, impersonationLevel);
}
hr = WBEM_S_NO_ERROR;
}
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}
//***************************************************************************
//
// SCODE CSWbemSecurity::get_Privileges
//
// DESCRIPTION:
//
// Return the Privilege override set
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CSWbemSecurity::get_Privileges (
ISWbemPrivilegeSet **ppPrivileges
)
{
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if (NULL == ppPrivileges)
hr = WBEM_E_INVALID_PARAMETER;
{
*ppPrivileges = NULL;
if (m_pPrivilegeSet)
{
if (SUCCEEDED (m_pPrivilegeSet->QueryInterface (IID_ISWbemPrivilegeSet,
(PPVOID) ppPrivileges)))
hr = WBEM_S_NO_ERROR;
}
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}
//***************************************************************************
//
// CSWbemSecurity::SecureInterface
//
// DESCRIPTION:
//
// Set the security on the specified interface using the security settings
// on this interface.
//
// PARAMETERS:
//
// pUnk The interface to secure
//
// RETURN VALUES:
// none
//***************************************************************************
void CSWbemSecurity::SecureInterface (IUnknown *pUnk)
{
if(pUnk)
{
if (m_pCurProxy)
{
DWORD dwAuthnLevel;
DWORD dwImpLevel;
if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
if (m_pProxyCache)
m_pProxyCache->SecureProxy (pUnk,
(WbemAuthenticationLevelEnum) dwAuthnLevel,
(WbemImpersonationLevelEnum) dwImpLevel);
}
}
}
//***************************************************************************
//
// CSWbemSecurity::SecureInterfaceRev
//
// DESCRIPTION:
//
// Set the security on this interface using the security settings
// on the specified interface.
//
// PARAMETERS:
//
// pUnk The interface whose security settings we will
// use to set this interface
//
// RETURN VALUES:
// none
//***************************************************************************
void CSWbemSecurity::SecureInterfaceRev (IUnknown *pUnk)
{
if (pUnk)
{
DWORD dwAuthnLevel;
DWORD dwImpLevel;
if (S_OK == GetAuthImp (pUnk, &dwAuthnLevel, &dwImpLevel))
{
if (m_pCurProxy)
{
m_pCurProxy->Release ();
m_pCurProxy = NULL;
}
if (m_pProxyCache)
{
m_pCurProxy = m_pProxyCache->GetProxy
((WbemAuthenticationLevelEnum) dwAuthnLevel,
(WbemImpersonationLevelEnum) dwImpLevel);
}
}
}
}
//***************************************************************************
//
// CSWbemSecurity::AdjustTokenPrivileges
//
// DESCRIPTION:
//
// Adjust the Privileges on the specified token without allowing a future
// restore of the current settings..
//
// PARAMETERS:
//
// hHandle Handle of the token on which to adjust privileges
// pPrivilegeSet Specified privilege adjustments
//
// RETURN VALUES:
// none
//***************************************************************************
void CSWbemSecurity::AdjustTokenPrivileges (
HANDLE hHandle,
CSWbemPrivilegeSet *pPrivilegeSet
)
{
DWORD lastErr = 0;
if (pPrivilegeSet)
{
pPrivilegeSet->AddRef ();
long lNumPrivileges = 0;
pPrivilegeSet->get_Count (&lNumPrivileges);
if (lNumPrivileges)
{
DWORD dwPrivilegeIndex = 0;
/*
* Set up the token privileges array. Note that some jiggery-pokery
* is required here because the Privileges field is an [ANYSIZE_ARRAY]
* type.
*/
TOKEN_PRIVILEGES *pTokenPrivileges = (TOKEN_PRIVILEGES *)
new BYTE [sizeof(TOKEN_PRIVILEGES) + (lNumPrivileges * sizeof (LUID_AND_ATTRIBUTES [1]))];
if (pTokenPrivileges)
{
// Get the iterator
PrivilegeMap::iterator next = pPrivilegeSet->m_PrivilegeMap.begin ();
while (next != pPrivilegeSet->m_PrivilegeMap.end ())
{
CSWbemPrivilege *pPrivilege = (*next).second;
pPrivilege->AddRef ();
LUID luid;
pPrivilege->GetLUID (&luid);
VARIANT_BOOL vBool;
pPrivilege->get_IsEnabled (&vBool);
pTokenPrivileges->Privileges [dwPrivilegeIndex].Luid = luid;
/*
* Note that any setting other than SE_PRIVILEGE_ENABLED
* is interpreted by AdjustTokenPrivileges as a DISABLE
* request for that Privilege.
*/
pTokenPrivileges->Privileges [dwPrivilegeIndex].Attributes
= (VARIANT_TRUE == vBool) ?
SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_ENABLED_BY_DEFAULT;
dwPrivilegeIndex++;
pPrivilege->Release ();
next++;
}
// Now we should have recorded the number of privileges that were OK
if (0 < dwPrivilegeIndex)
{
pTokenPrivileges->PrivilegeCount = dwPrivilegeIndex;
BOOL result = ::AdjustTokenPrivileges (hHandle, FALSE, pTokenPrivileges, 0, NULL, NULL);
lastErr = GetLastError ();
}
delete [] pTokenPrivileges;
}
}
pPrivilegeSet->Release ();
}
}
//***************************************************************************
//
// SCODE CSWbemSecurity::SetSecurity
//
// DESCRIPTION:
//
// Set Privileges on the Thread Token.
//
//***************************************************************************
BOOL CSWbemSecurity::SetSecurity (
bool &needToResetSecurity,
HANDLE &hThreadToken
)
{
BOOL result = TRUE; // Default is success
DWORD lastErr = 0;
hThreadToken = NULL; // Default assume we'll modify process token
needToResetSecurity = false; // Default assume we changed no privileges
// Win9x has no security support
if (IsNT ())
{
// Start by checking whether we are being impersonated. On an NT4
// box (which has no cloaking, and therefore cannot allow us to
// pass on this impersonation to Winmgmt) we should RevertToSelf
// if we have been configured to allow this. If we haven't been
// configured to allow this, bail out now.
if (4 >= GetNTMajorVersion ())
{
if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY|TOKEN_IMPERSONATE, true, &hThreadToken))
{
// We are being impersonated
if (s_bCanRevert)
{
if (result = RevertToSelf())
needToResetSecurity = true;
}
else
{
// Error - cannot do this! Time to bail out
CloseHandle (hThreadToken);
hThreadToken = NULL;
result = FALSE;
}
}
}
else
{
#ifdef WSCRPDEBUG
HANDLE hToken = NULL;
if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, false, &hToken))
{
PrintPrivileges (hToken);
CloseHandle (hToken);
}
#endif
}
if (result)
{
// Now we check if we need to set privileges
bool bIsUsingExplicitUserName = false;
if (m_pProxyCache)
bIsUsingExplicitUserName = m_pProxyCache->IsUsingExplicitUserName ();
/*
* Specifying a user only makes sense for remote operations, and we
* don't need to mess with privilege for remote operations since
* they are set up by server logon anyway.
*/
if (!bIsUsingExplicitUserName && m_pPrivilegeSet)
{
// Nothing to do unless some privilege overrides have been set
long lCount = 0;
m_pPrivilegeSet->get_Count (&lCount);
if (0 < lCount)
{
if (4 < GetNTMajorVersion ())
{
/*
* On NT5 we try to open the Thread token. If the client app
* is calling into us on an impersonated thread (as IIS may be,
* for example), this will succeed.
*/
HANDLE hToken;
SECURITY_IMPERSONATION_LEVEL secImpLevel = SecurityImpersonation;
if (!(result = OpenThreadToken (GetCurrentThread (), TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_IMPERSONATE, true, &hToken)))
{
// No thread token - go for the Process token instead
HANDLE hProcess = GetCurrentProcess ();
result = OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_DUPLICATE, &hToken);
CloseHandle (hProcess);
}
else
{
// We are working with a thread token
hThreadToken = hToken;
// Try and get the impersonation level of this token
DWORD dwReturnLength = 0;
BOOL thisRes = GetTokenInformation (hToken, TokenImpersonationLevel, &secImpLevel,
sizeof (SECURITY_IMPERSONATION_LEVEL), &dwReturnLength);
}
if (result)
{
/*
* Getting here means we have a valid token, be it process or thread. We
* now attempt to duplicate it before Adjusting the Privileges.
*/
#ifdef WSCRPDEBUG
PrintPrivileges (hToken);
#endif
HANDLE hDupToken;
EnterCriticalSection (&g_csSecurity);
result = s_pfnDuplicateTokenEx &&
s_pfnDuplicateTokenEx (hToken, TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE, NULL,
secImpLevel, TokenImpersonation, &hDupToken);
LeaveCriticalSection (&g_csSecurity);
if (result)
{
CSWbemSecurity::AdjustTokenPrivileges (hDupToken, m_pPrivilegeSet);
// Now use this token on the current thread
if (SetThreadToken(NULL, hDupToken))
{
needToResetSecurity = true;
#ifdef WSCRPDEBUG
CSWbemSecurity::PrintPrivileges (hDupToken);
#endif
// Reset the blanket for the benefit of RPC
DWORD dwAuthnLevel, dwImpLevel;
if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
{
// Force the cache to resecure the proxy
IUnknown *pNewProxy = m_pProxyCache->GetProxy
((WbemAuthenticationLevelEnum) dwAuthnLevel,
(WbemImpersonationLevelEnum) dwImpLevel, true);
if (pNewProxy)
{
if (m_pCurProxy)
m_pCurProxy->Release ();
m_pCurProxy = pNewProxy;
}
}
}
CloseHandle (hDupToken);
}
else
{
lastErr = GetLastError ();
}
/*
* If we are not using a thread token, close the token now. Otherwise
* the handle will be closed in the balanced call to RestorePrivileges ().
*/
if (!hThreadToken)
CloseHandle (hToken);
}
}
else
{
// For NT4 we adjust the privileges in the process token
HANDLE hProcessToken = NULL;
HANDLE hProcess = GetCurrentProcess ();
result = OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hProcessToken);
CloseHandle (hProcess);
// Adjust privilege on the process
if (result)
{
#ifdef WSCRPDEBUG
CSWbemSecurity::PrintPrivileges (hProcessToken);
#endif
CSWbemSecurity::AdjustTokenPrivileges (hProcessToken, m_pPrivilegeSet);
#ifdef WSCRPDEBUG
CSWbemSecurity::PrintPrivileges (hProcessToken);
#endif
CloseHandle (hProcessToken);
}
}
}
}
}
}
return result;
}
//***************************************************************************
//
// SCODE CSWbemSecurity::ResetSecurity
//
// DESCRIPTION:
//
// Restore Privileges on the Thread Token.
//
//***************************************************************************
void CSWbemSecurity::ResetSecurity (
HANDLE hThreadToken
)
{
// Win9x has no security palaver
if (IsNT ())
{
/*
* Set the supplied token (which may be NULL) into
* the current thread.
*/
BOOL result = SetThreadToken (NULL, hThreadToken);
DWORD error = 0;
if (!result)
error = GetLastError ();
#ifdef WSCRPDEBUG
// Print out the current privileges to see what's changed
HANDLE hToken = NULL;
if (!OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, false, &hToken))
{
// No thread token - go for the Process token instead
HANDLE hProcess = GetCurrentProcess ();
OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
CloseHandle (hProcess);
}
if (hToken)
{
PrintPrivileges (hToken);
CloseHandle (hToken);
}
#endif
if (hThreadToken)
CloseHandle (hThreadToken);
}
}
bool CSWbemSecurity::IsImpersonating (bool useDefaultUser, bool useDefaultAuthority)
{
bool result = false;
if (useDefaultUser && useDefaultAuthority && CSWbemSecurity::IsNT () &&
(4 < CSWbemSecurity::GetNTMajorVersion ()))
{
// A suitable candidate - find out if we are running on an impersonated thread
HANDLE hThreadToken = NULL;
if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, true, &hThreadToken))
{
// Check we have an impersonation token
SECURITY_IMPERSONATION_LEVEL secImpLevel;
DWORD dwReturnLength = 0;
if (GetTokenInformation (hThreadToken, TokenImpersonationLevel, &secImpLevel,
sizeof (SECURITY_IMPERSONATION_LEVEL), &dwReturnLength))
result = ((SecurityImpersonation == secImpLevel) || (SecurityDelegation == secImpLevel));
CloseHandle (hThreadToken);
}
}
return result;
}
HRESULT CSWbemSecurity::GetAuthority (BSTR *bsAuthority)
{
HRESULT hr = WBEM_E_FAILED;
if (m_pProxyCache)
{
*bsAuthority = SysAllocString(m_pProxyCache->GetAuthority ());
hr = S_OK;
}
return hr;
}
HRESULT CSWbemSecurity::GetUPD (BSTR *bsUser, BSTR *bsPassword, BSTR *bsDomain)
{
HRESULT hr = WBEM_E_FAILED;
if (m_pProxyCache)
{
COAUTHIDENTITY *pCoAuthIdentity = m_pProxyCache->GetCoAuthIdentity ();
if (pCoAuthIdentity)
{
*bsUser = SysAllocString (pCoAuthIdentity->User);
*bsPassword = SysAllocString (pCoAuthIdentity->Password);
*bsDomain = SysAllocString (pCoAuthIdentity->Domain);
WbemFreeAuthIdentity (pCoAuthIdentity);
}
hr = S_OK;
}
return hr;
}
HRESULT CSWbemSecurity::GetPrincipal (BSTR *bsPrincipal)
{
HRESULT hr = WBEM_E_FAILED;
if (m_pProxyCache)
{
*bsPrincipal = SysAllocString(m_pProxyCache->GetPrincipal ());
hr = S_OK;
}
return hr;
}
// CWbemLocatorSecurity methods
//***************************************************************************
//
// CSWbemLocatorSecurity::CSWbemLocatorSecurity
//
// CONSTRUCTOR
//
//***************************************************************************
CWbemLocatorSecurity::CWbemLocatorSecurity (CSWbemPrivilegeSet *pPrivilegeSet) :
m_cRef (1),
m_impLevelSet (false),
m_authnLevelSet (false),
m_pPrivilegeSet (NULL)
{
m_Dispatch.SetObj (this, IID_ISWbemSecurity,
CLSID_SWbemSecurity, L"SWbemSecurity");
InterlockedIncrement(&g_cObj);
if (pPrivilegeSet)
m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet);
else
m_pPrivilegeSet = new CSWbemPrivilegeSet;
}
CWbemLocatorSecurity::CWbemLocatorSecurity (CWbemLocatorSecurity *pCWbemLocatorSecurity) :
m_cRef (1),
m_impLevelSet (false),
m_authnLevelSet (false),
m_pPrivilegeSet (NULL)
{
m_Dispatch.SetObj (this, IID_ISWbemSecurity,
CLSID_SWbemSecurity, L"SWbemSecurity");
InterlockedIncrement(&g_cObj);
if (pCWbemLocatorSecurity)
{
m_pPrivilegeSet = new CSWbemPrivilegeSet (pCWbemLocatorSecurity->m_pPrivilegeSet);
m_impLevelSet = pCWbemLocatorSecurity->m_impLevelSet;
m_authnLevelSet = pCWbemLocatorSecurity->m_authnLevelSet;
if (m_impLevelSet)
m_impLevel = pCWbemLocatorSecurity->m_impLevel;
if (m_authnLevelSet)
m_authnLevel = pCWbemLocatorSecurity->m_authnLevel;
}
else
{
m_pPrivilegeSet = new CSWbemPrivilegeSet;
m_impLevelSet = false;
m_authnLevelSet = false;
}
}
//***************************************************************************
//
// CWbemLocatorSecurity::CWbemLocatorSecurity
//
// DESTRUCTOR
//
//***************************************************************************
CWbemLocatorSecurity::~CWbemLocatorSecurity (void)
{
InterlockedDecrement(&g_cObj);
if (m_pPrivilegeSet)
m_pPrivilegeSet->Release ();
}
//***************************************************************************
// HRESULT CWbemLocatorSecurity::QueryInterface
// long CWbemLocatorSecurity::AddRef
// long CWbemLocatorSecurity::Release
//
// DESCRIPTION:
//
// Standard Com IUNKNOWN functions.
//
//***************************************************************************
STDMETHODIMP CWbemLocatorSecurity::QueryInterface (
IN REFIID riid,
OUT LPVOID *ppv
)
{
*ppv=NULL;
if (IID_IUnknown==riid)
*ppv = reinterpret_cast<IUnknown*>(this);
else if (IID_ISWbemSecurity==riid)
*ppv = (ISWbemSecurity *)this;
else if (IID_IDispatch==riid)
*ppv = (IDispatch *)this;
else if (IID_ISupportErrorInfo==riid)
*ppv = (ISupportErrorInfo *)this;
else if (IID_IProvideClassInfo==riid)
*ppv = (IProvideClassInfo *)this;
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return ResultFromScode(E_NOINTERFACE);
}
STDMETHODIMP_(ULONG) CWbemLocatorSecurity::AddRef(void)
{
long l = InterlockedIncrement(&m_cRef);
return l;
}
STDMETHODIMP_(ULONG) CWbemLocatorSecurity::Release(void)
{
long l = InterlockedDecrement(&m_cRef);
if (0L!=l)
return l;
delete this;
return 0;
}
//***************************************************************************
// HRESULT CSWbemLocatorSecurity::InterfaceSupportsErrorInfo
//
// DESCRIPTION:
//
// Standard Com ISupportErrorInfo functions.
//
//***************************************************************************
STDMETHODIMP CWbemLocatorSecurity::InterfaceSupportsErrorInfo (IN REFIID riid)
{
return (IID_ISWbemSecurity == riid) ? S_OK : S_FALSE;
}
//***************************************************************************
//
// SCODE CWbemLocatorSecurity::get_AuthenticationLevel
//
// DESCRIPTION:
//
// Retrieve the authentication level
//
// PARAMETERS:
//
// pAuthenticationLevel holds the value on return
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CWbemLocatorSecurity::get_AuthenticationLevel (
WbemAuthenticationLevelEnum *pAuthenticationLevel
)
{
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if (NULL == pAuthenticationLevel)
hr = WBEM_E_INVALID_PARAMETER;
else if (m_authnLevelSet)
{
*pAuthenticationLevel = m_authnLevel;
hr = WBEM_S_NO_ERROR;
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}
//***************************************************************************
//
// SCODE CWbemLocatorSecurity::put_AuthenticationLevel
//
// DESCRIPTION:
//
// Set the authentication level
//
// PARAMETERS:
//
// authenticationLevel the new value
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CWbemLocatorSecurity::put_AuthenticationLevel (
WbemAuthenticationLevelEnum authenticationLevel
)
{
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if ((WBEMS_MIN_AUTHN_LEVEL > authenticationLevel) ||
(WBEMS_MAX_AUTHN_LEVEL < authenticationLevel))
hr = WBEM_E_INVALID_PARAMETER;
else
{
m_authnLevel = authenticationLevel;
m_authnLevelSet = true;
hr = WBEM_S_NO_ERROR;
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}
//***************************************************************************
//
// SCODE CWbemLocatorSecurity::get_ImpersonationLevel
//
// DESCRIPTION:
//
// Retrieve the impersonation level
//
// PARAMETERS:
//
// pImpersonationLevel holds the value on return
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CWbemLocatorSecurity::get_ImpersonationLevel (
WbemImpersonationLevelEnum *pImpersonationLevel
)
{
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if (NULL == pImpersonationLevel)
hr = WBEM_E_INVALID_PARAMETER;
else if (m_impLevelSet)
{
*pImpersonationLevel = m_impLevel;
hr = WBEM_S_NO_ERROR;
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}
//***************************************************************************
//
// SCODE CWbemLocatorSecurity::put_ImpersonationLevel
//
// DESCRIPTION:
//
// Set the impersonation level
//
// PARAMETERS:
//
// impersonationLevel the new value
//
// RETURN VALUES:
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CWbemLocatorSecurity::put_ImpersonationLevel (
WbemImpersonationLevelEnum impersonationLevel
)
{
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if ((WBEMS_MIN_IMP_LEVEL > impersonationLevel) || (WBEMS_MAX_IMP_LEVEL < impersonationLevel))
hr = WBEM_E_INVALID_PARAMETER;
else
{
m_impLevel = impersonationLevel;
m_impLevelSet = true;
hr = WBEM_S_NO_ERROR;
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}
//***************************************************************************
//
// SCODE CWbemLocatorSecurity::get_Privileges
//
// DESCRIPTION:
//
// Return the Privilege override set
//
// WBEM_S_NO_ERROR success
// WBEM_E_INVALID_PARAMETER bad input parameters
// WBEM_E_FAILED otherwise
//
//***************************************************************************
HRESULT CWbemLocatorSecurity::get_Privileges (
ISWbemPrivilegeSet **ppPrivileges
)
{
HRESULT hr = WBEM_E_FAILED;
ResetLastErrors ();
if (NULL == ppPrivileges)
hr = WBEM_E_INVALID_PARAMETER;
{
*ppPrivileges = NULL;
if (m_pPrivilegeSet)
{
if (SUCCEEDED (m_pPrivilegeSet->QueryInterface (IID_ISWbemPrivilegeSet,
(PPVOID) ppPrivileges)))
hr = WBEM_S_NO_ERROR;
}
}
if (FAILED(hr))
m_Dispatch.RaiseException (hr);
return hr;
}
//***************************************************************************
//
// SCODE CWbemLocatorSecurity::SetSecurity
//
// DESCRIPTION:
//
// Set Privileges on the Process Token.
//
//***************************************************************************
BOOL CWbemLocatorSecurity::SetSecurity (
BSTR bsUser,
bool &needToResetSecurity,
HANDLE &hThreadToken
)
{
BOOL result = TRUE;
needToResetSecurity = false;
hThreadToken = NULL;
/*
* NT5 supports the concept of dynamic cloaking, which means
* we can set privileges temporarily on a thread (impersonation)
* token basis immediately before a call to a remoted proxy.
*
* Setting prior to locator.connectserver therefore makes no
* sense for NT5.
*
* Oh and Win9x has no security support
*/
if (CSWbemSecurity::IsNT () && (4 >= CSWbemSecurity::GetNTMajorVersion ()))
{
/*
* Start by checking whether we are being impersonated. On an NT4
* box (which has no cloaking, and therefore cannot allow us to
* pass on this impersonation to Winmgmt) we should RevertToSelf
* if we have been configured to allow this. If we haven't been
* configured to allow this, bail out now.
*/
if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY|TOKEN_IMPERSONATE, false, &hThreadToken))
{
// We are being impersonated
if (CSWbemSecurity::CanRevertToSelf ())
{
if (result = RevertToSelf())
needToResetSecurity = true;
}
else
{
// Error - cannot do this! Time to bail out
CloseHandle (hThreadToken);
hThreadToken = NULL;
result = FALSE;
}
}
if (result && m_pPrivilegeSet)
{
/*
* Specifying a user only makes sense for remote operations, and we
* don't need to mess with privilege for remote operations since
* they are set up by server logon anyway.
*/
if (!bsUser || (0 == wcslen(bsUser)))
{
// Nothing to do unless some privilege overrides have been set
long lCount = 0;
m_pPrivilegeSet->get_Count (&lCount);
if (0 < lCount)
{
/*
* For NT4 privilege settings on impersonation tokens are ignored
* by DCOM/RPC. Hence we have to set this on the process token.
*
* On NT4 we must set the configured privileges on the Process
* Token before the first call to RPC (i.e. IWbemLocator::ConnectServer)
* if we need to guarantee privilege settings will be communicated to
* the server.
*
* This is because (a) NT4 does not support cloaking to allow the
* impersonation (i.e. thread) token privilege setting to propagate
* on a per-DCOM call basis, (b) changes to Process-token level
* privileges _may_ be ignored after the first remote DCOM call due
* to RPC caching behavior.
*
* Note that this is a non-reversible operation, and is highly discouraged
* on apps (such as IE and IIS) which host multiple "tasks" since it adjusts
* the Privilege set for all of the other threads in the process.
*/
HANDLE hProcess = GetCurrentProcess ();
HANDLE hProcessToken = NULL;
result = OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hProcessToken);
CloseHandle (hProcess);
if (result)
{
#ifdef WSCRPDEBUG
CSWbemSecurity::PrintPrivileges (hProcessToken);
#endif
CSWbemSecurity::AdjustTokenPrivileges (hProcessToken, m_pPrivilegeSet);
#ifdef WSCRPDEBUG
CSWbemSecurity::PrintPrivileges (hProcessToken);
#endif
CloseHandle (hProcessToken);
}
}
}
}
}
return result;
}
//***************************************************************************
//
// SCODE CWbemLocatorSecurity::ResetSecurity
//
// DESCRIPTION:
//
// Restore Privileges on the Thread Token.
//
//***************************************************************************
void CWbemLocatorSecurity::ResetSecurity (
HANDLE hThreadToken
)
{
// Win9x has no concept of impersonation
// On NT5 we never set privileges through this class anyway
if (CSWbemSecurity::IsNT () && (4 >= CSWbemSecurity::GetNTMajorVersion ())
&& hThreadToken)
{
/*
* Set the supplied token back into
* the current thread.
*/
BOOL result = SetThreadToken (NULL, hThreadToken);
#ifdef WSCRPDEBUG
// Print out the current privileges to see what's changed
HANDLE hToken = NULL;
if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, false, &hToken))
{
// No thread token - go for the Process token instead
HANDLE hProcess = GetCurrentProcess ();
OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
CloseHandle (hProcess);
}
if (hToken)
{
CSWbemSecurity::PrintPrivileges (hToken);
CloseHandle (hToken);
}
#endif
CloseHandle (hThreadToken);
}
}
#ifdef WSCRPDEBUG
//***************************************************************************
//
// SCODE CSWbemSecurity::PrintPrivileges
//
// DESCRIPTION:
//
// Debug logging for privileges and other token info
//
//***************************************************************************
void CSWbemSecurity::PrintPrivileges (HANDLE hToken)
{
DWORD dwSize = sizeof (TOKEN_PRIVILEGES);
TOKEN_PRIVILEGES *tp = (TOKEN_PRIVILEGES *) new BYTE [dwSize];
if (!tp)
{
return;
}
DWORD dwRequiredSize = 0;
DWORD dwLastError = 0;
FILE *fDebug = fopen ("C:/temp/wmidsec.txt", "a+");
fprintf (fDebug, "\n\n***********************************************\n\n");
bool status = false;
// Step 0 - get impersonation level
SECURITY_IMPERSONATION_LEVEL secImpLevel;
if (GetTokenInformation (hToken, TokenImpersonationLevel, &secImpLevel,
sizeof (SECURITY_IMPERSONATION_LEVEL), &dwRequiredSize))
{
switch (secImpLevel)
{
case SecurityAnonymous:
fprintf (fDebug, "IMPERSONATION LEVEL: Anonymous\n");
break;
case SecurityIdentification:
fprintf (fDebug, "IMPERSONATION LEVEL: Identification\n");
break;
case SecurityImpersonation:
fprintf (fDebug, "IMPERSONATION LEVEL: Impersonation\n");
break;
case SecurityDelegation:
fprintf (fDebug, "IMPERSONATION LEVEL: Delegation\n");
break;
default:
fprintf (fDebug, "IMPERSONATION LEVEL: Unknown!\n");
break;
}
fflush (fDebug);
}
DWORD dwUSize = sizeof (TOKEN_USER);
TOKEN_USER *tu = (TOKEN_USER *) new BYTE [dwUSize];
if (!tu)
{
delete [] tp;
fclose (fDebug);
return;
}
// Step 1 - get user info
if (0 == GetTokenInformation (hToken, TokenUser,
(LPVOID) tu, dwUSize, &dwRequiredSize))
{
delete [] tu;
dwUSize = dwRequiredSize;
dwRequiredSize = 0;
tu = (TOKEN_USER *) new BYTE [dwUSize];
if (!tu)
{
delete [] tp;
fclose (fDebug);
return;
}
if (!GetTokenInformation (hToken, TokenUser, (LPVOID) tu, dwUSize,
&dwRequiredSize))
dwLastError = GetLastError ();
else
status = true;
}
if (status)
{
// Dig out the user info
dwRequiredSize = BUFSIZ;
char *userName = new char [dwRequiredSize];
char *domainName = new char [dwRequiredSize];
if (!userName || !domainName)
{
delete [] tp;
delete [] tu;
delete [] userName;
delete [] domainName;
return;
}
SID_NAME_USE eUse;
LookupAccountSid (NULL, (tu->User).Sid, userName, &dwRequiredSize,
domainName, &dwRequiredSize, &eUse);
fprintf (fDebug, "USER: [%s\\%s]\n", domainName, userName);
fflush (fDebug);
delete [] userName;
delete [] domainName;
}
else
{
fprintf (fDebug, " FAILED : %d\n", dwLastError);
fflush (fDebug);
}
delete [] tu;
status = false;
dwRequiredSize = 0;
// Step 2 - get privilege info
if (0 == GetTokenInformation (hToken, TokenPrivileges,
(LPVOID) tp, dwSize, &dwRequiredSize))
{
delete [] tp;
dwSize = dwRequiredSize;
dwRequiredSize = 0;
tp = (TOKEN_PRIVILEGES *) new BYTE [dwSize];
if (!tp)
{
fclose (fDebug);
return;
}
if (!GetTokenInformation (hToken, TokenPrivileges,
(LPVOID) tp, dwSize, &dwRequiredSize))
{
dwLastError = GetLastError ();
}
else
status = true;
}
else
status = true;
if (status)
{
fprintf (fDebug, "PRIVILEGES: [%d]\n", tp->PrivilegeCount);
fflush (fDebug);
for (DWORD i = 0; i < tp->PrivilegeCount; i++)
{
DWORD dwNameSize = 256;
LPTSTR name = new TCHAR [dwNameSize + 1];
if (!name)
{
delete [] tp;
fclose (fDebug);
return;
}
DWORD dwRequiredSize = dwNameSize;
if (LookupPrivilegeName (NULL, &(tp->Privileges [i].Luid), name, &dwRequiredSize))
{
BOOL enabDefault = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT);
BOOL enabled = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED);
BOOL usedForAccess (tp->Privileges [i].Attributes & SE_PRIVILEGE_USED_FOR_ACCESS);
fprintf (fDebug, " %s: enabledByDefault=%d enabled=%d usedForAccess=%d\n",
name, enabDefault, enabled, usedForAccess);
fflush (fDebug);
}
else
{
dwLastError = GetLastError ();
delete [] name;
dwNameSize = dwRequiredSize;
name = new TCHAR [dwRequiredSize];
if (!name)
{
delete [] tp;
fclose (fDebug);
return;
}
if (LookupPrivilegeName (NULL, &(tp->Privileges [i].Luid), name, &dwRequiredSize))
{
BOOL enabDefault = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT);
BOOL enabled = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED);
BOOL usedForAccess (tp->Privileges [i].Attributes & SE_PRIVILEGE_USED_FOR_ACCESS);
fprintf (fDebug, " %s: enabledByDefault=%d enabled=%d usedForAccess=%d\n",
name, enabDefault, enabled, usedForAccess);
fflush (fDebug);
}
else
dwLastError = GetLastError ();
}
delete [] name;
}
}
else
{
fprintf (fDebug, " FAILED : %d\n", dwLastError);
fflush (fDebug);
}
delete [] tp;
fclose (fDebug);
}
#endif