Source code of Windows XP (NT5)
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.

2116 lines
51 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation
  4. //
  5. // SECURITY.CPP
  6. //
  7. // alanbos 28-Jun-98 Created.
  8. //
  9. // Defines the implementation of CSWbemSecurity
  10. //
  11. //***************************************************************************
  12. #include "precomp.h"
  13. // Used to protect security calls
  14. extern CRITICAL_SECTION g_csSecurity;
  15. bool CSWbemSecurity::s_bInitialized = false;
  16. bool CSWbemSecurity::s_bIsNT = false;
  17. DWORD CSWbemSecurity::s_dwNTMajorVersion = 0;
  18. HINSTANCE CSWbemSecurity::s_hAdvapi = NULL;
  19. bool CSWbemSecurity::s_bCanRevert = false;
  20. WbemImpersonationLevelEnum CSWbemSecurity::s_dwDefaultImpersonationLevel
  21. = wbemImpersonationLevelIdentify;
  22. // Declarations for function pointers that won't exist on Win9x
  23. BOOL (STDAPICALLTYPE *s_pfnDuplicateTokenEx) (
  24. HANDLE,
  25. DWORD,
  26. LPSECURITY_ATTRIBUTES,
  27. SECURITY_IMPERSONATION_LEVEL,
  28. TOKEN_TYPE,
  29. PHANDLE
  30. ) = NULL;
  31. //***************************************************************************
  32. //
  33. // SCODE CSWbemSecurity::Initialize
  34. //
  35. // DESCRIPTION:
  36. //
  37. // This static function is caused on DLL attachment to the process; it
  38. // sets up the function pointers for advanced API privilege functions.
  39. // On Win9x these functions are not supported which is why we need to
  40. // indirect through GetProcAddress.
  41. //
  42. //***************************************************************************
  43. void CSWbemSecurity::Initialize ()
  44. {
  45. EnterCriticalSection (&g_csSecurity);
  46. if (!s_bInitialized)
  47. {
  48. // Get OS info
  49. OSVERSIONINFO osVersionInfo;
  50. osVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  51. GetVersionEx (&osVersionInfo);
  52. s_bIsNT = (VER_PLATFORM_WIN32_NT == osVersionInfo.dwPlatformId);
  53. s_dwNTMajorVersion = osVersionInfo.dwMajorVersion;
  54. if (s_bIsNT)
  55. {
  56. HKEY hKey;
  57. // Security values are relevant for NT only - for Win9x leave as default
  58. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  59. WBEMS_RK_SCRIPTING, 0, KEY_QUERY_VALUE, &hKey))
  60. {
  61. DWORD dwDummy = 0;
  62. // Get revert flag value from registry - NT 4.0 or less only
  63. if (s_dwNTMajorVersion <= 4)
  64. {
  65. DWORD dwEnableForAsp = 0;
  66. dwDummy = sizeof (dwEnableForAsp);
  67. if (ERROR_SUCCESS == RegQueryValueEx (hKey, WBEMS_RV_ENABLEFORASP,
  68. NULL, NULL, (BYTE *) &dwEnableForAsp, &dwDummy))
  69. s_bCanRevert = (0 != dwEnableForAsp);
  70. }
  71. // Get default impersonation level from registry
  72. DWORD dwImpLevel = 0;
  73. dwDummy = sizeof (dwImpLevel);
  74. if (ERROR_SUCCESS == RegQueryValueEx (hKey, WBEMS_RV_DEFAULTIMPLEVEL,
  75. NULL, NULL, (BYTE *) &dwImpLevel, &dwDummy))
  76. s_dwDefaultImpersonationLevel = (WbemImpersonationLevelEnum) dwImpLevel;
  77. RegCloseKey (hKey);
  78. }
  79. // Set up security function pointers for NT
  80. if (!s_hAdvapi)
  81. {
  82. TCHAR dllName [] = _T("\\advapi32.dll");
  83. LPTSTR pszSysDir = new TCHAR[ MAX_PATH + _tcslen (dllName) + 1];
  84. if (pszSysDir)
  85. {
  86. pszSysDir[0] = NULL;
  87. UINT uSize = GetSystemDirectory(pszSysDir, MAX_PATH);
  88. if(uSize > MAX_PATH) {
  89. delete[] pszSysDir;
  90. pszSysDir = new TCHAR[ uSize + _tcslen (dllName) + 1];
  91. if (pszSysDir)
  92. {
  93. pszSysDir[0] = NULL;
  94. uSize = GetSystemDirectory(pszSysDir, uSize);
  95. }
  96. }
  97. if (pszSysDir)
  98. {
  99. _tcscat (pszSysDir, dllName);
  100. s_hAdvapi = LoadLibraryEx (pszSysDir, NULL, 0);
  101. if (s_hAdvapi)
  102. (FARPROC&) s_pfnDuplicateTokenEx = GetProcAddress(s_hAdvapi, "DuplicateTokenEx");
  103. delete [] pszSysDir;
  104. }
  105. }
  106. }
  107. }
  108. s_bInitialized = true;
  109. }
  110. LeaveCriticalSection (&g_csSecurity);
  111. }
  112. //***************************************************************************
  113. //
  114. // SCODE CSWbemSecurity::Uninitialize
  115. //
  116. // DESCRIPTION:
  117. //
  118. // This static function is caused on DLL detachment to the process; it
  119. // unloads the API loaded by Initialize (above) to obtain function pointers.
  120. //
  121. //***************************************************************************
  122. void CSWbemSecurity::Uninitialize ()
  123. {
  124. EnterCriticalSection (&g_csSecurity);
  125. if (s_hAdvapi)
  126. {
  127. s_pfnDuplicateTokenEx = NULL;
  128. FreeLibrary (s_hAdvapi);
  129. s_hAdvapi = NULL;
  130. }
  131. LeaveCriticalSection (&g_csSecurity);
  132. }
  133. //***************************************************************************
  134. //
  135. // SCODE CSWbemSecurity::LookupPrivilegeValue
  136. //
  137. // DESCRIPTION:
  138. //
  139. // This static function wraps the Win32 LookupPrivilegeValue function,
  140. // allowing us to do some OS-dependent stuff.
  141. //
  142. // PARAMETERS:
  143. //
  144. // lpName the privilege name
  145. // lpLuid holds the LUID on successful return
  146. //
  147. // RETURN VALUES:
  148. //
  149. // true On NT this means we found the privilege. On Win9x we
  150. // always return this.
  151. //
  152. // false On NT this means the privilege is not recognized. This
  153. // is never returned on Win9x.
  154. //
  155. //***************************************************************************
  156. BOOL CSWbemSecurity::LookupPrivilegeValue (
  157. LPCTSTR lpName,
  158. PLUID lpLuid
  159. )
  160. {
  161. // Allows any name to map to 0 LUID on Win9x - this aids script portability
  162. if (IsNT ())
  163. return ::LookupPrivilegeValue(NULL, lpName, lpLuid);
  164. else
  165. return true;
  166. }
  167. //***************************************************************************
  168. //
  169. // SCODE CSWbemSecurity::LookupPrivilegeDisplayName
  170. //
  171. // DESCRIPTION:
  172. //
  173. // This static function wraps the Win32 LookupPrivilegeDisplayName function,
  174. // allowing us to do some OS-dependent stuff.
  175. //
  176. // PARAMETERS:
  177. //
  178. // tName the privilege name
  179. // pDisplayName holds the display name on successful return
  180. //
  181. //***************************************************************************
  182. void CSWbemSecurity::LookupPrivilegeDisplayName (LPCTSTR lpName, BSTR *pDisplayName)
  183. {
  184. if (pDisplayName)
  185. {
  186. // Can't return display name on Win9x (no privilege support)
  187. if (IsNT ())
  188. {
  189. DWORD dwLangID;
  190. DWORD dwSize = 1;
  191. TCHAR dummy [1];
  192. // Get size of required buffer
  193. ::LookupPrivilegeDisplayName (NULL, lpName, dummy, &dwSize, &dwLangID);
  194. LPTSTR dname = new TCHAR[dwSize + 1];
  195. if (dname)
  196. {
  197. if (::LookupPrivilegeDisplayName (_T(""), lpName, dname, &dwSize, &dwLangID))
  198. {
  199. // Have a valid name - now copy it to a BSTR
  200. #ifdef _UNICODE
  201. *pDisplayName = SysAllocString (dname);
  202. #else
  203. size_t dnameLen = strlen (dname);
  204. OLECHAR *nameW = new OLECHAR [dnameLen + 1];
  205. if (nameW)
  206. {
  207. mbstowcs (nameW, dname, dnameLen);
  208. nameW [dnameLen] = NULL;
  209. *pDisplayName = SysAllocString (nameW);
  210. delete [] nameW;
  211. }
  212. #endif
  213. }
  214. delete [] dname;
  215. }
  216. }
  217. // If we failed, just set an empty string
  218. if (!(*pDisplayName))
  219. *pDisplayName = SysAllocString (L"");
  220. }
  221. }
  222. //***************************************************************************
  223. //
  224. // CSWbemSecurity::CSWbemSecurity
  225. //
  226. // CONSTRUCTOR
  227. // This form of the constructor is used for securing a new WBEM
  228. // remoted interface where no previous security has been applied.
  229. // It is only used to secure IWbemServices interfaces.
  230. // Note that the Locator may have security settings so these are
  231. // transferred if present.
  232. //
  233. //***************************************************************************
  234. CSWbemSecurity::CSWbemSecurity (
  235. IUnknown *pUnk,
  236. BSTR bsAuthority ,
  237. BSTR bsUser,
  238. BSTR bsPassword,
  239. CWbemLocatorSecurity *pLocatorSecurity) :
  240. m_pPrivilegeSet (NULL),
  241. m_pProxyCache (NULL),
  242. m_pCurProxy (NULL)
  243. {
  244. m_Dispatch.SetObj (this, IID_ISWbemSecurity,
  245. CLSID_SWbemSecurity, L"SWbemSecurity");
  246. m_cRef=1;
  247. m_pProxyCache = new CSWbemProxyCache (pUnk, bsAuthority,
  248. bsUser, bsPassword, pLocatorSecurity);
  249. if (m_pProxyCache)
  250. m_pCurProxy = m_pProxyCache->GetInitialProxy ();
  251. if (pLocatorSecurity)
  252. {
  253. // Clone the privilege set
  254. CSWbemPrivilegeSet *pPrivilegeSet = pLocatorSecurity->GetPrivilegeSet ();
  255. if (pPrivilegeSet)
  256. {
  257. m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet);
  258. pPrivilegeSet->Release ();
  259. }
  260. }
  261. else
  262. {
  263. // Create a new privilege set
  264. m_pPrivilegeSet = new CSWbemPrivilegeSet;
  265. }
  266. InterlockedIncrement(&g_cObj);
  267. }
  268. //***************************************************************************
  269. //
  270. // CSWbemSecurity::CSWbemSecurity
  271. //
  272. // CONSTRUCTOR
  273. // This form of the constructor is used for securing a new WBEM
  274. // remoted interface where no previous security has been applied,
  275. // and where the user credentials are expressed in the form of an
  276. // encrypted COAUTHIDENTITY plus principal and authority.
  277. // It is only used to secure IWbemServices interfaces.
  278. //
  279. //***************************************************************************
  280. CSWbemSecurity::CSWbemSecurity (
  281. IUnknown *pUnk,
  282. COAUTHIDENTITY *pCoAuthIdentity,
  283. BSTR bsPrincipal,
  284. BSTR bsAuthority) :
  285. m_pPrivilegeSet (NULL),
  286. m_pProxyCache (NULL),
  287. m_pCurProxy (NULL)
  288. {
  289. m_Dispatch.SetObj (this, IID_ISWbemSecurity,
  290. CLSID_SWbemSecurity, L"SWbemSecurity");
  291. m_cRef=1;
  292. m_pProxyCache = new CSWbemProxyCache (pUnk, pCoAuthIdentity,
  293. bsPrincipal, bsAuthority);
  294. if (m_pProxyCache)
  295. m_pCurProxy = m_pProxyCache->GetInitialProxy ();
  296. // Create a new privilege set
  297. m_pPrivilegeSet = new CSWbemPrivilegeSet;
  298. InterlockedIncrement(&g_cObj);
  299. }
  300. //***************************************************************************
  301. //
  302. // CSWbemSecurity::CSWbemSecurity
  303. //
  304. // CONSTRUCTOR
  305. // This form of the constructor is used for securing a new WBEM interface
  306. // non-remoted interface using the security attributes attached to another
  307. // (already secured) remoted interface; a non-remoted interface is secured
  308. // by virtue of securing a new proxy on an underlying remoted interface.
  309. // It is used to "secure" an ISWbemObjectEx interface using the security
  310. // settings of an IWbemServices interface.
  311. //
  312. //***************************************************************************
  313. CSWbemSecurity::CSWbemSecurity (
  314. CSWbemSecurity *pSecurity) :
  315. m_pPrivilegeSet (NULL),
  316. m_pProxyCache (NULL),
  317. m_pCurProxy (NULL)
  318. {
  319. m_Dispatch.SetObj (this, IID_ISWbemSecurity,
  320. CLSID_SWbemSecurity, L"SWbemSecurity");
  321. m_cRef=1;
  322. // Clone the privilege set
  323. if (pSecurity)
  324. {
  325. CSWbemPrivilegeSet *pPrivilegeSet = pSecurity->GetPrivilegeSet ();
  326. if (pPrivilegeSet)
  327. {
  328. m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet);
  329. pPrivilegeSet->Release ();
  330. }
  331. else
  332. {
  333. // Create a new one
  334. m_pPrivilegeSet = new CSWbemPrivilegeSet ();
  335. }
  336. m_pProxyCache = pSecurity->GetProxyCache ();
  337. m_pCurProxy = pSecurity->GetProxy ();
  338. }
  339. InterlockedIncrement(&g_cObj);
  340. }
  341. CSWbemSecurity::CSWbemSecurity (
  342. IUnknown *pUnk,
  343. ISWbemInternalSecurity *pISWbemInternalSecurity) :
  344. m_pPrivilegeSet (NULL),
  345. m_pProxyCache (NULL),
  346. m_pCurProxy (NULL)
  347. {
  348. m_Dispatch.SetObj (this, IID_ISWbemSecurity,
  349. CLSID_SWbemSecurity, L"SWbemSecurity");
  350. m_cRef=1;
  351. if (pISWbemInternalSecurity)
  352. {
  353. // Clone the privilege set
  354. ISWbemSecurity *pISWbemSecurity = NULL;
  355. if (SUCCEEDED(pISWbemInternalSecurity->QueryInterface (IID_ISWbemSecurity,
  356. (void**) &pISWbemSecurity)))
  357. {
  358. ISWbemPrivilegeSet *pISWbemPrivilegeSet = NULL;
  359. if (SUCCEEDED(pISWbemSecurity->get_Privileges (&pISWbemPrivilegeSet)))
  360. {
  361. // Build the privilege set
  362. m_pPrivilegeSet = new CSWbemPrivilegeSet (pISWbemPrivilegeSet);
  363. // Build the proxy cache
  364. BSTR bsAuthority = NULL;
  365. BSTR bsPrincipal = NULL;
  366. BSTR bsUser = NULL;
  367. BSTR bsPassword = NULL;
  368. BSTR bsDomain = NULL;
  369. pISWbemInternalSecurity->GetAuthority (&bsAuthority);
  370. pISWbemInternalSecurity->GetPrincipal (&bsPrincipal);
  371. pISWbemInternalSecurity->GetUPD (&bsUser, &bsPassword, &bsDomain);
  372. COAUTHIDENTITY *pCoAuthIdentity = NULL;
  373. // Decide if we need a COAUTHIDENTITY
  374. if ((bsUser && (0 < wcslen (bsUser))) ||
  375. (bsPassword && (0 < wcslen (bsPassword))) ||
  376. (bsDomain && (0 < wcslen (bsDomain))))
  377. WbemAllocAuthIdentity (bsUser, bsPassword, bsDomain, &pCoAuthIdentity);
  378. m_pProxyCache = new CSWbemProxyCache (pUnk, pCoAuthIdentity,
  379. bsPrincipal, bsAuthority);
  380. if (pCoAuthIdentity)
  381. WbemFreeAuthIdentity (pCoAuthIdentity);
  382. if (bsAuthority)
  383. SysFreeString (bsAuthority);
  384. if (bsPrincipal)
  385. SysFreeString (bsPrincipal);
  386. if (bsUser)
  387. SysFreeString (bsUser);
  388. if (bsPassword)
  389. SysFreeString (bsPassword);
  390. if (bsDomain)
  391. SysFreeString (bsDomain);
  392. if (m_pProxyCache)
  393. m_pCurProxy = m_pProxyCache->GetInitialProxy ();
  394. }
  395. pISWbemPrivilegeSet->Release ();
  396. }
  397. pISWbemSecurity->Release ();
  398. }
  399. InterlockedIncrement(&g_cObj);
  400. }
  401. //***************************************************************************
  402. //
  403. // CSWbemSecurity::CSWbemSecurity
  404. //
  405. // CONSTRUCTOR
  406. // This form of the constructor is used for securing a new WBEM remoted
  407. // interface interface using the security attributes attached to another
  408. // (already secured) remoted interface.
  409. // It is used to "secure" an ISWbemObjectSet interface using the security
  410. // settings of an IWbemServices interface.
  411. //
  412. //***************************************************************************
  413. CSWbemSecurity::CSWbemSecurity (
  414. IUnknown *pUnk,
  415. CSWbemSecurity *pSecurity) :
  416. m_pPrivilegeSet (NULL),
  417. m_pProxyCache (NULL),
  418. m_pCurProxy (NULL)
  419. {
  420. m_Dispatch.SetObj (this, IID_ISWbemSecurity,
  421. CLSID_SWbemSecurity, L"SWbemSecurity");
  422. m_cRef=1;
  423. InterlockedIncrement(&g_cObj);
  424. if (pSecurity)
  425. {
  426. // Clone the privilege set
  427. CSWbemPrivilegeSet *pPrivilegeSet = pSecurity->GetPrivilegeSet ();
  428. if (pPrivilegeSet)
  429. {
  430. m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet);
  431. pPrivilegeSet->Release ();
  432. }
  433. m_pProxyCache = new CSWbemProxyCache (pUnk, pSecurity);
  434. if (m_pProxyCache)
  435. m_pCurProxy = m_pProxyCache->GetInitialProxy ();
  436. }
  437. else
  438. {
  439. m_pPrivilegeSet = new CSWbemPrivilegeSet ();
  440. m_pProxyCache = new CSWbemProxyCache (pUnk, NULL);
  441. if (m_pProxyCache)
  442. m_pCurProxy = m_pProxyCache->GetInitialProxy ();
  443. }
  444. }
  445. //***************************************************************************
  446. //
  447. // CSWbemSecurity::~CSWbemSecurity
  448. //
  449. // DESTRUCTOR
  450. //
  451. //***************************************************************************
  452. CSWbemSecurity::~CSWbemSecurity (void)
  453. {
  454. InterlockedDecrement(&g_cObj);
  455. if (m_pCurProxy)
  456. m_pCurProxy->Release ();
  457. if (m_pProxyCache)
  458. m_pProxyCache->Release ();
  459. if (m_pPrivilegeSet)
  460. m_pPrivilegeSet->Release ();
  461. }
  462. //***************************************************************************
  463. // HRESULT CSWbemSecurity::QueryInterface
  464. // long CSWbemSecurity::AddRef
  465. // long CSWbemSecurity::Release
  466. //
  467. // DESCRIPTION:
  468. //
  469. // Standard Com IUNKNOWN functions.
  470. //
  471. //***************************************************************************
  472. STDMETHODIMP CSWbemSecurity::QueryInterface (
  473. IN REFIID riid,
  474. OUT LPVOID *ppv
  475. )
  476. {
  477. *ppv=NULL;
  478. if (IID_IUnknown==riid)
  479. *ppv = reinterpret_cast<IUnknown*>(this);
  480. else if (IID_ISWbemSecurity==riid)
  481. *ppv = (ISWbemSecurity *)this;
  482. else if (IID_IDispatch==riid)
  483. *ppv = (IDispatch *)this;
  484. else if (IID_ISupportErrorInfo==riid)
  485. *ppv = (ISupportErrorInfo *)this;
  486. else if (IID_ISWbemInternalSecurity==riid)
  487. *ppv = (ISWbemInternalSecurity *)this;
  488. else if (IID_IProvideClassInfo==riid)
  489. *ppv = (IProvideClassInfo *)this;
  490. if (NULL!=*ppv)
  491. {
  492. ((LPUNKNOWN)*ppv)->AddRef();
  493. return NOERROR;
  494. }
  495. return ResultFromScode(E_NOINTERFACE);
  496. }
  497. STDMETHODIMP_(ULONG) CSWbemSecurity::AddRef(void)
  498. {
  499. long l = InterlockedIncrement(&m_cRef);
  500. return l;
  501. }
  502. STDMETHODIMP_(ULONG) CSWbemSecurity::Release(void)
  503. {
  504. long l = InterlockedDecrement(&m_cRef);
  505. if (0L!=l)
  506. return l;
  507. delete this;
  508. return 0;
  509. }
  510. //***************************************************************************
  511. // HRESULT CSWbemSecurity::InterfaceSupportsErrorInfo
  512. //
  513. // DESCRIPTION:
  514. //
  515. // Standard Com ISupportErrorInfo functions.
  516. //
  517. //***************************************************************************
  518. STDMETHODIMP CSWbemSecurity::InterfaceSupportsErrorInfo (IN REFIID riid)
  519. {
  520. return (IID_ISWbemSecurity == riid) ? S_OK : S_FALSE;
  521. }
  522. //***************************************************************************
  523. //
  524. // SCODE CSWbemSecurity::get_AuthenticationLevel
  525. //
  526. // DESCRIPTION:
  527. //
  528. // Retrieve the authentication level
  529. //
  530. // PARAMETERS:
  531. //
  532. // pAuthenticationLevel holds the value on return
  533. //
  534. // RETURN VALUES:
  535. //
  536. // WBEM_S_NO_ERROR success
  537. // WBEM_E_INVALID_PARAMETER bad input parameters
  538. // WBEM_E_FAILED otherwise
  539. //
  540. //***************************************************************************
  541. HRESULT CSWbemSecurity::get_AuthenticationLevel (
  542. WbemAuthenticationLevelEnum *pAuthenticationLevel
  543. )
  544. {
  545. HRESULT hr = WBEM_E_FAILED;
  546. ResetLastErrors ();
  547. if (NULL == pAuthenticationLevel)
  548. hr = WBEM_E_INVALID_PARAMETER;
  549. else if (m_pCurProxy)
  550. {
  551. DWORD dwAuthnLevel;
  552. DWORD dwImpLevel;
  553. if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
  554. {
  555. *pAuthenticationLevel = (WbemAuthenticationLevelEnum) dwAuthnLevel;
  556. hr = WBEM_S_NO_ERROR;
  557. }
  558. }
  559. if (FAILED(hr))
  560. m_Dispatch.RaiseException (hr);
  561. return hr;
  562. }
  563. //***************************************************************************
  564. //
  565. // SCODE CSWbemSecurity::put_AuthenticationLevel
  566. //
  567. // DESCRIPTION:
  568. //
  569. // Set the authentication level
  570. //
  571. // PARAMETERS:
  572. //
  573. // authenticationLevel the new value
  574. //
  575. // RETURN VALUES:
  576. //
  577. // WBEM_S_NO_ERROR success
  578. // WBEM_E_INVALID_PARAMETER bad input parameters
  579. // WBEM_E_FAILED otherwise
  580. //
  581. //***************************************************************************
  582. HRESULT CSWbemSecurity::put_AuthenticationLevel (
  583. WbemAuthenticationLevelEnum authenticationLevel
  584. )
  585. {
  586. HRESULT hr = WBEM_E_FAILED;
  587. ResetLastErrors ();
  588. if ((WBEMS_MIN_AUTHN_LEVEL > authenticationLevel) ||
  589. (WBEMS_MAX_AUTHN_LEVEL < authenticationLevel))
  590. hr = WBEM_E_INVALID_PARAMETER;
  591. else if (m_pCurProxy && m_pProxyCache)
  592. {
  593. DWORD dwAuthnLevel;
  594. DWORD dwImpLevel;
  595. if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
  596. {
  597. // Only refressh from cache if settings have changed
  598. if (authenticationLevel != (WbemAuthenticationLevelEnum) dwAuthnLevel)
  599. {
  600. m_pCurProxy->Release ();
  601. m_pCurProxy = NULL;
  602. m_pCurProxy = m_pProxyCache->GetProxy
  603. (authenticationLevel, (WbemImpersonationLevelEnum) dwImpLevel);
  604. }
  605. hr = WBEM_S_NO_ERROR;
  606. }
  607. }
  608. if (FAILED(hr))
  609. m_Dispatch.RaiseException (hr);
  610. return hr;
  611. }
  612. //***************************************************************************
  613. //
  614. // SCODE CSWbemSecurity::get_ImpersonationLevel
  615. //
  616. // DESCRIPTION:
  617. //
  618. // Retrieve the impersonation level
  619. //
  620. // PARAMETERS:
  621. //
  622. // pImpersonationLevel holds the value on return
  623. //
  624. // RETURN VALUES:
  625. //
  626. // WBEM_S_NO_ERROR success
  627. // WBEM_E_INVALID_PARAMETER bad input parameters
  628. // WBEM_E_FAILED otherwise
  629. //
  630. //***************************************************************************
  631. HRESULT CSWbemSecurity::get_ImpersonationLevel (
  632. WbemImpersonationLevelEnum *pImpersonationLevel
  633. )
  634. {
  635. HRESULT hr = WBEM_E_FAILED;
  636. ResetLastErrors ();
  637. if (NULL == pImpersonationLevel)
  638. hr = WBEM_E_INVALID_PARAMETER;
  639. else if (m_pCurProxy)
  640. {
  641. DWORD dwAuthnLevel;
  642. DWORD dwImpLevel;
  643. if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
  644. {
  645. *pImpersonationLevel = (WbemImpersonationLevelEnum) dwImpLevel;
  646. hr = WBEM_S_NO_ERROR;
  647. }
  648. }
  649. if (FAILED(hr))
  650. m_Dispatch.RaiseException (hr);
  651. return hr;
  652. }
  653. //***************************************************************************
  654. //
  655. // SCODE CSWbemSecurity::put_ImpersonationLevel
  656. //
  657. // DESCRIPTION:
  658. //
  659. // Set the impersonation level
  660. //
  661. // PARAMETERS:
  662. //
  663. // impersonationLevel the new value
  664. //
  665. // RETURN VALUES:
  666. //
  667. // WBEM_S_NO_ERROR success
  668. // WBEM_E_INVALID_PARAMETER bad input parameters
  669. // WBEM_E_FAILED otherwise
  670. //
  671. //***************************************************************************
  672. HRESULT CSWbemSecurity::put_ImpersonationLevel (
  673. WbemImpersonationLevelEnum impersonationLevel
  674. )
  675. {
  676. HRESULT hr = WBEM_E_FAILED;
  677. ResetLastErrors ();
  678. if ((WBEMS_MIN_IMP_LEVEL > impersonationLevel) || (WBEMS_MAX_IMP_LEVEL < impersonationLevel))
  679. hr = WBEM_E_INVALID_PARAMETER;
  680. else if (m_pCurProxy && m_pProxyCache)
  681. {
  682. DWORD dwAuthnLevel;
  683. DWORD dwImpLevel;
  684. if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
  685. {
  686. // Only refressh from cache if settings have changed
  687. if (impersonationLevel != (WbemImpersonationLevelEnum) dwImpLevel)
  688. {
  689. m_pCurProxy->Release ();
  690. m_pCurProxy = NULL;
  691. m_pCurProxy = m_pProxyCache->GetProxy
  692. ((WbemAuthenticationLevelEnum) dwAuthnLevel, impersonationLevel);
  693. }
  694. hr = WBEM_S_NO_ERROR;
  695. }
  696. }
  697. if (FAILED(hr))
  698. m_Dispatch.RaiseException (hr);
  699. return hr;
  700. }
  701. //***************************************************************************
  702. //
  703. // SCODE CSWbemSecurity::get_Privileges
  704. //
  705. // DESCRIPTION:
  706. //
  707. // Return the Privilege override set
  708. //
  709. // WBEM_S_NO_ERROR success
  710. // WBEM_E_INVALID_PARAMETER bad input parameters
  711. // WBEM_E_FAILED otherwise
  712. //
  713. //***************************************************************************
  714. HRESULT CSWbemSecurity::get_Privileges (
  715. ISWbemPrivilegeSet **ppPrivileges
  716. )
  717. {
  718. HRESULT hr = WBEM_E_FAILED;
  719. ResetLastErrors ();
  720. if (NULL == ppPrivileges)
  721. hr = WBEM_E_INVALID_PARAMETER;
  722. {
  723. *ppPrivileges = NULL;
  724. if (m_pPrivilegeSet)
  725. {
  726. if (SUCCEEDED (m_pPrivilegeSet->QueryInterface (IID_ISWbemPrivilegeSet,
  727. (PPVOID) ppPrivileges)))
  728. hr = WBEM_S_NO_ERROR;
  729. }
  730. }
  731. if (FAILED(hr))
  732. m_Dispatch.RaiseException (hr);
  733. return hr;
  734. }
  735. //***************************************************************************
  736. //
  737. // CSWbemSecurity::SecureInterface
  738. //
  739. // DESCRIPTION:
  740. //
  741. // Set the security on the specified interface using the security settings
  742. // on this interface.
  743. //
  744. // PARAMETERS:
  745. //
  746. // pUnk The interface to secure
  747. //
  748. // RETURN VALUES:
  749. // none
  750. //***************************************************************************
  751. void CSWbemSecurity::SecureInterface (IUnknown *pUnk)
  752. {
  753. if(pUnk)
  754. {
  755. if (m_pCurProxy)
  756. {
  757. DWORD dwAuthnLevel;
  758. DWORD dwImpLevel;
  759. if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
  760. if (m_pProxyCache)
  761. m_pProxyCache->SecureProxy (pUnk,
  762. (WbemAuthenticationLevelEnum) dwAuthnLevel,
  763. (WbemImpersonationLevelEnum) dwImpLevel);
  764. }
  765. }
  766. }
  767. //***************************************************************************
  768. //
  769. // CSWbemSecurity::SecureInterfaceRev
  770. //
  771. // DESCRIPTION:
  772. //
  773. // Set the security on this interface using the security settings
  774. // on the specified interface.
  775. //
  776. // PARAMETERS:
  777. //
  778. // pUnk The interface whose security settings we will
  779. // use to set this interface
  780. //
  781. // RETURN VALUES:
  782. // none
  783. //***************************************************************************
  784. void CSWbemSecurity::SecureInterfaceRev (IUnknown *pUnk)
  785. {
  786. if (pUnk)
  787. {
  788. DWORD dwAuthnLevel;
  789. DWORD dwImpLevel;
  790. if (S_OK == GetAuthImp (pUnk, &dwAuthnLevel, &dwImpLevel))
  791. {
  792. if (m_pCurProxy)
  793. {
  794. m_pCurProxy->Release ();
  795. m_pCurProxy = NULL;
  796. }
  797. if (m_pProxyCache)
  798. {
  799. m_pCurProxy = m_pProxyCache->GetProxy
  800. ((WbemAuthenticationLevelEnum) dwAuthnLevel,
  801. (WbemImpersonationLevelEnum) dwImpLevel);
  802. }
  803. }
  804. }
  805. }
  806. //***************************************************************************
  807. //
  808. // CSWbemSecurity::AdjustTokenPrivileges
  809. //
  810. // DESCRIPTION:
  811. //
  812. // Adjust the Privileges on the specified token without allowing a future
  813. // restore of the current settings..
  814. //
  815. // PARAMETERS:
  816. //
  817. // hHandle Handle of the token on which to adjust privileges
  818. // pPrivilegeSet Specified privilege adjustments
  819. //
  820. // RETURN VALUES:
  821. // none
  822. //***************************************************************************
  823. void CSWbemSecurity::AdjustTokenPrivileges (
  824. HANDLE hHandle,
  825. CSWbemPrivilegeSet *pPrivilegeSet
  826. )
  827. {
  828. DWORD lastErr = 0;
  829. if (pPrivilegeSet)
  830. {
  831. pPrivilegeSet->AddRef ();
  832. long lNumPrivileges = 0;
  833. pPrivilegeSet->get_Count (&lNumPrivileges);
  834. if (lNumPrivileges)
  835. {
  836. DWORD dwPrivilegeIndex = 0;
  837. /*
  838. * Set up the token privileges array. Note that some jiggery-pokery
  839. * is required here because the Privileges field is an [ANYSIZE_ARRAY]
  840. * type.
  841. */
  842. TOKEN_PRIVILEGES *pTokenPrivileges = (TOKEN_PRIVILEGES *)
  843. new BYTE [sizeof(TOKEN_PRIVILEGES) + (lNumPrivileges * sizeof (LUID_AND_ATTRIBUTES [1]))];
  844. if (pTokenPrivileges)
  845. {
  846. // Get the iterator
  847. PrivilegeMap::iterator next = pPrivilegeSet->m_PrivilegeMap.begin ();
  848. while (next != pPrivilegeSet->m_PrivilegeMap.end ())
  849. {
  850. CSWbemPrivilege *pPrivilege = (*next).second;
  851. pPrivilege->AddRef ();
  852. LUID luid;
  853. pPrivilege->GetLUID (&luid);
  854. VARIANT_BOOL vBool;
  855. pPrivilege->get_IsEnabled (&vBool);
  856. pTokenPrivileges->Privileges [dwPrivilegeIndex].Luid = luid;
  857. /*
  858. * Note that any setting other than SE_PRIVILEGE_ENABLED
  859. * is interpreted by AdjustTokenPrivileges as a DISABLE
  860. * request for that Privilege.
  861. */
  862. pTokenPrivileges->Privileges [dwPrivilegeIndex].Attributes
  863. = (VARIANT_TRUE == vBool) ?
  864. SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_ENABLED_BY_DEFAULT;
  865. dwPrivilegeIndex++;
  866. pPrivilege->Release ();
  867. next++;
  868. }
  869. // Now we should have recorded the number of privileges that were OK
  870. if (0 < dwPrivilegeIndex)
  871. {
  872. pTokenPrivileges->PrivilegeCount = dwPrivilegeIndex;
  873. BOOL result = ::AdjustTokenPrivileges (hHandle, FALSE, pTokenPrivileges, 0, NULL, NULL);
  874. lastErr = GetLastError ();
  875. }
  876. delete [] pTokenPrivileges;
  877. }
  878. }
  879. pPrivilegeSet->Release ();
  880. }
  881. }
  882. //***************************************************************************
  883. //
  884. // SCODE CSWbemSecurity::SetSecurity
  885. //
  886. // DESCRIPTION:
  887. //
  888. // Set Privileges on the Thread Token.
  889. //
  890. //***************************************************************************
  891. BOOL CSWbemSecurity::SetSecurity (
  892. bool &needToResetSecurity,
  893. HANDLE &hThreadToken
  894. )
  895. {
  896. BOOL result = TRUE; // Default is success
  897. DWORD lastErr = 0;
  898. hThreadToken = NULL; // Default assume we'll modify process token
  899. needToResetSecurity = false; // Default assume we changed no privileges
  900. // Win9x has no security support
  901. if (IsNT ())
  902. {
  903. // Start by checking whether we are being impersonated. On an NT4
  904. // box (which has no cloaking, and therefore cannot allow us to
  905. // pass on this impersonation to Winmgmt) we should RevertToSelf
  906. // if we have been configured to allow this. If we haven't been
  907. // configured to allow this, bail out now.
  908. if (4 >= GetNTMajorVersion ())
  909. {
  910. if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY|TOKEN_IMPERSONATE, true, &hThreadToken))
  911. {
  912. // We are being impersonated
  913. if (s_bCanRevert)
  914. {
  915. if (result = RevertToSelf())
  916. needToResetSecurity = true;
  917. }
  918. else
  919. {
  920. // Error - cannot do this! Time to bail out
  921. CloseHandle (hThreadToken);
  922. hThreadToken = NULL;
  923. result = FALSE;
  924. }
  925. }
  926. }
  927. else
  928. {
  929. #ifdef WSCRPDEBUG
  930. HANDLE hToken = NULL;
  931. if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, false, &hToken))
  932. {
  933. PrintPrivileges (hToken);
  934. CloseHandle (hToken);
  935. }
  936. #endif
  937. }
  938. if (result)
  939. {
  940. // Now we check if we need to set privileges
  941. bool bIsUsingExplicitUserName = false;
  942. if (m_pProxyCache)
  943. bIsUsingExplicitUserName = m_pProxyCache->IsUsingExplicitUserName ();
  944. /*
  945. * Specifying a user only makes sense for remote operations, and we
  946. * don't need to mess with privilege for remote operations since
  947. * they are set up by server logon anyway.
  948. */
  949. if (!bIsUsingExplicitUserName && m_pPrivilegeSet)
  950. {
  951. // Nothing to do unless some privilege overrides have been set
  952. long lCount = 0;
  953. m_pPrivilegeSet->get_Count (&lCount);
  954. if (0 < lCount)
  955. {
  956. if (4 < GetNTMajorVersion ())
  957. {
  958. /*
  959. * On NT5 we try to open the Thread token. If the client app
  960. * is calling into us on an impersonated thread (as IIS may be,
  961. * for example), this will succeed.
  962. */
  963. HANDLE hToken;
  964. SECURITY_IMPERSONATION_LEVEL secImpLevel = SecurityImpersonation;
  965. if (!(result = OpenThreadToken (GetCurrentThread (), TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_IMPERSONATE, true, &hToken)))
  966. {
  967. // No thread token - go for the Process token instead
  968. HANDLE hProcess = GetCurrentProcess ();
  969. result = OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_DUPLICATE, &hToken);
  970. CloseHandle (hProcess);
  971. }
  972. else
  973. {
  974. // We are working with a thread token
  975. hThreadToken = hToken;
  976. // Try and get the impersonation level of this token
  977. DWORD dwReturnLength = 0;
  978. BOOL thisRes = GetTokenInformation (hToken, TokenImpersonationLevel, &secImpLevel,
  979. sizeof (SECURITY_IMPERSONATION_LEVEL), &dwReturnLength);
  980. }
  981. if (result)
  982. {
  983. /*
  984. * Getting here means we have a valid token, be it process or thread. We
  985. * now attempt to duplicate it before Adjusting the Privileges.
  986. */
  987. #ifdef WSCRPDEBUG
  988. PrintPrivileges (hToken);
  989. #endif
  990. HANDLE hDupToken;
  991. EnterCriticalSection (&g_csSecurity);
  992. result = s_pfnDuplicateTokenEx &&
  993. s_pfnDuplicateTokenEx (hToken, TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES|TOKEN_IMPERSONATE, NULL,
  994. secImpLevel, TokenImpersonation, &hDupToken);
  995. LeaveCriticalSection (&g_csSecurity);
  996. if (result)
  997. {
  998. CSWbemSecurity::AdjustTokenPrivileges (hDupToken, m_pPrivilegeSet);
  999. // Now use this token on the current thread
  1000. if (SetThreadToken(NULL, hDupToken))
  1001. {
  1002. needToResetSecurity = true;
  1003. #ifdef WSCRPDEBUG
  1004. CSWbemSecurity::PrintPrivileges (hDupToken);
  1005. #endif
  1006. // Reset the blanket for the benefit of RPC
  1007. DWORD dwAuthnLevel, dwImpLevel;
  1008. if (S_OK == GetAuthImp (m_pCurProxy, &dwAuthnLevel, &dwImpLevel))
  1009. {
  1010. // Force the cache to resecure the proxy
  1011. IUnknown *pNewProxy = m_pProxyCache->GetProxy
  1012. ((WbemAuthenticationLevelEnum) dwAuthnLevel,
  1013. (WbemImpersonationLevelEnum) dwImpLevel, true);
  1014. if (pNewProxy)
  1015. {
  1016. if (m_pCurProxy)
  1017. m_pCurProxy->Release ();
  1018. m_pCurProxy = pNewProxy;
  1019. }
  1020. }
  1021. }
  1022. CloseHandle (hDupToken);
  1023. }
  1024. else
  1025. {
  1026. lastErr = GetLastError ();
  1027. }
  1028. /*
  1029. * If we are not using a thread token, close the token now. Otherwise
  1030. * the handle will be closed in the balanced call to RestorePrivileges ().
  1031. */
  1032. if (!hThreadToken)
  1033. CloseHandle (hToken);
  1034. }
  1035. }
  1036. else
  1037. {
  1038. // For NT4 we adjust the privileges in the process token
  1039. HANDLE hProcessToken = NULL;
  1040. HANDLE hProcess = GetCurrentProcess ();
  1041. result = OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hProcessToken);
  1042. CloseHandle (hProcess);
  1043. // Adjust privilege on the process
  1044. if (result)
  1045. {
  1046. #ifdef WSCRPDEBUG
  1047. CSWbemSecurity::PrintPrivileges (hProcessToken);
  1048. #endif
  1049. CSWbemSecurity::AdjustTokenPrivileges (hProcessToken, m_pPrivilegeSet);
  1050. #ifdef WSCRPDEBUG
  1051. CSWbemSecurity::PrintPrivileges (hProcessToken);
  1052. #endif
  1053. CloseHandle (hProcessToken);
  1054. }
  1055. }
  1056. }
  1057. }
  1058. }
  1059. }
  1060. return result;
  1061. }
  1062. //***************************************************************************
  1063. //
  1064. // SCODE CSWbemSecurity::ResetSecurity
  1065. //
  1066. // DESCRIPTION:
  1067. //
  1068. // Restore Privileges on the Thread Token.
  1069. //
  1070. //***************************************************************************
  1071. void CSWbemSecurity::ResetSecurity (
  1072. HANDLE hThreadToken
  1073. )
  1074. {
  1075. // Win9x has no security palaver
  1076. if (IsNT ())
  1077. {
  1078. /*
  1079. * Set the supplied token (which may be NULL) into
  1080. * the current thread.
  1081. */
  1082. BOOL result = SetThreadToken (NULL, hThreadToken);
  1083. DWORD error = 0;
  1084. if (!result)
  1085. error = GetLastError ();
  1086. #ifdef WSCRPDEBUG
  1087. // Print out the current privileges to see what's changed
  1088. HANDLE hToken = NULL;
  1089. if (!OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, false, &hToken))
  1090. {
  1091. // No thread token - go for the Process token instead
  1092. HANDLE hProcess = GetCurrentProcess ();
  1093. OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
  1094. CloseHandle (hProcess);
  1095. }
  1096. if (hToken)
  1097. {
  1098. PrintPrivileges (hToken);
  1099. CloseHandle (hToken);
  1100. }
  1101. #endif
  1102. if (hThreadToken)
  1103. CloseHandle (hThreadToken);
  1104. }
  1105. }
  1106. bool CSWbemSecurity::IsImpersonating (bool useDefaultUser, bool useDefaultAuthority)
  1107. {
  1108. bool result = false;
  1109. if (useDefaultUser && useDefaultAuthority && CSWbemSecurity::IsNT () &&
  1110. (4 < CSWbemSecurity::GetNTMajorVersion ()))
  1111. {
  1112. // A suitable candidate - find out if we are running on an impersonated thread
  1113. HANDLE hThreadToken = NULL;
  1114. if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, true, &hThreadToken))
  1115. {
  1116. // Check we have an impersonation token
  1117. SECURITY_IMPERSONATION_LEVEL secImpLevel;
  1118. DWORD dwReturnLength = 0;
  1119. if (GetTokenInformation (hThreadToken, TokenImpersonationLevel, &secImpLevel,
  1120. sizeof (SECURITY_IMPERSONATION_LEVEL), &dwReturnLength))
  1121. result = ((SecurityImpersonation == secImpLevel) || (SecurityDelegation == secImpLevel));
  1122. CloseHandle (hThreadToken);
  1123. }
  1124. }
  1125. return result;
  1126. }
  1127. HRESULT CSWbemSecurity::GetAuthority (BSTR *bsAuthority)
  1128. {
  1129. HRESULT hr = WBEM_E_FAILED;
  1130. if (m_pProxyCache)
  1131. {
  1132. *bsAuthority = SysAllocString(m_pProxyCache->GetAuthority ());
  1133. hr = S_OK;
  1134. }
  1135. return hr;
  1136. }
  1137. HRESULT CSWbemSecurity::GetUPD (BSTR *bsUser, BSTR *bsPassword, BSTR *bsDomain)
  1138. {
  1139. HRESULT hr = WBEM_E_FAILED;
  1140. if (m_pProxyCache)
  1141. {
  1142. COAUTHIDENTITY *pCoAuthIdentity = m_pProxyCache->GetCoAuthIdentity ();
  1143. if (pCoAuthIdentity)
  1144. {
  1145. *bsUser = SysAllocString (pCoAuthIdentity->User);
  1146. *bsPassword = SysAllocString (pCoAuthIdentity->Password);
  1147. *bsDomain = SysAllocString (pCoAuthIdentity->Domain);
  1148. WbemFreeAuthIdentity (pCoAuthIdentity);
  1149. }
  1150. hr = S_OK;
  1151. }
  1152. return hr;
  1153. }
  1154. HRESULT CSWbemSecurity::GetPrincipal (BSTR *bsPrincipal)
  1155. {
  1156. HRESULT hr = WBEM_E_FAILED;
  1157. if (m_pProxyCache)
  1158. {
  1159. *bsPrincipal = SysAllocString(m_pProxyCache->GetPrincipal ());
  1160. hr = S_OK;
  1161. }
  1162. return hr;
  1163. }
  1164. // CWbemLocatorSecurity methods
  1165. //***************************************************************************
  1166. //
  1167. // CSWbemLocatorSecurity::CSWbemLocatorSecurity
  1168. //
  1169. // CONSTRUCTOR
  1170. //
  1171. //***************************************************************************
  1172. CWbemLocatorSecurity::CWbemLocatorSecurity (CSWbemPrivilegeSet *pPrivilegeSet) :
  1173. m_cRef (1),
  1174. m_impLevelSet (false),
  1175. m_authnLevelSet (false),
  1176. m_pPrivilegeSet (NULL)
  1177. {
  1178. m_Dispatch.SetObj (this, IID_ISWbemSecurity,
  1179. CLSID_SWbemSecurity, L"SWbemSecurity");
  1180. InterlockedIncrement(&g_cObj);
  1181. if (pPrivilegeSet)
  1182. m_pPrivilegeSet = new CSWbemPrivilegeSet (*pPrivilegeSet);
  1183. else
  1184. m_pPrivilegeSet = new CSWbemPrivilegeSet;
  1185. }
  1186. CWbemLocatorSecurity::CWbemLocatorSecurity (CWbemLocatorSecurity *pCWbemLocatorSecurity) :
  1187. m_cRef (1),
  1188. m_impLevelSet (false),
  1189. m_authnLevelSet (false),
  1190. m_pPrivilegeSet (NULL)
  1191. {
  1192. m_Dispatch.SetObj (this, IID_ISWbemSecurity,
  1193. CLSID_SWbemSecurity, L"SWbemSecurity");
  1194. InterlockedIncrement(&g_cObj);
  1195. if (pCWbemLocatorSecurity)
  1196. {
  1197. m_pPrivilegeSet = new CSWbemPrivilegeSet (pCWbemLocatorSecurity->m_pPrivilegeSet);
  1198. m_impLevelSet = pCWbemLocatorSecurity->m_impLevelSet;
  1199. m_authnLevelSet = pCWbemLocatorSecurity->m_authnLevelSet;
  1200. if (m_impLevelSet)
  1201. m_impLevel = pCWbemLocatorSecurity->m_impLevel;
  1202. if (m_authnLevelSet)
  1203. m_authnLevel = pCWbemLocatorSecurity->m_authnLevel;
  1204. }
  1205. else
  1206. {
  1207. m_pPrivilegeSet = new CSWbemPrivilegeSet;
  1208. m_impLevelSet = false;
  1209. m_authnLevelSet = false;
  1210. }
  1211. }
  1212. //***************************************************************************
  1213. //
  1214. // CWbemLocatorSecurity::CWbemLocatorSecurity
  1215. //
  1216. // DESTRUCTOR
  1217. //
  1218. //***************************************************************************
  1219. CWbemLocatorSecurity::~CWbemLocatorSecurity (void)
  1220. {
  1221. InterlockedDecrement(&g_cObj);
  1222. if (m_pPrivilegeSet)
  1223. m_pPrivilegeSet->Release ();
  1224. }
  1225. //***************************************************************************
  1226. // HRESULT CWbemLocatorSecurity::QueryInterface
  1227. // long CWbemLocatorSecurity::AddRef
  1228. // long CWbemLocatorSecurity::Release
  1229. //
  1230. // DESCRIPTION:
  1231. //
  1232. // Standard Com IUNKNOWN functions.
  1233. //
  1234. //***************************************************************************
  1235. STDMETHODIMP CWbemLocatorSecurity::QueryInterface (
  1236. IN REFIID riid,
  1237. OUT LPVOID *ppv
  1238. )
  1239. {
  1240. *ppv=NULL;
  1241. if (IID_IUnknown==riid)
  1242. *ppv = reinterpret_cast<IUnknown*>(this);
  1243. else if (IID_ISWbemSecurity==riid)
  1244. *ppv = (ISWbemSecurity *)this;
  1245. else if (IID_IDispatch==riid)
  1246. *ppv = (IDispatch *)this;
  1247. else if (IID_ISupportErrorInfo==riid)
  1248. *ppv = (ISupportErrorInfo *)this;
  1249. else if (IID_IProvideClassInfo==riid)
  1250. *ppv = (IProvideClassInfo *)this;
  1251. if (NULL!=*ppv)
  1252. {
  1253. ((LPUNKNOWN)*ppv)->AddRef();
  1254. return NOERROR;
  1255. }
  1256. return ResultFromScode(E_NOINTERFACE);
  1257. }
  1258. STDMETHODIMP_(ULONG) CWbemLocatorSecurity::AddRef(void)
  1259. {
  1260. long l = InterlockedIncrement(&m_cRef);
  1261. return l;
  1262. }
  1263. STDMETHODIMP_(ULONG) CWbemLocatorSecurity::Release(void)
  1264. {
  1265. long l = InterlockedDecrement(&m_cRef);
  1266. if (0L!=l)
  1267. return l;
  1268. delete this;
  1269. return 0;
  1270. }
  1271. //***************************************************************************
  1272. // HRESULT CSWbemLocatorSecurity::InterfaceSupportsErrorInfo
  1273. //
  1274. // DESCRIPTION:
  1275. //
  1276. // Standard Com ISupportErrorInfo functions.
  1277. //
  1278. //***************************************************************************
  1279. STDMETHODIMP CWbemLocatorSecurity::InterfaceSupportsErrorInfo (IN REFIID riid)
  1280. {
  1281. return (IID_ISWbemSecurity == riid) ? S_OK : S_FALSE;
  1282. }
  1283. //***************************************************************************
  1284. //
  1285. // SCODE CWbemLocatorSecurity::get_AuthenticationLevel
  1286. //
  1287. // DESCRIPTION:
  1288. //
  1289. // Retrieve the authentication level
  1290. //
  1291. // PARAMETERS:
  1292. //
  1293. // pAuthenticationLevel holds the value on return
  1294. //
  1295. // RETURN VALUES:
  1296. //
  1297. // WBEM_S_NO_ERROR success
  1298. // WBEM_E_INVALID_PARAMETER bad input parameters
  1299. // WBEM_E_FAILED otherwise
  1300. //
  1301. //***************************************************************************
  1302. HRESULT CWbemLocatorSecurity::get_AuthenticationLevel (
  1303. WbemAuthenticationLevelEnum *pAuthenticationLevel
  1304. )
  1305. {
  1306. HRESULT hr = WBEM_E_FAILED;
  1307. ResetLastErrors ();
  1308. if (NULL == pAuthenticationLevel)
  1309. hr = WBEM_E_INVALID_PARAMETER;
  1310. else if (m_authnLevelSet)
  1311. {
  1312. *pAuthenticationLevel = m_authnLevel;
  1313. hr = WBEM_S_NO_ERROR;
  1314. }
  1315. if (FAILED(hr))
  1316. m_Dispatch.RaiseException (hr);
  1317. return hr;
  1318. }
  1319. //***************************************************************************
  1320. //
  1321. // SCODE CWbemLocatorSecurity::put_AuthenticationLevel
  1322. //
  1323. // DESCRIPTION:
  1324. //
  1325. // Set the authentication level
  1326. //
  1327. // PARAMETERS:
  1328. //
  1329. // authenticationLevel the new value
  1330. //
  1331. // RETURN VALUES:
  1332. //
  1333. // WBEM_S_NO_ERROR success
  1334. // WBEM_E_INVALID_PARAMETER bad input parameters
  1335. // WBEM_E_FAILED otherwise
  1336. //
  1337. //***************************************************************************
  1338. HRESULT CWbemLocatorSecurity::put_AuthenticationLevel (
  1339. WbemAuthenticationLevelEnum authenticationLevel
  1340. )
  1341. {
  1342. HRESULT hr = WBEM_E_FAILED;
  1343. ResetLastErrors ();
  1344. if ((WBEMS_MIN_AUTHN_LEVEL > authenticationLevel) ||
  1345. (WBEMS_MAX_AUTHN_LEVEL < authenticationLevel))
  1346. hr = WBEM_E_INVALID_PARAMETER;
  1347. else
  1348. {
  1349. m_authnLevel = authenticationLevel;
  1350. m_authnLevelSet = true;
  1351. hr = WBEM_S_NO_ERROR;
  1352. }
  1353. if (FAILED(hr))
  1354. m_Dispatch.RaiseException (hr);
  1355. return hr;
  1356. }
  1357. //***************************************************************************
  1358. //
  1359. // SCODE CWbemLocatorSecurity::get_ImpersonationLevel
  1360. //
  1361. // DESCRIPTION:
  1362. //
  1363. // Retrieve the impersonation level
  1364. //
  1365. // PARAMETERS:
  1366. //
  1367. // pImpersonationLevel holds the value on return
  1368. //
  1369. // RETURN VALUES:
  1370. //
  1371. // WBEM_S_NO_ERROR success
  1372. // WBEM_E_INVALID_PARAMETER bad input parameters
  1373. // WBEM_E_FAILED otherwise
  1374. //
  1375. //***************************************************************************
  1376. HRESULT CWbemLocatorSecurity::get_ImpersonationLevel (
  1377. WbemImpersonationLevelEnum *pImpersonationLevel
  1378. )
  1379. {
  1380. HRESULT hr = WBEM_E_FAILED;
  1381. ResetLastErrors ();
  1382. if (NULL == pImpersonationLevel)
  1383. hr = WBEM_E_INVALID_PARAMETER;
  1384. else if (m_impLevelSet)
  1385. {
  1386. *pImpersonationLevel = m_impLevel;
  1387. hr = WBEM_S_NO_ERROR;
  1388. }
  1389. if (FAILED(hr))
  1390. m_Dispatch.RaiseException (hr);
  1391. return hr;
  1392. }
  1393. //***************************************************************************
  1394. //
  1395. // SCODE CWbemLocatorSecurity::put_ImpersonationLevel
  1396. //
  1397. // DESCRIPTION:
  1398. //
  1399. // Set the impersonation level
  1400. //
  1401. // PARAMETERS:
  1402. //
  1403. // impersonationLevel the new value
  1404. //
  1405. // RETURN VALUES:
  1406. //
  1407. // WBEM_S_NO_ERROR success
  1408. // WBEM_E_INVALID_PARAMETER bad input parameters
  1409. // WBEM_E_FAILED otherwise
  1410. //
  1411. //***************************************************************************
  1412. HRESULT CWbemLocatorSecurity::put_ImpersonationLevel (
  1413. WbemImpersonationLevelEnum impersonationLevel
  1414. )
  1415. {
  1416. HRESULT hr = WBEM_E_FAILED;
  1417. ResetLastErrors ();
  1418. if ((WBEMS_MIN_IMP_LEVEL > impersonationLevel) || (WBEMS_MAX_IMP_LEVEL < impersonationLevel))
  1419. hr = WBEM_E_INVALID_PARAMETER;
  1420. else
  1421. {
  1422. m_impLevel = impersonationLevel;
  1423. m_impLevelSet = true;
  1424. hr = WBEM_S_NO_ERROR;
  1425. }
  1426. if (FAILED(hr))
  1427. m_Dispatch.RaiseException (hr);
  1428. return hr;
  1429. }
  1430. //***************************************************************************
  1431. //
  1432. // SCODE CWbemLocatorSecurity::get_Privileges
  1433. //
  1434. // DESCRIPTION:
  1435. //
  1436. // Return the Privilege override set
  1437. //
  1438. // WBEM_S_NO_ERROR success
  1439. // WBEM_E_INVALID_PARAMETER bad input parameters
  1440. // WBEM_E_FAILED otherwise
  1441. //
  1442. //***************************************************************************
  1443. HRESULT CWbemLocatorSecurity::get_Privileges (
  1444. ISWbemPrivilegeSet **ppPrivileges
  1445. )
  1446. {
  1447. HRESULT hr = WBEM_E_FAILED;
  1448. ResetLastErrors ();
  1449. if (NULL == ppPrivileges)
  1450. hr = WBEM_E_INVALID_PARAMETER;
  1451. {
  1452. *ppPrivileges = NULL;
  1453. if (m_pPrivilegeSet)
  1454. {
  1455. if (SUCCEEDED (m_pPrivilegeSet->QueryInterface (IID_ISWbemPrivilegeSet,
  1456. (PPVOID) ppPrivileges)))
  1457. hr = WBEM_S_NO_ERROR;
  1458. }
  1459. }
  1460. if (FAILED(hr))
  1461. m_Dispatch.RaiseException (hr);
  1462. return hr;
  1463. }
  1464. //***************************************************************************
  1465. //
  1466. // SCODE CWbemLocatorSecurity::SetSecurity
  1467. //
  1468. // DESCRIPTION:
  1469. //
  1470. // Set Privileges on the Process Token.
  1471. //
  1472. //***************************************************************************
  1473. BOOL CWbemLocatorSecurity::SetSecurity (
  1474. BSTR bsUser,
  1475. bool &needToResetSecurity,
  1476. HANDLE &hThreadToken
  1477. )
  1478. {
  1479. BOOL result = TRUE;
  1480. needToResetSecurity = false;
  1481. hThreadToken = NULL;
  1482. /*
  1483. * NT5 supports the concept of dynamic cloaking, which means
  1484. * we can set privileges temporarily on a thread (impersonation)
  1485. * token basis immediately before a call to a remoted proxy.
  1486. *
  1487. * Setting prior to locator.connectserver therefore makes no
  1488. * sense for NT5.
  1489. *
  1490. * Oh and Win9x has no security support
  1491. */
  1492. if (CSWbemSecurity::IsNT () && (4 >= CSWbemSecurity::GetNTMajorVersion ()))
  1493. {
  1494. /*
  1495. * Start by checking whether we are being impersonated. On an NT4
  1496. * box (which has no cloaking, and therefore cannot allow us to
  1497. * pass on this impersonation to Winmgmt) we should RevertToSelf
  1498. * if we have been configured to allow this. If we haven't been
  1499. * configured to allow this, bail out now.
  1500. */
  1501. if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY|TOKEN_IMPERSONATE, false, &hThreadToken))
  1502. {
  1503. // We are being impersonated
  1504. if (CSWbemSecurity::CanRevertToSelf ())
  1505. {
  1506. if (result = RevertToSelf())
  1507. needToResetSecurity = true;
  1508. }
  1509. else
  1510. {
  1511. // Error - cannot do this! Time to bail out
  1512. CloseHandle (hThreadToken);
  1513. hThreadToken = NULL;
  1514. result = FALSE;
  1515. }
  1516. }
  1517. if (result && m_pPrivilegeSet)
  1518. {
  1519. /*
  1520. * Specifying a user only makes sense for remote operations, and we
  1521. * don't need to mess with privilege for remote operations since
  1522. * they are set up by server logon anyway.
  1523. */
  1524. if (!bsUser || (0 == wcslen(bsUser)))
  1525. {
  1526. // Nothing to do unless some privilege overrides have been set
  1527. long lCount = 0;
  1528. m_pPrivilegeSet->get_Count (&lCount);
  1529. if (0 < lCount)
  1530. {
  1531. /*
  1532. * For NT4 privilege settings on impersonation tokens are ignored
  1533. * by DCOM/RPC. Hence we have to set this on the process token.
  1534. *
  1535. * On NT4 we must set the configured privileges on the Process
  1536. * Token before the first call to RPC (i.e. IWbemLocator::ConnectServer)
  1537. * if we need to guarantee privilege settings will be communicated to
  1538. * the server.
  1539. *
  1540. * This is because (a) NT4 does not support cloaking to allow the
  1541. * impersonation (i.e. thread) token privilege setting to propagate
  1542. * on a per-DCOM call basis, (b) changes to Process-token level
  1543. * privileges _may_ be ignored after the first remote DCOM call due
  1544. * to RPC caching behavior.
  1545. *
  1546. * Note that this is a non-reversible operation, and is highly discouraged
  1547. * on apps (such as IE and IIS) which host multiple "tasks" since it adjusts
  1548. * the Privilege set for all of the other threads in the process.
  1549. */
  1550. HANDLE hProcess = GetCurrentProcess ();
  1551. HANDLE hProcessToken = NULL;
  1552. result = OpenProcessToken(hProcess, TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hProcessToken);
  1553. CloseHandle (hProcess);
  1554. if (result)
  1555. {
  1556. #ifdef WSCRPDEBUG
  1557. CSWbemSecurity::PrintPrivileges (hProcessToken);
  1558. #endif
  1559. CSWbemSecurity::AdjustTokenPrivileges (hProcessToken, m_pPrivilegeSet);
  1560. #ifdef WSCRPDEBUG
  1561. CSWbemSecurity::PrintPrivileges (hProcessToken);
  1562. #endif
  1563. CloseHandle (hProcessToken);
  1564. }
  1565. }
  1566. }
  1567. }
  1568. }
  1569. return result;
  1570. }
  1571. //***************************************************************************
  1572. //
  1573. // SCODE CWbemLocatorSecurity::ResetSecurity
  1574. //
  1575. // DESCRIPTION:
  1576. //
  1577. // Restore Privileges on the Thread Token.
  1578. //
  1579. //***************************************************************************
  1580. void CWbemLocatorSecurity::ResetSecurity (
  1581. HANDLE hThreadToken
  1582. )
  1583. {
  1584. // Win9x has no concept of impersonation
  1585. // On NT5 we never set privileges through this class anyway
  1586. if (CSWbemSecurity::IsNT () && (4 >= CSWbemSecurity::GetNTMajorVersion ())
  1587. && hThreadToken)
  1588. {
  1589. /*
  1590. * Set the supplied token back into
  1591. * the current thread.
  1592. */
  1593. BOOL result = SetThreadToken (NULL, hThreadToken);
  1594. #ifdef WSCRPDEBUG
  1595. // Print out the current privileges to see what's changed
  1596. HANDLE hToken = NULL;
  1597. if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, false, &hToken))
  1598. {
  1599. // No thread token - go for the Process token instead
  1600. HANDLE hProcess = GetCurrentProcess ();
  1601. OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
  1602. CloseHandle (hProcess);
  1603. }
  1604. if (hToken)
  1605. {
  1606. CSWbemSecurity::PrintPrivileges (hToken);
  1607. CloseHandle (hToken);
  1608. }
  1609. #endif
  1610. CloseHandle (hThreadToken);
  1611. }
  1612. }
  1613. #ifdef WSCRPDEBUG
  1614. //***************************************************************************
  1615. //
  1616. // SCODE CSWbemSecurity::PrintPrivileges
  1617. //
  1618. // DESCRIPTION:
  1619. //
  1620. // Debug logging for privileges and other token info
  1621. //
  1622. //***************************************************************************
  1623. void CSWbemSecurity::PrintPrivileges (HANDLE hToken)
  1624. {
  1625. DWORD dwSize = sizeof (TOKEN_PRIVILEGES);
  1626. TOKEN_PRIVILEGES *tp = (TOKEN_PRIVILEGES *) new BYTE [dwSize];
  1627. if (!tp)
  1628. {
  1629. return;
  1630. }
  1631. DWORD dwRequiredSize = 0;
  1632. DWORD dwLastError = 0;
  1633. FILE *fDebug = fopen ("C:/temp/wmidsec.txt", "a+");
  1634. fprintf (fDebug, "\n\n***********************************************\n\n");
  1635. bool status = false;
  1636. // Step 0 - get impersonation level
  1637. SECURITY_IMPERSONATION_LEVEL secImpLevel;
  1638. if (GetTokenInformation (hToken, TokenImpersonationLevel, &secImpLevel,
  1639. sizeof (SECURITY_IMPERSONATION_LEVEL), &dwRequiredSize))
  1640. {
  1641. switch (secImpLevel)
  1642. {
  1643. case SecurityAnonymous:
  1644. fprintf (fDebug, "IMPERSONATION LEVEL: Anonymous\n");
  1645. break;
  1646. case SecurityIdentification:
  1647. fprintf (fDebug, "IMPERSONATION LEVEL: Identification\n");
  1648. break;
  1649. case SecurityImpersonation:
  1650. fprintf (fDebug, "IMPERSONATION LEVEL: Impersonation\n");
  1651. break;
  1652. case SecurityDelegation:
  1653. fprintf (fDebug, "IMPERSONATION LEVEL: Delegation\n");
  1654. break;
  1655. default:
  1656. fprintf (fDebug, "IMPERSONATION LEVEL: Unknown!\n");
  1657. break;
  1658. }
  1659. fflush (fDebug);
  1660. }
  1661. DWORD dwUSize = sizeof (TOKEN_USER);
  1662. TOKEN_USER *tu = (TOKEN_USER *) new BYTE [dwUSize];
  1663. if (!tu)
  1664. {
  1665. delete [] tp;
  1666. fclose (fDebug);
  1667. return;
  1668. }
  1669. // Step 1 - get user info
  1670. if (0 == GetTokenInformation (hToken, TokenUser,
  1671. (LPVOID) tu, dwUSize, &dwRequiredSize))
  1672. {
  1673. delete [] tu;
  1674. dwUSize = dwRequiredSize;
  1675. dwRequiredSize = 0;
  1676. tu = (TOKEN_USER *) new BYTE [dwUSize];
  1677. if (!tu)
  1678. {
  1679. delete [] tp;
  1680. fclose (fDebug);
  1681. return;
  1682. }
  1683. if (!GetTokenInformation (hToken, TokenUser, (LPVOID) tu, dwUSize,
  1684. &dwRequiredSize))
  1685. dwLastError = GetLastError ();
  1686. else
  1687. status = true;
  1688. }
  1689. if (status)
  1690. {
  1691. // Dig out the user info
  1692. dwRequiredSize = BUFSIZ;
  1693. char *userName = new char [dwRequiredSize];
  1694. char *domainName = new char [dwRequiredSize];
  1695. if (!userName || !domainName)
  1696. {
  1697. delete [] tp;
  1698. delete [] tu;
  1699. delete [] userName;
  1700. delete [] domainName;
  1701. return;
  1702. }
  1703. SID_NAME_USE eUse;
  1704. LookupAccountSid (NULL, (tu->User).Sid, userName, &dwRequiredSize,
  1705. domainName, &dwRequiredSize, &eUse);
  1706. fprintf (fDebug, "USER: [%s\\%s]\n", domainName, userName);
  1707. fflush (fDebug);
  1708. delete [] userName;
  1709. delete [] domainName;
  1710. }
  1711. else
  1712. {
  1713. fprintf (fDebug, " FAILED : %d\n", dwLastError);
  1714. fflush (fDebug);
  1715. }
  1716. delete [] tu;
  1717. status = false;
  1718. dwRequiredSize = 0;
  1719. // Step 2 - get privilege info
  1720. if (0 == GetTokenInformation (hToken, TokenPrivileges,
  1721. (LPVOID) tp, dwSize, &dwRequiredSize))
  1722. {
  1723. delete [] tp;
  1724. dwSize = dwRequiredSize;
  1725. dwRequiredSize = 0;
  1726. tp = (TOKEN_PRIVILEGES *) new BYTE [dwSize];
  1727. if (!tp)
  1728. {
  1729. fclose (fDebug);
  1730. return;
  1731. }
  1732. if (!GetTokenInformation (hToken, TokenPrivileges,
  1733. (LPVOID) tp, dwSize, &dwRequiredSize))
  1734. {
  1735. dwLastError = GetLastError ();
  1736. }
  1737. else
  1738. status = true;
  1739. }
  1740. else
  1741. status = true;
  1742. if (status)
  1743. {
  1744. fprintf (fDebug, "PRIVILEGES: [%d]\n", tp->PrivilegeCount);
  1745. fflush (fDebug);
  1746. for (DWORD i = 0; i < tp->PrivilegeCount; i++)
  1747. {
  1748. DWORD dwNameSize = 256;
  1749. LPTSTR name = new TCHAR [dwNameSize + 1];
  1750. if (!name)
  1751. {
  1752. delete [] tp;
  1753. fclose (fDebug);
  1754. return;
  1755. }
  1756. DWORD dwRequiredSize = dwNameSize;
  1757. if (LookupPrivilegeName (NULL, &(tp->Privileges [i].Luid), name, &dwRequiredSize))
  1758. {
  1759. BOOL enabDefault = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT);
  1760. BOOL enabled = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED);
  1761. BOOL usedForAccess (tp->Privileges [i].Attributes & SE_PRIVILEGE_USED_FOR_ACCESS);
  1762. fprintf (fDebug, " %s: enabledByDefault=%d enabled=%d usedForAccess=%d\n",
  1763. name, enabDefault, enabled, usedForAccess);
  1764. fflush (fDebug);
  1765. }
  1766. else
  1767. {
  1768. dwLastError = GetLastError ();
  1769. delete [] name;
  1770. dwNameSize = dwRequiredSize;
  1771. name = new TCHAR [dwRequiredSize];
  1772. if (!name)
  1773. {
  1774. delete [] tp;
  1775. fclose (fDebug);
  1776. return;
  1777. }
  1778. if (LookupPrivilegeName (NULL, &(tp->Privileges [i].Luid), name, &dwRequiredSize))
  1779. {
  1780. BOOL enabDefault = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT);
  1781. BOOL enabled = (tp->Privileges [i].Attributes & SE_PRIVILEGE_ENABLED);
  1782. BOOL usedForAccess (tp->Privileges [i].Attributes & SE_PRIVILEGE_USED_FOR_ACCESS);
  1783. fprintf (fDebug, " %s: enabledByDefault=%d enabled=%d usedForAccess=%d\n",
  1784. name, enabDefault, enabled, usedForAccess);
  1785. fflush (fDebug);
  1786. }
  1787. else
  1788. dwLastError = GetLastError ();
  1789. }
  1790. delete [] name;
  1791. }
  1792. }
  1793. else
  1794. {
  1795. fprintf (fDebug, " FAILED : %d\n", dwLastError);
  1796. fflush (fDebug);
  1797. }
  1798. delete [] tp;
  1799. fclose (fDebug);
  1800. }
  1801. #endif