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

3782 lines
141 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2001
  5. //
  6. // File: signtoolactions.cpp
  7. //
  8. // Contents: The SignTool console tool action functions
  9. //
  10. // History: 4/30/2001 SCoyne Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #ifdef __cplusplus
  14. extern "C" {
  15. #endif
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #ifdef __cplusplus
  20. } // Matches extern "C" above
  21. #endif
  22. #undef ASSERT
  23. #include <afxdisp.h>
  24. #include <unicode.h>
  25. #include "signtool.h"
  26. #include "capicom.h"
  27. #include "resource.h"
  28. #include <cryptuiapi.h>
  29. #include <mscat.h>
  30. #include <comdef.h>
  31. #include <objbase.h>
  32. #include <shlwapi.h>
  33. #include <softpub.h>
  34. #include <wow64t.h>
  35. #ifdef SIGNTOOL_DEBUG
  36. extern BOOL gDebug;
  37. #define FormatIErrRet if (gDebug) wprintf(L"%hs (%u):\n", __FILE__, __LINE__); Format_IErrRet
  38. #else
  39. #define FormatIErrRet Format_IErrRet
  40. #endif
  41. extern HINSTANCE hModule;
  42. void PrintCertInfo(ICertificate2 *pICert2);
  43. void PrintCertChain(IChain *pIChain);
  44. void PrintCertInfoIndented(ICertificate2 *pICert2, DWORD dwIndent);
  45. void PrintSignerInfo(HANDLE hWVTStateData);
  46. BOOL ChainsToRoot(HANDLE hWVTStateData, LPWSTR wszRootName);
  47. BOOL HasTimestamp(HANDLE hWVTStateData);
  48. void Format_IErrRet(WCHAR *wszFunc, DWORD dwErr);
  49. void RegisterCAPICOM();
  50. BOOL GetProviderType(LPWSTR pwszProvName, LPDWORD pdwProvType);
  51. typedef BOOL (WINAPI * FUNC_CRYPTCATADMINREMOVECATALOG)(HCATADMIN, WCHAR *, DWORD);
  52. int SignTool_CatDb(INPUTINFO *InputInfo)
  53. {
  54. DWORD dwDone = 0;
  55. DWORD dwWarnings = 0;
  56. DWORD dwErrors = 0;
  57. DWORD dwcFound;
  58. WIN32_FIND_DATAW FindFileData;
  59. HANDLE hFind = NULL;
  60. HRESULT hr;
  61. PVOID OldWow64Setting;
  62. WCHAR wszTempFileName[MAX_PATH];
  63. WCHAR wszCanonicalFileName[MAX_PATH];
  64. LPWSTR wszTemp;
  65. int LastSlash;
  66. HCATADMIN hCatAdmin = NULL;
  67. HCATINFO hCatInfo = NULL;
  68. CATALOG_INFO CatInfo;
  69. HMODULE hModWintrust = NULL;
  70. FUNC_CRYPTCATADMINREMOVECATALOG fnCryptCATAdminRemoveCatalog = NULL;
  71. // Initialization:
  72. if (!(CryptCATAdminAcquireContext(&hCatAdmin, &InputInfo->CatDbGuid, 0)))
  73. {
  74. FormatErrRet(L"CryptCATAdminAcquireContext", GetLastError());
  75. return 1; // Error
  76. }
  77. switch (InputInfo->CatDbCommand)
  78. {
  79. case RemoveCat:
  80. // Attempt to fill the function pointer dynamically.
  81. // CryptCATAdminRemoveCatalog was introduced in XP.
  82. if (hModWintrust = GetModuleHandleA("wintrust.dll"))
  83. {
  84. fnCryptCATAdminRemoveCatalog = (FUNC_CRYPTCATADMINREMOVECATALOG)
  85. GetProcAddress(hModWintrust, "CryptCATAdminRemoveCatalog");
  86. if (fnCryptCATAdminRemoveCatalog == NULL)
  87. {
  88. dwErrors++;
  89. ResErr(IDS_ERR_REM_CAT_PLATFORM);
  90. goto CatDbCleanupAndExit;
  91. }
  92. }
  93. else
  94. {
  95. dwErrors++;
  96. FormatErrRet(L"GetModuleHandle", GetLastError());
  97. goto CatDbCleanupAndExit;
  98. }
  99. // Got the function pointer.
  100. // Loop over the catalogs to remove
  101. for (DWORD i=0; i<InputInfo->NumFiles; i++)
  102. {
  103. // Check for slashes and wildcards. They are not allowed.
  104. if (wcspbrk(InputInfo->rgwszFileNames[i], L"/\\*?") != NULL)
  105. {
  106. // This won't work, so bail out now with a helpful message
  107. dwErrors++;
  108. ResFormatErr(IDS_ERR_CATALOG_NAME, InputInfo->rgwszFileNames[i]);
  109. continue;
  110. }
  111. if (InputInfo->Verbose)
  112. {
  113. ResFormatOut(IDS_INFO_REMOVING_CAT, InputInfo->rgwszFileNames[i]);
  114. }
  115. if (!fnCryptCATAdminRemoveCatalog(hCatAdmin, InputInfo->rgwszFileNames[i], 0))
  116. {
  117. dwErrors++;
  118. if (!InputInfo->Quiet)
  119. {
  120. switch (hr = GetLastError())
  121. {
  122. case ERROR_NOT_FOUND:
  123. ResFormatErr(IDS_ERR_CAT_NOT_FOUND, InputInfo->rgwszFileNames[i]);
  124. break;
  125. default:
  126. FormatErrRet(L"CryptCATAdminRemoveCatalog", hr);
  127. }
  128. }
  129. ResFormatErr(IDS_ERR_REMOVING_CAT, InputInfo->rgwszFileNames[i]);
  130. continue;
  131. }
  132. // Successfully removed the catalog
  133. dwDone++;
  134. if (!InputInfo->Quiet)
  135. {
  136. ResFormatOut(IDS_INFO_REMOVED_CAT, InputInfo->rgwszFileNames[i]);
  137. }
  138. }
  139. // Done Removing catalogs
  140. break;
  141. case AddUniqueCat:
  142. case UpdateCat:
  143. // Check if we are in the 32-bit Emulator on a 64-bit system
  144. if (InputInfo->fIsWow64Process)
  145. {
  146. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  147. OldWow64Setting = Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  148. }
  149. // Loop over the files and Add/Update them:
  150. for (DWORD i=0; i<InputInfo->NumFiles; i++)
  151. {
  152. // Find the last slash in the path specification:
  153. LastSlash = 0;
  154. for (DWORD s=0; s<wcslen(InputInfo->rgwszFileNames[i]); s++)
  155. {
  156. if ((wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L"\\", 1) == 0) ||
  157. (wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L"/", 1) == 0) ||
  158. (wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L":", 1) == 0))
  159. {
  160. // Set LastSlash to the character after the last slash:
  161. LastSlash = s + 1;
  162. }
  163. }
  164. wcsncpy(wszTempFileName, InputInfo->rgwszFileNames[i], MAX_PATH);
  165. wszTempFileName[MAX_PATH-1] = L'\0';
  166. dwcFound = 0;
  167. hFind = FindFirstFileU(InputInfo->rgwszFileNames[i], &FindFileData);
  168. if (hFind == INVALID_HANDLE_VALUE)
  169. {
  170. // No files found matching that name
  171. dwErrors++;
  172. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->rgwszFileNames[i]);
  173. continue;
  174. }
  175. do
  176. {
  177. if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  178. {
  179. dwcFound++; // Increment number of files (not dirs) found
  180. // matching this filespec
  181. // Copy the filename on after the last slash:
  182. wcsncpy(&(wszTempFileName[LastSlash]),
  183. FindFileData.cFileName, MAX_PATH-LastSlash);
  184. wszTempFileName[MAX_PATH-1] = L'\0';
  185. // Canonicalize:
  186. if (PathIsRelativeW(wszCanonicalFileName))
  187. {
  188. // We need to make it an Absolute path for the CAT API.
  189. WCHAR wszTempFileName2[MAX_PATH];
  190. if (GetCurrentDirectoryW(MAX_PATH, wszTempFileName2) &&
  191. PathAppendW(wszTempFileName2, wszTempFileName))
  192. {
  193. PathCanonicalizeW(wszCanonicalFileName, wszTempFileName2);
  194. }
  195. }
  196. else
  197. {
  198. PathCanonicalizeW(wszCanonicalFileName, wszTempFileName);
  199. }
  200. if (InputInfo->fIsWow64Process)
  201. {
  202. // Disable WOW64 file-system redirection for our current file only
  203. Wow64SetFilesystemRedirectorEx(wszCanonicalFileName);
  204. }
  205. if (InputInfo->Verbose)
  206. {
  207. ResFormatOut(IDS_INFO_ADDING_CAT, wszTempFileName);
  208. #ifdef SIGNTOOL_DEBUG
  209. if (gDebug)
  210. {
  211. wprintf(L"\tCanonical Filename: %s\n", wszCanonicalFileName);
  212. wprintf(L"\tFindFile.cFileName: %s\n", FindFileData.cFileName);
  213. }
  214. #endif
  215. }
  216. // Add the catalog
  217. if (InputInfo->CatDbCommand == UpdateCat)
  218. {
  219. hCatInfo = CryptCATAdminAddCatalog(hCatAdmin,
  220. wszCanonicalFileName,
  221. FindFileData.cFileName,
  222. 0);
  223. }
  224. else // CatDbCommand must equal AddUniqueCat
  225. {
  226. hCatInfo = CryptCATAdminAddCatalog(hCatAdmin,
  227. wszCanonicalFileName,
  228. NULL, // Don't specify the name
  229. 0);
  230. }
  231. // Check for failure
  232. if (hCatInfo == NULL)
  233. {
  234. dwErrors++;
  235. if (!InputInfo->Quiet)
  236. {
  237. switch (hr = GetLastError())
  238. {
  239. case ERROR_BAD_FORMAT:
  240. ResFormatErr(IDS_ERR_CAT_NOT_FOUND, wszTempFileName);
  241. break;
  242. default:
  243. FormatErrRet(L"CryptCATAdminAddCatalog", hr);
  244. }
  245. }
  246. ResFormatErr(IDS_ERR_ADDING_CAT, wszTempFileName);
  247. if (InputInfo->fIsWow64Process)
  248. {
  249. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  250. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  251. }
  252. continue;
  253. }
  254. dwDone++;
  255. // Print success message
  256. if (!InputInfo->Quiet)
  257. {
  258. if (InputInfo->CatDbCommand == UpdateCat)
  259. {
  260. ResFormatOut(IDS_INFO_ADDED_CAT, wszTempFileName);
  261. }
  262. else // CatDbCommand must equal AddUniqueCat
  263. {
  264. if (CryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0))
  265. {
  266. wszTemp = wcsstr(CatInfo.wszCatalogFile, L"\\");
  267. if (wszTemp == NULL)
  268. {
  269. wszTemp = CatInfo.wszCatalogFile;
  270. }
  271. ResFormatOut(IDS_INFO_ADDED_CAT_AS, wszTempFileName, wszTemp);
  272. }
  273. }
  274. }
  275. // Close the Catalog Info Context
  276. CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
  277. }
  278. if (InputInfo->fIsWow64Process)
  279. {
  280. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  281. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  282. }
  283. } while (FindNextFileU(hFind, &FindFileData));
  284. if (dwcFound == 0) // No files were found matching this filespec
  285. { // this will only fire if only directories were found.
  286. dwErrors++;
  287. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->rgwszFileNames[i]);
  288. continue;
  289. }
  290. FindClose(hFind);
  291. hFind = NULL;
  292. }
  293. if (InputInfo->fIsWow64Process)
  294. {
  295. // Re-ensable WOW64 file-system redirection
  296. Wow64SetFilesystemRedirectorEx(OldWow64Setting);
  297. }
  298. // Done Adding/Updating catalogs
  299. break;
  300. default:
  301. ResErr(IDS_ERR_UNEXPECTED);
  302. goto CatDbCleanupAndExit;
  303. }
  304. CatDbCleanupAndExit:
  305. //Print Summary Information:
  306. if (InputInfo->Verbose || (!InputInfo->Quiet && (dwErrors || dwWarnings)))
  307. {
  308. wprintf(L"\n");
  309. if (InputInfo->Verbose || dwDone)
  310. switch (InputInfo->CatDbCommand)
  311. {
  312. case AddUniqueCat:
  313. case UpdateCat:
  314. ResFormatOut(IDS_INFO_CATS_ADDED, dwDone);
  315. break;
  316. case RemoveCat:
  317. ResFormatOut(IDS_INFO_CATS_REMOVED, dwDone);
  318. break;
  319. default:
  320. ResErr(IDS_ERR_UNEXPECTED);
  321. }
  322. // Commented out because no warnings are possible in this function yet:
  323. // if (InputInfo->Verbose || dwWarnings)
  324. // ResFormatOut(IDS_INFO_WARNINGS, dwWarnings);
  325. if (InputInfo->Verbose || dwErrors)
  326. ResFormatOut(IDS_INFO_ERRORS, dwErrors);
  327. }
  328. CryptCATAdminReleaseContext(hCatAdmin, 0);
  329. if (dwErrors)
  330. return 1; // Error
  331. if (dwWarnings)
  332. return 2; // Warning
  333. if (dwDone)
  334. return 0; // Success
  335. // One of the above returns should fire, so
  336. // this should never happen:
  337. ResErr(IDS_ERR_NO_FILES_DONE);
  338. ResErr(IDS_ERR_UNEXPECTED);
  339. return 1; // Error
  340. }
  341. int SignTool_Sign(INPUTINFO *InputInfo)
  342. {
  343. DWORD dwcFound;
  344. DWORD dwDone = 0;
  345. DWORD dwWarnings = 0;
  346. DWORD dwErrors = 0;
  347. DWORD dwTemp;
  348. WIN32_FIND_DATAW FindFileData;
  349. HANDLE hFind = NULL;
  350. HCERTSTORE hStore = NULL;
  351. HRESULT hr;
  352. WCHAR wszTempFileName[MAX_PATH];
  353. WCHAR wszSHA1[41];
  354. ICertificate2 *pICert2Selected = NULL;
  355. ICertificate2 *pICert2Temp = NULL;
  356. ICertificates *pICerts = NULL;
  357. ICertificates2 *pICerts2Original = NULL;
  358. ICertificates2 *pICerts2Selected = NULL;
  359. ICertificates2 *pICerts2Temp = NULL;
  360. ISignedCode *pISignedCode = NULL;
  361. ISigner2 *pISigner2 = NULL;
  362. ICSigner *pICSigner = NULL;
  363. IStore2 *pIStore2 = NULL;
  364. IStore2 *pIStore2Temp = NULL;
  365. ICertStore *pICertStore = NULL;
  366. IPrivateKey *pIPrivateKey = NULL;
  367. IUtilities *pIUtils = NULL;
  368. PVOID OldWow64Setting;
  369. DATE dateBest;
  370. DATE dateTemp;
  371. COleDateTime DateTime;
  372. VARIANT varTemp;
  373. VARIANT_BOOL boolTemp;
  374. COleVariant cvarTemp;
  375. #ifdef SIGNTOOL_DEBUG
  376. CAPICOM_PROV_TYPE provtypeTemp;
  377. CAPICOM_KEY_SPEC keyspecTemp;
  378. #endif
  379. BSTR bstrTemp;
  380. BSTR bstrTemp2;
  381. int LastSlash;
  382. long longTemp;
  383. // Initialize COM:
  384. if ((hr = CoInitialize(NULL)) != S_OK)
  385. {
  386. FormatErrRet(L"CoInitialize", hr);
  387. return 1; // Error
  388. }
  389. VariantInit(&varTemp);
  390. // Create the store object, and check if CAPICOM is installed.
  391. hr = CoCreateInstance(__uuidof(Store), NULL, CLSCTX_ALL,
  392. __uuidof(IStore2), (LPVOID*)&pIStore2);
  393. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  394. {
  395. // In this case, give it one more chance:
  396. RegisterCAPICOM();
  397. hr = CoCreateInstance(__uuidof(Store), NULL, CLSCTX_ALL,
  398. __uuidof(IStore2), (LPVOID*)&pIStore2);
  399. }
  400. if (FAILED(hr))
  401. {
  402. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  403. {
  404. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  405. }
  406. else
  407. {
  408. FormatErrRet(L"CoCreateInstance", hr);
  409. }
  410. dwErrors++;
  411. goto SignCleanupAndExit;
  412. }
  413. // Open the Store and Original Certificates2 collection
  414. if (InputInfo->wszCertFile)
  415. {
  416. // Get the cert from a file, so open the file as a store:
  417. if ((bstrTemp = SysAllocString(L"SignToolTemporaryPFXMemoryStore")) == NULL)
  418. {
  419. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  420. dwErrors++;
  421. goto SignCleanupAndExit;
  422. }
  423. hr = pIStore2->Open(CAPICOM_MEMORY_STORE,
  424. bstrTemp, // Store Name
  425. CAPICOM_STORE_OPEN_READ_WRITE);
  426. SysFreeString(bstrTemp);
  427. if (FAILED(hr))
  428. {
  429. FormatIErrRet(L"IStore2::Open", hr);
  430. dwErrors++;
  431. goto SignCleanupAndExit;
  432. }
  433. // Set the BSTRs needed for the Load call
  434. bstrTemp = SysAllocString(InputInfo->wszCertFile);
  435. if (bstrTemp == NULL)
  436. {
  437. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  438. dwErrors++;
  439. goto SignCleanupAndExit;
  440. }
  441. if (InputInfo->wszPassword)
  442. {
  443. bstrTemp2 = SysAllocString(InputInfo->wszPassword);
  444. }
  445. else
  446. {
  447. bstrTemp2 = SysAllocString(L"");
  448. }
  449. if (bstrTemp2 == NULL)
  450. {
  451. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  452. dwErrors++;
  453. goto SignCleanupAndExit;
  454. }
  455. // Load the Cert File into the new Memory Store:
  456. hr = pIStore2->Load(bstrTemp, // Filename
  457. bstrTemp2, // Password
  458. CAPICOM_KEY_STORAGE_DEFAULT);
  459. if (InputInfo->wszPassword)
  460. {
  461. // Wipe both copies of the password. We're done with it.
  462. SecureZeroMemory(bstrTemp2, wcslen(bstrTemp2) * sizeof(WCHAR));
  463. SecureZeroMemory(InputInfo->wszPassword,
  464. wcslen(InputInfo->wszPassword) * sizeof(WCHAR));
  465. }
  466. SysFreeString(bstrTemp);
  467. SysFreeString(bstrTemp2);
  468. if (FAILED(hr)) // Check return value of Load command above
  469. {
  470. switch (HRESULT_CODE(hr))
  471. {
  472. case ERROR_INVALID_PASSWORD:
  473. ResErr(IDS_ERR_PFX_BAD_PASSWORD);
  474. break;
  475. case ERROR_FILE_NOT_FOUND:
  476. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->wszCertFile);
  477. break;
  478. case ERROR_SHARING_VIOLATION:
  479. ResErr(IDS_ERR_SHARING_VIOLATION);
  480. break;
  481. default:
  482. FormatIErrRet(L"IStore2::Load", hr);
  483. ResFormatErr(IDS_ERR_CERT_FILE, InputInfo->wszCertFile);
  484. }
  485. dwErrors++;
  486. goto SignCleanupAndExit;
  487. }
  488. // The store is Open and Loaded. Now get the Certificates collection:
  489. hr = pIStore2->get_Certificates(&pICerts);
  490. if (FAILED(hr))
  491. {
  492. FormatIErrRet(L"IStore2::get_Certificates", hr);
  493. dwErrors++;
  494. goto SignCleanupAndExit;
  495. }
  496. // And then get the Certificates2 interface:
  497. hr = pICerts->QueryInterface(__uuidof(ICertificates2),
  498. (LPVOID*)&pICerts2Original);
  499. if (FAILED(hr))
  500. {
  501. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  502. {
  503. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  504. }
  505. else
  506. {
  507. FormatErrRet(L"ICertificates::QueryInterface", hr);
  508. }
  509. dwErrors++;
  510. goto SignCleanupAndExit;
  511. }
  512. // Release the Certificates interface:
  513. pICerts->Release();
  514. pICerts = NULL;
  515. }
  516. else
  517. {
  518. // Get the cert from a store, so open the requested store:
  519. if (InputInfo->wszStoreName)
  520. {
  521. bstrTemp = SysAllocString(InputInfo->wszStoreName);
  522. }
  523. else
  524. {
  525. bstrTemp = SysAllocString(L"My");
  526. }
  527. if (bstrTemp == NULL)
  528. {
  529. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  530. dwErrors++;
  531. goto SignCleanupAndExit;
  532. }
  533. hr = pIStore2->Open(InputInfo->OpenMachineStore?
  534. CAPICOM_LOCAL_MACHINE_STORE:
  535. CAPICOM_CURRENT_USER_STORE,
  536. bstrTemp,
  537. CAPICOM_STORE_OPEN_MODE(
  538. CAPICOM_STORE_OPEN_READ_ONLY |
  539. CAPICOM_STORE_OPEN_EXISTING_ONLY));
  540. if (FAILED(hr))
  541. {
  542. switch (HRESULT_CODE(hr))
  543. {
  544. case ERROR_FILE_NOT_FOUND:
  545. case ERROR_INVALID_NAME:
  546. ResFormatErr(IDS_ERR_STORE_NOT_FOUND, bstrTemp);
  547. break;
  548. default:
  549. FormatIErrRet(L"IStore2::Open", hr);
  550. ResFormatErr(IDS_ERR_STORE, bstrTemp);
  551. }
  552. SysFreeString(bstrTemp);
  553. dwErrors++;
  554. goto SignCleanupAndExit;
  555. }
  556. SysFreeString(bstrTemp);
  557. // The store is open. Now get the Certificates collection:
  558. hr = pIStore2->get_Certificates(&pICerts);
  559. if (FAILED(hr))
  560. {
  561. FormatIErrRet(L"IStore2::get_Certificates", hr);
  562. dwErrors++;
  563. goto SignCleanupAndExit;
  564. }
  565. // And then get the Certificates2 interface:
  566. hr = pICerts->QueryInterface(__uuidof(ICertificates2),
  567. (LPVOID*)&pICerts2Original);
  568. if (FAILED(hr))
  569. {
  570. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  571. {
  572. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  573. }
  574. else
  575. {
  576. FormatErrRet(L"ICertificates::QueryInterface", hr);
  577. }
  578. dwErrors++;
  579. goto SignCleanupAndExit;
  580. }
  581. // Release the Certificates interface:
  582. pICerts->Release();
  583. pICerts = NULL;
  584. }
  585. #ifdef SIGNTOOL_DEBUG
  586. if (gDebug)
  587. {
  588. hr = pICerts2Original->get_Count(&longTemp);
  589. if (FAILED(hr))
  590. {
  591. FormatIErrRet(L"ICertificates2::get_Count", hr);
  592. dwErrors++;
  593. goto SignCleanupAndExit;
  594. }
  595. wprintf(L"\nThe following certificates were considered:\n");
  596. for (long l=1; l <= longTemp; l++)
  597. {
  598. hr = pICerts2Original->get_Item(l, &varTemp);
  599. if (FAILED(hr))
  600. {
  601. FormatIErrRet(L"ICertificates2::get_Item", hr);
  602. dwErrors++;
  603. goto SignCleanupAndExit;
  604. }
  605. // And then get the Certificate2 interface:
  606. hr = varTemp.pdispVal->QueryInterface(__uuidof(ICertificate2),
  607. (LPVOID*)&pICert2Temp);
  608. if (FAILED(hr))
  609. {
  610. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  611. {
  612. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  613. }
  614. else
  615. {
  616. FormatErrRet(L"IDispatch::QueryInterface", hr);
  617. }
  618. dwErrors++;
  619. goto SignCleanupAndExit;
  620. }
  621. PrintCertInfo(pICert2Temp);
  622. pICert2Temp->Release();
  623. pICert2Temp = NULL;
  624. VariantClear(&varTemp);
  625. }
  626. }
  627. #endif
  628. // We now have an open Cert2 collection in pICerts2Original.
  629. // Find the certs we want from that Certificates2 collection:
  630. // Start by narrowing it down to those with the right EKU:
  631. // This cannot be bypassed, because we don't want to sign with certs
  632. // that aren't valid for code signing. The user has to explicitly choose
  633. // a different EKU if they want to sign with an invalid cert.
  634. if (InputInfo->wszEKU)
  635. {
  636. cvarTemp = InputInfo->wszEKU;
  637. }
  638. else
  639. {
  640. cvarTemp.SetString(CAPICOM_OID_CODE_SIGNING, VT_BSTR);
  641. }
  642. hr = pICerts2Original->Find(CAPICOM_CERTIFICATE_FIND_APPLICATION_POLICY,
  643. cvarTemp,
  644. FALSE,
  645. &pICerts2Selected);
  646. if (FAILED(hr))
  647. {
  648. FormatIErrRet(L"ICertificates2::Find", hr);
  649. cvarTemp.Clear();
  650. dwErrors++;
  651. goto SignCleanupAndExit;
  652. }
  653. cvarTemp.Clear();
  654. // We now have pICerts2Selected, containing all certs with the right EKU.
  655. // Now filter based on whatever additional criteria were presented:
  656. #ifdef SIGNTOOL_DEBUG
  657. if (gDebug)
  658. {
  659. hr = pICerts2Selected->get_Count(&longTemp);
  660. if (FAILED(hr))
  661. {
  662. FormatIErrRet(L"ICertificates2::get_Count", hr);
  663. dwErrors++;
  664. goto SignCleanupAndExit;
  665. }
  666. wprintf(L"After EKU filter, %ld certs were left.\n", longTemp);
  667. }
  668. #endif
  669. // Filtering on Hash
  670. if (InputInfo->SHA1.cbData == 20)
  671. {
  672. for (DWORD d = 0; d < 20; d++)
  673. {
  674. swprintf(&wszSHA1[d*2], L"%02X", InputInfo->SHA1.pbData[d]);
  675. }
  676. cvarTemp = wszSHA1;
  677. hr = pICerts2Selected->Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH,
  678. cvarTemp,
  679. FALSE,
  680. &pICerts2Temp);
  681. if (FAILED(hr))
  682. {
  683. FormatIErrRet(L"ICertificates2::Find", hr);
  684. cvarTemp.Clear();
  685. dwErrors++;
  686. goto SignCleanupAndExit;
  687. }
  688. cvarTemp.Clear();
  689. pICerts2Selected->Release();
  690. pICerts2Selected = pICerts2Temp;
  691. pICerts2Temp = NULL;
  692. #ifdef SIGNTOOL_DEBUG
  693. if (gDebug)
  694. {
  695. hr = pICerts2Selected->get_Count(&longTemp);
  696. if (FAILED(hr))
  697. {
  698. FormatIErrRet(L"ICertificates2::get_Count", hr);
  699. dwErrors++;
  700. goto SignCleanupAndExit;
  701. }
  702. wprintf(L"After Hash filter, %ld certs were left.\n", longTemp);
  703. }
  704. #endif
  705. }
  706. // Filtering on SubjectName:
  707. if (InputInfo->wszSubjectName)
  708. {
  709. cvarTemp = InputInfo->wszSubjectName;
  710. hr = pICerts2Selected->Find(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME,
  711. cvarTemp,
  712. FALSE,
  713. &pICerts2Temp);
  714. if (FAILED(hr))
  715. {
  716. FormatIErrRet(L"ICertificates2::Find", hr);
  717. cvarTemp.Clear();
  718. dwErrors++;
  719. goto SignCleanupAndExit;
  720. }
  721. cvarTemp.Clear();
  722. pICerts2Selected->Release();
  723. pICerts2Selected = pICerts2Temp;
  724. pICerts2Temp = NULL;
  725. #ifdef SIGNTOOL_DEBUG
  726. if (gDebug)
  727. {
  728. hr = pICerts2Selected->get_Count(&longTemp);
  729. if (FAILED(hr))
  730. {
  731. FormatIErrRet(L"ICertificates2::get_Count", hr);
  732. dwErrors++;
  733. goto SignCleanupAndExit;
  734. }
  735. wprintf(L"After Subject Name filter, %ld certs were left.\n", longTemp);
  736. }
  737. #endif
  738. }
  739. // Filtering on IssuerName:
  740. if (InputInfo->wszIssuerName)
  741. {
  742. cvarTemp = InputInfo->wszIssuerName;
  743. hr = pICerts2Selected->Find(CAPICOM_CERTIFICATE_FIND_ISSUER_NAME,
  744. cvarTemp,
  745. FALSE,
  746. &pICerts2Temp);
  747. if (FAILED(hr))
  748. {
  749. FormatIErrRet(L"ICertificates2::Find", hr);
  750. cvarTemp.Clear();
  751. dwErrors++;
  752. goto SignCleanupAndExit;
  753. }
  754. cvarTemp.Clear();
  755. pICerts2Selected->Release();
  756. pICerts2Selected = pICerts2Temp;
  757. pICerts2Temp = NULL;
  758. #ifdef SIGNTOOL_DEBUG
  759. if (gDebug)
  760. {
  761. hr = pICerts2Selected->get_Count(&longTemp);
  762. if (FAILED(hr))
  763. {
  764. FormatIErrRet(L"ICertificates2::get_Count", hr);
  765. dwErrors++;
  766. goto SignCleanupAndExit;
  767. }
  768. wprintf(L"After Issuer Name filter, %ld certs were left.\n", longTemp);
  769. }
  770. #endif
  771. }
  772. // Filtering on TemplateName:
  773. if (InputInfo->wszTemplateName)
  774. {
  775. cvarTemp = InputInfo->wszTemplateName;
  776. hr = pICerts2Selected->Find(CAPICOM_CERTIFICATE_FIND_TEMPLATE_NAME,
  777. cvarTemp,
  778. FALSE,
  779. &pICerts2Temp);
  780. if (FAILED(hr))
  781. {
  782. FormatIErrRet(L"ICertificates2::Find", hr);
  783. cvarTemp.Clear();
  784. dwErrors++;
  785. goto SignCleanupAndExit;
  786. }
  787. cvarTemp.Clear();
  788. pICerts2Selected->Release();
  789. pICerts2Selected = pICerts2Temp;
  790. pICerts2Temp = NULL;
  791. #ifdef SIGNTOOL_DEBUG
  792. if (gDebug)
  793. {
  794. hr = pICerts2Selected->get_Count(&longTemp);
  795. if (FAILED(hr))
  796. {
  797. FormatIErrRet(L"ICertificates2::get_Count", hr);
  798. dwErrors++;
  799. goto SignCleanupAndExit;
  800. }
  801. wprintf(L"After Template Name filter, %ld certs were left.\n", longTemp);
  802. }
  803. #endif
  804. }
  805. // Filtering on those with Private Keys.
  806. if (InputInfo->wszCSP == NULL) // Only if we aren't specifying the key
  807. {
  808. cvarTemp = (long)CAPICOM_PROPID_KEY_PROV_INFO;
  809. hr = pICerts2Selected->Find(CAPICOM_CERTIFICATE_FIND_EXTENDED_PROPERTY,
  810. cvarTemp,
  811. FALSE,
  812. &pICerts2Temp);
  813. if (FAILED(hr))
  814. {
  815. FormatIErrRet(L"ICertificates2::Find", hr);
  816. cvarTemp.Clear();
  817. dwErrors++;
  818. goto SignCleanupAndExit;
  819. }
  820. cvarTemp.Clear();
  821. pICerts2Selected->Release();
  822. pICerts2Selected = pICerts2Temp;
  823. pICerts2Temp = NULL;
  824. #ifdef SIGNTOOL_DEBUG
  825. if (gDebug)
  826. {
  827. hr = pICerts2Selected->get_Count(&longTemp);
  828. if (FAILED(hr))
  829. {
  830. FormatIErrRet(L"ICertificates2::get_Count", hr);
  831. dwErrors++;
  832. goto SignCleanupAndExit;
  833. }
  834. wprintf(L"After Private Key filter, %ld certs were left.\n", longTemp);
  835. }
  836. #endif
  837. }
  838. // Filtering on RootName:
  839. if (InputInfo->wszRootName)
  840. {
  841. cvarTemp = InputInfo->wszRootName;
  842. hr = pICerts2Selected->Find(CAPICOM_CERTIFICATE_FIND_ROOT_NAME,
  843. cvarTemp,
  844. FALSE,
  845. &pICerts2Temp);
  846. if (FAILED(hr))
  847. {
  848. FormatIErrRet(L"ICertificates2::Find", hr);
  849. cvarTemp.Clear();
  850. dwErrors++;
  851. goto SignCleanupAndExit;
  852. }
  853. cvarTemp.Clear();
  854. pICerts2Selected->Release();
  855. pICerts2Selected = pICerts2Temp;
  856. pICerts2Temp = NULL;
  857. #ifdef SIGNTOOL_DEBUG
  858. if (gDebug)
  859. {
  860. hr = pICerts2Selected->get_Count(&longTemp);
  861. if (FAILED(hr))
  862. {
  863. FormatIErrRet(L"ICertificates2::get_Count", hr);
  864. dwErrors++;
  865. goto SignCleanupAndExit;
  866. }
  867. wprintf(L"After Root Name filter, %ld certs were left.\n", longTemp);
  868. }
  869. #endif
  870. }
  871. // Make sure we have a single cert:
  872. hr = pICerts2Selected->get_Count(&longTemp);
  873. if (FAILED(hr))
  874. {
  875. FormatIErrRet(L"ICertificates2::get_Count", hr);
  876. dwErrors++;
  877. goto SignCleanupAndExit;
  878. }
  879. if (longTemp == 0)
  880. {
  881. // No certificates found
  882. ResErr(IDS_ERR_NO_CERT);
  883. dwErrors++;
  884. goto SignCleanupAndExit;
  885. }
  886. else if (longTemp == 1)
  887. {
  888. // We have exactly one certificate.
  889. // Get that certificate:
  890. hr = pICerts2Selected->get_Item(1, &varTemp);
  891. if (FAILED(hr))
  892. {
  893. FormatIErrRet(L"ICertificates2::get_Item", hr);
  894. dwErrors++;
  895. goto SignCleanupAndExit;
  896. }
  897. // And then get the Certificate2 interface:
  898. hr = varTemp.pdispVal->QueryInterface(__uuidof(ICertificate2),
  899. (LPVOID*)&pICert2Selected);
  900. if (FAILED(hr))
  901. {
  902. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  903. {
  904. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  905. }
  906. else
  907. {
  908. FormatErrRet(L"IDispatch::QueryInterface", hr);
  909. }
  910. dwErrors++;
  911. goto SignCleanupAndExit;
  912. }
  913. VariantClear(&varTemp);
  914. }
  915. else if (longTemp > 1)
  916. {
  917. // We have too many certs. Maybe we can select automatically
  918. if (InputInfo->CatDbSelect)
  919. {
  920. // Let's select automatically
  921. dateBest = 0;
  922. for (long l=1; l <= longTemp; l++)
  923. {
  924. if (SUCCEEDED(pICerts2Selected->get_Item(l, &varTemp)))
  925. {
  926. hr = varTemp.pdispVal->QueryInterface(__uuidof(ICertificate2),
  927. (LPVOID*)&pICert2Temp);
  928. if (FAILED(hr))
  929. {
  930. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  931. {
  932. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  933. }
  934. else
  935. {
  936. FormatErrRet(L"IDispatch::QueryInterface", hr);
  937. }
  938. dwErrors++;
  939. goto SignCleanupAndExit;
  940. }
  941. VariantClear(&varTemp);
  942. hr = pICert2Temp->get_ValidToDate(&dateTemp);
  943. if (FAILED(hr))
  944. {
  945. FormatIErrRet(L"ICertificates2::get_ValidToDate", hr);
  946. dwErrors++;
  947. goto SignCleanupAndExit;
  948. }
  949. if (dateTemp > dateBest)
  950. {
  951. dateBest = dateTemp;
  952. if (pICert2Selected)
  953. {
  954. pICert2Selected->Release();
  955. }
  956. pICert2Selected = pICert2Temp;
  957. pICert2Temp = NULL;
  958. }
  959. else
  960. {
  961. pICert2Temp->Release();
  962. pICert2Temp = NULL;
  963. }
  964. }
  965. }
  966. if ((dateBest == 0) || (pICert2Selected == NULL))
  967. {
  968. // Somehow we had at least one certificate,
  969. // but its date wasn't greater than zero
  970. // This should never happen.
  971. ResErr(IDS_ERR_UNEXPECTED);
  972. dwErrors++;
  973. goto SignCleanupAndExit;
  974. }
  975. }
  976. else
  977. {
  978. // We can't select automatically.
  979. // Report the Error and list all valid certs:
  980. ResErr(IDS_ERR_CERT_MULTIPLE);
  981. for (long l=1; l <= longTemp; l++)
  982. {
  983. if (SUCCEEDED(pICerts2Selected->get_Item(l, &varTemp)))
  984. {
  985. // Get the Certificate2 interface:
  986. hr = varTemp.pdispVal->QueryInterface(__uuidof(ICertificate2),
  987. (LPVOID*)&pICert2Temp);
  988. if (FAILED(hr))
  989. {
  990. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  991. {
  992. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  993. }
  994. else
  995. {
  996. FormatErrRet(L"IDispatch::QueryInterface", hr);
  997. }
  998. dwErrors++;
  999. goto SignCleanupAndExit;
  1000. }
  1001. // Print the Certificate Information:
  1002. PrintCertInfo(pICert2Temp);
  1003. pICert2Temp->Release();
  1004. pICert2Temp = NULL;
  1005. VariantClear(&varTemp);
  1006. }
  1007. }
  1008. dwErrors++;
  1009. goto SignCleanupAndExit;
  1010. }
  1011. }
  1012. else
  1013. {
  1014. // longTemp was negative. This should never happen.
  1015. ResErr(IDS_ERR_UNEXPECTED);
  1016. dwErrors++;
  1017. goto SignCleanupAndExit;
  1018. }
  1019. // Our signing certificate is now in pICert2Selected
  1020. if (InputInfo->Verbose)
  1021. {
  1022. ResOut(IDS_INFO_CERT_SELECTED);
  1023. PrintCertInfo(pICert2Selected);
  1024. }
  1025. // Check for Private Key info
  1026. if (InputInfo->wszCSP && InputInfo->wszContainerName)
  1027. {
  1028. // We must add the Private Key info to the cert.
  1029. if (!InputInfo->wszCertFile)
  1030. {
  1031. // If we didn't open our certs from a file, we opened a registry
  1032. // store read-only. So that we don't modify that cert, we should
  1033. // create a temporary memory store and copy the cert there
  1034. // before we modify its private key info.
  1035. // Create a new memory Store:
  1036. hr = CoCreateInstance(__uuidof(Store), NULL, CLSCTX_ALL,
  1037. __uuidof(IStore2), (LPVOID*)&pIStore2Temp);
  1038. if (FAILED(hr))
  1039. {
  1040. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  1041. {
  1042. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  1043. }
  1044. else
  1045. {
  1046. FormatErrRet(L"CoCreateInstance", hr);
  1047. }
  1048. dwErrors++;
  1049. goto SignCleanupAndExit;
  1050. }
  1051. bstrTemp = SysAllocString(L"SignToolTemporaryMemoryStore");
  1052. if (bstrTemp == NULL)
  1053. {
  1054. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  1055. dwErrors++;
  1056. goto SignCleanupAndExit;
  1057. }
  1058. hr = pIStore2Temp->Open(CAPICOM_MEMORY_STORE,
  1059. bstrTemp,
  1060. CAPICOM_STORE_OPEN_READ_WRITE);
  1061. if (FAILED(hr))
  1062. {
  1063. FormatIErrRet(L"IStore2::Open", hr);
  1064. dwErrors++;
  1065. goto SignCleanupAndExit;
  1066. }
  1067. // Add our cert to that store:
  1068. hr = pIStore2Temp->Add(pICert2Selected);
  1069. if (FAILED(hr))
  1070. {
  1071. FormatIErrRet(L"IStore2::Add", hr);
  1072. dwErrors++;
  1073. goto SignCleanupAndExit;
  1074. }
  1075. // Release our Interface to the Cert in the old Store:
  1076. pICert2Selected->Release();
  1077. pICert2Selected = NULL;
  1078. // Get the Certificates Collection from the new Store:
  1079. hr = pIStore2Temp->get_Certificates(&pICerts);
  1080. if (FAILED(hr))
  1081. {
  1082. FormatIErrRet(L"IStore2::get_Certificates", hr);
  1083. dwErrors++;
  1084. goto SignCleanupAndExit;
  1085. }
  1086. // Get the Certificate Object from the Certificates collection:
  1087. hr = pICerts->get_Item(1, &varTemp);
  1088. if (FAILED(hr))
  1089. {
  1090. FormatIErrRet(L"ICertificates::get_Item", hr);
  1091. dwErrors++;
  1092. goto SignCleanupAndExit;
  1093. }
  1094. // Get the Certificate2 interface of our selected Cert in the new Store:
  1095. hr = varTemp.pdispVal->QueryInterface(__uuidof(ICertificate2), (LPVOID*)&pICert2Selected);
  1096. if (FAILED(hr))
  1097. {
  1098. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  1099. {
  1100. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  1101. }
  1102. else
  1103. {
  1104. FormatErrRet(L"IDispatch::QueryInterface", hr);
  1105. }
  1106. dwErrors++;
  1107. goto SignCleanupAndExit;
  1108. }
  1109. VariantClear(&varTemp);
  1110. pICerts->Release();
  1111. pICerts = NULL;
  1112. }
  1113. // Now the Cert is free to be modified.
  1114. // Create the Private Key object:
  1115. hr = CoCreateInstance(__uuidof(PrivateKey), NULL, CLSCTX_ALL,
  1116. __uuidof(IPrivateKey), (LPVOID*)&pIPrivateKey);
  1117. if (FAILED(hr))
  1118. {
  1119. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  1120. {
  1121. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  1122. }
  1123. else
  1124. {
  1125. FormatErrRet(L"CoCreateInstance", hr);
  1126. }
  1127. dwErrors++;
  1128. goto SignCleanupAndExit;
  1129. }
  1130. // Setup Private Key info:
  1131. bstrTemp = SysAllocString(InputInfo->wszContainerName);
  1132. bstrTemp2 = SysAllocString(InputInfo->wszCSP);
  1133. if ((bstrTemp == NULL) || (bstrTemp2 == NULL))
  1134. {
  1135. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  1136. dwErrors++;
  1137. goto SignCleanupAndExit;
  1138. }
  1139. // Open the specified private key:
  1140. // First try the RSA_FULL provider type:
  1141. hr = pIPrivateKey->Open(bstrTemp, // Container Name
  1142. bstrTemp2, // CSP
  1143. CAPICOM_PROV_RSA_FULL,
  1144. CAPICOM_KEY_SPEC_SIGNATURE,
  1145. CAPICOM_CURRENT_USER_STORE,
  1146. TRUE);
  1147. if (FAILED(hr) && (hr != NTE_PROV_TYPE_NO_MATCH))
  1148. hr = pIPrivateKey->Open(bstrTemp, // Container Name
  1149. bstrTemp2, // CSP
  1150. CAPICOM_PROV_RSA_FULL,
  1151. CAPICOM_KEY_SPEC_KEYEXCHANGE,
  1152. CAPICOM_CURRENT_USER_STORE,
  1153. TRUE);
  1154. if (FAILED(hr) && (hr != NTE_PROV_TYPE_NO_MATCH))
  1155. hr = pIPrivateKey->Open(bstrTemp, // Container Name
  1156. bstrTemp2, // CSP
  1157. CAPICOM_PROV_RSA_FULL,
  1158. CAPICOM_KEY_SPEC_SIGNATURE,
  1159. CAPICOM_LOCAL_MACHINE_STORE,
  1160. TRUE);
  1161. if (FAILED(hr) && (hr != NTE_PROV_TYPE_NO_MATCH))
  1162. hr = pIPrivateKey->Open(bstrTemp, // Container Name
  1163. bstrTemp2, // CSP
  1164. CAPICOM_PROV_RSA_FULL,
  1165. CAPICOM_KEY_SPEC_KEYEXCHANGE,
  1166. CAPICOM_LOCAL_MACHINE_STORE,
  1167. TRUE);
  1168. // If the provider type was wrong, then
  1169. // find the right provider type and try again:
  1170. if (hr == NTE_PROV_TYPE_NO_MATCH)
  1171. {
  1172. #ifdef SIGNTOOL_DEBUG
  1173. if (gDebug)
  1174. wprintf(L"Attempting to find the correct CSP Type...\n");
  1175. #endif
  1176. if (GetProviderType(bstrTemp2, &dwTemp) == FALSE)
  1177. {
  1178. // This will most likely never happen, because in order to
  1179. // get here the CSP must exist, but...
  1180. ResErr(IDS_ERR_BAD_CSP);
  1181. SysFreeString(bstrTemp);
  1182. SysFreeString(bstrTemp2);
  1183. dwErrors++;
  1184. goto SignCleanupAndExit;
  1185. }
  1186. #ifdef SIGNTOOL_DEBUG
  1187. if (gDebug)
  1188. wprintf(L"Provider Type is: %d\n", dwTemp);
  1189. #endif
  1190. hr = pIPrivateKey->Open(bstrTemp, // Container Name
  1191. bstrTemp2, // CSP
  1192. (CAPICOM_PROV_TYPE) dwTemp,
  1193. CAPICOM_KEY_SPEC_SIGNATURE,
  1194. CAPICOM_CURRENT_USER_STORE,
  1195. TRUE);
  1196. if (FAILED(hr))
  1197. hr = pIPrivateKey->Open(bstrTemp, // Container Name
  1198. bstrTemp2, // CSP
  1199. (CAPICOM_PROV_TYPE) dwTemp,
  1200. CAPICOM_KEY_SPEC_KEYEXCHANGE,
  1201. CAPICOM_CURRENT_USER_STORE,
  1202. TRUE);
  1203. if (FAILED(hr))
  1204. hr = pIPrivateKey->Open(bstrTemp, // Container Name
  1205. bstrTemp2, // CSP
  1206. (CAPICOM_PROV_TYPE) dwTemp,
  1207. CAPICOM_KEY_SPEC_SIGNATURE,
  1208. CAPICOM_LOCAL_MACHINE_STORE,
  1209. TRUE);
  1210. if (FAILED(hr))
  1211. hr = pIPrivateKey->Open(bstrTemp, // Container Name
  1212. bstrTemp2, // CSP
  1213. (CAPICOM_PROV_TYPE) dwTemp,
  1214. CAPICOM_KEY_SPEC_KEYEXCHANGE,
  1215. CAPICOM_LOCAL_MACHINE_STORE,
  1216. TRUE);
  1217. }
  1218. SysFreeString(bstrTemp);
  1219. SysFreeString(bstrTemp2);
  1220. if (FAILED(hr))
  1221. {
  1222. switch (hr)
  1223. {
  1224. case NTE_BAD_KEYSET:
  1225. // The CSP replied that the keyset does not exist
  1226. ResErr(IDS_ERR_BAD_KEY_CONTAINER);
  1227. break;
  1228. case NTE_KEYSET_NOT_DEF:
  1229. // The CSP probably doesn't exist
  1230. ResErr(IDS_ERR_BAD_CSP);
  1231. break;
  1232. default:
  1233. FormatIErrRet(L"IPrivateKey::Open", hr);
  1234. ResErr(IDS_ERR_PRIV_KEY);
  1235. }
  1236. dwErrors++;
  1237. goto SignCleanupAndExit;
  1238. }
  1239. // We've got a private key. Now associate it with the Cert:
  1240. hr = pICert2Selected->put_PrivateKey(pIPrivateKey);
  1241. if (FAILED(hr))
  1242. {
  1243. switch (hr)
  1244. {
  1245. case NTE_BAD_PUBLIC_KEY:
  1246. ResErr(IDS_ERR_PRIV_KEY_MISMATCH);
  1247. break;
  1248. case E_ACCESSDENIED:
  1249. default:
  1250. FormatIErrRet(L"ICertificate2::put_PrivateKey", hr);
  1251. }
  1252. dwErrors++;
  1253. goto SignCleanupAndExit;
  1254. }
  1255. pIPrivateKey->Release();
  1256. pIPrivateKey = NULL;
  1257. }
  1258. else
  1259. {
  1260. // We don't have to add Key info, so just check that it's there:
  1261. hr = pICert2Selected->HasPrivateKey(&boolTemp);
  1262. if (FAILED(hr))
  1263. {
  1264. FormatIErrRet(L"ICertificate2::HasPrivateKey", hr);
  1265. dwErrors++;
  1266. goto SignCleanupAndExit;
  1267. }
  1268. if (boolTemp == FALSE)
  1269. {
  1270. ResErr(IDS_ERR_CERT_NO_PRIV_KEY);
  1271. dwErrors++;
  1272. goto SignCleanupAndExit;
  1273. }
  1274. }
  1275. #ifdef SIGNTOOL_DEBUG
  1276. if (gDebug)
  1277. {
  1278. // Print the private key info of the selected cert:
  1279. if (SUCCEEDED(pICert2Selected->get_PrivateKey(&pIPrivateKey)))
  1280. {
  1281. wprintf(L"Private Key Info:\n");
  1282. if (SUCCEEDED(pIPrivateKey->get_ProviderName(&bstrTemp)))
  1283. {
  1284. wprintf(L"\tProvider: %s\n", bstrTemp);
  1285. SysFreeString(bstrTemp);
  1286. }
  1287. if (SUCCEEDED(pIPrivateKey->get_ContainerName(&bstrTemp)))
  1288. {
  1289. wprintf(L"\tContainer: %s\n", bstrTemp);
  1290. SysFreeString(bstrTemp);
  1291. }
  1292. if (SUCCEEDED(pIPrivateKey->get_ProviderType(&provtypeTemp)))
  1293. {
  1294. wprintf(L"\tProvider Type: ");
  1295. switch (provtypeTemp)
  1296. {
  1297. case CAPICOM_PROV_RSA_FULL: wprintf(L"RSA_FULL\n"); break;
  1298. case CAPICOM_PROV_RSA_SIG: wprintf(L"RSA_SIG\n"); break;
  1299. case CAPICOM_PROV_DSS: wprintf(L"DSS\n"); break;
  1300. case CAPICOM_PROV_FORTEZZA: wprintf(L"FORTEZZA\n"); break;
  1301. case CAPICOM_PROV_MS_EXCHANGE: wprintf(L"MS_EXCHANGE\n"); break;
  1302. case CAPICOM_PROV_SSL: wprintf(L"SSL\n"); break;
  1303. case CAPICOM_PROV_RSA_SCHANNEL: wprintf(L"RSA_SCHANNEL\n"); break;
  1304. case CAPICOM_PROV_DSS_DH: wprintf(L"DSS_DH\n"); break;
  1305. case CAPICOM_PROV_EC_ECDSA_SIG: wprintf(L"EC_ECDSA_SIG\n"); break;
  1306. case CAPICOM_PROV_EC_ECNRA_SIG: wprintf(L"EC_ECNRA_SIG\n"); break;
  1307. case CAPICOM_PROV_EC_ECDSA_FULL: wprintf(L"EC_ECDSA_FULL\n"); break;
  1308. case CAPICOM_PROV_EC_ECNRA_FULL: wprintf(L"EC_ECNRA_FULL\n"); break;
  1309. case CAPICOM_PROV_DH_SCHANNEL: wprintf(L"DH_SCHANNEL\n"); break;
  1310. case CAPICOM_PROV_SPYRUS_LYNKS: wprintf(L"SPYRUS_LYNKS\n"); break;
  1311. case CAPICOM_PROV_RNG: wprintf(L"RNG\n"); break;
  1312. case CAPICOM_PROV_INTEL_SEC: wprintf(L"INTEL_SEC\n"); break;
  1313. case CAPICOM_PROV_REPLACE_OWF: wprintf(L"REPLACE_OWF\n"); break;
  1314. case CAPICOM_PROV_RSA_AES: wprintf(L"RSA_AES\n"); break;
  1315. default: wprintf(L"Unrecognized Type (0x%08X)\n", provtypeTemp);
  1316. }
  1317. }
  1318. if (SUCCEEDED(pIPrivateKey->get_KeySpec(&keyspecTemp)))
  1319. {
  1320. wprintf(L"\tKey Spec: ");
  1321. switch (keyspecTemp)
  1322. {
  1323. case CAPICOM_KEY_SPEC_KEYEXCHANGE: wprintf(L"KEYEXCHANGE\n"); break;
  1324. case CAPICOM_KEY_SPEC_SIGNATURE: wprintf(L"SIGNATURE\n"); break;
  1325. default: wprintf(L"Unrecognized (0x%08X)\n", keyspecTemp);
  1326. }
  1327. }
  1328. if (SUCCEEDED(pIPrivateKey->IsMachineKeyset(&boolTemp)))
  1329. {
  1330. wprintf(L"\tKey Set Type: ");
  1331. if (boolTemp)
  1332. wprintf(L"MACHINE\n");
  1333. else
  1334. wprintf(L"USER\n");
  1335. }
  1336. }
  1337. }
  1338. #endif
  1339. // Create the SignedCode object:
  1340. hr = CoCreateInstance(__uuidof(SignedCode), NULL, CLSCTX_ALL,
  1341. __uuidof(ISignedCode), (LPVOID*)&pISignedCode);
  1342. if (FAILED(hr))
  1343. {
  1344. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  1345. {
  1346. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  1347. }
  1348. else
  1349. {
  1350. FormatErrRet(L"CoCreateInstance", hr);
  1351. }
  1352. dwErrors++;
  1353. goto SignCleanupAndExit;
  1354. }
  1355. // Create and Build the Signer Object:
  1356. hr = CoCreateInstance(__uuidof(Signer), NULL, CLSCTX_ALL,
  1357. __uuidof(ISigner2), (LPVOID*)&pISigner2);
  1358. if (FAILED(hr))
  1359. {
  1360. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  1361. {
  1362. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  1363. }
  1364. else
  1365. {
  1366. FormatErrRet(L"CoCreateInstance", hr);
  1367. }
  1368. dwErrors++;
  1369. goto SignCleanupAndExit;
  1370. }
  1371. hr = pISigner2->put_Certificate(pICert2Selected);
  1372. if (FAILED(hr))
  1373. {
  1374. FormatIErrRet(L"ISigner2::put_Certificate", hr);
  1375. dwErrors++;
  1376. goto SignCleanupAndExit;
  1377. }
  1378. hr = pISigner2->put_Options(CAPICOM_CERTIFICATE_INCLUDE_CHAIN_EXCEPT_ROOT);
  1379. if (FAILED(hr))
  1380. {
  1381. FormatIErrRet(L"ISigner2::put_Options", hr);
  1382. dwErrors++;
  1383. goto SignCleanupAndExit;
  1384. }
  1385. // If we opened our cert from a file, add that file to the Signer
  1386. // as an additional cert store for optimal chaining.
  1387. if (InputInfo->wszCertFile)
  1388. {
  1389. // Get the ICertStore interface:
  1390. hr = pIStore2->QueryInterface(__uuidof(ICertStore),
  1391. (LPVOID*)&pICertStore);
  1392. if (FAILED(hr))
  1393. {
  1394. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  1395. {
  1396. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  1397. }
  1398. else
  1399. {
  1400. FormatErrRet(L"ISigner2::QueryInterface", hr);
  1401. }
  1402. dwErrors++;
  1403. goto SignCleanupAndExit;
  1404. }
  1405. // Get the HCERTSTORE of the store:
  1406. hr = pICertStore->get_StoreHandle((LONG*) &hStore);
  1407. if (FAILED(hr))
  1408. {
  1409. FormatIErrRet(L"ICertStore::get_StoreHandle", hr);
  1410. dwErrors++;
  1411. goto SignCleanupAndExit;
  1412. }
  1413. // Get the ICSigner interface:
  1414. hr = pISigner2->QueryInterface(__uuidof(ICSigner),
  1415. (LPVOID*)&pICSigner);
  1416. if (FAILED(hr))
  1417. {
  1418. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  1419. {
  1420. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  1421. }
  1422. else
  1423. {
  1424. FormatErrRet(L"ISigner2::QueryInterface", hr);
  1425. }
  1426. dwErrors++;
  1427. goto SignCleanupAndExit;
  1428. }
  1429. // Add the HCERTSTORE handle to the Signer:
  1430. hr = pICSigner->put_AdditionalStore((LONG) hStore);
  1431. if (FAILED(hr))
  1432. {
  1433. FormatIErrRet(L"ICertStore::get_StoreHandle", hr);
  1434. dwErrors++;
  1435. goto SignCleanupAndExit;
  1436. }
  1437. //CertCloseStore(hStore, 0);
  1438. //hStore = NULL;
  1439. printf("Done Adding Additional Store\n");
  1440. }
  1441. // Check if we are in the 32-bit Emulator on a 64-bit system
  1442. if (InputInfo->fIsWow64Process)
  1443. {
  1444. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1445. OldWow64Setting = Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1446. }
  1447. // Loop over the files and sign them:
  1448. for (DWORD i=0; i<InputInfo->NumFiles; i++)
  1449. {
  1450. // Find the last slash in the path specification:
  1451. LastSlash = 0;
  1452. for (DWORD s=0; s<wcslen(InputInfo->rgwszFileNames[i]); s++)
  1453. {
  1454. if ((wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L"\\", 1) == 0) ||
  1455. (wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L"/", 1) == 0) ||
  1456. (wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L":", 1) == 0))
  1457. {
  1458. // Set LastSlash to the character after the last slash:
  1459. LastSlash = s + 1;
  1460. }
  1461. }
  1462. wcsncpy(wszTempFileName, InputInfo->rgwszFileNames[i], MAX_PATH);
  1463. wszTempFileName[MAX_PATH-1] = L'\0';
  1464. dwcFound = 0;
  1465. hFind = FindFirstFileU(InputInfo->rgwszFileNames[i], &FindFileData);
  1466. if (hFind == INVALID_HANDLE_VALUE)
  1467. {
  1468. // No files found matching that name
  1469. dwErrors++;
  1470. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->rgwszFileNames[i]);
  1471. continue;
  1472. }
  1473. do
  1474. {
  1475. if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  1476. {
  1477. dwcFound++; // Increment number of files (not dirs) found
  1478. // matching this filespec
  1479. // Copy the filename on after the last slash:
  1480. wcsncpy(&(wszTempFileName[LastSlash]),
  1481. FindFileData.cFileName, MAX_PATH-LastSlash);
  1482. wszTempFileName[MAX_PATH-1] = L'\0';
  1483. if (InputInfo->Verbose)
  1484. {
  1485. ResFormatOut(IDS_INFO_SIGN_ATTEMPT, wszTempFileName);
  1486. }
  1487. if (InputInfo->fIsWow64Process)
  1488. {
  1489. // Disable WOW64 file-system redirection for our current file only
  1490. Wow64SetFilesystemRedirectorEx(wszTempFileName);
  1491. }
  1492. // Set the filename in the SignedCode object:
  1493. if ((bstrTemp = SysAllocString(wszTempFileName)) != NULL)
  1494. {
  1495. hr = pISignedCode->put_FileName(bstrTemp);
  1496. if (FAILED(hr))
  1497. {
  1498. FormatIErrRet(L"ISignedCode::put_FileName", hr);
  1499. dwErrors++;
  1500. if (InputInfo->fIsWow64Process)
  1501. {
  1502. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1503. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1504. }
  1505. continue;
  1506. }
  1507. SysFreeString(bstrTemp);
  1508. }
  1509. else
  1510. {
  1511. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  1512. dwErrors++;
  1513. if (InputInfo->fIsWow64Process)
  1514. {
  1515. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1516. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1517. }
  1518. continue;
  1519. }
  1520. // Set the Description:
  1521. if (InputInfo->wszDescription)
  1522. {
  1523. if ((bstrTemp = SysAllocString(InputInfo->wszDescription)) != NULL)
  1524. {
  1525. hr = pISignedCode->put_Description(bstrTemp);
  1526. SysFreeString(bstrTemp);
  1527. if (FAILED(hr))
  1528. {
  1529. FormatIErrRet(L"ISignedCode::put_Description", hr);
  1530. dwErrors++;
  1531. if (InputInfo->fIsWow64Process)
  1532. {
  1533. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1534. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1535. }
  1536. continue;
  1537. }
  1538. }
  1539. else
  1540. {
  1541. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  1542. dwErrors++;
  1543. if (InputInfo->fIsWow64Process)
  1544. {
  1545. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1546. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1547. }
  1548. continue;
  1549. }
  1550. }
  1551. // Set the Description URL:
  1552. if (InputInfo->wszDescURL)
  1553. {
  1554. if ((bstrTemp = SysAllocString(InputInfo->wszDescURL)) != NULL)
  1555. {
  1556. hr = pISignedCode->put_DescriptionURL(bstrTemp);
  1557. SysFreeString(bstrTemp);
  1558. if (FAILED(hr))
  1559. {
  1560. FormatIErrRet(L"ISignedCode::put_DescriptionURL", hr);
  1561. dwErrors++;
  1562. if (InputInfo->fIsWow64Process)
  1563. {
  1564. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1565. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1566. }
  1567. continue;
  1568. }
  1569. }
  1570. else
  1571. {
  1572. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  1573. dwErrors++;
  1574. if (InputInfo->fIsWow64Process)
  1575. {
  1576. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1577. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1578. }
  1579. continue;
  1580. }
  1581. }
  1582. // Sign the file:
  1583. hr = pISignedCode->Sign(pISigner2);
  1584. if (SUCCEEDED(hr))
  1585. {
  1586. if (InputInfo->wszTimeStampURL)
  1587. {
  1588. bstrTemp = SysAllocString(InputInfo->wszTimeStampURL);
  1589. if (bstrTemp == NULL)
  1590. {
  1591. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  1592. dwErrors++;
  1593. if (InputInfo->fIsWow64Process)
  1594. {
  1595. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1596. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1597. }
  1598. continue;
  1599. }
  1600. hr = pISignedCode->Timestamp(bstrTemp);
  1601. if (SUCCEEDED(hr))
  1602. {
  1603. // Signing and Timestamping succeeded
  1604. if (!InputInfo->Quiet)
  1605. {
  1606. ResFormatOut(IDS_INFO_SIGN_SUCCESS_T,
  1607. wszTempFileName);
  1608. }
  1609. SysFreeString(bstrTemp);
  1610. dwDone++;
  1611. }
  1612. else
  1613. {
  1614. // Signing succeeded, but timestamping failed
  1615. if (!InputInfo->Quiet)
  1616. {
  1617. switch (hr)
  1618. {
  1619. case CAPICOM_E_CODE_NOT_SIGNED:
  1620. ResErr(IDS_ERR_TIMESTAMP_NO_SIG);
  1621. break;
  1622. case CAPICOM_E_CODE_INVALID_TIMESTAMP_URL:
  1623. case CRYPT_E_ASN1_BADTAG:
  1624. ResErr(IDS_ERR_TIMESTAMP_BAD_URL);
  1625. break;
  1626. default:
  1627. FormatIErrRet(L"ISignedCode::Timestamp", hr);
  1628. }
  1629. }
  1630. ResFormatErr(IDS_WARN_SIGN_NO_TIMESTAMP,
  1631. wszTempFileName);
  1632. SysFreeString(bstrTemp);
  1633. dwWarnings++;
  1634. dwDone++;
  1635. }
  1636. }
  1637. else
  1638. {
  1639. // Signing succeeded
  1640. if (!InputInfo->Quiet)
  1641. {
  1642. ResFormatOut(IDS_INFO_SIGN_SUCCESS,
  1643. wszTempFileName);
  1644. }
  1645. dwDone++;
  1646. }
  1647. }
  1648. else
  1649. {
  1650. // Signing Failed
  1651. if (!InputInfo->Quiet)
  1652. {
  1653. switch (hr)
  1654. {
  1655. case TRUST_E_SUBJECT_FORM_UNKNOWN:
  1656. ResErr(IDS_ERR_SIGN_FILE_FORMAT);
  1657. break;
  1658. case E_ACCESSDENIED:
  1659. ResErr(IDS_ERR_ACCESS_DENIED);
  1660. break;
  1661. case 0x80070020: // ERROR_SHARING_VIOLATION
  1662. ResErr(IDS_ERR_SHARING_VIOLATION);
  1663. break;
  1664. case 0x800703EE: // STATUS_MAPPED_FILE_SIZE_ZERO
  1665. ResErr(IDS_ERR_FILE_SIZE_ZERO);
  1666. break;
  1667. default:
  1668. FormatIErrRet(L"ISignedCode::Sign", hr);
  1669. }
  1670. }
  1671. ResFormatErr(IDS_ERR_SIGN, wszTempFileName);
  1672. dwErrors++;
  1673. }
  1674. if (InputInfo->fIsWow64Process)
  1675. {
  1676. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1677. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1678. }
  1679. }
  1680. } while (FindNextFileU(hFind, &FindFileData));
  1681. if (dwcFound == 0) // No files were found matching this filespec
  1682. { // this will only fire if only directories were found.
  1683. dwErrors++;
  1684. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->rgwszFileNames[i]);
  1685. continue;
  1686. }
  1687. FindClose(hFind);
  1688. hFind = NULL;
  1689. }
  1690. if (InputInfo->fIsWow64Process)
  1691. {
  1692. // Re-ensable WOW64 file-system redirection
  1693. Wow64SetFilesystemRedirectorEx(OldWow64Setting);
  1694. }
  1695. SignCleanupAndExit:
  1696. //Print Summary Information:
  1697. if (InputInfo->Verbose || (!InputInfo->Quiet && (dwErrors || dwWarnings)))
  1698. {
  1699. wprintf(L"\n");
  1700. if (InputInfo->Verbose || dwDone)
  1701. ResFormatOut(IDS_INFO_SIGNED, dwDone);
  1702. if (InputInfo->Verbose || dwWarnings)
  1703. ResFormatOut(IDS_INFO_WARNINGS, dwWarnings);
  1704. if (InputInfo->Verbose || dwErrors)
  1705. ResFormatOut(IDS_INFO_ERRORS, dwErrors);
  1706. }
  1707. if (pISigner2)
  1708. pISigner2->Release();
  1709. if (pICSigner)
  1710. pICSigner->Release();
  1711. if (pISignedCode)
  1712. pISignedCode->Release();
  1713. if (pIPrivateKey)
  1714. pIPrivateKey->Release();
  1715. if (pICert2Selected)
  1716. pICert2Selected->Release();
  1717. if (pICert2Temp)
  1718. pICert2Temp->Release();
  1719. if (pICerts)
  1720. pICerts->Release();
  1721. if (pICerts2Original)
  1722. pICerts2Original->Release();
  1723. if (pICerts2Selected)
  1724. pICerts2Selected->Release();
  1725. if (pICerts2Temp)
  1726. pICerts2Temp->Release();
  1727. if (hStore)
  1728. CertCloseStore(hStore, 0);
  1729. if (pICertStore)
  1730. pICertStore->Release();
  1731. if (pIStore2Temp)
  1732. pIStore2Temp->Release();
  1733. if (pIStore2)
  1734. pIStore2->Release();
  1735. CoUninitialize();
  1736. if (dwErrors)
  1737. return 1; // Error
  1738. if (dwWarnings)
  1739. return 2; // Warning
  1740. if (dwDone)
  1741. return 0; // Success
  1742. // One of the above returns should fire, so
  1743. // this should never happen:
  1744. ResErr(IDS_ERR_NO_FILES_DONE);
  1745. ResErr(IDS_ERR_UNEXPECTED);
  1746. return 1; // Error
  1747. }
  1748. int SignTool_SignWizard(INPUTINFO *InputInfo)
  1749. {
  1750. DWORD dwcFound;
  1751. DWORD dwDone = 0;
  1752. DWORD dwWarnings = 0;
  1753. DWORD dwErrors = 0;
  1754. WIN32_FIND_DATAW FindFileData;
  1755. HANDLE hFind = NULL;
  1756. HRESULT hr;
  1757. PVOID OldWow64Setting;
  1758. WCHAR wszTempFileName[MAX_PATH];
  1759. int LastSlash;
  1760. CRYPTUI_WIZ_DIGITAL_SIGN_INFO DigitalSignInfo;
  1761. // If no files were specified, launch the wizard without parameters:
  1762. if (InputInfo->rgwszFileNames == NULL)
  1763. {
  1764. // Set up the Wizard's struct:
  1765. ZeroMemory(&DigitalSignInfo, sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO));
  1766. DigitalSignInfo.dwSize = sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO);
  1767. if (InputInfo->Verbose)
  1768. {
  1769. ResFormatOut(IDS_INFO_SIGNWIZARD_ATTEMPT, L"<>");
  1770. }
  1771. // Invoke the Wizard:
  1772. if (CryptUIWizDigitalSign(0,
  1773. NULL,
  1774. NULL,
  1775. &DigitalSignInfo,
  1776. NULL))
  1777. {
  1778. // Success
  1779. if (!InputInfo->Quiet)
  1780. {
  1781. ResFormatOut(IDS_INFO_SIGNWIZARD_SUCCESS, L"<>");
  1782. }
  1783. dwDone++;
  1784. }
  1785. else
  1786. {
  1787. // Failure
  1788. if (InputInfo->Verbose)
  1789. {
  1790. FormatErrRet(L"CryptUIWizDigitalSign", GetLastError());
  1791. }
  1792. ResFormatErr(IDS_ERR_SIGNWIZARD, L"<>");
  1793. dwErrors++;
  1794. }
  1795. goto SignWizardCleanupAndExit;
  1796. }
  1797. // Check if we are in the 32-bit Emulator on a 64-bit system
  1798. if (InputInfo->fIsWow64Process)
  1799. {
  1800. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1801. OldWow64Setting = Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1802. }
  1803. // Loop over the files and send them to the signing wizard:
  1804. for (DWORD i=0; i<InputInfo->NumFiles; i++)
  1805. {
  1806. // Find the last slash in the path specification:
  1807. LastSlash = 0;
  1808. for (DWORD s=0; s<wcslen(InputInfo->rgwszFileNames[i]); s++)
  1809. {
  1810. if ((wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L"\\", 1) == 0) ||
  1811. (wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L"/", 1) == 0) ||
  1812. (wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L":", 1) == 0))
  1813. {
  1814. // Set LastSlash to the character after the last slash:
  1815. LastSlash = s + 1;
  1816. }
  1817. }
  1818. wcsncpy(wszTempFileName, InputInfo->rgwszFileNames[i], MAX_PATH);
  1819. wszTempFileName[MAX_PATH-1] = L'\0';
  1820. dwcFound = 0;
  1821. hFind = FindFirstFileU(InputInfo->rgwszFileNames[i], &FindFileData);
  1822. if (hFind == INVALID_HANDLE_VALUE)
  1823. {
  1824. // No files found matching that name
  1825. dwErrors++;
  1826. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->rgwszFileNames[i]);
  1827. continue;
  1828. }
  1829. do
  1830. {
  1831. if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  1832. {
  1833. dwcFound++; // Increment number of files (not dirs) found
  1834. // matching this filespec
  1835. // Copy the filename on after the last slash:
  1836. wcsncpy(&(wszTempFileName[LastSlash]),
  1837. FindFileData.cFileName, MAX_PATH-LastSlash);
  1838. wszTempFileName[MAX_PATH-1] = L'\0';
  1839. if (InputInfo->fIsWow64Process)
  1840. {
  1841. // Disable WOW64 file-system redirection for our current file only
  1842. Wow64SetFilesystemRedirectorEx(wszTempFileName);
  1843. }
  1844. if (InputInfo->Verbose)
  1845. {
  1846. ResFormatOut(IDS_INFO_SIGNWIZARD_ATTEMPT, wszTempFileName);
  1847. }
  1848. // Set up the Wizard's struct:
  1849. ZeroMemory(&DigitalSignInfo, sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO));
  1850. DigitalSignInfo.dwSize = sizeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO);
  1851. DigitalSignInfo.dwSubjectChoice = CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE;
  1852. DigitalSignInfo.pwszFileName = wszTempFileName;
  1853. // Invoke the Wizard:
  1854. if (CryptUIWizDigitalSign(0,
  1855. NULL,
  1856. NULL,
  1857. &DigitalSignInfo,
  1858. NULL))
  1859. {
  1860. // Success
  1861. if (!InputInfo->Quiet)
  1862. {
  1863. ResFormatOut(IDS_INFO_SIGNWIZARD_SUCCESS,
  1864. wszTempFileName);
  1865. }
  1866. dwDone++;
  1867. }
  1868. else
  1869. {
  1870. // Failure
  1871. if (InputInfo->Verbose)
  1872. {
  1873. FormatErrRet(L"CryptUIWizDigitalSign", GetLastError());
  1874. }
  1875. ResFormatErr(IDS_ERR_SIGNWIZARD, wszTempFileName);
  1876. dwErrors++;
  1877. }
  1878. if (InputInfo->fIsWow64Process)
  1879. {
  1880. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1881. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1882. }
  1883. }
  1884. } while (FindNextFileU(hFind, &FindFileData));
  1885. if (dwcFound == 0) // No files were found matching this filespec
  1886. { // this will only fire if only directories were found.
  1887. dwErrors++;
  1888. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->rgwszFileNames[i]);
  1889. continue;
  1890. }
  1891. FindClose(hFind);
  1892. hFind = NULL;
  1893. }
  1894. if (InputInfo->fIsWow64Process)
  1895. {
  1896. // Re-ensable WOW64 file-system redirection
  1897. Wow64SetFilesystemRedirectorEx(OldWow64Setting);
  1898. }
  1899. SignWizardCleanupAndExit:
  1900. if (dwErrors)
  1901. return 1; // Error
  1902. if (dwWarnings)
  1903. return 2; // Warning
  1904. if (dwDone)
  1905. return 0; // Success
  1906. // One of the above returns should fire, so
  1907. // this should never happen:
  1908. ResErr(IDS_ERR_NO_FILES_DONE);
  1909. ResErr(IDS_ERR_UNEXPECTED);
  1910. return 1; // Error
  1911. }
  1912. int SignTool_Timestamp(INPUTINFO *InputInfo)
  1913. {
  1914. DWORD dwcFound;
  1915. DWORD dwDone = 0;
  1916. DWORD dwWarnings = 0;
  1917. DWORD dwErrors = 0;
  1918. WIN32_FIND_DATAW FindFileData;
  1919. HANDLE hFind = NULL;
  1920. HRESULT hr;
  1921. PVOID OldWow64Setting;
  1922. WCHAR wszTempFileName[MAX_PATH];
  1923. ISignedCode *pISignedCode = NULL;
  1924. BSTR bstrTemp;
  1925. int LastSlash;
  1926. // Initialize COM:
  1927. if ((hr = CoInitialize(NULL)) != S_OK)
  1928. {
  1929. FormatErrRet(L"CoInitialize", hr);
  1930. return 1; // Error
  1931. }
  1932. if (InputInfo->wszTimeStampURL == NULL)
  1933. {
  1934. ResErr(IDS_ERR_UNEXPECTED);
  1935. dwErrors++;
  1936. goto TimestampCleanupAndExit;
  1937. }
  1938. // Create the SignedCode object:
  1939. hr = CoCreateInstance(__uuidof(SignedCode), NULL, CLSCTX_ALL,
  1940. __uuidof(ISignedCode), (LPVOID*)&pISignedCode);
  1941. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  1942. {
  1943. // In this case, give it one more chance:
  1944. RegisterCAPICOM();
  1945. hr = CoCreateInstance(__uuidof(SignedCode), NULL, CLSCTX_ALL,
  1946. __uuidof(ISignedCode), (LPVOID*)&pISignedCode);
  1947. }
  1948. if (FAILED(hr))
  1949. {
  1950. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  1951. {
  1952. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  1953. }
  1954. else
  1955. {
  1956. FormatErrRet(L"CoCreateInstance", hr);
  1957. }
  1958. dwErrors++;
  1959. goto TimestampCleanupAndExit;
  1960. }
  1961. // Check if we are in the 32-bit Emulator on a 64-bit system
  1962. if (InputInfo->fIsWow64Process)
  1963. {
  1964. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  1965. OldWow64Setting = Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  1966. }
  1967. // Loop over the files and timestamp them:
  1968. for (DWORD i=0; i<InputInfo->NumFiles; i++)
  1969. {
  1970. // Find the last slash in the path specification:
  1971. LastSlash = 0;
  1972. for (DWORD s=0; s<wcslen(InputInfo->rgwszFileNames[i]); s++)
  1973. {
  1974. if ((wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L"\\", 1) == 0) ||
  1975. (wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L"/", 1) == 0) ||
  1976. (wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L":", 1) == 0))
  1977. {
  1978. // Set LastSlash to the character after the last slash:
  1979. LastSlash = s + 1;
  1980. }
  1981. }
  1982. wcsncpy(wszTempFileName, InputInfo->rgwszFileNames[i], MAX_PATH);
  1983. wszTempFileName[MAX_PATH-1] = L'\0';
  1984. dwcFound = 0;
  1985. hFind = FindFirstFileU(InputInfo->rgwszFileNames[i], &FindFileData);
  1986. if (hFind == INVALID_HANDLE_VALUE)
  1987. {
  1988. // No files found matching that name
  1989. dwErrors++;
  1990. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->rgwszFileNames[i]);
  1991. continue;
  1992. }
  1993. do
  1994. {
  1995. if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  1996. {
  1997. dwcFound++; // Increment number of files (not dirs) found
  1998. // matching this filespec
  1999. // Copy the filename on after the last slash:
  2000. wcsncpy(&(wszTempFileName[LastSlash]),
  2001. FindFileData.cFileName, MAX_PATH-LastSlash);
  2002. wszTempFileName[MAX_PATH-1] = L'\0';
  2003. if (InputInfo->fIsWow64Process)
  2004. {
  2005. // Disable WOW64 file-system redirection for our current file only
  2006. Wow64SetFilesystemRedirectorEx(wszTempFileName);
  2007. }
  2008. if (InputInfo->Verbose)
  2009. {
  2010. ResFormatOut(IDS_INFO_TIMESTAMP_ATTEMPT, wszTempFileName);
  2011. }
  2012. // Set the filename in the SignedCode object:
  2013. if ((bstrTemp = SysAllocString(wszTempFileName)) != NULL)
  2014. {
  2015. hr = pISignedCode->put_FileName(bstrTemp);
  2016. if (FAILED(hr))
  2017. {
  2018. FormatIErrRet(L"ISignedCode::put_FileName", hr);
  2019. SysFreeString(bstrTemp);
  2020. dwErrors++;
  2021. if (InputInfo->fIsWow64Process)
  2022. {
  2023. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  2024. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  2025. }
  2026. continue;
  2027. }
  2028. SysFreeString(bstrTemp);
  2029. }
  2030. else
  2031. {
  2032. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  2033. dwErrors++;
  2034. if (InputInfo->fIsWow64Process)
  2035. {
  2036. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  2037. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  2038. }
  2039. continue;
  2040. }
  2041. bstrTemp = SysAllocString(InputInfo->wszTimeStampURL);
  2042. if (bstrTemp == NULL)
  2043. {
  2044. FormatErrRet(L"SysAllocString", ERROR_OUTOFMEMORY);
  2045. dwErrors++;
  2046. if (InputInfo->fIsWow64Process)
  2047. {
  2048. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  2049. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  2050. }
  2051. continue;
  2052. }
  2053. // Timestamp the file:
  2054. hr = pISignedCode->Timestamp(bstrTemp);
  2055. if (SUCCEEDED(hr))
  2056. {
  2057. // Timestamping succeeded
  2058. if (!InputInfo->Quiet)
  2059. {
  2060. ResFormatOut(IDS_INFO_TIMESTAMP_SUCCESS,
  2061. wszTempFileName);
  2062. }
  2063. dwDone++;
  2064. }
  2065. else
  2066. {
  2067. // Timestamping Failed
  2068. if (!InputInfo->Quiet)
  2069. {
  2070. switch (hr)
  2071. {
  2072. case CAPICOM_E_CODE_NOT_SIGNED:
  2073. ResErr(IDS_ERR_TIMESTAMP_NO_SIG);
  2074. break;
  2075. case CAPICOM_E_CODE_INVALID_TIMESTAMP_URL:
  2076. case CRYPT_E_ASN1_BADTAG:
  2077. ResErr(IDS_ERR_TIMESTAMP_BAD_URL);
  2078. break;
  2079. case E_ACCESSDENIED:
  2080. ResErr(IDS_ERR_ACCESS_DENIED);
  2081. break;
  2082. case 0x80070020: // ERROR_SHARING_VIOLATION
  2083. ResErr(IDS_ERR_SHARING_VIOLATION);
  2084. break;
  2085. case 0x800703EE: // STATUS_MAPPED_FILE_SIZE_ZERO
  2086. ResErr(IDS_ERR_FILE_SIZE_ZERO);
  2087. break;
  2088. default:
  2089. FormatIErrRet(L"ISignedCode::Timestamp", hr);
  2090. }
  2091. }
  2092. ResFormatErr(IDS_ERR_TIMESTAMP, wszTempFileName);
  2093. dwErrors++;
  2094. }
  2095. SysFreeString(bstrTemp);
  2096. }
  2097. if (InputInfo->fIsWow64Process)
  2098. {
  2099. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  2100. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  2101. }
  2102. } while (FindNextFileU(hFind, &FindFileData));
  2103. if (dwcFound == 0) // No files were found matching this filespec
  2104. { // this will only fire if only directories were found.
  2105. dwErrors++;
  2106. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->rgwszFileNames[i]);
  2107. continue;
  2108. }
  2109. FindClose(hFind);
  2110. hFind = NULL;
  2111. }
  2112. if (InputInfo->fIsWow64Process)
  2113. {
  2114. // Re-ensable WOW64 file-system redirection
  2115. Wow64SetFilesystemRedirectorEx(OldWow64Setting);
  2116. }
  2117. TimestampCleanupAndExit:
  2118. //Print Summary Information:
  2119. if (InputInfo->Verbose || (!InputInfo->Quiet && (dwErrors || dwWarnings)))
  2120. {
  2121. wprintf(L"\n");
  2122. if (InputInfo->Verbose || dwDone)
  2123. ResFormatOut(IDS_INFO_TIMESTAMPED, dwDone);
  2124. // Commented out because no warnings are possible in this function yet:
  2125. // if (InputInfo->Verbose || dwWarnings)
  2126. // ResFormatOut(IDS_INFO_WARNINGS, dwWarnings);
  2127. if (InputInfo->Verbose || dwErrors)
  2128. ResFormatOut(IDS_INFO_ERRORS, dwErrors);
  2129. }
  2130. if (pISignedCode)
  2131. pISignedCode->Release();
  2132. CoUninitialize();
  2133. if (dwErrors)
  2134. return 1; // Error
  2135. if (dwWarnings)
  2136. return 2; // Warning
  2137. if (dwDone)
  2138. return 0; // Success
  2139. // One of the above returns should fire, so
  2140. // this should never happen:
  2141. ResErr(IDS_ERR_NO_FILES_DONE);
  2142. ResErr(IDS_ERR_UNEXPECTED);
  2143. return 1; // Error
  2144. }
  2145. void Format_IErrRet(WCHAR *wszFunc, DWORD dwErr)
  2146. {
  2147. BSTR bstrTemp;
  2148. IErrorInfo *pIErrorInfo;
  2149. if (SUCCEEDED(GetErrorInfo(0, &pIErrorInfo)))
  2150. {
  2151. if (SUCCEEDED(pIErrorInfo->GetDescription(&bstrTemp)))
  2152. {
  2153. ResFormat_Err(IDS_ERR_FUNCTION, wszFunc, dwErr, bstrTemp);
  2154. SysFreeString(bstrTemp);
  2155. }
  2156. else
  2157. {
  2158. Format_ErrRet(wszFunc, dwErr);
  2159. }
  2160. pIErrorInfo->Release();
  2161. }
  2162. else
  2163. {
  2164. Format_ErrRet(wszFunc, dwErr);
  2165. }
  2166. }
  2167. void RegisterCAPICOM()
  2168. {
  2169. typedef HRESULT (STDAPICALLTYPE *PFN_DLL_REGISTER_SERVER) (void);
  2170. WCHAR wszPath[MAX_PATH+1];
  2171. HMODULE hLib = NULL;
  2172. PFN_DLL_REGISTER_SERVER pRegFunc;
  2173. HRESULT hr;
  2174. #ifdef SIGNTOOL_DEBUG
  2175. if (gDebug)
  2176. {
  2177. wprintf(L"Attempting to register CAPICOM\n");
  2178. hr = E_UNEXPECTED; // Initialize to an Error
  2179. }
  2180. #endif
  2181. if (GetModuleFileNameU(hModule, wszPath, MAX_PATH) &&
  2182. PathRemoveFileSpecW(wszPath) &&
  2183. (wcslen(wszPath) < (MAX_PATH-12)) &&
  2184. PathAppendW(wszPath, L"\\capicom.dll"))
  2185. {
  2186. #ifdef SIGNTOOL_DEBUG
  2187. if (gDebug)
  2188. {
  2189. wprintf(L"Looking in: %s\n", wszPath);
  2190. }
  2191. #endif
  2192. hLib = LoadLibraryU(wszPath);
  2193. if (hLib != NULL)
  2194. {
  2195. pRegFunc = (PFN_DLL_REGISTER_SERVER)
  2196. GetProcAddress(hLib, "DllRegisterServer");
  2197. if (pRegFunc != NULL)
  2198. {
  2199. hr = pRegFunc();
  2200. }
  2201. #ifdef SIGNTOOL_DEBUG
  2202. else
  2203. {
  2204. wprintf(L"GetProcAddress Failed with error: 0x%08X\n", GetLastError());
  2205. }
  2206. #endif
  2207. FreeLibrary(hLib);
  2208. }
  2209. #ifdef SIGNTOOL_DEBUG
  2210. else
  2211. {
  2212. wprintf(L"LoadLibrary Failed with error: 0x%08X\n", GetLastError());
  2213. }
  2214. #endif
  2215. }
  2216. #ifdef SIGNTOOL_DEBUG
  2217. if (gDebug)
  2218. {
  2219. if (SUCCEEDED(hr))
  2220. wprintf(L"Successfully registered CAPICOM\n");
  2221. else
  2222. wprintf(L"Failed to register CAPICOM\n");
  2223. }
  2224. #endif
  2225. }
  2226. BOOL GetProviderType(LPWSTR pwszProvName, LPDWORD pdwProvType)
  2227. {
  2228. WCHAR rgProvName [MAX_PATH * sizeof(WCHAR)];
  2229. DWORD cb = sizeof(rgProvName);
  2230. DWORD dwIndex = 0;
  2231. memset(rgProvName, 0, sizeof(rgProvName));
  2232. while (CryptEnumProvidersU(
  2233. dwIndex,
  2234. NULL,
  2235. 0,
  2236. pdwProvType,
  2237. rgProvName,
  2238. &cb))
  2239. {
  2240. if (0 == wcscmp(rgProvName, pwszProvName))
  2241. {
  2242. return TRUE;
  2243. }
  2244. else
  2245. {
  2246. dwIndex++;
  2247. cb = sizeof(rgProvName);
  2248. }
  2249. }
  2250. return FALSE;
  2251. }
  2252. BOOL ChainsToRoot(HANDLE hWVTStateData, LPWSTR wszRootName)
  2253. {
  2254. CRYPT_PROVIDER_DATA *pCryptProvData;
  2255. CRYPT_PROVIDER_SGNR *pCryptProvSgnr;
  2256. ICertificates *pICerts = NULL;
  2257. ICertificate2 *pICert2 = NULL;
  2258. IChain2 *pIChain2 = NULL;
  2259. IChainContext *pIChainContext = NULL;
  2260. HRESULT hr;
  2261. LONG longRootTemp;
  2262. BSTR bstrTemp;
  2263. VARIANT varTemp;
  2264. VariantInit(&varTemp);
  2265. if (hWVTStateData == NULL)
  2266. {
  2267. ResErr(IDS_ERR_UNEXPECTED);
  2268. return FALSE; // Unexpected Error
  2269. }
  2270. pCryptProvData = WTHelperProvDataFromStateData(hWVTStateData);
  2271. if (pCryptProvData == NULL)
  2272. {
  2273. ResErr(IDS_ERR_UNEXPECTED);
  2274. return FALSE; // Unexpected Error
  2275. }
  2276. pCryptProvSgnr = WTHelperGetProvSignerFromChain(pCryptProvData, 0, FALSE, 0);
  2277. if (pCryptProvSgnr == NULL)
  2278. {
  2279. ResErr(IDS_ERR_UNEXPECTED);
  2280. return FALSE; // Unexpected Error
  2281. }
  2282. hr = CoCreateInstance(__uuidof(Chain), NULL, CLSCTX_ALL,
  2283. __uuidof(IChainContext), (LPVOID*)&pIChainContext);
  2284. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  2285. {
  2286. // In this case, give it one more chance:
  2287. RegisterCAPICOM();
  2288. hr = CoCreateInstance(__uuidof(Chain), NULL, CLSCTX_ALL,
  2289. __uuidof(IChainContext), (LPVOID*)&pIChainContext);
  2290. }
  2291. if (FAILED(hr))
  2292. {
  2293. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  2294. {
  2295. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  2296. }
  2297. else
  2298. {
  2299. FormatErrRet(L"CoCreateInstance", hr);
  2300. }
  2301. goto ErrorCleanup;
  2302. }
  2303. // fill in the pIChain2 with the Signer:
  2304. pIChainContext->put_ChainContext((LONG)pCryptProvSgnr->pChainContext);
  2305. // This will not compile on 64-bit architechtures.
  2306. // Neither will CAPICOM, which is requiring this stupid typecast.
  2307. // And then get the Chain2 interface:
  2308. hr = pIChainContext->QueryInterface(__uuidof(IChain2),
  2309. (LPVOID*)&pIChain2);
  2310. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  2311. {
  2312. // In this case, give it one more chance:
  2313. RegisterCAPICOM();
  2314. hr = pIChainContext->QueryInterface(__uuidof(IChain2),
  2315. (LPVOID*)&pIChain2);
  2316. }
  2317. if (FAILED(hr))
  2318. {
  2319. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  2320. {
  2321. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  2322. }
  2323. else
  2324. {
  2325. FormatErrRet(L"IChainContext::QueryInterface", hr);
  2326. }
  2327. goto ErrorCleanup;
  2328. }
  2329. // Release the ChainContext interface:
  2330. pIChainContext->Release();
  2331. pIChainContext = NULL;
  2332. // Get the Certs collection from the Chain:
  2333. hr = pIChain2->get_Certificates(&pICerts);
  2334. if (FAILED(hr))
  2335. {
  2336. FormatErrRet(L"IChain2::get_Certificates", hr);
  2337. goto ErrorCleanup;
  2338. }
  2339. pIChain2->Release();
  2340. pIChain2 = NULL;
  2341. // Get the Count in the Chain Certs list:
  2342. hr = pICerts->get_Count(&longRootTemp);
  2343. if (FAILED(hr))
  2344. {
  2345. FormatErrRet(L"IChain2::get_Count", hr);
  2346. goto ErrorCleanup;
  2347. }
  2348. // Sanity check:
  2349. if (longRootTemp < 1)
  2350. goto ErrorCleanup;
  2351. // Get the last cert in the chain (the Root);
  2352. hr = pICerts->get_Item(longRootTemp, &varTemp);
  2353. if (FAILED(hr))
  2354. {
  2355. FormatErrRet(L"IChain2::get_Item", hr);
  2356. goto ErrorCleanup;
  2357. }
  2358. pICerts->Release();
  2359. pICerts = NULL;
  2360. // Get the Certificate2 Interface:
  2361. hr = varTemp.pdispVal->QueryInterface(__uuidof(ICertificate2),
  2362. (LPVOID*)&pICert2);
  2363. if (FAILED(hr))
  2364. {
  2365. FormatErrRet(L"ICertificate::QueryInterface", hr);
  2366. goto ErrorCleanup;
  2367. }
  2368. VariantClear(&varTemp);
  2369. // Get the Name of the Root Cert:
  2370. hr = pICert2->get_SubjectName(&bstrTemp);
  2371. if (FAILED(hr))
  2372. {
  2373. FormatErrRet(L"ICertificate2::get_SubjectName", hr);
  2374. goto ErrorCleanup;
  2375. }
  2376. pICert2->Release();
  2377. pICert2 = NULL;
  2378. _wcslwr(bstrTemp); // The Root name passed in must also be lowercased.
  2379. if (wcsstr(bstrTemp, wszRootName) == NULL)
  2380. {
  2381. // Then this is the wrong Root Cert.
  2382. // It failed. Report Error:
  2383. #ifdef SIGNTOOL_DEBUG
  2384. if (gDebug)
  2385. {
  2386. wprintf(L"Root subject name does not match: %s\n", bstrTemp);
  2387. }
  2388. #endif
  2389. SysFreeString(bstrTemp);
  2390. return FALSE;
  2391. }
  2392. else
  2393. {
  2394. // It matched. Success.
  2395. #ifdef SIGNTOOL_DEBUG
  2396. if (gDebug)
  2397. {
  2398. wprintf(L"Root subject name matches: %s\n", bstrTemp);
  2399. }
  2400. #endif
  2401. SysFreeString(bstrTemp);
  2402. return TRUE;
  2403. }
  2404. ErrorCleanup:
  2405. if (pICert2)
  2406. pICert2->Release();
  2407. if (pICerts)
  2408. pICerts->Release();
  2409. if (pIChain2)
  2410. pIChain2->Release();
  2411. if (pIChainContext)
  2412. pIChainContext->Release();
  2413. return FALSE;
  2414. }
  2415. BOOL HasTimestamp(HANDLE hWVTStateData)
  2416. {
  2417. CRYPT_PROVIDER_DATA *pCryptProvData;
  2418. CRYPT_PROVIDER_SGNR *pCryptProvSgnr;
  2419. if (hWVTStateData == NULL)
  2420. return FALSE; // Unexpected Error
  2421. pCryptProvData = WTHelperProvDataFromStateData(hWVTStateData);
  2422. if (pCryptProvData == NULL)
  2423. return FALSE; // Unexpected Error
  2424. pCryptProvSgnr = WTHelperGetProvSignerFromChain(pCryptProvData, 0, FALSE, 0);
  2425. if (pCryptProvSgnr == NULL)
  2426. return FALSE; // Unexpected Error
  2427. return(pCryptProvSgnr->csCounterSigners == 1); // Valid result
  2428. }
  2429. void PrintSignerInfo(HANDLE hWVTStateData)
  2430. {
  2431. CRYPT_PROVIDER_DATA *pCryptProvData;
  2432. CRYPT_PROVIDER_SGNR *pCryptProvSgnr;
  2433. WCHAR wcsTemp[200];
  2434. IChain2 *pIChain2 = NULL;
  2435. IChainContext *pIChainContext = NULL;
  2436. COleDateTime DateTime;
  2437. HRESULT hr;
  2438. if (hWVTStateData == NULL)
  2439. goto Cleanup;
  2440. pCryptProvData = WTHelperProvDataFromStateData(hWVTStateData);
  2441. if (pCryptProvData == NULL)
  2442. goto Cleanup;
  2443. pCryptProvSgnr = WTHelperGetProvSignerFromChain(pCryptProvData, 0, FALSE, 0);
  2444. if (pCryptProvSgnr == NULL)
  2445. goto Cleanup;
  2446. hr = CoCreateInstance(__uuidof(Chain), NULL, CLSCTX_ALL,
  2447. __uuidof(IChainContext), (LPVOID*)&pIChainContext);
  2448. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  2449. {
  2450. // In this case, give it one more chance:
  2451. RegisterCAPICOM();
  2452. hr = CoCreateInstance(__uuidof(Chain), NULL, CLSCTX_ALL,
  2453. __uuidof(IChainContext), (LPVOID*)&pIChainContext);
  2454. }
  2455. if (FAILED(hr))
  2456. {
  2457. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  2458. {
  2459. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  2460. }
  2461. else
  2462. {
  2463. FormatErrRet(L"CoCreateInstance", hr);
  2464. }
  2465. goto Cleanup;
  2466. }
  2467. // fill in the pIChain2 with the Signer:
  2468. pIChainContext->put_ChainContext((LONG)pCryptProvSgnr->pChainContext);
  2469. // This will not compile on 64-bit architechtures.
  2470. // Neither will CAPICOM, which is requiring this stupid typecast.
  2471. // And then get the Chain2 interface:
  2472. hr = pIChainContext->QueryInterface(__uuidof(IChain2),
  2473. (LPVOID*)&pIChain2);
  2474. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  2475. {
  2476. // In this case, give it one more chance:
  2477. RegisterCAPICOM();
  2478. hr = pIChainContext->QueryInterface(__uuidof(IChain2),
  2479. (LPVOID*)&pIChain2);
  2480. }
  2481. if (FAILED(hr))
  2482. {
  2483. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  2484. {
  2485. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  2486. }
  2487. else
  2488. {
  2489. FormatErrRet(L"IChainContext::QueryInterface", hr);
  2490. }
  2491. goto Cleanup;
  2492. }
  2493. // Release the ChainContext interface:
  2494. pIChainContext->Release();
  2495. pIChainContext = NULL;
  2496. // Print the Signer chain
  2497. ResOut(IDS_INFO_VERIFY_SIGNER);
  2498. PrintCertChain(pIChain2);
  2499. pIChain2->Release();
  2500. pIChain2 = NULL;
  2501. if (pCryptProvSgnr->csCounterSigners == 1)
  2502. {
  2503. // Then it's timestamped.
  2504. DateTime = pCryptProvSgnr->sftVerifyAsOf;
  2505. if (MultiByteToWideChar(CP_THREAD_ACP, 0,
  2506. DateTime.Format(0, LANG_USER_DEFAULT), -1,
  2507. wcsTemp, 199) == 0)
  2508. {
  2509. // Try again with ANSI codepage:
  2510. MultiByteToWideChar(CP_ACP, 0,
  2511. DateTime.Format(0, LANG_USER_DEFAULT), -1,
  2512. wcsTemp, 199);
  2513. }
  2514. wcsTemp[199] = L'\0';
  2515. ResFormatOut(IDS_INFO_VERIFY_TIME, wcsTemp);
  2516. ResOut(IDS_INFO_VERIFY_TIMESTAMP);
  2517. // Build and print the timestamp chain:
  2518. pCryptProvSgnr = WTHelperGetProvSignerFromChain(pCryptProvData, 0, TRUE, 0);
  2519. if (pCryptProvSgnr == NULL)
  2520. goto Cleanup;
  2521. hr = CoCreateInstance(__uuidof(Chain), NULL, CLSCTX_ALL,
  2522. __uuidof(IChainContext), (LPVOID*)&pIChainContext);
  2523. if (FAILED(hr))
  2524. goto Cleanup;
  2525. // fill in the pIChainContext with the Timestamper:
  2526. pIChainContext->put_ChainContext((LONG)pCryptProvSgnr->pChainContext);
  2527. // This will not compile on 64-bit architechtures.
  2528. // Neither will CAPICOM, which is requiring this stupid typecast.
  2529. // And then get the Chain2 interface:
  2530. hr = pIChainContext->QueryInterface(__uuidof(IChain2),
  2531. (LPVOID*)&pIChain2);
  2532. if (FAILED(hr))
  2533. {
  2534. if ((hr == REGDB_E_CLASSNOTREG) || (hr == E_NOINTERFACE) || (hr == 0x8007007E))
  2535. {
  2536. ResErr(IDS_ERR_CAPICOM_NOT_REG);
  2537. }
  2538. else
  2539. {
  2540. FormatErrRet(L"ICertificates::QueryInterface", hr);
  2541. }
  2542. goto Cleanup;
  2543. }
  2544. // Release the ChainContext interface:
  2545. pIChainContext->Release();
  2546. pIChainContext = NULL;
  2547. // Print the Timestamper chain
  2548. PrintCertChain(pIChain2);
  2549. pIChain2->Release();
  2550. pIChain2 = NULL;
  2551. }
  2552. else
  2553. {
  2554. ResOut(IDS_INFO_VERIFY_NO_TIMESTAMP);
  2555. }
  2556. Cleanup:
  2557. if (pIChain2)
  2558. pIChain2->Release();
  2559. if (pIChainContext)
  2560. pIChainContext->Release();
  2561. }
  2562. void _indent(DWORD dwIndent)
  2563. {
  2564. for (DWORD i=0; i<dwIndent; i++)
  2565. wprintf(L" ");
  2566. }
  2567. void PrintCertInfo(ICertificate2 *pICert2)
  2568. {
  2569. PrintCertInfoIndented(pICert2, 4);
  2570. }
  2571. void PrintCertInfoIndented(ICertificate2 *pICert2, DWORD dwIndent)
  2572. {
  2573. BSTR bstrTemp;
  2574. DATE dateTemp;
  2575. COleDateTime DateTime;
  2576. WCHAR wcsTemp[200];
  2577. if (pICert2 == NULL)
  2578. {
  2579. return;
  2580. }
  2581. // Issued to:
  2582. if (pICert2->GetInfo(CAPICOM_CERT_INFO_SUBJECT_SIMPLE_NAME, &bstrTemp) == S_OK)
  2583. {
  2584. _indent(dwIndent);
  2585. ResFormatOut(IDS_INFO_CERT_NAME, bstrTemp);
  2586. SysFreeString(bstrTemp);
  2587. }
  2588. // Issued by:
  2589. if (pICert2->GetInfo(CAPICOM_CERT_INFO_ISSUER_SIMPLE_NAME, &bstrTemp) == S_OK)
  2590. {
  2591. _indent(dwIndent);
  2592. ResFormatOut(IDS_INFO_CERT_ISSUER, bstrTemp);
  2593. SysFreeString(bstrTemp);
  2594. }
  2595. // Expiration date:
  2596. if (pICert2->get_ValidToDate(&dateTemp) == S_OK)
  2597. {
  2598. DateTime = dateTemp;
  2599. if (MultiByteToWideChar(CP_THREAD_ACP, 0,
  2600. DateTime.Format(0, LANG_USER_DEFAULT), -1,
  2601. wcsTemp, 199) == 0)
  2602. {
  2603. // Try again with ANSI codepage:
  2604. MultiByteToWideChar(CP_ACP, 0,
  2605. DateTime.Format(0, LANG_USER_DEFAULT), -1,
  2606. wcsTemp, 199);
  2607. }
  2608. _indent(dwIndent);
  2609. wcsTemp[199] = L'\0';
  2610. ResFormatOut(IDS_INFO_CERT_EXPIRE, wcsTemp);
  2611. }
  2612. // SHA1 hash:
  2613. if (pICert2->get_Thumbprint(&bstrTemp) == S_OK)
  2614. {
  2615. _indent(dwIndent);
  2616. ResFormatOut(IDS_INFO_CERT_SHA1, bstrTemp);
  2617. SysFreeString(bstrTemp);
  2618. }
  2619. wprintf(L"\n");
  2620. }
  2621. void PrintCertChain(IChain *pIChain)
  2622. {
  2623. ICertificates *pICerts = NULL;
  2624. ICertificate *pICert = NULL;
  2625. ICertificate2 *pICert2 = NULL;
  2626. HRESULT hr;
  2627. VARIANT varTemp;
  2628. long longTemp;
  2629. long l;
  2630. VariantInit(&varTemp);
  2631. hr = pIChain->get_Certificates(&pICerts);
  2632. if (FAILED(hr))
  2633. {
  2634. goto Cleanup;
  2635. }
  2636. hr = pICerts->get_Count(&longTemp);
  2637. if (FAILED(hr))
  2638. {
  2639. goto Cleanup;
  2640. }
  2641. if (longTemp < 1)
  2642. {
  2643. goto Cleanup;
  2644. }
  2645. for (l=longTemp; l>0; l--)
  2646. {
  2647. hr = pICerts->get_Item(l, &varTemp);
  2648. if (FAILED(hr))
  2649. {
  2650. goto Cleanup;
  2651. }
  2652. hr = varTemp.pdispVal->QueryInterface(__uuidof(ICertificate2),
  2653. (LPVOID*)&pICert2);
  2654. if (FAILED(hr))
  2655. {
  2656. goto Cleanup;
  2657. }
  2658. VariantClear(&varTemp);
  2659. PrintCertInfoIndented(pICert2, 4*(1+longTemp-l));
  2660. pICert2->Release();
  2661. pICert2 = NULL;
  2662. }
  2663. Cleanup:
  2664. if (pICerts)
  2665. pICerts->Release();
  2666. if (pICert)
  2667. pICert->Release();
  2668. if (pICert2)
  2669. pICert2->Release();
  2670. }
  2671. int SignTool_Verify(INPUTINFO *InputInfo)
  2672. {
  2673. WIN32_FIND_DATAW FindFileData;
  2674. HRESULT hr;
  2675. HANDLE hFind;
  2676. HANDLE hFile;
  2677. HANDLE hCat = NULL;
  2678. HCATADMIN hCatAdmin = NULL;
  2679. HCATINFO hCatInfo = NULL;
  2680. CATALOG_INFO CatInfo;
  2681. CRYPTCATMEMBER *pCatMember;
  2682. WINTRUST_DATA WVTData;
  2683. WINTRUST_FILE_INFO_ WVTFile;
  2684. WINTRUST_CATALOG_INFO_ WVTCat;
  2685. GUID WVTGenericActionID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  2686. GUID WVTDriverActionID = DRIVER_ACTION_VERIFY;
  2687. DRIVER_VER_INFO DriverInfo;
  2688. PVOID OldWow64Setting;
  2689. DWORD dwcFound;
  2690. DWORD dwDone = 0;
  2691. DWORD dwWarnings = 0;
  2692. DWORD dwErrors = 0;
  2693. DWORD dwTemp;
  2694. WCHAR wszTempFileName[MAX_PATH];
  2695. WCHAR wszSHA1[41];
  2696. int LastSlash;
  2697. // Initialize COM:
  2698. if ((hr = CoInitialize(NULL)) != S_OK)
  2699. {
  2700. FormatErrRet(L"CoInitialize", hr);
  2701. return 1; // Error
  2702. }
  2703. // Check if we are in the 32-bit Emulator on a 64-bit system
  2704. if (InputInfo->fIsWow64Process)
  2705. {
  2706. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  2707. OldWow64Setting = Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  2708. }
  2709. // Loop over the files and verify them:
  2710. for (DWORD i=0; i<InputInfo->NumFiles; i++)
  2711. {
  2712. // Find the last slash in the path specification:
  2713. LastSlash = 0;
  2714. for (DWORD s=0; s<wcslen(InputInfo->rgwszFileNames[i]); s++)
  2715. {
  2716. if ((wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L"\\", 1) == 0) ||
  2717. (wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L"/", 1) == 0) ||
  2718. (wcsncmp(&(InputInfo->rgwszFileNames[i][s]), L":", 1) == 0))
  2719. {
  2720. // Set LastSlash to the character after the last slash:
  2721. LastSlash = s + 1;
  2722. }
  2723. }
  2724. wcsncpy(wszTempFileName, InputInfo->rgwszFileNames[i], MAX_PATH);
  2725. wszTempFileName[MAX_PATH-1] = L'\0';
  2726. dwcFound = 0;
  2727. hFind = FindFirstFileU(InputInfo->rgwszFileNames[i], &FindFileData);
  2728. if (hFind == INVALID_HANDLE_VALUE)
  2729. {
  2730. // No files found matching that name
  2731. dwErrors++;
  2732. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->rgwszFileNames[i]);
  2733. continue;
  2734. }
  2735. do
  2736. {
  2737. if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  2738. {
  2739. dwcFound++; // Increment number of files (not dirs) found
  2740. // matching this filespec
  2741. // For each file reset the WVT data to prevent contamination:
  2742. memset(&WVTData, 0, sizeof(WINTRUST_DATA));
  2743. WVTData.cbStruct = sizeof(WINTRUST_DATA);
  2744. WVTData.dwUIChoice = WTD_UI_NONE;
  2745. WVTData.fdwRevocationChecks = WTD_REVOKE_NONE;
  2746. memset(&WVTFile, 0, sizeof(WINTRUST_FILE_INFO_));
  2747. WVTFile.cbStruct = sizeof(WINTRUST_FILE_INFO_);
  2748. memset(&WVTCat, 0, sizeof(WINTRUST_CATALOG_INFO_));
  2749. WVTCat.cbStruct = sizeof(WINTRUST_CATALOG_INFO_);
  2750. memset(&DriverInfo, 0, sizeof(DRIVER_VER_INFO));
  2751. DriverInfo.cbStruct = sizeof(DRIVER_VER_INFO);
  2752. if (InputInfo->wszVersion)
  2753. {
  2754. DriverInfo.dwPlatform = InputInfo->dwPlatform;
  2755. DriverInfo.sOSVersionHigh.dwMajor = DriverInfo.sOSVersionLow.dwMajor = InputInfo->dwMajorVersion;
  2756. DriverInfo.sOSVersionHigh.dwMinor = DriverInfo.sOSVersionLow.dwMinor = InputInfo->dwMinorVersion;
  2757. DriverInfo.dwBuildNumberHigh = DriverInfo.dwBuildNumberLow = InputInfo->dwBuildNumber;
  2758. }
  2759. else
  2760. {
  2761. WVTData.dwProvFlags = WTD_USE_DEFAULT_OSVER_CHECK;
  2762. }
  2763. // Copy the filename on after the last slash:
  2764. wcsncpy(&(wszTempFileName[LastSlash]),
  2765. FindFileData.cFileName, MAX_PATH-LastSlash);
  2766. wszTempFileName[MAX_PATH-1] = L'\0';
  2767. if (InputInfo->fIsWow64Process)
  2768. {
  2769. // Disable WOW64 file-system redirection for our current file only
  2770. Wow64SetFilesystemRedirectorEx(wszTempFileName);
  2771. }
  2772. // Perform the action:
  2773. // Start by opening the catalog database, or skipping
  2774. // catalogs altogether:
  2775. if (InputInfo->wszCatFile)
  2776. {
  2777. if (hCat == NULL) // Only open this on the first pass.
  2778. {
  2779. hCat = CryptCATOpen(InputInfo->wszCatFile,
  2780. CRYPTCAT_OPEN_EXISTING,
  2781. NULL, NULL, NULL);
  2782. if ((hCat == NULL) || (hCat == INVALID_HANDLE_VALUE))
  2783. {
  2784. switch (GetLastError())
  2785. {
  2786. case ERROR_ACCESS_DENIED:
  2787. ResErr(IDS_ERR_ACCESS_DENIED);
  2788. break;
  2789. case ERROR_SHARING_VIOLATION:
  2790. ResErr(IDS_ERR_SHARING_VIOLATION);
  2791. break;
  2792. case ERROR_NOT_FOUND:
  2793. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->wszCatFile);
  2794. break;
  2795. default:
  2796. FormatErrRet(L"CryptCATOpen", GetLastError());
  2797. }
  2798. ResFormatErr(IDS_ERR_VERIFY_CAT_OPEN,
  2799. InputInfo->wszCatFile);
  2800. hCat = NULL;
  2801. dwErrors++;
  2802. goto VerifyCleanupAndExit;
  2803. }
  2804. }
  2805. }
  2806. else
  2807. {
  2808. switch (InputInfo->CatDbSelect)
  2809. {
  2810. case NoCatDb:
  2811. if (InputInfo->Verbose)
  2812. {
  2813. ResFormatOut(IDS_INFO_VERIFY_ATTEMPT, wszTempFileName);
  2814. }
  2815. goto SkipCatalogs;
  2816. break;
  2817. case FullAutoCatDb:
  2818. if (hCatAdmin == NULL)
  2819. {
  2820. CryptCATAdminAcquireContext(&hCatAdmin, NULL, NULL);
  2821. }
  2822. break;
  2823. case SystemCatDb:
  2824. case DefaultCatDb:
  2825. case GuidCatDb:
  2826. if (hCatAdmin == NULL)
  2827. {
  2828. CryptCATAdminAcquireContext(&hCatAdmin, &InputInfo->CatDbGuid, NULL);
  2829. }
  2830. break;
  2831. default:
  2832. // This should never happen because there are no other
  2833. // legal values for Auto.
  2834. ResFormatErr(IDS_ERR_UNEXPECTED);
  2835. return 1; // Error
  2836. }
  2837. }
  2838. // At this point we are dealing with catalog issues only.
  2839. if (InputInfo->Verbose)
  2840. {
  2841. ResFormatOut(IDS_INFO_VERIFY_ATTEMPT, wszTempFileName);
  2842. }
  2843. // Create the hash for catalog lookup:
  2844. if (InputInfo->SHA1.cbData == 0)
  2845. {
  2846. InputInfo->SHA1.pbData = (BYTE*)malloc(20);
  2847. if (InputInfo->SHA1.pbData)
  2848. {
  2849. InputInfo->SHA1.cbData = 20;
  2850. }
  2851. else
  2852. {
  2853. if (!InputInfo->Quiet)
  2854. {
  2855. FormatErrRet(L"malloc", GetLastError());
  2856. }
  2857. ResFormatErr(IDS_ERR_VERIFY, wszTempFileName);
  2858. dwErrors++;
  2859. goto VerifyNextFile;
  2860. }
  2861. }
  2862. hFile = CreateFileU(wszTempFileName,
  2863. GENERIC_READ,
  2864. FILE_SHARE_READ,
  2865. NULL,
  2866. OPEN_EXISTING,
  2867. FILE_ATTRIBUTE_NORMAL,
  2868. NULL);
  2869. if (!hFile)
  2870. {
  2871. if (!InputInfo->Quiet)
  2872. {
  2873. switch (GetLastError())
  2874. {
  2875. case ERROR_ACCESS_DENIED:
  2876. ResErr(IDS_ERR_ACCESS_DENIED);
  2877. break;
  2878. case ERROR_SHARING_VIOLATION:
  2879. ResErr(IDS_ERR_SHARING_VIOLATION);
  2880. break;
  2881. default:
  2882. FormatErrRet(L"CreateFile", GetLastError());
  2883. }
  2884. }
  2885. ResFormatErr(IDS_ERR_VERIFY, wszTempFileName);
  2886. dwErrors++;
  2887. goto VerifyNextFile;
  2888. }
  2889. if (!CryptCATAdminCalcHashFromFileHandle(hFile,
  2890. &InputInfo->SHA1.cbData,
  2891. InputInfo->SHA1.pbData,
  2892. NULL))
  2893. {
  2894. if (!InputInfo->Quiet)
  2895. {
  2896. switch (GetLastError())
  2897. {
  2898. case ERROR_FILE_INVALID:
  2899. ResErr(IDS_ERR_FILE_SIZE_ZERO);
  2900. break;
  2901. default:
  2902. FormatErrRet(L"CryptCATAdminCalcHashFromFileHandle", GetLastError());
  2903. }
  2904. }
  2905. ResFormatErr(IDS_ERR_VERIFY, wszTempFileName);
  2906. CloseHandle(hFile);
  2907. dwErrors++;
  2908. goto VerifyNextFile;
  2909. }
  2910. CloseHandle(hFile);
  2911. for (DWORD j = 0; j<InputInfo->SHA1.cbData; j++)
  2912. { // Print the hash to a string:
  2913. swprintf(&(wszSHA1[j*2]), L"%02X", InputInfo->SHA1.pbData[j]);
  2914. }
  2915. #ifdef SIGNTOOL_DEBUG
  2916. if (gDebug)
  2917. {
  2918. wprintf(L"SHA1 hash of file: %s\n", wszSHA1);
  2919. }
  2920. #endif
  2921. // Finished calculating the hash.
  2922. // If the catalog was specifically selected
  2923. if (InputInfo->wszCatFile)
  2924. {
  2925. // Then make sure the hash we found is in the catalog:
  2926. pCatMember = CryptCATGetMemberInfo(hCat, wszSHA1);
  2927. if (pCatMember) // Is the hash found in the catalog?
  2928. {
  2929. if (InputInfo->Verbose)
  2930. {
  2931. ResFormatOut(IDS_INFO_VERIFY_CAT, InputInfo->wszCatFile);
  2932. }
  2933. CatInfo.cbStruct = sizeof(CATALOG_INFO);
  2934. wcsncpy(CatInfo.wszCatalogFile, InputInfo->wszCatFile, MAX_PATH);
  2935. CatInfo.wszCatalogFile[MAX_PATH-1] = L'\0';
  2936. // Now verify the catalog:
  2937. // Set up the rest of the WVT structure:
  2938. WVTCat.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
  2939. WVTCat.pcwszMemberFilePath = wszTempFileName;
  2940. WVTCat.pcwszMemberTag = wszSHA1;
  2941. WVTCat.cbCalculatedFileHash = InputInfo->SHA1.cbData;
  2942. WVTCat.pbCalculatedFileHash = InputInfo->SHA1.pbData;
  2943. WVTData.dwUnionChoice = WTD_CHOICE_CATALOG;
  2944. WVTData.pCatalog = &WVTCat;
  2945. if (InputInfo->Verbose || InputInfo->TSWarn || InputInfo->wszRootName ||
  2946. (InputInfo->Policy != SystemDriver))
  2947. {
  2948. WVTData.dwStateAction = WTD_STATEACTION_VERIFY;
  2949. }
  2950. else
  2951. {
  2952. WVTData.dwStateAction = WTD_STATEACTION_AUTO_CACHE;
  2953. }
  2954. // Call WinVerifyTrust to do the real work:
  2955. switch (InputInfo->Policy)
  2956. {
  2957. case SystemDriver:
  2958. WVTData.pPolicyCallbackData = &DriverInfo;
  2959. hr = WinVerifyTrust(NULL, &WVTDriverActionID, &WVTData);
  2960. break;
  2961. case DefaultAuthenticode:
  2962. hr = WinVerifyTrust(NULL, &WVTGenericActionID, &WVTData);
  2963. break;
  2964. case GuidActionID:
  2965. hr = WinVerifyTrust(NULL, &InputInfo->PolicyGuid, &WVTData);
  2966. break;
  2967. default:
  2968. // This should never happen because there are no other
  2969. // legal values for Policy.
  2970. ResFormatErr(IDS_ERR_UNEXPECTED);
  2971. goto VerifyCleanupAndExit;
  2972. }
  2973. switch (hr)
  2974. {
  2975. case ERROR_SUCCESS:
  2976. // Print the Signer information:
  2977. if (InputInfo->Verbose)
  2978. {
  2979. PrintSignerInfo(WVTData.hWVTStateData);
  2980. }
  2981. // Check for Timestamp:
  2982. if (InputInfo->TSWarn && !HasTimestamp(WVTData.hWVTStateData))
  2983. {
  2984. ResFormatErr(IDS_WARN_VERIFY_NO_TS, wszTempFileName);
  2985. dwWarnings++;
  2986. }
  2987. // Check Root Name:
  2988. if (InputInfo->wszRootName &&
  2989. !ChainsToRoot(WVTData.hWVTStateData, InputInfo->wszRootName))
  2990. {
  2991. ResErr(IDS_ERR_VERIFY_ROOT);
  2992. break;
  2993. }
  2994. // Print Success message
  2995. if (!InputInfo->Quiet)
  2996. {
  2997. ResFormatOut(IDS_INFO_VERIFY_SUCCESS, wszTempFileName);
  2998. }
  2999. // Close Verify State Data:
  3000. WVTData.dwStateAction = WTD_STATEACTION_CLOSE;
  3001. switch (InputInfo->Policy)
  3002. {
  3003. case SystemDriver:
  3004. hr = WinVerifyTrust(NULL, &WVTDriverActionID, &WVTData);
  3005. WVTData.pPolicyCallbackData = NULL;
  3006. if (DriverInfo.pcSignerCertContext)
  3007. {
  3008. CertFreeCertificateContext(DriverInfo.pcSignerCertContext);
  3009. }
  3010. break;
  3011. case DefaultAuthenticode:
  3012. hr = WinVerifyTrust(NULL, &WVTGenericActionID, &WVTData);
  3013. break;
  3014. case GuidActionID:
  3015. hr = WinVerifyTrust(NULL, &InputInfo->PolicyGuid, &WVTData);
  3016. break;
  3017. default:
  3018. // This should never happen because there are no other
  3019. // legal values for Policy.
  3020. ResFormatErr(IDS_ERR_UNEXPECTED);
  3021. goto VerifyCleanupAndExit;
  3022. }
  3023. dwDone++;
  3024. goto VerifyNextFile;
  3025. case ERROR_APP_WRONG_OS:
  3026. if (!InputInfo->Quiet)
  3027. {
  3028. if (InputInfo->wszVersion)
  3029. {
  3030. // Failed to verify against user-specified OS version.
  3031. ResFormatErr(IDS_ERR_VERIFY_VERSION);
  3032. }
  3033. else
  3034. {
  3035. // Failed to verify against current OS version
  3036. ResFormatErr(IDS_ERR_VERIFY_CUR_VERSION);
  3037. }
  3038. }
  3039. break;
  3040. case CERT_E_WRONG_USAGE:
  3041. ResErr(IDS_ERR_BAD_USAGE);
  3042. if (InputInfo->Policy != DefaultAuthenticode)
  3043. ResErr(IDS_ERR_TRY_OTHER_POLICY);
  3044. break;
  3045. case TRUST_E_NOSIGNATURE:
  3046. if (!InputInfo->Quiet)
  3047. {
  3048. ResErr(IDS_ERR_NOT_SIGNED);
  3049. }
  3050. break;
  3051. default:
  3052. if (!InputInfo->Quiet)
  3053. {
  3054. FormatErrRet(L"WinVerifyTrust", hr);
  3055. }
  3056. if (InputInfo->Verbose)
  3057. {
  3058. PrintSignerInfo(WVTData.hWVTStateData);
  3059. }
  3060. }
  3061. // Close Verify State Data:
  3062. WVTData.dwStateAction = WTD_STATEACTION_CLOSE;
  3063. switch (InputInfo->Policy)
  3064. {
  3065. case SystemDriver:
  3066. hr = WinVerifyTrust(NULL, &WVTDriverActionID, &WVTData);
  3067. WVTData.pPolicyCallbackData = NULL;
  3068. if (DriverInfo.pcSignerCertContext)
  3069. {
  3070. CertFreeCertificateContext(DriverInfo.pcSignerCertContext);
  3071. }
  3072. break;
  3073. case DefaultAuthenticode:
  3074. hr = WinVerifyTrust(NULL, &WVTGenericActionID, &WVTData);
  3075. break;
  3076. case GuidActionID:
  3077. hr = WinVerifyTrust(NULL, &InputInfo->PolicyGuid, &WVTData);
  3078. break;
  3079. default:
  3080. // This should never happen because there are no other
  3081. // legal values for Policy.
  3082. ResFormatErr(IDS_ERR_UNEXPECTED);
  3083. goto VerifyCleanupAndExit;
  3084. }
  3085. WVTData.dwStateAction = WTD_STATEACTION_VERIFY;
  3086. }
  3087. else
  3088. {
  3089. // The file was not found in the specified catalog.
  3090. ResErr(IDS_ERR_VERIFY_NOT_IN_CAT);
  3091. }
  3092. // Then we failed to verify it using specified catalog.
  3093. dwErrors++;
  3094. ResFormatErr(IDS_ERR_VERIFY_INVALID, wszTempFileName);
  3095. goto VerifyNextFile;
  3096. }
  3097. else
  3098. {
  3099. // Or else we should look up the catalog in the Cat DB:
  3100. if (hCatInfo != NULL)
  3101. {
  3102. CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
  3103. hCatInfo = NULL;
  3104. }
  3105. memset(&CatInfo, 0, sizeof(CATALOG_INFO));
  3106. CatInfo.cbStruct = sizeof(CATALOG_INFO);
  3107. hr = ERROR_SUCCESS;
  3108. while ((hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin,
  3109. InputInfo->SHA1.pbData,
  3110. InputInfo->SHA1.cbData,
  3111. 0,
  3112. &hCatInfo)) != NULL)
  3113. {
  3114. if (!(CryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0)))
  3115. {
  3116. ResErr(IDS_ERR_UNEXPECTED);
  3117. continue;
  3118. }
  3119. if (InputInfo->Verbose)
  3120. {
  3121. ResFormatOut(IDS_INFO_VERIFY_CAT, CatInfo.wszCatalogFile);
  3122. }
  3123. // Now verify the catalog:
  3124. // Set up the rest of the WVT structure:
  3125. WVTCat.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
  3126. WVTCat.pcwszMemberFilePath = wszTempFileName;
  3127. WVTCat.pcwszMemberTag = wszSHA1;
  3128. WVTCat.cbCalculatedFileHash = InputInfo->SHA1.cbData;
  3129. WVTCat.pbCalculatedFileHash = InputInfo->SHA1.pbData;
  3130. WVTData.dwUnionChoice = WTD_CHOICE_CATALOG;
  3131. WVTData.pCatalog = &WVTCat;
  3132. if (InputInfo->Verbose || InputInfo->TSWarn || InputInfo->wszRootName ||
  3133. (InputInfo->Policy != SystemDriver))
  3134. {
  3135. WVTData.dwStateAction = WTD_STATEACTION_VERIFY;
  3136. }
  3137. else
  3138. {
  3139. WVTData.dwStateAction = WTD_STATEACTION_AUTO_CACHE;
  3140. }
  3141. // Call WinVerifyTrust to do the real work:
  3142. switch (InputInfo->Policy)
  3143. {
  3144. case SystemDriver:
  3145. WVTData.pPolicyCallbackData = &DriverInfo;
  3146. hr = WinVerifyTrust(NULL, &WVTDriverActionID, &WVTData);
  3147. break;
  3148. case DefaultAuthenticode:
  3149. hr = WinVerifyTrust(NULL, &WVTGenericActionID, &WVTData);
  3150. break;
  3151. case GuidActionID:
  3152. hr = WinVerifyTrust(NULL, &InputInfo->PolicyGuid, &WVTData);
  3153. break;
  3154. default:
  3155. // This should never happen because there are no other
  3156. // legal values for Policy.
  3157. ResFormatErr(IDS_ERR_UNEXPECTED);
  3158. goto VerifyCleanupAndExit;
  3159. }
  3160. switch (hr)
  3161. {
  3162. case ERROR_SUCCESS:
  3163. // Print the Signer information:
  3164. if (InputInfo->Verbose)
  3165. {
  3166. PrintSignerInfo(WVTData.hWVTStateData);
  3167. }
  3168. // Check for Timestamp:
  3169. if (InputInfo->TSWarn && !HasTimestamp(WVTData.hWVTStateData))
  3170. {
  3171. ResFormatErr(IDS_WARN_VERIFY_NO_TS, wszTempFileName);
  3172. dwWarnings++;
  3173. }
  3174. // Check Root Name:
  3175. if (InputInfo->wszRootName &&
  3176. !ChainsToRoot(WVTData.hWVTStateData, InputInfo->wszRootName))
  3177. {
  3178. ResErr(IDS_ERR_VERIFY_ROOT);
  3179. break;
  3180. }
  3181. // Print Success message
  3182. if (!InputInfo->Quiet)
  3183. {
  3184. ResFormatOut(IDS_INFO_VERIFY_SUCCESS, wszTempFileName);
  3185. }
  3186. // Close Verify State Data:
  3187. WVTData.dwStateAction = WTD_STATEACTION_CLOSE;
  3188. switch (InputInfo->Policy)
  3189. {
  3190. case SystemDriver:
  3191. hr = WinVerifyTrust(NULL, &WVTDriverActionID, &WVTData);
  3192. WVTData.pPolicyCallbackData = NULL;
  3193. if (DriverInfo.pcSignerCertContext)
  3194. {
  3195. CertFreeCertificateContext(DriverInfo.pcSignerCertContext);
  3196. }
  3197. break;
  3198. case DefaultAuthenticode:
  3199. hr = WinVerifyTrust(NULL, &WVTGenericActionID, &WVTData);
  3200. break;
  3201. case GuidActionID:
  3202. hr = WinVerifyTrust(NULL, &InputInfo->PolicyGuid, &WVTData);
  3203. break;
  3204. default:
  3205. // This should never happen because there are no other
  3206. // legal values for Policy.
  3207. ResFormatErr(IDS_ERR_UNEXPECTED);
  3208. goto VerifyCleanupAndExit;
  3209. }
  3210. dwDone++;
  3211. goto VerifyNextFile;
  3212. case ERROR_APP_WRONG_OS:
  3213. if (!InputInfo->Quiet)
  3214. {
  3215. if (InputInfo->wszVersion)
  3216. {
  3217. // Failed to verify against user-specified OS version.
  3218. ResFormatErr(IDS_ERR_VERIFY_VERSION);
  3219. }
  3220. else
  3221. {
  3222. // Failed to verify against current OS version
  3223. ResFormatErr(IDS_ERR_VERIFY_CUR_VERSION);
  3224. }
  3225. }
  3226. break;
  3227. case CERT_E_WRONG_USAGE:
  3228. ResErr(IDS_ERR_BAD_USAGE);
  3229. if (InputInfo->Policy != DefaultAuthenticode)
  3230. ResErr(IDS_ERR_TRY_OTHER_POLICY);
  3231. break;
  3232. case TRUST_E_NOSIGNATURE:
  3233. if (!InputInfo->Quiet)
  3234. {
  3235. ResErr(IDS_ERR_NOT_SIGNED);
  3236. }
  3237. break;
  3238. default:
  3239. if (!InputInfo->Quiet)
  3240. {
  3241. FormatErrRet(L"WinVerifyTrust", hr);
  3242. }
  3243. if (InputInfo->Verbose)
  3244. {
  3245. PrintSignerInfo(WVTData.hWVTStateData);
  3246. }
  3247. }
  3248. // Close Verify State Data:
  3249. WVTData.dwStateAction = WTD_STATEACTION_CLOSE;
  3250. switch (InputInfo->Policy)
  3251. {
  3252. case SystemDriver:
  3253. hr = WinVerifyTrust(NULL, &WVTDriverActionID, &WVTData);
  3254. WVTData.pPolicyCallbackData = NULL;
  3255. if (DriverInfo.pcSignerCertContext)
  3256. {
  3257. CertFreeCertificateContext(DriverInfo.pcSignerCertContext);
  3258. }
  3259. break;
  3260. case DefaultAuthenticode:
  3261. hr = WinVerifyTrust(NULL, &WVTGenericActionID, &WVTData);
  3262. break;
  3263. case GuidActionID:
  3264. hr = WinVerifyTrust(NULL, &InputInfo->PolicyGuid, &WVTData);
  3265. break;
  3266. default:
  3267. // This should never happen because there are no other
  3268. // legal values for Policy.
  3269. ResFormatErr(IDS_ERR_UNEXPECTED);
  3270. goto VerifyCleanupAndExit;
  3271. }
  3272. WVTData.dwStateAction = WTD_STATEACTION_VERIFY;
  3273. }
  3274. // Failed to verify using the catalog DB.
  3275. dwTemp = GetLastError();
  3276. if ((InputInfo->Verbose) &&
  3277. (dwTemp != ERROR_NOT_FOUND))
  3278. {
  3279. FormatErrRet(L"CryptCATAdminEnumCatalogFromHash", dwTemp);
  3280. }
  3281. // If we are on full auto, try direct signature. Otherwise
  3282. // it's an error.
  3283. if ((InputInfo->CatDbSelect == FullAutoCatDb) && (hr != ERROR_APP_WRONG_OS))
  3284. {
  3285. if (InputInfo->Verbose)
  3286. {
  3287. ResOut(IDS_INFO_VERIFY_BADCAT);
  3288. }
  3289. // Reset the driver structure:
  3290. memset(&DriverInfo, 0, sizeof(DRIVER_VER_INFO));
  3291. DriverInfo.cbStruct = sizeof(DRIVER_VER_INFO);
  3292. if (InputInfo->wszVersion)
  3293. {
  3294. DriverInfo.dwPlatform = InputInfo->dwPlatform;
  3295. DriverInfo.sOSVersionHigh.dwMajor = DriverInfo.sOSVersionLow.dwMajor = InputInfo->dwMajorVersion;
  3296. DriverInfo.sOSVersionHigh.dwMinor = DriverInfo.sOSVersionLow.dwMinor = InputInfo->dwMinorVersion;
  3297. DriverInfo.dwBuildNumberHigh = DriverInfo.dwBuildNumberLow = InputInfo->dwBuildNumber;
  3298. }
  3299. else
  3300. {
  3301. WVTData.dwProvFlags = WTD_USE_DEFAULT_OSVER_CHECK;
  3302. }
  3303. }
  3304. else
  3305. {
  3306. hr = 0;
  3307. ResFormatErr(IDS_ERR_VERIFY_INVALID, wszTempFileName);
  3308. dwErrors++;
  3309. goto VerifyNextFile;
  3310. }
  3311. }
  3312. // Unable to verify using a catalog.
  3313. // Done with all catalog stuff.
  3314. SkipCatalogs:
  3315. // Now try to verify if it is signed directly:
  3316. memset(&WVTData, 0, sizeof(WINTRUST_DATA));
  3317. WVTData.cbStruct = sizeof(WINTRUST_DATA);
  3318. WVTData.dwStateAction = WTD_STATEACTION_VERIFY;
  3319. WVTData.dwUIChoice = WTD_UI_NONE;
  3320. WVTData.fdwRevocationChecks = WTD_REVOKE_NONE;
  3321. memset(&WVTFile, 0, sizeof(WINTRUST_FILE_INFO_));
  3322. WVTFile.cbStruct = sizeof(WINTRUST_FILE_INFO_);
  3323. WVTFile.pcwszFilePath = wszTempFileName;
  3324. WVTData.dwUnionChoice = WTD_CHOICE_FILE;
  3325. WVTData.pFile = &WVTFile;
  3326. //WVTData.pPolicyCallbackData = &DriverInfo;
  3327. WVTData.pPolicyCallbackData = NULL;
  3328. switch (InputInfo->Policy)
  3329. {
  3330. case SystemDriver:
  3331. hr = WinVerifyTrust(NULL, &WVTDriverActionID, &WVTData);
  3332. break;
  3333. case DefaultAuthenticode:
  3334. hr = WinVerifyTrust(NULL, &WVTGenericActionID, &WVTData);
  3335. break;
  3336. case GuidActionID:
  3337. hr = WinVerifyTrust(NULL, &InputInfo->PolicyGuid, &WVTData);
  3338. break;
  3339. default:
  3340. // This should never happen because there are no other
  3341. // legal values for Policy.
  3342. ResFormatErr(IDS_ERR_UNEXPECTED);
  3343. goto VerifyCleanupAndExit;
  3344. }
  3345. if (hr == ERROR_SUCCESS)
  3346. {
  3347. // Print the Signer information:
  3348. if (InputInfo->Verbose)
  3349. {
  3350. PrintSignerInfo(WVTData.hWVTStateData);
  3351. }
  3352. // Check for Timestamp:
  3353. if (InputInfo->TSWarn && !HasTimestamp(WVTData.hWVTStateData))
  3354. {
  3355. ResFormatErr(IDS_WARN_VERIFY_NO_TS, wszTempFileName);
  3356. dwWarnings++;
  3357. }
  3358. // Check Root Name:
  3359. if (InputInfo->wszRootName &&
  3360. !ChainsToRoot(WVTData.hWVTStateData, InputInfo->wszRootName))
  3361. {
  3362. ResErr(IDS_ERR_VERIFY_ROOT);
  3363. ResFormatErr(IDS_ERR_VERIFY_INVALID, wszTempFileName);
  3364. dwErrors++;
  3365. }
  3366. else
  3367. {
  3368. // Print Success message
  3369. if (!InputInfo->Quiet)
  3370. {
  3371. ResFormatOut(IDS_INFO_VERIFY_SUCCESS, wszTempFileName);
  3372. }
  3373. dwDone++;
  3374. }
  3375. }
  3376. else
  3377. {
  3378. if (!InputInfo->Quiet)
  3379. {
  3380. switch (hr)
  3381. {
  3382. case ERROR_SUCCESS:
  3383. break;
  3384. case TRUST_E_SUBJECT_FORM_UNKNOWN:
  3385. ResErr(IDS_ERR_VERIFY_FILE_FORMAT);
  3386. break;
  3387. case E_ACCESSDENIED:
  3388. ResErr(IDS_ERR_ACCESS_DENIED);
  3389. break;
  3390. case 0x80070020: // ERROR_SHARING_VIOLATION
  3391. ResErr(IDS_ERR_SHARING_VIOLATION);
  3392. break;
  3393. case 0x800703EE: // STATUS_MAPPED_FILE_SIZE_ZERO
  3394. ResErr(IDS_ERR_FILE_SIZE_ZERO);
  3395. break;
  3396. case CERT_E_WRONG_USAGE:
  3397. ResErr(IDS_ERR_BAD_USAGE);
  3398. if (InputInfo->Policy != DefaultAuthenticode)
  3399. ResErr(IDS_ERR_TRY_OTHER_POLICY);
  3400. break;
  3401. case TRUST_E_NOSIGNATURE:
  3402. ResErr(IDS_ERR_NOT_SIGNED);
  3403. break;
  3404. case CERT_E_UNTRUSTEDROOT:
  3405. ResErr(IDS_ERR_UNTRUSTED_ROOT);
  3406. break;
  3407. default:
  3408. FormatErrRet(L"WinVerifyTrust", hr);
  3409. }
  3410. }
  3411. if (InputInfo->Verbose)
  3412. {
  3413. PrintSignerInfo(WVTData.hWVTStateData);
  3414. }
  3415. ResFormatErr(IDS_ERR_VERIFY_INVALID, wszTempFileName);
  3416. dwErrors++;
  3417. }
  3418. // Close Verify State Data:
  3419. WVTData.dwStateAction = WTD_STATEACTION_CLOSE;
  3420. switch (InputInfo->Policy)
  3421. {
  3422. case SystemDriver:
  3423. hr = WinVerifyTrust(NULL, &WVTDriverActionID, &WVTData);
  3424. break;
  3425. case DefaultAuthenticode:
  3426. hr = WinVerifyTrust(NULL, &WVTGenericActionID, &WVTData);
  3427. break;
  3428. case GuidActionID:
  3429. hr = WinVerifyTrust(NULL, &InputInfo->PolicyGuid, &WVTData);
  3430. break;
  3431. default:
  3432. // This should never happen because there are no other
  3433. // legal values for Policy.
  3434. ResFormatErr(IDS_ERR_UNEXPECTED);
  3435. goto VerifyCleanupAndExit;
  3436. }
  3437. VerifyNextFile:;
  3438. if (InputInfo->fIsWow64Process)
  3439. {
  3440. // Disable WOW64 file-system redirection entirely for our FindFirst/NextFile
  3441. Wow64SetFilesystemRedirectorEx(WOW64_FILE_SYSTEM_DISABLE_REDIRECT_LEGACY);
  3442. }
  3443. }
  3444. } while (FindNextFileU(hFind, &FindFileData));
  3445. if (dwcFound == 0) // No files were found matching this filespec
  3446. { // this will only fire if only directories were found.
  3447. dwErrors++;
  3448. ResFormatErr(IDS_ERR_FILE_NOT_FOUND, InputInfo->rgwszFileNames[i]);
  3449. continue;
  3450. }
  3451. FindClose(hFind);
  3452. hFind = NULL;
  3453. }
  3454. VerifyCleanupAndExit:
  3455. //Print Summary Information:
  3456. if (InputInfo->Verbose || (!InputInfo->Quiet && (dwErrors || dwWarnings)))
  3457. {
  3458. wprintf(L"\n");
  3459. if (InputInfo->Verbose || dwDone)
  3460. ResFormatOut(IDS_INFO_VERIFIED, dwDone);
  3461. if (InputInfo->Verbose || dwWarnings)
  3462. ResFormatOut(IDS_INFO_WARNINGS, dwWarnings);
  3463. if (InputInfo->Verbose || dwErrors)
  3464. ResFormatOut(IDS_INFO_ERRORS, dwErrors);
  3465. }
  3466. if (InputInfo->fIsWow64Process)
  3467. Wow64SetFilesystemRedirectorEx(OldWow64Setting);
  3468. if (hCatInfo)
  3469. CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
  3470. if (hCatAdmin)
  3471. CryptCATAdminReleaseContext(hCatAdmin, NULL);
  3472. if (hCat)
  3473. CryptCATClose(hCat);
  3474. if ((InputInfo->SHA1.cbData == 20) && (InputInfo->SHA1.pbData))
  3475. {
  3476. free(InputInfo->SHA1.pbData);
  3477. InputInfo->SHA1.cbData = 0;
  3478. InputInfo->SHA1.pbData = NULL;
  3479. }
  3480. CoUninitialize();
  3481. if (dwErrors)
  3482. return 1; // Error
  3483. if (dwWarnings)
  3484. return 2; // Warning
  3485. if (dwDone)
  3486. return 0; // Success
  3487. // One of the above returns should fire, so
  3488. // this should never happen:
  3489. ResErr(IDS_ERR_NO_FILES_DONE);
  3490. ResErr(IDS_ERR_UNEXPECTED);
  3491. return 1; // Error
  3492. }