Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

713 lines
19 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1998-1999 Microsoft Corporation
  4. //
  5. // PXYCACHE.CPP
  6. //
  7. // alanbos 22-Sep-98 Created.
  8. //
  9. // Defines the CSWbemProxyCache class
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. // Need to try and figure out the domain
  14. static BSTR BuildDomainUser (BSTR bsSimpleUser)
  15. {
  16. BSTR bsDomainUser = NULL;
  17. HANDLE hToken = NULL;
  18. if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, TRUE, &hToken) ||
  19. OpenProcessToken (GetCurrentProcess (), TOKEN_READ, &hToken))
  20. {
  21. // Get the user sid
  22. TOKEN_USER tu;
  23. DWORD dwLen = 0;
  24. GetTokenInformation (hToken, TokenUser, &tu, sizeof(tu), &dwLen);
  25. if (0 < dwLen)
  26. {
  27. BYTE* pTemp = new BYTE[dwLen];
  28. if (pTemp)
  29. {
  30. DWORD dwRealLen = dwLen;
  31. if (GetTokenInformation (hToken, TokenUser, pTemp, dwRealLen, &dwLen))
  32. {
  33. PSID pSid = ((TOKEN_USER*)pTemp)->User.Sid;
  34. // Do the first lookup to get the buffer sizes required.
  35. DWORD dwNameLen = 0;
  36. DWORD dwDomainLen = 0;
  37. LPWSTR pUser = 0;
  38. LPWSTR pDomain = 0;
  39. SID_NAME_USE Use;
  40. LookupAccountSidW (NULL, pSid, pUser, &dwNameLen,
  41. pDomain, &dwDomainLen, &Use);
  42. DWORD dwLastErr = GetLastError();
  43. if (ERROR_INSUFFICIENT_BUFFER == dwLastErr)
  44. {
  45. // Allocate the required buffers and look them up again.
  46. pUser = new WCHAR [dwNameLen + 1];
  47. if (pUser)
  48. {
  49. pDomain = new WCHAR [dwDomainLen + wcslen (bsSimpleUser) + 2];
  50. if (pDomain)
  51. {
  52. if (LookupAccountSidW (NULL, pSid, pUser, &dwNameLen,
  53. pDomain, &dwDomainLen, &Use))
  54. {
  55. // Now get the domain out
  56. if (pDomain)
  57. {
  58. wcscat (pDomain, L"\\");
  59. wcscat (pDomain, bsSimpleUser);
  60. bsDomainUser = SysAllocString (pDomain);
  61. }
  62. }
  63. delete [] pDomain;
  64. }
  65. delete [] pUser;
  66. }
  67. }
  68. }
  69. delete [] pTemp;
  70. }
  71. }
  72. CloseHandle(hToken);
  73. }
  74. return bsDomainUser;
  75. }
  76. //***************************************************************************
  77. //
  78. // CSWbemProxyCache::CSWbemProxyCache
  79. //
  80. // CONSTRUCTOR
  81. // Create a new proxy cache based on the supplied proxy and
  82. // authentication parameters.
  83. //
  84. //***************************************************************************
  85. CSWbemProxyCache::CSWbemProxyCache (
  86. IUnknown *pUnk,
  87. BSTR bsAuthority,
  88. BSTR bsUser,
  89. BSTR bsPassword,
  90. CWbemLocatorSecurity *pLocatorSecurity)
  91. {
  92. InitializeCriticalSection (&m_cs);
  93. EnterCriticalSection (&m_cs);
  94. InitializeMembers (pUnk);
  95. /*
  96. // Don't need this any more - the scenario this was fixing (see SMS Bug DB #53347) works in Whistler
  97. // without this workaround. Also, this is causing Scripting to fail with UPN names since DetermineLoginTypeEx
  98. // below doesn't recognize UPN user names.
  99. if (CSWbemSecurity::IsNT() && bsUser && (0 < wcslen (bsUser)))
  100. {
  101. // On NT make sure we have a valid domain name if one is not specified
  102. BSTR bsDomain = NULL;
  103. BSTR bsSimpleUser = NULL;
  104. BSTR bsPrincipalDummy = NULL;
  105. if (SUCCEEDED (DetermineLoginTypeEx (bsDomain, bsSimpleUser, bsPrincipalDummy,
  106. bsAuthority, bsUser)))
  107. {
  108. if (!bsDomain || (0 == wcslen (bsDomain)))
  109. m_bsUser = BuildDomainUser (bsSimpleUser);
  110. }
  111. SysFreeString (bsPrincipalDummy);
  112. SysFreeString (bsSimpleUser);
  113. SysFreeString (bsDomain);
  114. }
  115. */
  116. // Unless we've already set this, do it now
  117. if (!m_bsUser)
  118. m_bsUser = SysAllocString (bsUser);
  119. m_bsAuthority = SysAllocString (bsAuthority);
  120. m_bsPassword = SysAllocString (bsPassword);
  121. m_bUsingExplicitUserName = m_bsUser && (0 < wcslen (m_bsUser));
  122. InitializeCache (pUnk, pLocatorSecurity,
  123. (pLocatorSecurity) && pLocatorSecurity->IsAuthenticationSet (),
  124. (pLocatorSecurity) && pLocatorSecurity->IsImpersonationSet ());
  125. // No longer need the credentials at this point - zap 'em
  126. ClearCredentials ();
  127. LeaveCriticalSection (&m_cs);
  128. }
  129. //***************************************************************************
  130. //
  131. // CSWbemProxyCache::CSWbemProxyCache
  132. //
  133. // CONSTRUCTOR
  134. // Create a new proxy cache based on the supplied proxy and
  135. // authentication parameters.
  136. //
  137. //***************************************************************************
  138. CSWbemProxyCache::CSWbemProxyCache (
  139. IUnknown *pUnk,
  140. COAUTHIDENTITY *pCoAuthIdentity,
  141. BSTR bsPrincipal,
  142. BSTR bsAuthority)
  143. {
  144. InitializeCriticalSection (&m_cs);
  145. EnterCriticalSection (&m_cs);
  146. InitializeMembers (pUnk);
  147. if (bsAuthority)
  148. m_bsAuthority = SysAllocString (bsAuthority);
  149. if (bsPrincipal)
  150. m_bsPrincipal = SysAllocString (bsPrincipal);
  151. if (pCoAuthIdentity)
  152. WbemAllocAuthIdentity (pCoAuthIdentity->User, pCoAuthIdentity->Password,
  153. pCoAuthIdentity->Domain, &m_pCoAuthIdentity);
  154. m_bUsingExplicitUserName = m_pCoAuthIdentity && m_pCoAuthIdentity->User &&
  155. (0 < wcslen (m_pCoAuthIdentity->User));
  156. InitializeCache (pUnk);
  157. LeaveCriticalSection (&m_cs);
  158. }
  159. CSWbemProxyCache::CSWbemProxyCache (
  160. IUnknown *pUnk,
  161. CSWbemSecurity *pSecurity)
  162. {
  163. InitializeCriticalSection (&m_cs);
  164. EnterCriticalSection (&m_cs);
  165. InitializeMembers (pUnk);
  166. if (pSecurity)
  167. {
  168. m_pCoAuthIdentity = pSecurity->GetCoAuthIdentity ();
  169. m_bsPrincipal = SysAllocString (pSecurity->GetPrincipal ());
  170. m_bsAuthority = SysAllocString (pSecurity->GetAuthority ());
  171. m_bUsingExplicitUserName = pSecurity->IsUsingExplicitUserName ();
  172. }
  173. InitializeCache (pUnk, pSecurity);
  174. LeaveCriticalSection (&m_cs);
  175. }
  176. void CSWbemProxyCache::InitializeMembers (IUnknown *pUnk)
  177. {
  178. m_cRef = 1;
  179. m_pCoAuthIdentity = NULL;
  180. m_bsPrincipal = NULL;
  181. m_bsAuthority = NULL;
  182. m_bsUser = NULL;
  183. m_bsPassword = NULL;
  184. m_bUsingExplicitUserName = false;
  185. m_bUseDefaultInfo = true; //DetermineBlanketOptions (pUnk);
  186. }
  187. //***************************************************************************
  188. //
  189. // CSWbemProxyCache::~CSWbemProxyCache
  190. //
  191. // DESTRUCTOR
  192. //
  193. //***************************************************************************
  194. CSWbemProxyCache::~CSWbemProxyCache ()
  195. {
  196. EnterCriticalSection (&m_cs);
  197. ClearCredentials ();
  198. if (m_bsAuthority)
  199. SysFreeString (m_bsAuthority);
  200. if (m_bsPrincipal)
  201. SysFreeString (m_bsPrincipal);
  202. if (m_pCoAuthIdentity)
  203. {
  204. WbemFreeAuthIdentity (m_pCoAuthIdentity);
  205. m_pCoAuthIdentity = NULL;
  206. }
  207. for (int i = 0; i < WBEMS_MAX_AUTHN_LEVEL + 1 - WBEMS_MIN_AUTHN_LEVEL; i++)
  208. for (int j = 0; j < WBEMS_MAX_IMP_LEVEL + 1 - WBEMS_MIN_IMP_LEVEL; j++)
  209. if (pUnkArray [i][j])
  210. {
  211. pUnkArray [i][j] -> Release ();
  212. pUnkArray [i] [j] = NULL;
  213. }
  214. LeaveCriticalSection (&m_cs);
  215. DeleteCriticalSection (&m_cs);
  216. }
  217. //***************************************************************************
  218. // HRESULT CSWbemProxyCache::QueryInterface
  219. // long CSWbemProxyCache::AddRef
  220. // long CSWbemProxyCache::Release
  221. //
  222. // DESCRIPTION:
  223. //
  224. // Standard Com IUNKNOWN functions.
  225. //
  226. //***************************************************************************
  227. STDMETHODIMP CSWbemProxyCache::QueryInterface (
  228. IN REFIID riid,
  229. OUT LPVOID *ppv
  230. )
  231. {
  232. *ppv=NULL;
  233. if (IID_IUnknown==riid)
  234. *ppv=this;
  235. if (NULL!=*ppv)
  236. {
  237. ((LPUNKNOWN)*ppv)->AddRef();
  238. return NOERROR;
  239. }
  240. return ResultFromScode(E_NOINTERFACE);
  241. }
  242. STDMETHODIMP_(ULONG) CSWbemProxyCache::AddRef(void)
  243. {
  244. long l = InterlockedIncrement(&m_cRef);
  245. return l;
  246. }
  247. STDMETHODIMP_(ULONG) CSWbemProxyCache::Release(void)
  248. {
  249. LONG cRef = InterlockedDecrement(&m_cRef);
  250. if (0 != cRef)
  251. {
  252. _ASSERT(cRef > 0);
  253. return cRef;
  254. }
  255. delete this;
  256. return 0;
  257. }
  258. //***************************************************************************
  259. //
  260. // CSWbemProxyCache::SetBlanketOptions
  261. //
  262. // DESCRIPTION:
  263. //
  264. // Called from constructor only to set up interaction mode with
  265. // SetBlanket calls.
  266. //
  267. //***************************************************************************
  268. bool CSWbemProxyCache::DetermineBlanketOptions (IUnknown *pUnk)
  269. {
  270. bool result = false;
  271. if (CSWbemSecurity::IsNT() && (4 < CSWbemSecurity::GetNTMajorVersion ()))
  272. {
  273. HANDLE hToken = NULL;
  274. if (OpenThreadToken (GetCurrentThread(), TOKEN_QUERY, true, &hToken))
  275. {
  276. // Certainly a candidate to use default settings for
  277. // authorization and authentication service on the blanket.
  278. // Check if we are delegating.
  279. DWORD dwBytesReturned = 0;
  280. SECURITY_IMPERSONATION_LEVEL impLevel;
  281. if (GetTokenInformation(hToken, TokenImpersonationLevel, &impLevel,
  282. sizeof(SECURITY_IMPERSONATION_LEVEL), &dwBytesReturned) &&
  283. (SecurityDelegation == impLevel))
  284. {
  285. // Looks promising - now check for whether we are using kerberos
  286. IClientSecurity *pSec;
  287. DWORD dwAuthnSvc, dwAuthzSvc, dwImp, dwAuth, dwCapabilities;
  288. if (pUnk && SUCCEEDED(pUnk->QueryInterface(IID_IClientSecurity, (void **) &pSec)))
  289. {
  290. if (SUCCEEDED (pSec->QueryBlanket(pUnk, &dwAuthnSvc, &dwAuthzSvc,
  291. NULL,
  292. &dwAuth, &dwImp,
  293. NULL, &dwCapabilities)))
  294. {
  295. if (RPC_C_AUTHN_WINNT != dwAuthnSvc)
  296. result = true;
  297. }
  298. pSec->Release ();
  299. }
  300. }
  301. CloseHandle (hToken);
  302. }
  303. }
  304. return result;
  305. }
  306. //***************************************************************************
  307. //
  308. // CSWbemProxyCache::InitializeCache
  309. //
  310. // DESCRIPTION:
  311. //
  312. // Called from constructor only to set up cache and initial pUnk..
  313. //
  314. // PARAMETERS:
  315. //
  316. // pUnk "seed" pUnk
  317. // pSecurity if specified, is an ISWbemSecurity used to
  318. // override the intial authn/imp/etc. settings
  319. //
  320. //***************************************************************************
  321. void CSWbemProxyCache::InitializeCache (
  322. IUnknown *pUnk,
  323. ISWbemSecurity *pSecurity,
  324. bool bPropagateAuthentication,
  325. bool bPropagateImpersonation
  326. )
  327. {
  328. for (int i = 0; i < WBEMS_MAX_AUTHN_LEVEL + 1 - WBEMS_MIN_AUTHN_LEVEL; i++)
  329. for (int j = 0; j < WBEMS_MAX_IMP_LEVEL + 1 - WBEMS_MIN_IMP_LEVEL; j++)
  330. pUnkArray [i] [j] = NULL;
  331. if (pUnk)
  332. {
  333. DWORD dwAuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT;
  334. DWORD dwImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
  335. HRESULT hr = GetAuthImp (pUnk, &dwAuthnLevel, &dwImpLevel);
  336. if(FAILED(hr))
  337. {
  338. dwAuthnLevel = RPC_C_AUTHN_LEVEL_DEFAULT;
  339. dwImpLevel = CSWbemSecurity::GetDefaultImpersonationLevel ();
  340. }
  341. /*
  342. * If we have been passed a "seed" Security object, use the auth/imp
  343. * settings of that Seed as our initial setting. Otherwise
  344. * use the settings supplied in the current proxy.
  345. */
  346. if (pSecurity)
  347. {
  348. if (!bPropagateImpersonation || FAILED(pSecurity->get_ImpersonationLevel (&m_dwInitialImpLevel)))
  349. m_dwInitialImpLevel = (WbemImpersonationLevelEnum) dwImpLevel;
  350. if (!bPropagateAuthentication || FAILED(pSecurity->get_AuthenticationLevel (&m_dwInitialAuthnLevel)))
  351. m_dwInitialAuthnLevel = (WbemAuthenticationLevelEnum) dwAuthnLevel;
  352. /*
  353. * If settings are identical, use the proxy we have but set the
  354. * blanket to ensure user/password/authority are set.
  355. */
  356. if (((WbemImpersonationLevelEnum) dwImpLevel == m_dwInitialImpLevel) &&
  357. ((WbemAuthenticationLevelEnum) dwAuthnLevel == m_dwInitialAuthnLevel))
  358. {
  359. SecureProxy (pUnk, m_dwInitialAuthnLevel, m_dwInitialImpLevel);
  360. pUnkArray [m_dwInitialAuthnLevel - WBEMS_MIN_AUTHN_LEVEL]
  361. [m_dwInitialImpLevel - WBEMS_MIN_IMP_LEVEL] = pUnk;
  362. pUnk->AddRef ();
  363. }
  364. else
  365. {
  366. // Need to create a new proxy
  367. IClientSecurity *pCliSec = NULL;
  368. if (S_OK == pUnk->QueryInterface (IID_IClientSecurity, (PPVOID) &pCliSec))
  369. {
  370. IUnknown *pNewUnk = NULL;
  371. // If successful this AddRef's pUnk
  372. HRESULT sc = pCliSec->CopyProxy(pUnk, &pNewUnk);
  373. if (S_OK == sc)
  374. {
  375. SecureProxy (pNewUnk, m_dwInitialAuthnLevel, m_dwInitialImpLevel);
  376. pUnkArray [m_dwInitialAuthnLevel - WBEMS_MIN_AUTHN_LEVEL]
  377. [m_dwInitialImpLevel - WBEMS_MIN_IMP_LEVEL] = pNewUnk;
  378. // NB: pNewUnk already AddRef'd above by CopyProxy
  379. }
  380. pCliSec->Release ();
  381. }
  382. }
  383. }
  384. else
  385. {
  386. m_dwInitialAuthnLevel = (WbemAuthenticationLevelEnum) dwAuthnLevel;
  387. m_dwInitialImpLevel = (WbemImpersonationLevelEnum) dwImpLevel;
  388. pUnkArray [m_dwInitialAuthnLevel - WBEMS_MIN_AUTHN_LEVEL]
  389. [m_dwInitialImpLevel - WBEMS_MIN_IMP_LEVEL] = pUnk;
  390. pUnk->AddRef ();
  391. }
  392. }
  393. }
  394. //***************************************************************************
  395. //
  396. // CSWbemProxyCache::GetProxy
  397. //
  398. // DESCRIPTION:
  399. //
  400. // Return a proxy from the cache with the desired authentication and
  401. // impersonation level.
  402. //
  403. // PARAMETERS:
  404. //
  405. // authnLevel required authentication level
  406. // impLevel required impersonation level
  407. // forceResecure whether to force a resecure of an extant proxy
  408. //
  409. // RETURN VALUES:
  410. // Pointer to copied proxy, or NULL. If not NULL, caller must Release.
  411. //
  412. //***************************************************************************
  413. IUnknown *CSWbemProxyCache::GetProxy (
  414. WbemAuthenticationLevelEnum authnLevel,
  415. WbemImpersonationLevelEnum impLevel,
  416. bool forceResecure)
  417. {
  418. EnterCriticalSection (&m_cs);
  419. IUnknown *pUnk = pUnkArray [authnLevel - WBEMS_MIN_AUTHN_LEVEL]
  420. [impLevel - WBEMS_MIN_IMP_LEVEL];
  421. if (pUnk)
  422. {
  423. // Already cached this proxy - reuse
  424. pUnk->AddRef ();
  425. // Force a resecure? This is useful if we have just changed the
  426. // privileges in the current token and need to stim RPC to pick
  427. // them up.
  428. if (forceResecure)
  429. SecureProxy (pUnk, authnLevel, impLevel);
  430. }
  431. else
  432. {
  433. // Need to create a copy of the proxy; use the first
  434. // created element as a base
  435. IUnknown *pUnkFirst = pUnkArray [m_dwInitialAuthnLevel - WBEMS_MIN_AUTHN_LEVEL]
  436. [m_dwInitialImpLevel - WBEMS_MIN_IMP_LEVEL];
  437. if (pUnkFirst)
  438. {
  439. // Now copy the proxy
  440. IClientSecurity *pCliSec = NULL;
  441. if (S_OK == pUnkFirst->QueryInterface (IID_IClientSecurity, (PPVOID) &pCliSec))
  442. {
  443. // If successful this AddRef's pUnk
  444. HRESULT sc = pCliSec->CopyProxy(pUnkFirst, &pUnk);
  445. if (S_OK == sc)
  446. {
  447. SecureProxy (pUnk, authnLevel, impLevel);
  448. pUnkArray [authnLevel - WBEMS_MIN_AUTHN_LEVEL]
  449. [impLevel - WBEMS_MIN_IMP_LEVEL] = pUnk;
  450. // AddRef because we are handing pUnk back
  451. pUnk->AddRef ();
  452. }
  453. pCliSec->Release ();
  454. }
  455. }
  456. }
  457. LeaveCriticalSection (&m_cs);
  458. return pUnk;
  459. }
  460. //***************************************************************************
  461. //
  462. // CSWbemProxyCache::SecureProxy
  463. //
  464. // DESCRIPTION:
  465. //
  466. // Secure the given proxy using the provided settings
  467. //
  468. // PARAMETERS:
  469. //
  470. // authnLevel authentication level of proxy
  471. // impLevel impersonation level of proxy
  472. //
  473. // RETURN VALUES:
  474. // none
  475. //
  476. //***************************************************************************
  477. void CSWbemProxyCache::SecureProxy (
  478. IUnknown *pUnk,
  479. WbemAuthenticationLevelEnum authnLevel,
  480. WbemImpersonationLevelEnum impLevel)
  481. {
  482. /*
  483. * Due to the vagaries of the IClientSecurity::SetBlanket call,
  484. * any COAUTHIDENTITY pointer passed into that call must remain
  485. * valid either until SetBlanket is called again or all proxies
  486. * on the object are released. So we need to store any returned
  487. * COAUTHIDENTITY so that it remains valid for the lifetime
  488. * of this cache.
  489. */
  490. EnterCriticalSection (&m_cs);
  491. if (pUnk)
  492. {
  493. /*
  494. * Note that our implicit assumption is that we only ever
  495. * need one COAUTHIDENTITY per cache. This is because
  496. * the ingredients of the structure (user, password and
  497. * authority) are set at cache initialization time and
  498. * never change thereafter.
  499. */
  500. if (m_pCoAuthIdentity)
  501. {
  502. SetInterfaceSecurityDecrypt (pUnk, m_pCoAuthIdentity, m_bsPrincipal,
  503. authnLevel, impLevel, GetCapabilities (),
  504. m_bUseDefaultInfo);
  505. }
  506. else
  507. {
  508. // See if we get one
  509. BSTR bsPrincipal = NULL;
  510. SetInterfaceSecurityEncrypt (pUnk, m_bsAuthority, m_bsUser, m_bsPassword,
  511. authnLevel, impLevel, GetCapabilities (),
  512. &m_pCoAuthIdentity, &bsPrincipal, m_bUseDefaultInfo);
  513. if (bsPrincipal)
  514. {
  515. if (m_bsPrincipal)
  516. SysFreeString (m_bsPrincipal);
  517. m_bsPrincipal = bsPrincipal;
  518. }
  519. }
  520. }
  521. LeaveCriticalSection (&m_cs);
  522. return;
  523. }
  524. //***************************************************************************
  525. //
  526. // CSWbemProxyCache::GetCapabilities
  527. //
  528. // DESCRIPTION:
  529. //
  530. // Return the EOAC capabilities value depending on the OS platform and
  531. // user credentials (or absence thereof).
  532. //
  533. // RETURN VALUES:
  534. //
  535. // The determined capabilities.
  536. //
  537. //***************************************************************************
  538. DWORD CSWbemProxyCache::GetCapabilities ()
  539. {
  540. /*
  541. * For NT5 (and presumably greater) we enable Static
  542. * Cloaking on the proxy. This allows RPC to use the
  543. * Privilege settings in the Impersonation token.
  544. *
  545. * Note that we use static cloaking so that thread identity
  546. * is only used during CoSetProxyBlanket calls; dynamic
  547. * cloaking forces it to be used on all calls to the proxy,
  548. * so is much less efficient. Since we don't allow different
  549. * users to access the same proxy, static cloaking is sufficient.
  550. *
  551. * It makes no sense to explicitly supply a User/Password and specify
  552. * cloaking, as DCOM authentication of proxy uses either
  553. * an explicit SEC_WINNT_AUTH_IDENTITY (for User & Password)
  554. * or the current proxy identity (in the process token or
  555. * impersonation token). Requesting cloaking implies that the
  556. * proxy identity in the impersonation token is to be used, and
  557. * therefore that any User/Password is irrelevant (and vice-versa).
  558. *
  559. * See MSDN documentation on CoSetProxyBlanket for more info.
  560. */
  561. DWORD dwCapabilities = EOAC_NONE;
  562. if (CSWbemSecurity::IsNT () && (4 < CSWbemSecurity::GetNTMajorVersion ()) &&
  563. !m_bUsingExplicitUserName)
  564. dwCapabilities |= EOAC_STATIC_CLOAKING;
  565. return dwCapabilities ;
  566. }
  567. COAUTHIDENTITY *CSWbemProxyCache::GetCoAuthIdentity ()
  568. {
  569. HRESULT hr = E_FAIL;
  570. COAUTHIDENTITY *pAuthIdent = NULL;
  571. if (m_pCoAuthIdentity)
  572. hr = WbemAllocAuthIdentity (m_pCoAuthIdentity->User,
  573. m_pCoAuthIdentity->Password, m_pCoAuthIdentity->Domain, &pAuthIdent);
  574. return pAuthIdent;
  575. }
  576. void CSWbemProxyCache::ClearCredentials ()
  577. {
  578. if (m_bsUser)
  579. {
  580. _wcsnset (m_bsUser, L'0', wcslen (m_bsUser));
  581. SysFreeString (m_bsUser);
  582. m_bsUser = NULL;
  583. }
  584. if (m_bsPassword)
  585. {
  586. _wcsnset (m_bsPassword, L'0', wcslen (m_bsPassword));
  587. SysFreeString (m_bsPassword);
  588. m_bsPassword = NULL;
  589. }
  590. }