703 lines
18 KiB
C++
703 lines
18 KiB
C++
|
//***************************************************************************
|
||
|
//
|
||
|
// Copyright (c) 1998-1999 Microsoft Corporation
|
||
|
//
|
||
|
// PXYCACHE.CPP
|
||
|
//
|
||
|
// alanbos 22-Sep-98 Created.
|
||
|
//
|
||
|
// Defines the CSWbemProxyCache class
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
// Need to try and figure out the domain
|
||
|
static BSTR BuildDomainUser (BSTR bsSimpleUser)
|
||
|
{
|
||
|
BSTR bsDomainUser = NULL;
|
||
|
HANDLE hToken = NULL;
|
||
|
|
||
|
if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, TRUE, &hToken) ||
|
||
|
OpenProcessToken (GetCurrentProcess (), TOKEN_READ, &hToken))
|
||
|
{
|
||
|
// Get the user sid
|
||
|
TOKEN_USER tu;
|
||
|
DWORD dwLen = 0;
|
||
|
|
||
|
GetTokenInformation (hToken, TokenUser, &tu, sizeof(tu), &dwLen);
|
||
|
|
||
|
if (0 < dwLen)
|
||
|
{
|
||
|
BYTE* pTemp = new BYTE[dwLen];
|
||
|
|
||
|
if (pTemp)
|
||
|
{
|
||
|
DWORD dwRealLen = dwLen;
|
||
|
|
||
|
if (GetTokenInformation (hToken, TokenUser, pTemp, dwRealLen, &dwLen))
|
||
|
{
|
||
|
PSID pSid = ((TOKEN_USER*)pTemp)->User.Sid;
|
||
|
|
||
|
// Do the first lookup to get the buffer sizes required.
|
||
|
DWORD dwNameLen = 0;
|
||
|
DWORD dwDomainLen = 0;
|
||
|
LPWSTR pUser = 0;
|
||
|
LPWSTR pDomain = 0;
|
||
|
SID_NAME_USE Use;
|
||
|
|
||
|
LookupAccountSidW (NULL, pSid, pUser, &dwNameLen,
|
||
|
pDomain, &dwDomainLen, &Use);
|
||
|
|
||
|
DWORD dwLastErr = GetLastError();
|
||
|
|
||
|
if (ERROR_INSUFFICIENT_BUFFER == dwLastErr)
|
||
|
{
|
||
|
// Allocate the required buffers and look them up again.
|
||
|
pUser = new WCHAR [dwNameLen + 1];
|
||
|
|
||
|
if (pUser)
|
||
|
{
|
||
|
pDomain = new WCHAR [dwDomainLen + wcslen (bsSimpleUser) + 2];
|
||
|
|
||
|
if (pDomain)
|
||
|
{
|
||
|
if (LookupAccountSidW (NULL, pSid, pUser, &dwNameLen,
|
||
|
pDomain, &dwDomainLen, &Use))
|
||
|
{
|
||
|
// Now get the domain out
|
||
|
if (pDomain)
|
||
|
{
|
||
|
wcscat (pDomain, L"\\");
|
||
|
wcscat (pDomain, bsSimpleUser);
|
||
|
bsDomainUser = SysAllocString (pDomain);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete [] pDomain;
|
||
|
}
|
||
|
|
||
|
delete [] pUser;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete [] pTemp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CloseHandle(hToken);
|
||
|
}
|
||
|
|
||
|
return bsDomainUser;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CSWbemProxyCache::CSWbemProxyCache
|
||
|
//
|
||
|
// CONSTRUCTOR
|
||
|
// Create a new proxy cache based on the supplied proxy and
|
||
|
// authentication parameters.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
CSWbemProxyCache::CSWbemProxyCache (
|
||
|
IUnknown *pUnk,
|
||
|
BSTR bsAuthority,
|
||
|
BSTR bsUser,
|
||
|
BSTR bsPassword,
|
||
|
CWbemLocatorSecurity *pLocatorSecurity)
|
||
|
{
|
||
|
InitializeCriticalSection (&m_cs);
|
||
|
|
||
|
EnterCriticalSection (&m_cs);
|
||
|
|
||
|
InitializeMembers (pUnk);
|
||
|
|
||
|
/*
|
||
|
// Don't need this any more - the scenario this was fixing (see SMS Bug DB #53347) works in Whistler
|
||
|
// without this workaround. Also, this is causing Scripting to fail with UPN names since DetermineLoginTypeEx
|
||
|
// below doesn't recognize UPN user names.
|
||
|
|
||
|
if (CSWbemSecurity::IsNT() && bsUser && (0 < wcslen (bsUser)))
|
||
|
{
|
||
|
// On NT make sure we have a valid domain name if one is not specified
|
||
|
BSTR bsDomain = NULL;
|
||
|
BSTR bsSimpleUser = NULL;
|
||
|
BSTR bsPrincipalDummy = NULL;
|
||
|
|
||
|
if (SUCCEEDED (DetermineLoginTypeEx (bsDomain, bsSimpleUser, bsPrincipalDummy,
|
||
|
bsAuthority, bsUser)))
|
||
|
{
|
||
|
if (!bsDomain || (0 == wcslen (bsDomain)))
|
||
|
m_bsUser = BuildDomainUser (bsSimpleUser);
|
||
|
}
|
||
|
|
||
|
SysFreeString (bsPrincipalDummy);
|
||
|
SysFreeString (bsSimpleUser);
|
||
|
SysFreeString (bsDomain);
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
// Unless we've already set this, do it now
|
||
|
if (!m_bsUser)
|
||
|
m_bsUser = SysAllocString (bsUser);
|
||
|
|
||
|
m_bsAuthority = SysAllocString (bsAuthority);
|
||
|
m_bsPassword = SysAllocString (bsPassword);
|
||
|
|
||
|
m_bUsingExplicitUserName = m_bsUser && (0 < wcslen (m_bsUser));
|
||
|
|
||
|
InitializeCache (pUnk, pLocatorSecurity,
|
||
|
(pLocatorSecurity) && pLocatorSecurity->IsAuthenticationSet (),
|
||
|
(pLocatorSecurity) && pLocatorSecurity->IsImpersonationSet ());
|
||
|
|
||
|
// No longer need the credentials at this point - zap 'em
|
||
|
ClearCredentials ();
|
||
|
|
||
|
LeaveCriticalSection (&m_cs);
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CSWbemProxyCache::CSWbemProxyCache
|
||
|
//
|
||
|
// CONSTRUCTOR
|
||
|
// Create a new proxy cache based on the supplied proxy and
|
||
|
// authentication parameters.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
CSWbemProxyCache::CSWbemProxyCache (
|
||
|
IUnknown *pUnk,
|
||
|
COAUTHIDENTITY *pCoAuthIdentity,
|
||
|
BSTR bsPrincipal,
|
||
|
BSTR bsAuthority)
|
||
|
{
|
||
|
InitializeCriticalSection (&m_cs);
|
||
|
|
||
|
EnterCriticalSection (&m_cs);
|
||
|
|
||
|
InitializeMembers (pUnk);
|
||
|
|
||
|
if (bsAuthority)
|
||
|
m_bsAuthority = SysAllocString (bsAuthority);
|
||
|
|
||
|
if (bsPrincipal)
|
||
|
m_bsPrincipal = SysAllocString (bsPrincipal);
|
||
|
|
||
|
if (pCoAuthIdentity)
|
||
|
WbemAllocAuthIdentity (pCoAuthIdentity->User, pCoAuthIdentity->Password,
|
||
|
pCoAuthIdentity->Domain, &m_pCoAuthIdentity);
|
||
|
|
||
|
m_bUsingExplicitUserName = m_pCoAuthIdentity && m_pCoAuthIdentity->User &&
|
||
|
(0 < wcslen (m_pCoAuthIdentity->User));
|
||
|
|
||
|
InitializeCache (pUnk);
|
||
|
|
||
|
LeaveCriticalSection (&m_cs);
|
||
|
}
|
||
|
|
||
|
CSWbemProxyCache::CSWbemProxyCache (
|
||
|
IUnknown *pUnk,
|
||
|
CSWbemSecurity *pSecurity)
|
||
|
{
|
||
|
InitializeCriticalSection (&m_cs);
|
||
|
|
||
|
EnterCriticalSection (&m_cs);
|
||
|
|
||
|
InitializeMembers (pUnk);
|
||
|
|
||
|
if (pSecurity)
|
||
|
{
|
||
|
m_pCoAuthIdentity = pSecurity->GetCoAuthIdentity ();
|
||
|
m_bsPrincipal = SysAllocString (pSecurity->GetPrincipal ());
|
||
|
m_bsAuthority = SysAllocString (pSecurity->GetAuthority ());
|
||
|
m_bUsingExplicitUserName = pSecurity->IsUsingExplicitUserName ();
|
||
|
}
|
||
|
|
||
|
InitializeCache (pUnk, pSecurity);
|
||
|
LeaveCriticalSection (&m_cs);
|
||
|
}
|
||
|
|
||
|
void CSWbemProxyCache::InitializeMembers (IUnknown *pUnk)
|
||
|
{
|
||
|
m_cRef = 1;
|
||
|
m_pCoAuthIdentity = NULL;
|
||
|
m_bsPrincipal = NULL;
|
||
|
m_bsAuthority = NULL;
|
||
|
m_bsUser = NULL;
|
||
|
m_bsPassword = NULL;
|
||
|
m_bUsingExplicitUserName = false;
|
||
|
m_bUseDefaultInfo = DetermineBlanketOptions (pUnk);
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CSWbemProxyCache::~CSWbemProxyCache
|
||
|
//
|
||
|
// DESTRUCTOR
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
CSWbemProxyCache::~CSWbemProxyCache ()
|
||
|
{
|
||
|
EnterCriticalSection (&m_cs);
|
||
|
|
||
|
ClearCredentials ();
|
||
|
|
||
|
if (m_bsAuthority)
|
||
|
SysFreeString (m_bsAuthority);
|
||
|
|
||
|
if (m_bsPrincipal)
|
||
|
SysFreeString (m_bsPrincipal);
|
||
|
|
||
|
if (m_pCoAuthIdentity)
|
||
|
{
|
||
|
WbemFreeAuthIdentity (m_pCoAuthIdentity);
|
||
|
m_pCoAuthIdentity = NULL;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < WBEMS_MAX_AUTHN_LEVEL + 1 - WBEMS_MIN_AUTHN_LEVEL; i++)
|
||
|
for (int j = 0; j < WBEMS_MAX_IMP_LEVEL + 1 - WBEMS_MIN_IMP_LEVEL; j++)
|
||
|
if (pUnkArray [i][j])
|
||
|
{
|
||
|
pUnkArray [i][j] -> Release ();
|
||
|
pUnkArray [i] [j] = NULL;
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection (&m_cs);
|
||
|
DeleteCriticalSection (&m_cs);
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
// HRESULT CSWbemProxyCache::QueryInterface
|
||
|
// long CSWbemProxyCache::AddRef
|
||
|
// long CSWbemProxyCache::Release
|
||
|
//
|
||
|
// DESCRIPTION:
|
||
|
//
|
||
|
// Standard Com IUNKNOWN functions.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
STDMETHODIMP CSWbemProxyCache::QueryInterface (
|
||
|
|
||
|
IN REFIID riid,
|
||
|
OUT LPVOID *ppv
|
||
|
)
|
||
|
{
|
||
|
*ppv=NULL;
|
||
|
|
||
|
if (IID_IUnknown==riid)
|
||
|
*ppv=this;
|
||
|
|
||
|
if (NULL!=*ppv)
|
||
|
{
|
||
|
((LPUNKNOWN)*ppv)->AddRef();
|
||
|
return NOERROR;
|
||
|
}
|
||
|
|
||
|
return ResultFromScode(E_NOINTERFACE);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CSWbemProxyCache::AddRef(void)
|
||
|
{
|
||
|
long l = InterlockedIncrement(&m_cRef);
|
||
|
return l;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CSWbemProxyCache::Release(void)
|
||
|
{
|
||
|
long l = InterlockedDecrement(&m_cRef);
|
||
|
if (0L!=l)
|
||
|
return l;
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CSWbemProxyCache::SetBlanketOptions
|
||
|
//
|
||
|
// DESCRIPTION:
|
||
|
//
|
||
|
// Called from constructor only to set up interaction mode with
|
||
|
// SetBlanket calls.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
bool CSWbemProxyCache::DetermineBlanketOptions (IUnknown *pUnk)
|
||
|
{
|
||
|
bool result = false;
|
||
|
|
||
|
if (CSWbemSecurity::IsNT() && (4 < CSWbemSecurity::GetNTMajorVersion ()))
|
||
|
{
|
||
|
HANDLE hToken = NULL;
|
||
|
|
||
|
if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, true, &hToken))
|
||
|
{
|
||
|
// Certainly a candidate to use default settings for
|
||
|
// authorization and authentication service on the blanket.
|
||
|
// Check if we are delegating.
|
||
|
|
||
|
DWORD dwBytesReturned = 0;
|
||
|
SECURITY_IMPERSONATION_LEVEL impLevel;
|
||
|
|
||
|
if (GetTokenInformation(hToken, TokenImpersonationLevel, &impLevel,
|
||
|
sizeof(SECURITY_IMPERSONATION_LEVEL), &dwBytesReturned) &&
|
||
|
(SecurityDelegation == impLevel))
|
||
|
{
|
||
|
// Looks promising - now check for whether we are using kerberos
|
||
|
IClientSecurity *pSec;
|
||
|
DWORD dwAuthnSvc, dwAuthzSvc, dwImp, dwAuth, dwCapabilities;
|
||
|
|
||
|
if (pUnk && SUCCEEDED(pUnk->QueryInterface(IID_IClientSecurity, (void **) &pSec)))
|
||
|
{
|
||
|
if (SUCCEEDED (pSec->QueryBlanket(pUnk, &dwAuthnSvc, &dwAuthzSvc,
|
||
|
NULL,
|
||
|
&dwAuth, &dwImp,
|
||
|
NULL, &dwCapabilities)))
|
||
|
{
|
||
|
if (RPC_C_AUTHN_WINNT != dwAuthnSvc)
|
||
|
result = true;
|
||
|
}
|
||
|
|
||
|
pSec->Release ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CloseHandle (hToken);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CSWbemProxyCache::InitializeCache
|
||
|
//
|
||
|
// DESCRIPTION:
|
||
|
//
|
||
|
// Called from constructor only to set up cache and initial pUnk..
|
||
|
//
|
||
|
// PARAMETERS:
|
||
|
//
|
||
|
// pUnk "seed" pUnk
|
||
|
// pSecurity if specified, is an ISWbemSecurity used to
|
||
|
// override the intial authn/imp/etc. settings
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
void CSWbemProxyCache::InitializeCache (
|
||
|
IUnknown *pUnk,
|
||
|
ISWbemSecurity *pSecurity,
|
||
|
bool bPropagateAuthentication,
|
||
|
bool bPropagateImpersonation
|
||
|
)
|
||
|
{
|
||
|
for (int i = 0; i < WBEMS_MAX_AUTHN_LEVEL + 1 - WBEMS_MIN_AUTHN_LEVEL; i++)
|
||
|
for (int j = 0; j < WBEMS_MAX_IMP_LEVEL + 1 - WBEMS_MIN_IMP_LEVEL; j++)
|
||
|
pUnkArray [i] [j] = NULL;
|
||
|
|
||
|
if (pUnk)
|
||
|
{
|
||
|
DWORD dwAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT;
|
||
|
DWORD dwImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
|
||
|
|
||
|
HRESULT hr = GetAuthImp (pUnk, &dwAuthnLevel, &dwImpLevel);
|
||
|
|
||
|
/*
|
||
|
* If we have been passed a "seed" Security object, use the auth/imp
|
||
|
* settings of that Seed as our initial setting. Otherwise
|
||
|
* use the settings supplied in the current proxy.
|
||
|
*/
|
||
|
if (pSecurity)
|
||
|
{
|
||
|
if (!bPropagateImpersonation || FAILED(pSecurity->get_ImpersonationLevel (&m_dwInitialImpLevel)))
|
||
|
m_dwInitialImpLevel = (WbemImpersonationLevelEnum) dwImpLevel;
|
||
|
|
||
|
if (!bPropagateAuthentication || FAILED(pSecurity->get_AuthenticationLevel (&m_dwInitialAuthnLevel)))
|
||
|
m_dwInitialAuthnLevel = (WbemAuthenticationLevelEnum) dwAuthnLevel;
|
||
|
|
||
|
/*
|
||
|
* If settings are identical, use the proxy we have but set the
|
||
|
* blanket to ensure user/password/authority are set.
|
||
|
*/
|
||
|
|
||
|
if (((WbemImpersonationLevelEnum) dwImpLevel == m_dwInitialImpLevel) &&
|
||
|
((WbemAuthenticationLevelEnum) dwAuthnLevel == m_dwInitialAuthnLevel))
|
||
|
{
|
||
|
SecureProxy (pUnk, m_dwInitialAuthnLevel, m_dwInitialImpLevel);
|
||
|
|
||
|
pUnkArray [m_dwInitialAuthnLevel - WBEMS_MIN_AUTHN_LEVEL]
|
||
|
[m_dwInitialImpLevel - WBEMS_MIN_IMP_LEVEL] = pUnk;
|
||
|
pUnk->AddRef ();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Need to create a new proxy
|
||
|
IClientSecurity *pCliSec = NULL;
|
||
|
|
||
|
if (S_OK == pUnk->QueryInterface (IID_IClientSecurity, (PPVOID) &pCliSec))
|
||
|
{
|
||
|
IUnknown *pNewUnk = NULL;
|
||
|
|
||
|
// If successful this AddRef's pUnk
|
||
|
HRESULT sc = pCliSec->CopyProxy(pUnk, &pNewUnk);
|
||
|
|
||
|
if (S_OK == sc)
|
||
|
{
|
||
|
SecureProxy (pNewUnk, m_dwInitialAuthnLevel, m_dwInitialImpLevel);
|
||
|
|
||
|
pUnkArray [m_dwInitialAuthnLevel - WBEMS_MIN_AUTHN_LEVEL]
|
||
|
[m_dwInitialImpLevel - WBEMS_MIN_IMP_LEVEL] = pNewUnk;
|
||
|
// NB: pNewUnk already AddRef'd above by CopyProxy
|
||
|
}
|
||
|
|
||
|
pCliSec->Release ();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_dwInitialAuthnLevel = (WbemAuthenticationLevelEnum) dwAuthnLevel;
|
||
|
m_dwInitialImpLevel = (WbemImpersonationLevelEnum) dwImpLevel;
|
||
|
pUnkArray [m_dwInitialAuthnLevel - WBEMS_MIN_AUTHN_LEVEL]
|
||
|
[m_dwInitialImpLevel - WBEMS_MIN_IMP_LEVEL] = pUnk;
|
||
|
pUnk->AddRef ();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CSWbemProxyCache::GetProxy
|
||
|
//
|
||
|
// DESCRIPTION:
|
||
|
//
|
||
|
// Return a proxy from the cache with the desired authentication and
|
||
|
// impersonation level.
|
||
|
//
|
||
|
// PARAMETERS:
|
||
|
//
|
||
|
// authnLevel required authentication level
|
||
|
// impLevel required impersonation level
|
||
|
// forceResecure whether to force a resecure of an extant proxy
|
||
|
//
|
||
|
// RETURN VALUES:
|
||
|
// Pointer to copied proxy, or NULL. If not NULL, caller must Release.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
IUnknown *CSWbemProxyCache::GetProxy (
|
||
|
WbemAuthenticationLevelEnum authnLevel,
|
||
|
WbemImpersonationLevelEnum impLevel,
|
||
|
bool forceResecure)
|
||
|
{
|
||
|
EnterCriticalSection (&m_cs);
|
||
|
|
||
|
IUnknown *pUnk = pUnkArray [authnLevel - WBEMS_MIN_AUTHN_LEVEL]
|
||
|
[impLevel - WBEMS_MIN_IMP_LEVEL];
|
||
|
|
||
|
if (pUnk)
|
||
|
{
|
||
|
// Already cached this proxy - reuse
|
||
|
pUnk->AddRef ();
|
||
|
|
||
|
// Force a resecure? This is useful if we have just changed the
|
||
|
// privileges in the current token and need to stim RPC to pick
|
||
|
// them up.
|
||
|
if (forceResecure)
|
||
|
SecureProxy (pUnk, authnLevel, impLevel);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Need to create a copy of the proxy; use the first
|
||
|
// created element as a base
|
||
|
|
||
|
IUnknown *pUnkFirst = pUnkArray [m_dwInitialAuthnLevel - WBEMS_MIN_AUTHN_LEVEL]
|
||
|
[m_dwInitialImpLevel - WBEMS_MIN_IMP_LEVEL];
|
||
|
|
||
|
if (pUnkFirst)
|
||
|
{
|
||
|
// Now copy the proxy
|
||
|
IClientSecurity *pCliSec = NULL;
|
||
|
|
||
|
if (S_OK == pUnkFirst->QueryInterface (IID_IClientSecurity, (PPVOID) &pCliSec))
|
||
|
{
|
||
|
// If successful this AddRef's pUnk
|
||
|
HRESULT sc = pCliSec->CopyProxy(pUnkFirst, &pUnk);
|
||
|
|
||
|
if (S_OK == sc)
|
||
|
{
|
||
|
SecureProxy (pUnk, authnLevel, impLevel);
|
||
|
|
||
|
pUnkArray [authnLevel - WBEMS_MIN_AUTHN_LEVEL]
|
||
|
[impLevel - WBEMS_MIN_IMP_LEVEL] = pUnk;
|
||
|
|
||
|
// AddRef because we are handing pUnk back
|
||
|
pUnk->AddRef ();
|
||
|
}
|
||
|
|
||
|
pCliSec->Release ();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection (&m_cs);
|
||
|
|
||
|
return pUnk;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CSWbemProxyCache::SecureProxy
|
||
|
//
|
||
|
// DESCRIPTION:
|
||
|
//
|
||
|
// Secure the given proxy using the provided settings
|
||
|
//
|
||
|
// PARAMETERS:
|
||
|
//
|
||
|
// authnLevel authentication level of proxy
|
||
|
// impLevel impersonation level of proxy
|
||
|
//
|
||
|
// RETURN VALUES:
|
||
|
// none
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
void CSWbemProxyCache::SecureProxy (
|
||
|
IUnknown *pUnk,
|
||
|
WbemAuthenticationLevelEnum authnLevel,
|
||
|
WbemImpersonationLevelEnum impLevel)
|
||
|
{
|
||
|
/*
|
||
|
* Due to the vagaries of the IClientSecurity::SetBlanket call,
|
||
|
* any COAUTHIDENTITY pointer passed into that call must remain
|
||
|
* valid either until SetBlanket is called again or all proxies
|
||
|
* on the object are released. So we need to store any returned
|
||
|
* COAUTHIDENTITY so that it remains valid for the lifetime
|
||
|
* of this cache.
|
||
|
*/
|
||
|
|
||
|
EnterCriticalSection (&m_cs);
|
||
|
|
||
|
if (pUnk)
|
||
|
{
|
||
|
/*
|
||
|
* Note that our implicit assumption is that we only ever
|
||
|
* need one COAUTHIDENTITY per cache. This is because
|
||
|
* the ingredients of the structure (user, password and
|
||
|
* authority) are set at cache initialization time and
|
||
|
* never change thereafter.
|
||
|
*/
|
||
|
if (m_pCoAuthIdentity)
|
||
|
{
|
||
|
SetInterfaceSecurityDecrypt (pUnk, m_pCoAuthIdentity, m_bsPrincipal,
|
||
|
authnLevel, impLevel, GetCapabilities (),
|
||
|
m_bUseDefaultInfo);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// See if we get one
|
||
|
BSTR bsPrincipal = NULL;
|
||
|
|
||
|
SetInterfaceSecurityEncrypt (pUnk, m_bsAuthority, m_bsUser, m_bsPassword,
|
||
|
authnLevel, impLevel, GetCapabilities (),
|
||
|
&m_pCoAuthIdentity, &bsPrincipal, m_bUseDefaultInfo);
|
||
|
|
||
|
if (bsPrincipal)
|
||
|
{
|
||
|
if (m_bsPrincipal)
|
||
|
SysFreeString (m_bsPrincipal);
|
||
|
|
||
|
m_bsPrincipal = bsPrincipal;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LeaveCriticalSection (&m_cs);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//***************************************************************************
|
||
|
//
|
||
|
// CSWbemProxyCache::GetCapabilities
|
||
|
//
|
||
|
// DESCRIPTION:
|
||
|
//
|
||
|
// Return the EOAC capabilities value depending on the OS platform and
|
||
|
// user credentials (or absence thereof).
|
||
|
//
|
||
|
// RETURN VALUES:
|
||
|
//
|
||
|
// The determined capabilities.
|
||
|
//
|
||
|
//***************************************************************************
|
||
|
|
||
|
DWORD CSWbemProxyCache::GetCapabilities ()
|
||
|
{
|
||
|
/*
|
||
|
* For NT5 (and presumably greater) we enable Static
|
||
|
* Cloaking on the proxy. This allows RPC to use the
|
||
|
* Privilege settings in the Impersonation token.
|
||
|
*
|
||
|
* Note that we use static cloaking so that thread identity
|
||
|
* is only used during CoSetProxyBlanket calls; dynamic
|
||
|
* cloaking forces it to be used on all calls to the proxy,
|
||
|
* so is much less efficient. Since we don't allow different
|
||
|
* users to access the same proxy, static cloaking is sufficient.
|
||
|
*
|
||
|
* It makes no sense to explicitly supply a User/Password and specify
|
||
|
* cloaking, as DCOM authentication of proxy uses either
|
||
|
* an explicit SEC_WINNT_AUTH_IDENTITY (for User & Password)
|
||
|
* or the current proxy identity (in the process token or
|
||
|
* impersonation token). Requesting cloaking implies that the
|
||
|
* proxy identity in the impersonation token is to be used, and
|
||
|
* therefore that any User/Password is irrelevant (and vice-versa).
|
||
|
*
|
||
|
* See MSDN documentation on CoSetProxyBlanket for more info.
|
||
|
*/
|
||
|
DWORD dwCapabilities = EOAC_NONE;
|
||
|
|
||
|
if (CSWbemSecurity::IsNT () && (4 < CSWbemSecurity::GetNTMajorVersion ()) &&
|
||
|
!m_bUsingExplicitUserName)
|
||
|
dwCapabilities |= EOAC_STATIC_CLOAKING;
|
||
|
|
||
|
return dwCapabilities ;
|
||
|
}
|
||
|
|
||
|
COAUTHIDENTITY *CSWbemProxyCache::GetCoAuthIdentity ()
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
COAUTHIDENTITY *pAuthIdent = NULL;
|
||
|
|
||
|
if (m_pCoAuthIdentity)
|
||
|
hr = WbemAllocAuthIdentity (m_pCoAuthIdentity->User,
|
||
|
m_pCoAuthIdentity->Password, m_pCoAuthIdentity->Domain, &pAuthIdent);
|
||
|
|
||
|
return pAuthIdent;
|
||
|
}
|
||
|
|
||
|
void CSWbemProxyCache::ClearCredentials ()
|
||
|
{
|
||
|
if (m_bsUser)
|
||
|
{
|
||
|
_wcsnset (m_bsUser, L'0', wcslen (m_bsUser));
|
||
|
SysFreeString (m_bsUser);
|
||
|
m_bsUser = NULL;
|
||
|
}
|
||
|
|
||
|
if (m_bsPassword)
|
||
|
{
|
||
|
_wcsnset (m_bsPassword, L'0', wcslen (m_bsPassword));
|
||
|
SysFreeString (m_bsPassword);
|
||
|
m_bsPassword = NULL;
|
||
|
}
|
||
|
}
|