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.

1000 lines
29 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. crypto.c
  5. Abstract:
  6. Implementation of crypto access.
  7. Author:
  8. Wesley Witt (wesw) 18-Dec-1998
  9. Revision History:
  10. Andrew Ritz (andrewr) 7-Jul-1999 : added comments
  11. --*/
  12. #include "sfcp.h"
  13. #pragma hdrstop
  14. typedef BOOL
  15. (WINAPI *PCRYPTCATADMINRESOLVECATALOGPATH)(
  16. IN HCATADMIN hCatAdmin,
  17. IN WCHAR *pwszCatalogFile,
  18. IN OUT CATALOG_INFO *psCatInfo,
  19. IN DWORD dwFlags
  20. );
  21. BOOL
  22. SfcRestoreSingleCatalog(
  23. IN PCWSTR CatalogName,
  24. IN PCWSTR CatalogFullPath
  25. );
  26. //
  27. // pointers to the crypto functions we call
  28. //
  29. PCRYPTCATADMINRESOLVECATALOGPATH pCryptCATAdminResolveCatalogPath;
  30. //
  31. // global system catalog guid we pass into WinVerifyTrust
  32. //
  33. GUID DriverVerifyGuid = DRIVER_ACTION_VERIFY;
  34. //
  35. // Specifies if crypto API is initialized
  36. //
  37. BOOL g_bCryptoInitialized = FALSE;
  38. NTSTATUS g_CryptoStatus = STATUS_SUCCESS;
  39. //
  40. // critical section to protect crypto initialization and exception packages file tree
  41. //
  42. RTL_CRITICAL_SECTION g_GeneralCS;
  43. BOOL
  44. MyCryptCATAdminResolveCatalogPath(
  45. IN HCATADMIN hCatAdmin,
  46. IN WCHAR *pwszCatalogFile,
  47. IN OUT CATALOG_INFO *psCatInfo,
  48. IN DWORD dwFlags
  49. )
  50. {
  51. ExpandEnvironmentStrings(
  52. L"%systemroot%\\system32\\catroot\\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}\\",
  53. psCatInfo->wszCatalogFile,
  54. MAX_PATH);
  55. wcscat(psCatInfo->wszCatalogFile,pwszCatalogFile);
  56. return TRUE;
  57. }
  58. BOOL
  59. SfcValidateSingleCatalog(
  60. IN PCWSTR CatalogNameFullPath
  61. )
  62. /*++
  63. Routine Description:
  64. Routine to determine if the specified system catalog has a valid signature.
  65. Arguments:
  66. CatalogNameFullPath - null terminated string indicating full path to
  67. catalog file to be validated
  68. Return Value:
  69. Win32 error code indicating outcome.
  70. --*/
  71. {
  72. ULONG SigErr = ERROR_SUCCESS;
  73. WINTRUST_DATA WintrustData;
  74. WINTRUST_FILE_INFO WintrustFileInfo;
  75. DRIVER_VER_INFO OsAttrVersionInfo;
  76. OSVERSIONINFO OsVersionInfo;
  77. ASSERT(CatalogNameFullPath != NULL);
  78. //
  79. // build up the structure to pass into winverifytrust
  80. //
  81. ZeroMemory( &WintrustData, sizeof(WINTRUST_DATA) );
  82. WintrustData.cbStruct = sizeof(WINTRUST_DATA);
  83. WintrustData.dwUIChoice = WTD_UI_NONE;
  84. WintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
  85. WintrustData.dwStateAction = WTD_STATEACTION_IGNORE;
  86. WintrustData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
  87. WintrustData.dwUnionChoice = WTD_CHOICE_FILE;
  88. WintrustData.pFile = &WintrustFileInfo;
  89. ZeroMemory( &WintrustFileInfo, sizeof(WINTRUST_FILE_INFO) );
  90. WintrustFileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO);
  91. WintrustFileInfo.pcwszFilePath = CatalogNameFullPath;
  92. //
  93. // Initialize the DRIVER_VER_INFO structure to validate
  94. // against 5.0 and 5.1 OSATTR
  95. //
  96. ZeroMemory( &OsVersionInfo, sizeof(OSVERSIONINFO));
  97. OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  98. ZeroMemory(&OsAttrVersionInfo, sizeof(DRIVER_VER_INFO));
  99. OsAttrVersionInfo.cbStruct = sizeof(DRIVER_VER_INFO);
  100. OsAttrVersionInfo.dwPlatform = VER_PLATFORM_WIN32_NT;
  101. OsAttrVersionInfo.sOSVersionLow.dwMajor = 5;
  102. OsAttrVersionInfo.sOSVersionLow.dwMinor = 0;
  103. if (GetVersionEx(&OsVersionInfo)) {
  104. OsAttrVersionInfo.sOSVersionHigh.dwMajor = OsVersionInfo.dwMajorVersion;
  105. OsAttrVersionInfo.sOSVersionHigh.dwMinor = OsVersionInfo.dwMinorVersion;
  106. //Set this only if all went well
  107. WintrustData.pPolicyCallbackData = (LPVOID)(&OsAttrVersionInfo);
  108. }else{
  109. DebugPrint1( LVL_MINIMAL, L"Could not get OS Version while validating single catalog - GetVersionEx failed (%d)", GetLastError() );
  110. }
  111. //
  112. // call winverfifytrust to check signature
  113. //
  114. SigErr = (DWORD)WinVerifyTrust(
  115. NULL,
  116. &DriverVerifyGuid,
  117. &WintrustData
  118. );
  119. if(SigErr != ERROR_SUCCESS) {
  120. DebugPrint2(
  121. LVL_MINIMAL,
  122. L"WinVerifyTrust of catalog %s failed, ec=0x%08x",
  123. CatalogNameFullPath,
  124. SigErr );
  125. SetLastError(SigErr);
  126. return FALSE;
  127. }
  128. //
  129. // Free the pcSignerCertContext member of the DRIVER_VER_INFO struct
  130. // that was allocated in our call to WinVerifyTrust.
  131. //
  132. if (OsAttrVersionInfo.pcSignerCertContext != NULL) {
  133. CertFreeCertificateContext(OsAttrVersionInfo.pcSignerCertContext);
  134. OsAttrVersionInfo.pcSignerCertContext = NULL;
  135. }
  136. return TRUE;
  137. }
  138. BOOL
  139. SfcRestoreSingleCatalog(
  140. IN PCWSTR CatalogName,
  141. IN PCWSTR CatalogFullPath
  142. )
  143. /*++
  144. Routine Description:
  145. Routine to restore the specified catalog. The catalog must be reinstalled
  146. by calling the CryptCATAdminAddCatalog API (pSetupInstallCatalog is a wrapper
  147. for this API).
  148. Note that this function may block if a user is not currently logged on.
  149. Arguments:
  150. CatalogName - name of catalog to be restored. This is just the filename
  151. part of the catalog, not the complete path.
  152. CatalogFullPath - name of catalog file to be restored. This is the full
  153. path to the file so we can validate it when it is restored.
  154. Return Value:
  155. TRUE for success, FALSE for failure.
  156. --*/
  157. {
  158. BOOL b = FALSE;
  159. NTSTATUS Status;
  160. WCHAR Buffer[MAX_PATH];
  161. DWORD d;
  162. PWSTR p;
  163. UNICODE_STRING FileString;
  164. //
  165. // check if the catalog file is in the dllcache, and if so, try to restore
  166. // it
  167. //
  168. if (SfcProtectedDllFileDirectory) {
  169. MYASSERT(SfcProtectedDllPath.Buffer != NULL);
  170. wcscpy(Buffer,SfcProtectedDllPath.Buffer);
  171. pSetupConcatenatePaths(Buffer, CatalogName, MAX_PATH, NULL);
  172. if (!SfcValidateSingleCatalog( Buffer )) {
  173. //
  174. // the catalog in the dll cache is invalid. Get rid of it.
  175. //
  176. DebugPrint1(
  177. LVL_MINIMAL,
  178. L"catalog %s in dllcache is invalid, deleting it.",
  179. Buffer);
  180. RtlInitUnicodeString(&FileString,CatalogName);
  181. SfcDeleteFile(
  182. SfcProtectedDllFileDirectory,
  183. &FileString );
  184. } else {
  185. //
  186. // the catalog in the dll cache is valid. Let's isntall it.
  187. //
  188. d = pSetupInstallCatalog(Buffer,CatalogName,NULL);
  189. if (d == NO_ERROR) {
  190. DebugPrint1(
  191. LVL_MINIMAL,
  192. L"catalog %s was successfully installed.",
  193. CatalogName);
  194. return(SfcValidateSingleCatalog(CatalogFullPath));
  195. } else {
  196. DebugPrint2(
  197. LVL_MINIMAL,
  198. L"catalog %s failed to install, ec = 0x%08x",
  199. Buffer,
  200. d);
  201. //
  202. // we could try to restore from media at this point, but if we
  203. // failed to restore from the dllcache even though that copy is
  204. // valid, I don't see how restoring from media will be any
  205. // more successful.
  206. //
  207. return(FALSE);
  208. }
  209. }
  210. }
  211. //
  212. // either the catalog file was invalid in the dllcache (and has since been
  213. // deleted), or the dllcache isn't initialized to anything valid.
  214. //
  215. // We have to wait for someone to logon so that we can restore the catalog
  216. // from installation media
  217. // -- note that we just restore from media if we're in GUI
  218. // Setup.
  219. //
  220. if (SFCDisable != SFC_DISABLE_SETUP) {
  221. Status = NtWaitForSingleObject(hEventLogon,TRUE,NULL);
  222. if (!NT_SUCCESS(Status)) {
  223. DebugPrint1(
  224. LVL_MINIMAL,
  225. L"Failed waiting for the logon event, ec=0x%08x",
  226. Status);
  227. }
  228. }
  229. if (!SfcProtectedDllFileDirectory) {
  230. ExpandEnvironmentStrings(L"%systemroot%\\system32", Buffer, sizeof(Buffer)/sizeof(WCHAR));
  231. } else {
  232. wcscpy(Buffer,SfcProtectedDllPath.Buffer);
  233. }
  234. p = Buffer;
  235. b = SfcRestoreFileFromInstallMedia(
  236. NULL,
  237. CatalogName,
  238. CatalogName,
  239. p,
  240. NULL,
  241. NULL,
  242. FALSE, // ###
  243. FALSE, // target is NOT cache (it really could be, but
  244. // pretend it isn't for the sake of this call)
  245. (SFCDisable == SFC_DISABLE_SETUP) ? FALSE : TRUE,
  246. NULL );
  247. if (b) {
  248. pSetupConcatenatePaths(Buffer, CatalogName, MAX_PATH, NULL);
  249. d = pSetupInstallCatalog(Buffer,CatalogName,NULL);
  250. b = (d == NO_ERROR);
  251. //
  252. // if we installed the catalog to somewhere besides the dllcache, then
  253. // we need to cleanup the temporary file that we installed.
  254. //
  255. if (!SfcProtectedDllFileDirectory) {
  256. HANDLE hDir;
  257. p = wcsrchr(Buffer,L'\\');
  258. if (*p) {
  259. *p = L'\0';
  260. }
  261. hDir = SfcOpenDir( TRUE, TRUE, Buffer );
  262. RtlInitUnicodeString(&FileString,CatalogName);
  263. SfcDeleteFile( hDir , &FileString );
  264. CloseHandle( hDir );
  265. }
  266. if (d == NO_ERROR) {
  267. DebugPrint1(
  268. LVL_MINIMAL,
  269. L"catalog %s was successfully installed.",
  270. CatalogName);
  271. return(SfcValidateSingleCatalog(CatalogFullPath));
  272. } else {
  273. DebugPrint2(
  274. LVL_MINIMAL,
  275. L"catalog %s failed to install, ec = 0x%08x",
  276. Buffer,
  277. d);
  278. }
  279. }
  280. return(b);
  281. }
  282. BOOL SfcRestoreASingleFile(
  283. IN HCATADMIN hCatAdmin,
  284. IN PUNICODE_STRING FileName,
  285. IN HANDLE DirHandle,
  286. IN PWSTR FilePathPartOnly
  287. )
  288. /*++
  289. Routine Description:
  290. Routine to restore the specified file. We first check for the file in the
  291. dllcache, and if the copy in the dll cache is valid, we use it, otherwise
  292. we restore from media.
  293. Note that this function may block if a user is not currently logged on.
  294. Arguments:
  295. hCatAdmin - catalog context for restoring the file
  296. FileName - unicode string to file to be restored
  297. DirHandle - directory handle of file to be restored
  298. FilePathPartOnly - string indicating the path to the file to be restored.
  299. Return Value:
  300. TRUE for success, FALSE for failure.
  301. --*/
  302. {
  303. BOOL b = FALSE;
  304. NTSTATUS Status;
  305. WCHAR Buffer[MAX_PATH];
  306. HANDLE FileHandle;
  307. //
  308. // check if the file is in the dllcache and signed, and if so, try to restore
  309. // it
  310. //
  311. if (SfcProtectedDllFileDirectory) {
  312. MYASSERT(SfcProtectedDllPath.Buffer != NULL);
  313. wcscpy(Buffer,SfcProtectedDllPath.Buffer);
  314. pSetupConcatenatePaths(Buffer, FileName->Buffer, MAX_PATH, NULL);
  315. Status = SfcOpenFile(
  316. FileName,
  317. SfcProtectedDllFileDirectory,
  318. SHARE_ALL,
  319. &FileHandle );
  320. if (NT_SUCCESS(Status)) {
  321. if (!SfcValidateFileSignature(
  322. hCatAdmin,
  323. FileHandle,
  324. FileName->Buffer,
  325. Buffer)) {
  326. //
  327. // the file in the dll cache is invalid. Get rid of it.
  328. //
  329. DebugPrint1(
  330. LVL_MINIMAL,
  331. L"file %s in dllcache is invalid, deleting it.",
  332. Buffer);
  333. SfcDeleteFile(
  334. SfcProtectedDllFileDirectory,
  335. FileName );
  336. CloseHandle(FileHandle);
  337. FileHandle = NULL;
  338. } else {
  339. //
  340. // the file in the dll cache is valid. copy it into place.
  341. //
  342. Status = SfcCopyFile( SfcProtectedDllFileDirectory,
  343. SfcProtectedDllPath.Buffer,
  344. DirHandle,
  345. FilePathPartOnly,
  346. FileName,
  347. NULL);
  348. if (NT_SUCCESS(Status)) {
  349. DebugPrint1(
  350. LVL_MINIMAL,
  351. L"file %wZ was successfully installed, checking it's signature",
  352. FileName);
  353. CloseHandle(FileHandle);
  354. FileHandle = NULL;
  355. Status = SfcOpenFile(
  356. FileName,
  357. DirHandle,
  358. SHARE_ALL,
  359. &FileHandle);
  360. wcscpy(Buffer,FilePathPartOnly);
  361. pSetupConcatenatePaths(Buffer, FileName->Buffer, MAX_PATH, NULL);
  362. if (NT_SUCCESS(Status)
  363. && SfcValidateFileSignature(
  364. hCatAdmin,
  365. FileHandle,
  366. FileName->Buffer,
  367. Buffer)) {
  368. DebugPrint1(
  369. LVL_MINIMAL,
  370. L"file %wZ was successfully installed and validated",
  371. FileName);
  372. CloseHandle(FileHandle);
  373. return(TRUE);
  374. } else {
  375. DebugPrint1(
  376. LVL_MINIMAL,
  377. L"file %s failed to validate",
  378. Buffer);
  379. if (FileHandle) {
  380. CloseHandle(FileHandle);
  381. FileHandle = NULL;
  382. }
  383. //
  384. // we could try to restore from media at this point, but if we
  385. // failed to restore from the dllcache even though that copy is
  386. // valid, I don't see how restoring from media will be any
  387. // more successful.
  388. //
  389. return(FALSE);
  390. }
  391. }
  392. }
  393. }
  394. }
  395. //
  396. // either the file file was invalid in the dllcache (and has since been
  397. // deleted), or the dllcache isn't initialized to anything valid.
  398. //
  399. // We have to wait for someone to logon so that we can restore the file
  400. // from installation media
  401. // -- note that we just restore from media if we're in GUI
  402. // Setup.
  403. //
  404. if (SFCDisable != SFC_DISABLE_SETUP) {
  405. MYASSERT( hEventLogon != NULL );
  406. Status = NtWaitForSingleObject(hEventLogon,TRUE,NULL);
  407. if (!NT_SUCCESS(Status)) {
  408. DebugPrint1(
  409. LVL_MINIMAL,
  410. L"Failed waiting for the logon event, ec=0x%08x",
  411. Status);
  412. }
  413. }
  414. b = SfcRestoreFileFromInstallMedia(
  415. NULL,
  416. FileName->Buffer,
  417. FileName->Buffer,
  418. FilePathPartOnly,
  419. NULL,
  420. NULL,
  421. FALSE, // ###
  422. FALSE, // target is NOT cache
  423. (SFCDisable == SFC_DISABLE_SETUP) ? FALSE : TRUE,
  424. NULL );
  425. if (b) {
  426. Status = SfcOpenFile(
  427. FileName,
  428. DirHandle,
  429. SHARE_ALL,
  430. &FileHandle);
  431. wcscpy(Buffer,FilePathPartOnly);
  432. pSetupConcatenatePaths(Buffer, FileName->Buffer, MAX_PATH, NULL);
  433. if (NT_SUCCESS(Status)) {
  434. b = SfcValidateFileSignature(
  435. hCatAdmin,
  436. FileHandle,
  437. FileName->Buffer,
  438. Buffer);
  439. CloseHandle(FileHandle);
  440. DebugPrint2(
  441. LVL_MINIMAL,
  442. L"file %wZ was%s successfully installed and validated",
  443. FileName,
  444. b ? L" " : L" not");
  445. } else {
  446. b = FALSE;
  447. }
  448. } else {
  449. DebugPrint2(
  450. LVL_MINIMAL,
  451. L"file %s failed to install, ec = 0x%08x",
  452. Buffer,
  453. GetLastError());
  454. }
  455. return(b);
  456. }
  457. BOOL
  458. SfcValidateCatalogs(
  459. VOID
  460. )
  461. /*++
  462. Routine Description:
  463. Validates that all system catalogs have a valid signature. If
  464. a system catalog is not signed, then WFP will try to restore the files.
  465. Note that simply copying the file into place is NOT sufficient. Instead,
  466. we must re-register the catalog with the crypto subsystem.
  467. This function runs very early on during WFP initialization, and may rely on
  468. the following:
  469. 1) crypto subsystem being initialized so we can check file signatures.
  470. 2) syssetup.inf being present on the system and signed. Syssetup.inf
  471. contains the list of system catalogs. If syssetup.inf isn't signed,
  472. we'll have to restore it, and this may require network access or
  473. prompting a user, when one finally logs on.
  474. Arguments:
  475. NONE.
  476. Return Value:
  477. TRUE if all critical system catalogs were validated as OK , FALSE on failure.
  478. If some "non-critical" catalogs fail to validate and restore, we still
  479. return TRUE. We will log an error about the non-critical catalogs failing
  480. to install, however.
  481. --*/
  482. {
  483. NTSTATUS Status;
  484. PWSTR pInfPathOnly, pInfFullPath;
  485. BOOL RetVal = FALSE, CriticalCatalogFailedToValidateOrRestore = FALSE;
  486. HCATADMIN hCatAdmin = NULL;
  487. HANDLE InfDirHandle,InfFileHandle;
  488. UNICODE_STRING FileString;
  489. CATALOG_INFO CatInfo;
  490. PCWSTR CriticalCatalogList[] = {
  491. L"nt5inf.cat",
  492. L"nt5.cat" };
  493. #define CriticalCatalogCount (sizeof(CriticalCatalogList)/sizeof(PCWSTR))
  494. BOOL CriticalCatalogVector[CriticalCatalogCount] = {FALSE};
  495. DWORD i,Count;
  496. HINF hInf;
  497. pInfPathOnly = MemAlloc(sizeof(WCHAR)*MAX_PATH);
  498. if (!pInfPathOnly) {
  499. goto e0;
  500. }
  501. pInfFullPath = MemAlloc(sizeof(WCHAR)*MAX_PATH);
  502. if (!pInfFullPath) {
  503. goto e1;
  504. }
  505. ExpandEnvironmentStrings(L"%systemroot%\\inf", pInfPathOnly, MAX_PATH);
  506. wcscpy(pInfFullPath, pInfPathOnly);
  507. pSetupConcatenatePaths(pInfFullPath, L"syssetup.inf", MAX_PATH, NULL);
  508. InfDirHandle = SfcOpenDir( TRUE, TRUE, pInfPathOnly );
  509. if (!InfDirHandle) {
  510. DebugPrint1( LVL_MINIMAL, L"failed to open inf directory, ec=%d", GetLastError() );
  511. goto e2;
  512. }
  513. RtlInitUnicodeString(&FileString,L"syssetup.inf");
  514. Status = SfcOpenFile( &FileString, InfDirHandle, SHARE_ALL, &InfFileHandle );
  515. if (!NT_SUCCESS(Status)) {
  516. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  517. DebugPrint( LVL_MINIMAL, L"syssetup.inf is missing. Trying to restore it" );
  518. goto restore_inf;
  519. }
  520. DebugPrint1( LVL_MINIMAL, L"failed to open syssetup.inf, ec=0x%08x", Status );
  521. goto e2;
  522. }
  523. //
  524. // aquire an HCATADMIN so we can check the signature of syssetup.inf.
  525. //
  526. if(!CryptCATAdminAcquireContext(&hCatAdmin, &DriverVerifyGuid, 0)) {
  527. DebugPrint1( LVL_MINIMAL, L"CCAAC() failed, ec=%x", GetLastError() );
  528. return(FALSE);
  529. }
  530. //
  531. // Flush the Cache once before we start any Crypto operations
  532. //
  533. SfcFlushCryptoCache();
  534. if (!SfcValidateFileSignature(
  535. hCatAdmin,
  536. InfFileHandle,
  537. L"syssetup.inf",
  538. pInfFullPath )) {
  539. CloseHandle(InfFileHandle);
  540. DebugPrint1( LVL_MINIMAL, L"syssetup.inf isn't signed, attempting to restore. ec=%x", GetLastError() );
  541. goto restore_inf;
  542. }
  543. CloseHandle(InfFileHandle);
  544. goto full_catalog_validation;
  545. restore_inf:
  546. if (!SfcRestoreASingleFile(
  547. hCatAdmin,
  548. &FileString,
  549. InfDirHandle,
  550. pInfPathOnly
  551. )) {
  552. DebugPrint1( LVL_MINIMAL, L"couldn't restore syssetup.inf, ec=%d", GetLastError() );
  553. goto minimal_catalog_validation;
  554. }
  555. full_catalog_validation:
  556. //
  557. // 2. validate syssetup.inf against that catalog. If syssetup.inf is
  558. // unsigned, then default to checking if nt5inf.cat is signed. If it
  559. // is signed, then restore syssetup.inf and start over, but bail out if
  560. // we've been here before.
  561. //
  562. hInf = SetupOpenInfFile(pInfFullPath, NULL, INF_STYLE_WIN4, NULL);
  563. if (hInf == INVALID_HANDLE_VALUE) {
  564. DebugPrint1(
  565. LVL_MINIMAL,
  566. L"couldn't open syssetup.inf, doing minimal catalog validation, ec=%d",
  567. GetLastError() );
  568. goto minimal_catalog_validation;
  569. }
  570. Count = SetupGetLineCount( hInf, L"ProductCatalogsToInstall");
  571. if (Count == 0) {
  572. DebugPrint(
  573. LVL_MINIMAL,
  574. L"failed to retreive catalogs via syssetup.inf, validate using critical catalog list");
  575. goto minimal_catalog_validation;
  576. }
  577. for (i = 0; i < Count; i++) {
  578. INFCONTEXT InfContext;
  579. WCHAR CatalogName[MAX_PATH];
  580. BOOL SuccessfullyValidatedOrRestoredACatalog = FALSE;
  581. if(SetupGetLineByIndex(
  582. hInf,
  583. L"ProductCatalogsToInstall",
  584. i,
  585. &InfContext) &&
  586. (SetupGetStringField(
  587. &InfContext,
  588. 1,
  589. CatalogName,
  590. sizeof(CatalogName)/sizeof(WCHAR),
  591. NULL))) {
  592. CatInfo.cbStruct = sizeof(CATALOG_INFO);
  593. pCryptCATAdminResolveCatalogPath(
  594. hCatAdmin,
  595. CatalogName,
  596. &CatInfo,
  597. 0 );
  598. if (!SfcValidateSingleCatalog( CatInfo.wszCatalogFile )) {
  599. if (!SfcRestoreSingleCatalog(
  600. CatalogName,
  601. CatInfo.wszCatalogFile )) {
  602. DWORD j;
  603. DebugPrint2(
  604. LVL_MINIMAL,
  605. L"couldn't restore catalog %s, ec=%d",
  606. CatInfo.wszCatalogFile,
  607. GetLastError() );
  608. for (j = 0; j < CriticalCatalogCount; j++) {
  609. if (0 == _wcsicmp(CatalogName,CriticalCatalogList[j])) {
  610. CriticalCatalogFailedToValidateOrRestore = TRUE;
  611. break;
  612. }
  613. }
  614. } else {
  615. SuccessfullyValidatedOrRestoredACatalog = TRUE;
  616. }
  617. } else {
  618. SuccessfullyValidatedOrRestoredACatalog = TRUE;
  619. }
  620. if (SuccessfullyValidatedOrRestoredACatalog) {
  621. DWORD j;
  622. for (j = 0; j < CriticalCatalogCount; j++) {
  623. if (0 == _wcsicmp(CatalogName,CriticalCatalogList[j])) {
  624. CriticalCatalogVector[j] = TRUE;
  625. break;
  626. }
  627. }
  628. } else {
  629. DWORD LastError = GetLastError();
  630. //
  631. // log an error
  632. //
  633. DebugPrint2(
  634. LVL_MINIMAL,
  635. L"couldn't restore or validate catalog %s, ec=%d",
  636. CatInfo.wszCatalogFile,
  637. LastError );
  638. SfcReportEvent(
  639. MSG_CATALOG_RESTORE_FAILURE,
  640. CatInfo.wszCatalogFile,
  641. NULL,
  642. LastError);
  643. }
  644. } else {
  645. DebugPrint(
  646. LVL_MINIMAL,
  647. L"failed to retreive catalogs via syssetup.inf, validate using critical catalog list");
  648. goto minimal_catalog_validation;
  649. }
  650. }
  651. if (CriticalCatalogFailedToValidateOrRestore) {
  652. RetVal = FALSE;
  653. goto e3;
  654. } else {
  655. CriticalCatalogFailedToValidateOrRestore = FALSE;
  656. for (i = 0; i< CriticalCatalogCount; i++) {
  657. if (!CriticalCatalogVector[i]) {
  658. CriticalCatalogFailedToValidateOrRestore = TRUE;
  659. }
  660. }
  661. RetVal = !CriticalCatalogFailedToValidateOrRestore;
  662. goto e3;
  663. }
  664. MYASSERT(FALSE && "Should never get here");
  665. //
  666. // 3. validate all remaining catalogs in [ProductCatalogsToInstall] section.
  667. // Keep an internal list of critical catalogs, and if any of these fail to
  668. // be signed (and restored), then we should fail this function, and thus
  669. // fail to initialize WFP. Otherwise, we'll treat the other catalogs being
  670. // invalid as a non-fatal error.
  671. minimal_catalog_validation:
  672. CriticalCatalogFailedToValidateOrRestore = FALSE;
  673. for (i = 0; i < CriticalCatalogCount; i++) {
  674. CatInfo.cbStruct = sizeof(CATALOG_INFO);
  675. pCryptCATAdminResolveCatalogPath(
  676. hCatAdmin,
  677. (PWSTR) CriticalCatalogList[i],
  678. &CatInfo,
  679. 0 );
  680. if (!SfcValidateSingleCatalog( CatInfo.wszCatalogFile )) {
  681. if (!SfcRestoreSingleCatalog(
  682. CriticalCatalogList[i],
  683. CatInfo.wszCatalogFile )) {
  684. DebugPrint2(
  685. LVL_MINIMAL,
  686. L"couldn't restore critical catalog %s, ec=%d",
  687. CatInfo.wszCatalogFile,
  688. GetLastError() );
  689. CriticalCatalogFailedToValidateOrRestore = TRUE;
  690. }
  691. }
  692. }
  693. RetVal = !CriticalCatalogFailedToValidateOrRestore;
  694. e3:
  695. CryptCATAdminReleaseContext( hCatAdmin, 0 );
  696. e2:
  697. MemFree(pInfFullPath);
  698. e1:
  699. MemFree(pInfPathOnly);
  700. e0:
  701. return(RetVal);
  702. }
  703. NTSTATUS
  704. LoadCrypto(
  705. VOID
  706. )
  707. /*++
  708. Routine Description:
  709. Loads all of the required DLLs that are necessary for
  710. doing driver signing and cataloge verification.
  711. This dynamic calling mechanism is necessary because this
  712. code is actually NOT used by session manager at this time.
  713. It is build here and is used conditionaly at runtime. This
  714. code is linked into SMSS and WINLOGON, but only used by
  715. WINLOGON right now. When the crypto functions are available
  716. as NT functions then the dynamic code here can be removed.
  717. Arguments:
  718. None.
  719. Return Value:
  720. NT status code.
  721. --*/
  722. {
  723. HMODULE hModuleWinTrust;
  724. RtlEnterCriticalSection(&g_GeneralCS);
  725. if(g_bCryptoInitialized)
  726. {
  727. RtlLeaveCriticalSection(&g_GeneralCS);
  728. return g_CryptoStatus; // exit here to avoid cleanup
  729. }
  730. g_bCryptoInitialized = TRUE; // set this anyway so no other thread will enter again
  731. hModuleWinTrust = GetModuleHandleW(L"wintrust.dll");
  732. ASSERT(hModuleWinTrust != NULL);
  733. pCryptCATAdminResolveCatalogPath = SfcGetProcAddress( hModuleWinTrust, "CryptCATAdminResolveCatalogPath" );
  734. if (pCryptCATAdminResolveCatalogPath == NULL) {
  735. pCryptCATAdminResolveCatalogPath = MyCryptCATAdminResolveCatalogPath;
  736. }
  737. if (!SfcValidateCatalogs()) {
  738. DebugPrint1( LVL_MINIMAL, L"LoadCrypto: failed SfcValidateCatalogs, ec=%d", GetLastError() );
  739. g_CryptoStatus = STATUS_NO_SUCH_FILE;
  740. }
  741. RtlLeaveCriticalSection(&g_GeneralCS);
  742. if (!(NT_SUCCESS(g_CryptoStatus))) {
  743. DebugPrint1( LVL_MINIMAL, L"LoadCrypto failed, ec=0x%08x", g_CryptoStatus );
  744. //
  745. // Terminate WFP
  746. //
  747. SfcTerminateWatcherThread();
  748. }
  749. return g_CryptoStatus;
  750. }
  751. void
  752. SfcFlushCryptoCache(
  753. void
  754. )
  755. /*++
  756. Routine Description:
  757. Flushes the crypto catalog cache. Crypto by default maintains a per process based
  758. cache that it uses for fast signature verification. The bad part is that the cache
  759. is not updated if somebody updates (remove/add) a catalog file outside of this process.
  760. This can be a problem with install/uninstall/install of service packs etc. To workaround this
  761. we will need to flush the cache before we do any set of verifications. We want to do this at
  762. the beginning of such a set of operations as we don't want to affect performance by tearing
  763. down the cache before every file verification as we do today.
  764. Arguments:
  765. None.
  766. Return Value:
  767. None.
  768. --*/
  769. {
  770. WINTRUST_DATA WintrustData;
  771. ULONG SigErr = ERROR_SUCCESS;
  772. ZeroMemory(&WintrustData, sizeof(WINTRUST_DATA));
  773. WintrustData.dwUnionChoice = WTD_CHOICE_CATALOG;
  774. WintrustData.cbStruct = sizeof(WINTRUST_DATA);
  775. WintrustData.dwUIChoice = WTD_UI_NONE;
  776. WintrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
  777. WintrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE_FLUSH;
  778. WintrustData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
  779. //Call WinVerifyTrust to flush the cache
  780. SigErr = (DWORD)WinVerifyTrust(
  781. NULL,
  782. &DriverVerifyGuid,
  783. &WintrustData
  784. );
  785. if(SigErr != ERROR_SUCCESS)
  786. DebugPrint1( LVL_MINIMAL, L"SFCC failed : WinVerifyTrust(1) failed, ec=0x%08x", SigErr );
  787. return;
  788. }