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.

656 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1996
  6. //
  7. // File: tcatdb.cpp
  8. //
  9. // Contents:
  10. //
  11. //
  12. //
  13. //
  14. // Functions: main
  15. //
  16. // History: 11-Apr-00 reidk created
  17. //
  18. //--------------------------------------------------------------------------
  19. #include <windows.h>
  20. #include <assert.h>
  21. #include "wincrypt.h"
  22. #include "wintrust.h"
  23. #include "mscat.h"
  24. #include "unicode.h"
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <stdio.h>
  28. #include <memory.h>
  29. #include <time.h>
  30. #include "catutil.h"
  31. #define WSZ_CATALOG_NEW_BASE_DIRECTORY L"CatRoot2"
  32. typedef struct _CTL_SLOT
  33. {
  34. PCCTL_CONTEXT pCTLContext;
  35. HANDLE hMappedFile;
  36. BYTE *pbMappedFile;
  37. LPWSTR pwszCatalog;
  38. } CTL_SLOT, *PCTL_SLOT;
  39. GUID g_guidCatRoot;
  40. BOOL g_fUseSingleContext = TRUE;
  41. BOOL g_fDatabaseConsistencyCheck = FALSE;
  42. BOOL g_fUseDefaultGUID = FALSE;
  43. BOOL g_fVerbose = FALSE;
  44. BOOL g_fDatabaseReverseConsistencyCheck = FALSE;
  45. WCHAR g_wszDefaultSystemDir[MAX_PATH + 1];
  46. LPWSTR g_pwszCatalogDir = NULL;
  47. WCHAR g_wszSubSysGUID[1024];
  48. LPWSTR g_pwszCatalogSearchString = NULL;
  49. const char RgchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  50. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  51. //////////////////////////////////////////////////////////////////////////////////////
  52. //
  53. //////////////////////////////////////////////////////////////////////////////////////
  54. void FormatHashString(LPSTR *ppString, DWORD cbBlob, BYTE *pblob)
  55. {
  56. DWORD i, j = 0;
  57. BYTE *pb = NULL;
  58. DWORD numCharsInserted = 0;
  59. LPSTR psz;
  60. *ppString = NULL;
  61. pb = pblob;
  62. // fill the buffer
  63. i=0;
  64. while (j < cbBlob)
  65. {
  66. if ((*ppString) == NULL)
  67. {
  68. psz = NULL;
  69. *ppString = (LPSTR) malloc(3 * sizeof(char));
  70. }
  71. else
  72. {
  73. psz = *ppString;
  74. #pragma prefast(suppress:308, "the pointer was saved above (PREfast bug 506)")
  75. *ppString = (LPSTR) realloc(*ppString, (j+1) * 3 * sizeof(char));
  76. }
  77. if (*ppString == NULL)
  78. {
  79. if (psz != NULL)
  80. {
  81. free(psz);
  82. }
  83. return;
  84. }
  85. (*ppString)[i++] = RgchHex[(*pb & 0xf0) >> 4];
  86. (*ppString)[i++] = RgchHex[*pb & 0x0f];
  87. (*ppString)[i++] = ' ';
  88. pb++;
  89. j++;
  90. }
  91. (*ppString)[i-1] = 0;
  92. }
  93. //---------------------------------------------------------------------------------------
  94. //
  95. // FindAndDecodeHashInCatEntry
  96. //
  97. //---------------------------------------------------------------------------------------
  98. BOOL
  99. FindAndDecodeHashInCatEntry(
  100. PCTL_ENTRY pctlEntry,
  101. SPC_INDIRECT_DATA_CONTENT **ppIndirectData)
  102. {
  103. BOOL fRet = TRUE;
  104. DWORD i;
  105. DWORD cbIndirectData = 0;
  106. *ppIndirectData = NULL;
  107. //
  108. // Search for the hash in the attributes
  109. //
  110. for (i=0; i<pctlEntry->cAttribute; i++)
  111. {
  112. if (strcmp(pctlEntry->rgAttribute[i].pszObjId, SPC_INDIRECT_DATA_OBJID) == 0)
  113. {
  114. break;
  115. }
  116. }
  117. //
  118. // Make sure the hash was found
  119. //
  120. if (i >= pctlEntry->cAttribute)
  121. {
  122. printf("Unexpected error... hash not found in CTL entry\n");
  123. goto ErrorReturn;
  124. }
  125. //
  126. // decode the indirect data
  127. //
  128. if (!CryptDecodeObject(
  129. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  130. SPC_INDIRECT_DATA_CONTENT_STRUCT,
  131. pctlEntry->rgAttribute[i].rgValue[0].pbData,
  132. pctlEntry->rgAttribute[i].rgValue[0].cbData,
  133. 0,
  134. NULL,
  135. &cbIndirectData))
  136. {
  137. printf("CryptDecodeObject failure\nGLE = %lx\n", GetLastError());
  138. goto ErrorReturn;
  139. }
  140. if (NULL == (*ppIndirectData = (SPC_INDIRECT_DATA_CONTENT *)
  141. malloc(cbIndirectData)))
  142. {
  143. printf("malloc failure\n");
  144. goto ErrorReturn;
  145. }
  146. if (!CryptDecodeObject(
  147. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  148. SPC_INDIRECT_DATA_CONTENT_STRUCT,
  149. pctlEntry->rgAttribute[i].rgValue[0].pbData,
  150. pctlEntry->rgAttribute[i].rgValue[0].cbData,
  151. 0,
  152. *ppIndirectData,
  153. &cbIndirectData))
  154. {
  155. printf("CryptDecodeObject failure\nGLE = %lx\n", GetLastError());
  156. goto ErrorReturn;
  157. }
  158. CommonReturn:
  159. return fRet;
  160. ErrorReturn:
  161. fRet = FALSE;
  162. goto CommonReturn;
  163. }
  164. BOOL
  165. CheckCatFileEntries(HCATADMIN hCatAdmin, LPWSTR pwszCatalogFile)
  166. {
  167. BOOL fRet = TRUE;
  168. PCCTL_CONTEXT pCTLContext = NULL;
  169. HANDLE hMappedFile = NULL;
  170. BYTE *pbMappedFile = NULL;
  171. DWORD i;
  172. SPC_INDIRECT_DATA_CONTENT *pIndirectData = NULL;
  173. HCATINFO hCatInfo;
  174. BOOL fCatalogFound;
  175. CATALOG_INFO sCatInfo;
  176. LPSTR pszHash = NULL;
  177. HCATADMIN hCatAdminLocal = NULL;
  178. LPWSTR pwszShortCatName = wcsrchr(pwszCatalogFile, L'\\');
  179. pwszShortCatName++;
  180. if (g_fVerbose)
  181. {
  182. printf(" Processing cat file: %S\n", pwszShortCatName);
  183. }
  184. //
  185. // Open, and create a file mapping of the catalog file
  186. //
  187. if (!CatUtil_CreateCTLContextFromFileName(
  188. pwszCatalogFile,
  189. &hMappedFile,
  190. &pbMappedFile,
  191. &pCTLContext,
  192. FALSE))
  193. {
  194. printf(" Error opening catalog file: %S\n", pwszCatalogFile);
  195. goto ErrorReturn;
  196. }
  197. //
  198. // Go through each entry in the catalog
  199. //
  200. for (i=0; i<pCTLContext->pCtlInfo->cCTLEntry; i++)
  201. {
  202. if (!FindAndDecodeHashInCatEntry(
  203. &(pCTLContext->pCtlInfo->rgCTLEntry[i]),
  204. &pIndirectData))
  205. {
  206. goto ErrorReturn;
  207. }
  208. if (!g_fUseSingleContext)
  209. {
  210. if (!(CryptCATAdminAcquireContext(&hCatAdminLocal, &g_guidCatRoot, 0)))
  211. {
  212. printf(" CryptCATAdminAcquireContext failure\nGLE = %lx\n", GetLastError());
  213. goto ErrorReturn;
  214. }
  215. }
  216. fCatalogFound = FALSE;
  217. hCatInfo = NULL;
  218. while (hCatInfo = CryptCATAdminEnumCatalogFromHash(
  219. g_fUseSingleContext ? hCatAdmin : hCatAdminLocal,
  220. pIndirectData->Digest.pbData,
  221. pIndirectData->Digest.cbData,
  222. 0,
  223. &hCatInfo))
  224. {
  225. memset(&sCatInfo, 0x00, sizeof(CATALOG_INFO));
  226. sCatInfo.cbStruct = sizeof(CATALOG_INFO);
  227. if (!(CryptCATCatalogInfoFromContext(hCatInfo, &sCatInfo, 0)))
  228. {
  229. printf(" CryptCATCatalogInfoFromContext failure\nGLE = %lx\n", GetLastError());
  230. goto ErrorReturn;
  231. }
  232. if (_wcsicmp(&(sCatInfo.wszCatalogFile[0]), pwszCatalogFile) == 0)
  233. {
  234. fCatalogFound = TRUE;
  235. break;
  236. }
  237. }
  238. if (!fCatalogFound)
  239. {
  240. FormatHashString(&pszHash, pIndirectData->Digest.cbData, pIndirectData->Digest.pbData);
  241. printf(" FAILURE: Could not enum: %S\n from hash: %s\n", pwszShortCatName, pszHash);
  242. if (g_fVerbose)
  243. {
  244. printf(" GLE: %lx\n", GetLastError());
  245. }
  246. }
  247. if (!g_fUseSingleContext)
  248. {
  249. CryptCATAdminReleaseContext(hCatAdminLocal, NULL);
  250. hCatAdminLocal = NULL;
  251. }
  252. free(pIndirectData);
  253. pIndirectData = NULL;
  254. }
  255. CommonReturn:
  256. if (pIndirectData != NULL)
  257. {
  258. free(pIndirectData);
  259. }
  260. if (pCTLContext != NULL)
  261. {
  262. CertFreeCTLContext(pCTLContext);
  263. }
  264. if (pbMappedFile != NULL)
  265. {
  266. UnmapViewOfFile(pbMappedFile);
  267. }
  268. if (hMappedFile != NULL)
  269. {
  270. CloseHandle(hMappedFile);
  271. }
  272. if (pszHash != NULL)
  273. {
  274. free(pszHash);
  275. }
  276. if (hCatAdminLocal != NULL)
  277. {
  278. CryptCATAdminReleaseContext(hCatAdminLocal, NULL);
  279. }
  280. return(fRet);
  281. ErrorReturn:
  282. fRet = FALSE;
  283. goto CommonReturn;
  284. }
  285. BOOL DoDatabaseConsistencyCheck()
  286. {
  287. BOOL fRet = TRUE;
  288. HCATADMIN hCatAdmin = NULL;
  289. LPWSTR pwszCatalogFile = NULL;
  290. HANDLE hFindHandleCatalogsInDir = INVALID_HANDLE_VALUE;
  291. WIN32_FIND_DATAW FindDataCatalogsInDir;
  292. PCCTL_CONTEXT pCTLContext = NULL;
  293. HANDLE hFile = INVALID_HANDLE_VALUE;
  294. HANDLE hMappedFile = NULL;
  295. DWORD cbFile = 0;
  296. BYTE *pbMappedFile = NULL;
  297. printf("Starting database consistency check\n");
  298. if (g_fUseSingleContext)
  299. {
  300. if (!(CryptCATAdminAcquireContext(&hCatAdmin, &g_guidCatRoot, 0)))
  301. {
  302. printf(" CryptCATAdminAcquireContext failure\nGLE = %lx\n", GetLastError());
  303. goto ErrorReturn;
  304. }
  305. }
  306. //
  307. // Find each catalog in the dir
  308. //
  309. //
  310. // Start the catalog enumeration
  311. //
  312. hFindHandleCatalogsInDir = FindFirstFileW(
  313. g_pwszCatalogSearchString,
  314. &FindDataCatalogsInDir);
  315. if (hFindHandleCatalogsInDir == INVALID_HANDLE_VALUE)
  316. {
  317. // no files found
  318. if (GetLastError() == ERROR_NO_MORE_FILES)
  319. {
  320. SetLastError(0);
  321. }
  322. else
  323. {
  324. goto ErrorReturn;
  325. }
  326. }
  327. else
  328. {
  329. while (1)
  330. {
  331. if ((wcscmp(FindDataCatalogsInDir.cFileName, L".") != 0) &&
  332. (wcscmp(FindDataCatalogsInDir.cFileName, L"..") != 0) &&
  333. (!(FindDataCatalogsInDir.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)))
  334. {
  335. //
  336. // Construct fully qualified path name to catalog file
  337. //
  338. if (NULL == (pwszCatalogFile = (LPWSTR)
  339. malloc(sizeof(WCHAR) *
  340. (wcslen(g_pwszCatalogDir) +
  341. wcslen(FindDataCatalogsInDir.cFileName) +
  342. 1))))
  343. {
  344. printf(" malloc failure\n");
  345. goto ErrorReturn;
  346. }
  347. wcscpy(pwszCatalogFile, g_pwszCatalogDir);
  348. wcscat(pwszCatalogFile, FindDataCatalogsInDir.cFileName);
  349. //
  350. // Verify that this is a catalog
  351. //
  352. if (IsCatalogFile(NULL, pwszCatalogFile))
  353. {
  354. CheckCatFileEntries(hCatAdmin, pwszCatalogFile);
  355. }
  356. else
  357. {
  358. LPWSTR pwsz = wcsrchr(pwszCatalogFile, L'\\');
  359. pwsz++;
  360. if (_wcsicmp(pwsz, L"CatDB") != 0)
  361. {
  362. wprintf(L" File found that is not a catalog file: %s\n", pwsz);
  363. }
  364. }
  365. free(pwszCatalogFile);
  366. pwszCatalogFile = NULL;
  367. }
  368. //
  369. // Get next catalog file
  370. //
  371. if (!FindNextFileW(hFindHandleCatalogsInDir, &FindDataCatalogsInDir))
  372. {
  373. if (GetLastError() == ERROR_NO_MORE_FILES)
  374. {
  375. SetLastError(0);
  376. break;
  377. }
  378. else
  379. {
  380. goto ErrorReturn;
  381. }
  382. }
  383. }
  384. }
  385. CommonReturn:
  386. printf("Database consistency check complete\n");
  387. if (pwszCatalogFile != NULL)
  388. {
  389. free(pwszCatalogFile);
  390. }
  391. if (hFindHandleCatalogsInDir != INVALID_HANDLE_VALUE)
  392. {
  393. FindClose(hFindHandleCatalogsInDir);
  394. }
  395. if (hCatAdmin != NULL)
  396. {
  397. CryptCATAdminReleaseContext(hCatAdmin, NULL);
  398. }
  399. return (fRet);
  400. ErrorReturn:
  401. fRet = FALSE;
  402. goto CommonReturn;
  403. }
  404. static void Usage(void)
  405. {
  406. printf("Usage: tcatdb [options] <GUID>\n");
  407. printf("Options are:\n");
  408. printf(" -h - This message\n");
  409. printf(" -v - Verbose output\n");
  410. printf(" -d - Use default GUID (system GUID)\n");
  411. printf(" -c - Check database consistency\n");
  412. printf(" -s - Use a single HCATADMIN for all calls (default)\n");
  413. printf(" -n - Use a new HCATADMIN for every call\n");
  414. printf("\n");
  415. }
  416. int _cdecl main(int argc, char * argv[])
  417. {
  418. LPSTR pszGUID = NULL;
  419. WCHAR wsz[1024];
  420. int ret = 0;
  421. LPSTR pszCatalogToDelete = NULL;
  422. HCATADMIN hCatAdminLocal = NULL;
  423. while (--argc>0)
  424. {
  425. if (**++argv == '-')
  426. {
  427. switch(argv[0][1])
  428. {
  429. case 'c':
  430. case 'C':
  431. g_fDatabaseConsistencyCheck = TRUE;
  432. break;
  433. case 'd':
  434. case 'D':
  435. g_fUseDefaultGUID = TRUE;
  436. break;
  437. case 's':
  438. case 'S':
  439. g_fUseSingleContext = TRUE;
  440. break;
  441. case 'n':
  442. case 'N':
  443. g_fUseSingleContext = FALSE;
  444. break;
  445. case 'v':
  446. case 'V':
  447. g_fVerbose = TRUE;
  448. break;
  449. case 'h':
  450. case 'H':
  451. default:
  452. Usage();
  453. return -1;
  454. }
  455. } else
  456. pszGUID = argv[0];
  457. }
  458. if (!g_fUseDefaultGUID && (pszGUID == NULL))
  459. {
  460. printf("missing <GUID>\n");
  461. Usage();
  462. return -1;
  463. }
  464. else if (g_fUseDefaultGUID)
  465. {
  466. wstr2guid(L"{F750E6C3-38EE-11D1-85E5-00C04FC295EE}", &g_guidCatRoot);
  467. }
  468. else
  469. {
  470. MultiByteToWideChar(CP_ACP, 0, pszGUID, -1, wsz, 1024);
  471. if (!(wstr2guid(wsz, &g_guidCatRoot)))
  472. {
  473. return -1;
  474. }
  475. }
  476. //
  477. // setup defaults
  478. //
  479. guid2wstr(&g_guidCatRoot, g_wszSubSysGUID);
  480. g_wszDefaultSystemDir[0] = NULL;
  481. if (0 == GetSystemDirectoryW(&g_wszDefaultSystemDir[0], MAX_PATH))
  482. {
  483. printf("GetSystemDirectory failure\nGLE = %lx\n", GetLastError());
  484. goto ErrorReturn;
  485. }
  486. if (NULL == (g_pwszCatalogDir = (LPWSTR)
  487. malloc(sizeof(WCHAR) *
  488. (wcslen(g_wszDefaultSystemDir) +
  489. wcslen(WSZ_CATALOG_NEW_BASE_DIRECTORY) +
  490. wcslen(g_wszSubSysGUID) +
  491. 4))))
  492. {
  493. printf("malloc failure\n");
  494. goto ErrorReturn;
  495. }
  496. wcscpy(g_pwszCatalogDir, g_wszDefaultSystemDir);
  497. if ((g_pwszCatalogDir[0]) &&
  498. (g_pwszCatalogDir[wcslen(&g_wszDefaultSystemDir[0]) - 1] != L'\\'))
  499. {
  500. wcscat(g_pwszCatalogDir, L"\\");
  501. }
  502. wcscat(g_pwszCatalogDir, WSZ_CATALOG_NEW_BASE_DIRECTORY);
  503. wcscat(g_pwszCatalogDir, L"\\");
  504. wcscat(g_pwszCatalogDir, g_wszSubSysGUID);
  505. wcscat(g_pwszCatalogDir, L"\\");
  506. //
  507. // make the search string
  508. //
  509. if (NULL == (g_pwszCatalogSearchString = (LPWSTR)
  510. malloc(sizeof(WCHAR) *
  511. (wcslen(g_wszDefaultSystemDir) +
  512. wcslen(WSZ_CATALOG_NEW_BASE_DIRECTORY) +
  513. wcslen(g_wszSubSysGUID) +
  514. wcslen(L"*") +
  515. 4))))
  516. {
  517. printf(" malloc failure\n");
  518. goto ErrorReturn;
  519. }
  520. wcscpy(g_pwszCatalogSearchString, g_wszDefaultSystemDir);
  521. if ((g_pwszCatalogSearchString[0]) &&
  522. (g_pwszCatalogSearchString[wcslen(&g_wszDefaultSystemDir[0]) - 1] != L'\\'))
  523. {
  524. wcscat(g_pwszCatalogSearchString, L"\\");
  525. }
  526. wcscat(g_pwszCatalogSearchString, WSZ_CATALOG_NEW_BASE_DIRECTORY);
  527. wcscat(g_pwszCatalogSearchString, L"\\");
  528. wcscat(g_pwszCatalogSearchString, g_wszSubSysGUID);
  529. wcscat(g_pwszCatalogSearchString, L"\\");
  530. wcscat(g_pwszCatalogSearchString, L"*");
  531. //
  532. // run requested operations
  533. //
  534. if (g_fDatabaseConsistencyCheck)
  535. {
  536. DoDatabaseConsistencyCheck();
  537. }
  538. //
  539. // cleanup
  540. //
  541. CommonReturn:
  542. if (hCatAdminLocal != NULL)
  543. {
  544. CryptCATAdminReleaseContext(hCatAdminLocal, 0);
  545. }
  546. if (g_pwszCatalogDir != NULL)
  547. {
  548. free(g_pwszCatalogDir);
  549. }
  550. if (g_pwszCatalogSearchString != NULL)
  551. {
  552. free(g_pwszCatalogSearchString);
  553. }
  554. printf("Done\n");
  555. return (ret);
  556. ErrorReturn:
  557. ret = -1;
  558. goto CommonReturn;
  559. }