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.

609 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. /////////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Microsoft Windows
  5. // Copyright (C) Microsoft Corporation, 1997-2001.
  6. //
  7. // File: ComponentDataRSOP.cpp
  8. //
  9. // Contents: Implementation of RSOP portions CCertMgrComponentData
  10. //
  11. //----------------------------------------------------------------------------
  12. #include "stdafx.h"
  13. #include <gpedit.h>
  14. #include "compdata.h"
  15. #include "dataobj.h"
  16. #include "cookie.h"
  17. #include "Certifct.h"
  18. #pragma warning(push, 3)
  19. #include <wintrust.h>
  20. #include <cryptui.h>
  21. #include <sceattch.h>
  22. #pragma warning(pop)
  23. #include "StoreRSOP.h"
  24. #ifdef _DEBUG
  25. #ifndef ALPHA
  26. #define new DEBUG_NEW
  27. #endif
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. //
  32. // CCertMgrComponentData
  33. //
  34. HRESULT CCertMgrComponentData::BuildWMIList (LPDATAOBJECT pDataObject, bool bIsComputer)
  35. {
  36. _TRACE (1, L"Entering CCertMgrComponentData::BuildWMIList (%s)\n", bIsComputer ? L"computer" : L"user");
  37. HRESULT hr = S_OK;
  38. #if DBG
  39. if ( bIsComputer )
  40. {
  41. _TRACE (0, L"m_rsopObjectArrayComputer contains %d objects\n",
  42. m_rsopObjectArrayComputer.GetUpperBound ());
  43. }
  44. else
  45. {
  46. _TRACE (0, L"m_rsopObjectArrayUser contains %d objects\n",
  47. m_rsopObjectArrayUser.GetUpperBound ());
  48. }
  49. #endif
  50. if ( bIsComputer )
  51. m_rsopObjectArrayComputer.RemoveAll ();
  52. else
  53. m_rsopObjectArrayUser.RemoveAll ();
  54. if ( ((bIsComputer && !m_pRSOPInformationComputer) ||
  55. (!bIsComputer && !m_pRSOPInformationUser) )
  56. && pDataObject )
  57. {
  58. IUnknown* pIUnknown = 0;
  59. hr = ExtractData (pDataObject,
  60. CCertMgrDataObject::m_CFSCE_RSOPUnknown,
  61. &pIUnknown, sizeof (IUnknown*));
  62. ASSERT (SUCCEEDED (hr));
  63. if ( SUCCEEDED (hr) )
  64. {
  65. if ( bIsComputer )
  66. {
  67. hr = pIUnknown->QueryInterface (
  68. IID_PPV_ARG (IRSOPInformation, &m_pRSOPInformationComputer));
  69. }
  70. else
  71. {
  72. hr = pIUnknown->QueryInterface (
  73. IID_PPV_ARG (IRSOPInformation, &m_pRSOPInformationUser));
  74. }
  75. ASSERT (SUCCEEDED (hr));
  76. if ( SUCCEEDED (hr) )
  77. {
  78. if ( bIsComputer )
  79. {
  80. hr = m_pRSOPInformationComputer->GetFlags (&m_dwRSOPFlagsComputer);
  81. }
  82. else
  83. {
  84. hr = m_pRSOPInformationUser->GetFlags (&m_dwRSOPFlagsUser);
  85. }
  86. ASSERT (SUCCEEDED (hr));
  87. int cchMaxLength = 512;
  88. LPOLESTR pszNameSpace = (LPOLESTR) LocalAlloc (LPTR, cchMaxLength * sizeof (WCHAR));
  89. if ( pszNameSpace )
  90. {
  91. DWORD dwSection = 0;
  92. switch (m_dwSCEMode)
  93. {
  94. case SCE_MODE_LOCAL_USER:
  95. case SCE_MODE_DOMAIN_USER:
  96. case SCE_MODE_OU_USER:
  97. case SCE_MODE_REMOTE_USER:
  98. case SCE_MODE_RSOP_USER:
  99. dwSection = GPO_SECTION_USER;
  100. break;
  101. case SCE_MODE_LOCAL_COMPUTER:
  102. case SCE_MODE_DOMAIN_COMPUTER:
  103. case SCE_MODE_OU_COMPUTER:
  104. case SCE_MODE_RSOP_COMPUTER:
  105. case SCE_MODE_REMOTE_COMPUTER:
  106. dwSection = GPO_SECTION_MACHINE;
  107. break;
  108. default:
  109. ASSERT (0);
  110. return E_UNEXPECTED;
  111. }
  112. if ( bIsComputer )
  113. {
  114. hr = m_pRSOPInformationComputer->GetNamespace (
  115. dwSection,
  116. pszNameSpace,
  117. cchMaxLength);
  118. }
  119. else
  120. {
  121. hr = m_pRSOPInformationUser->GetNamespace (
  122. dwSection,
  123. pszNameSpace,
  124. cchMaxLength);
  125. }
  126. if ( SUCCEEDED (hr) )
  127. {
  128. IWbemLocator *pIWbemLocator = 0;
  129. hr = CoCreateInstance (CLSID_WbemLocator,
  130. NULL,
  131. CLSCTX_INPROC_SERVER,
  132. IID_PPV_ARG(IWbemLocator, &pIWbemLocator));
  133. if ( SUCCEEDED (hr) )
  134. {
  135. BSTR bstrNameSpace = SysAllocString (pszNameSpace);
  136. if ( bstrNameSpace )
  137. {
  138. if ( bIsComputer )
  139. {
  140. hr = pIWbemLocator->ConnectServer (bstrNameSpace,
  141. NULL, NULL, 0, 0, NULL, NULL,
  142. &m_pIWbemServicesComputer);
  143. }
  144. else
  145. {
  146. hr = pIWbemLocator->ConnectServer (bstrNameSpace,
  147. NULL, NULL, 0, 0, NULL, NULL,
  148. &m_pIWbemServicesUser);
  149. }
  150. if ( FAILED (hr) )
  151. {
  152. _TRACE (0, L"IWbemLocator::ConnectServer (%s) failed: 0x%x(%s)\n",
  153. bstrNameSpace, hr, (PCWSTR) GetSystemMessage (hr));
  154. }
  155. SysFreeString (bstrNameSpace);
  156. }
  157. else
  158. hr = E_OUTOFMEMORY;
  159. pIWbemLocator->Release ();
  160. }
  161. }
  162. LocalFree (pszNameSpace);
  163. }
  164. else
  165. hr = E_OUTOFMEMORY;
  166. }
  167. }
  168. }
  169. if ( SUCCEEDED (hr) && ((bIsComputer && m_pIWbemServicesComputer) ||
  170. (!bIsComputer && m_pIWbemServicesUser)) )
  171. {
  172. IEnumWbemClassObject * pEnum = 0;
  173. IWbemClassObject *pObject = 0;
  174. ULONG ulRet = 0;
  175. //
  176. // Execute the query
  177. //
  178. if ( bIsComputer )
  179. {
  180. hr = m_pIWbemServicesComputer->ExecQuery (m_pbstrLanguage, m_pbstrQuery,
  181. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  182. NULL, &pEnum);
  183. }
  184. else
  185. {
  186. hr = m_pIWbemServicesUser->ExecQuery (m_pbstrLanguage, m_pbstrQuery,
  187. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  188. NULL, &pEnum);
  189. }
  190. if ( SUCCEEDED (hr) )
  191. {
  192. //
  193. // Loop through the results retrieving the registry key and value names
  194. //
  195. while ( (hr = pEnum->Next(WBEM_INFINITE, 1, &pObject, &ulRet)) == WBEM_S_NO_ERROR )
  196. {
  197. hr = GetValuesAndInsertInRSOPObjectList (pObject,
  198. bIsComputer ? m_rsopObjectArrayComputer : m_rsopObjectArrayUser,
  199. bIsComputer);
  200. pObject->Release ();
  201. if ( FAILED (hr) )
  202. break;
  203. }
  204. pEnum->Release();
  205. #if DBG
  206. int nIndex = 0;
  207. INT_PTR nUpperBound = 0;
  208. if ( bIsComputer )
  209. nUpperBound = m_rsopObjectArrayComputer.GetUpperBound ();
  210. else
  211. nUpperBound = m_rsopObjectArrayUser.GetUpperBound ();
  212. while ( nUpperBound >= nIndex )
  213. {
  214. CRSOPObject* pCurrObject = 0;
  215. if ( bIsComputer )
  216. pCurrObject = m_rsopObjectArrayComputer.GetAt (nIndex);
  217. else
  218. pCurrObject = m_rsopObjectArrayUser.GetAt (nIndex);
  219. if ( !pCurrObject )
  220. break;
  221. _TRACE (0, L"\t%d\t%s\t%s\n", pCurrObject->GetPrecedence (),
  222. (PCWSTR) pCurrObject->GetRegistryKey (),
  223. (PCWSTR) pCurrObject->GetValueName ());
  224. nIndex++;
  225. }
  226. #endif
  227. }
  228. }
  229. _TRACE (-1, L"Leaving CCertMgrComponentData::BuildWMIList (): 0x%x\n", hr);
  230. return hr;
  231. }
  232. HRESULT CCertMgrComponentData::GetValuesAndInsertInRSOPObjectList (
  233. IWbemClassObject* pObject,
  234. CRSOPObjectArray& rRsopObjectArray,
  235. bool bIsComputer)
  236. {
  237. HRESULT hr = S_OK;
  238. if ( !pObject )
  239. return E_POINTER;
  240. //
  241. // Check if the allocations succeeded
  242. //
  243. if ( m_pbstrLanguage && m_pbstrQuery && m_pbstrRegistryKey &&
  244. m_pbstrValueName && m_pbstrValue &&
  245. m_pbstrPrecedence && m_pbstrGPOid )
  246. {
  247. COleVariant varRegistryKey;
  248. COleVariant varValueName;
  249. COleVariant varValue;
  250. COleVariant varPrecedence;
  251. COleVariant varGPOid;
  252. hr = pObject->Get (m_pbstrRegistryKey, 0, &varRegistryKey, NULL, NULL);
  253. if (SUCCEEDED(hr))
  254. {
  255. hr = pObject->Get (m_pbstrValueName, 0, &varValueName, NULL, NULL);
  256. if (SUCCEEDED(hr))
  257. {
  258. hr = pObject->Get (m_pbstrValue, 0, &varValue, NULL, NULL);
  259. if (SUCCEEDED(hr))
  260. {
  261. //#ifndef DBG
  262. // only include objects that have a value name
  263. if ( varValueName.bstrVal[0] )
  264. //#endif
  265. {
  266. //#ifndef DBG
  267. // Only include those objects that are in the system store registry
  268. // path or in the cryptography\autoenrollment path
  269. if ( FoundInRSOPFilter (varRegistryKey.bstrVal) )
  270. //#endif
  271. {
  272. hr = pObject->Get (m_pbstrPrecedence, 0, &varPrecedence, NULL, NULL);
  273. if (SUCCEEDED(hr))
  274. {
  275. hr = pObject->Get (m_pbstrGPOid, 0, &varGPOid, NULL, NULL);
  276. if (SUCCEEDED(hr))
  277. {
  278. PWSTR lpGPOName = 0;
  279. hr = GetGPOFriendlyName (
  280. varGPOid.bstrVal,
  281. &lpGPOName,
  282. bIsComputer);
  283. if (SUCCEEDED(hr))
  284. {
  285. CRSOPObject* pRSOPObject = new CRSOPObject (
  286. varRegistryKey.bstrVal,
  287. varValueName.bstrVal,
  288. lpGPOName,
  289. varPrecedence.uintVal,
  290. varValue);
  291. if ( pRSOPObject )
  292. {
  293. CRSOPObject* pCurrObject = 0;
  294. int nIndex = 0;
  295. bool bInserted = false;
  296. INT_PTR nUpperBound = rRsopObjectArray.GetUpperBound ();
  297. while ( nUpperBound >= nIndex )
  298. {
  299. pCurrObject = rRsopObjectArray.GetAt (nIndex);
  300. if ( !pCurrObject )
  301. break;
  302. // Sort first by registry key name,
  303. // then by value name, then by
  304. // precedence
  305. int nCmpVal = wcscmp (pCurrObject->GetRegistryKey (),
  306. pRSOPObject->GetRegistryKey ());
  307. if ( nCmpVal > 0 )
  308. {
  309. rRsopObjectArray.InsertAt (nIndex, pRSOPObject);
  310. bInserted = true;
  311. break;
  312. }
  313. else if ( nCmpVal == 0 )
  314. {
  315. // Sort by value name
  316. nCmpVal = wcscmp (pCurrObject->GetValueName (),
  317. pRSOPObject->GetValueName ());
  318. if ( nCmpVal > 0 )
  319. {
  320. rRsopObjectArray.InsertAt (nIndex, pRSOPObject);
  321. bInserted = true;
  322. break;
  323. }
  324. else if ( nCmpVal == 0 )
  325. {
  326. // Sort by precedence
  327. if ( pCurrObject->GetPrecedence () >
  328. pRSOPObject->GetPrecedence () )
  329. {
  330. rRsopObjectArray.InsertAt (nIndex, pRSOPObject);
  331. bInserted = true;
  332. break;
  333. }
  334. else if ( pCurrObject->GetPrecedence () ==
  335. pRSOPObject->GetPrecedence () )
  336. {
  337. // The registry key, value name and precedence
  338. // are the same - this is a duplicate. Pretend
  339. // we've added it and move on.
  340. bInserted = true;
  341. break;
  342. }
  343. }
  344. }
  345. nIndex++;
  346. }
  347. if ( !bInserted )
  348. rRsopObjectArray.Add (pRSOPObject);
  349. }
  350. LocalFree (lpGPOName);
  351. }
  352. varGPOid.Clear ();
  353. }
  354. varPrecedence.Clear ();
  355. }
  356. }
  357. }
  358. varValue.Clear ();
  359. }
  360. varValueName.Clear ();
  361. }
  362. varRegistryKey.Clear ();
  363. }
  364. }
  365. else
  366. hr = E_OUTOFMEMORY;
  367. return hr;
  368. }
  369. HRESULT CCertMgrComponentData::GetGPOFriendlyName (PWSTR lpGPOID, PWSTR *pGPOName, bool bIsComputer)
  370. {
  371. BSTR pQuery = NULL, pName = NULL;
  372. LPTSTR lpQuery = NULL;
  373. IEnumWbemClassObject * pEnum = NULL;
  374. IWbemClassObject *pObjects[2];
  375. HRESULT hr;
  376. ULONG ulRet;
  377. VARIANT varGPOName;
  378. //
  379. // Set the default
  380. //
  381. *pGPOName = NULL;
  382. //
  383. // Build the query
  384. //
  385. lpQuery = (LPTSTR) LocalAlloc (LPTR, ((lstrlen(lpGPOID) + 50) * sizeof(TCHAR)));
  386. if (!lpQuery)
  387. {
  388. _TRACE (0, L"CCertMgrComponentData::GetGPOFriendlyName: Failed to allocate memory for unicode query");
  389. hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  390. goto Exit;
  391. }
  392. wsprintf (lpQuery, TEXT("SELECT name, id FROM RSOP_GPO where id=\"%s\""), lpGPOID);
  393. pQuery = SysAllocString (lpQuery);
  394. if (!pQuery)
  395. {
  396. _TRACE (0, L"CCertMgrComponentData::GetGPOFriendlyName: Failed to allocate memory for query");
  397. hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  398. goto Exit;
  399. }
  400. //
  401. // Allocate BSTRs for the property names we want to retreive
  402. //
  403. pName = SysAllocString (TEXT("name"));
  404. if (!pName)
  405. {
  406. _TRACE (0, L"CCertMgrComponentData::GetGPOFriendlyName: Failed to allocate memory for name");
  407. hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  408. goto Exit;
  409. }
  410. //
  411. // Execute the query
  412. //
  413. if ( bIsComputer )
  414. {
  415. hr = m_pIWbemServicesComputer->ExecQuery (m_pbstrLanguage, pQuery,
  416. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  417. NULL, &pEnum);
  418. }
  419. else
  420. {
  421. hr = m_pIWbemServicesUser->ExecQuery (m_pbstrLanguage, pQuery,
  422. WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
  423. NULL, &pEnum);
  424. }
  425. if (FAILED(hr))
  426. {
  427. _TRACE (0, L"CCertMgrComponentData::GetGPOFriendlyName: Failed to query for %s with 0x%x\n",
  428. pQuery, hr);
  429. goto Exit;
  430. }
  431. //
  432. // Loop through the results
  433. //
  434. hr = pEnum->Next(WBEM_INFINITE, 1, pObjects, &ulRet);
  435. if (FAILED(hr))
  436. {
  437. _TRACE (0, L"CCertMgrComponentData::GetGPOFriendlyName: Failed to get first item in query results for %s with 0x%x\n",
  438. pQuery, hr);
  439. goto Exit;
  440. }
  441. //
  442. // Check for the "data not available case"
  443. //
  444. if (ulRet == 0)
  445. {
  446. hr = S_OK;
  447. goto Exit;
  448. }
  449. //
  450. // Get the name
  451. //
  452. hr = pObjects[0]->Get (pName, 0, &varGPOName, NULL, NULL);
  453. if (FAILED(hr))
  454. {
  455. _TRACE (0, L"CCertMgrComponentData::GetGPOFriendlyName: Failed to get gponame in query results for %s with 0x%x\n",
  456. pQuery, hr);
  457. goto Exit;
  458. }
  459. //
  460. // Save the name
  461. //
  462. *pGPOName = (LPTSTR) LocalAlloc (LPTR, (lstrlen(varGPOName.bstrVal) + 1) * sizeof(TCHAR));
  463. if (!(*pGPOName))
  464. {
  465. _TRACE (0, L"CCertMgrComponentData::GetGPOFriendlyName: Failed to allocate memory for GPO Name");
  466. hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  467. goto Exit;
  468. }
  469. lstrcpy (*pGPOName, varGPOName.bstrVal);
  470. VariantClear (&varGPOName);
  471. hr = S_OK;
  472. Exit:
  473. if (pEnum)
  474. {
  475. pEnum->Release();
  476. }
  477. if (pQuery)
  478. {
  479. SysFreeString (pQuery);
  480. }
  481. if (lpQuery)
  482. {
  483. LocalFree (lpQuery);
  484. }
  485. if (pName)
  486. {
  487. SysFreeString (pName);
  488. }
  489. return hr;
  490. }
  491. ///////////////////////////////////////////////////////////////////////////////
  492. ///////////////////////////////////////////////////////////////////////////////
  493. bool CCertMgrPKPolExtension::FoundInRSOPFilter (BSTR bstrKey) const
  494. {
  495. static size_t nRegPathLen = wcslen (CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH);
  496. static size_t nTrustedPublisherKeyLen =
  497. wcslen (CERT_TRUST_PUB_SAFER_GROUP_POLICY_TRUSTED_PUBLISHER_STORE_REGPATH);
  498. static size_t nDisallowedKeyLen =
  499. wcslen (CERT_TRUST_PUB_SAFER_GROUP_POLICY_DISALLOWED_STORE_REGPATH);
  500. static size_t nSaferKeyLen = wcslen (SAFER_HKLM_REGBASE);
  501. static size_t nEFSKeyLen = wcslen (EFS_SETTINGS_REGPATH);
  502. //Include group policy system stores but not trusted publisher or disallowed
  503. if ( !_wcsnicmp (CERT_GROUP_POLICY_SYSTEM_STORE_REGPATH, bstrKey, nRegPathLen) &&
  504. (_wcsnicmp (CERT_TRUST_PUB_SAFER_GROUP_POLICY_TRUSTED_PUBLISHER_STORE_REGPATH,
  505. bstrKey, nTrustedPublisherKeyLen) &&
  506. _wcsnicmp (CERT_TRUST_PUB_SAFER_GROUP_POLICY_DISALLOWED_STORE_REGPATH,
  507. bstrKey, nDisallowedKeyLen)) )
  508. {
  509. return true;
  510. }
  511. else if ( !_wcsnicmp (SAFER_HKLM_REGBASE, bstrKey, nSaferKeyLen) ||
  512. !_wcsnicmp (EFS_SETTINGS_REGPATH, bstrKey, nEFSKeyLen) ||
  513. !_wcsicmp (AUTO_ENROLLMENT_KEY, bstrKey) )
  514. {
  515. return true;
  516. }
  517. else
  518. return false;
  519. }