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.

1009 lines
29 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: updcat.cpp
  7. //
  8. // Contents: Update Catalog Entry
  9. //
  10. // History: 02-Sep-98 kirtd Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <windows.h>
  14. #include <assert.h>
  15. #include "wincrypt.h"
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <memory.h>
  20. #include <time.h>
  21. #include <mscat.h>
  22. #include <mssip.h>
  23. #include <sipguids.h>
  24. #include <wintrust.h>
  25. // Prototypes
  26. // BOOL AddFileToCatalog (IN HANDLE hCatalog, IN LPWSTR pwszFileName);
  27. BOOL RemoveHashFromCatalog(IN LPWSTR pwszCatalogFile, IN LPSTR pszHash);
  28. BOOL AddFileOrAuthAttrToCatalog(IN HANDLE hCatalog, IN LPWSTR pwszFileName,
  29. IN DWORD dwAttrFlags, IN LPWSTR pwszAttrName,
  30. IN LPWSTR pwszAttrValue);
  31. BOOL CheckFileSize(IN LPWSTR pFileName, IN ULONG size);
  32. extern "C" BOOL MsCatConstructHashTag (IN DWORD cbDigest, IN LPBYTE pbDigest, OUT LPWSTR* ppwszHashTag);
  33. extern "C" VOID MsCatFreeHashTag (IN LPWSTR pwszHashTag);
  34. #define AddFileToCatalog(cat, file) AddFileOrAuthAttrToCatalog(cat, file, 0, NULL, NULL)
  35. #define PWSZ_SPATTR L"SpAttr"
  36. #define PSZ_SPATTR_OPTION "-SpAttr:"
  37. ULONG sizeLimit = 0;
  38. //+---------------------------------------------------------------------------
  39. //
  40. // Function: Usage
  41. //
  42. // Synopsis: prints the usage statement
  43. //
  44. //----------------------------------------------------------------------------
  45. static void Usage(void)
  46. {
  47. printf("Usage: updcat <Catalog File> [-s <Size>] [-a <FileName>]\n");
  48. printf("Usage: updcat <Catalog File> [-d <Hash>]\n");
  49. printf("Usage: updcat <Catalog File> [-s <Size>] [-r <Hash> <FileName>]\n");
  50. printf("Usage: updcat <Catalog File> [-attr <FileName> <Name> <Value>]\n");
  51. printf(" -a, add the file by hash to the catalog\n");
  52. printf(" -d, delete the hash from the catalog\n");
  53. printf(" -r, replace the hash in the catalog with the hash of the file\n");
  54. printf(" -s, fail if the file is smaller than this size (in bytes)\n");
  55. printf(" -attr, add an ASCII attribute to a file's catalog entry\n");
  56. printf(" -SpAttr:, replace the current (or add new) SpAttr in the catalog\n");
  57. }
  58. //+---------------------------------------------------------------------------
  59. //
  60. // Function: main
  61. //
  62. // Synopsis: main program entry point
  63. //
  64. //----------------------------------------------------------------------------
  65. int _cdecl main(int argc, char * argv[])
  66. {
  67. BOOL fResult = TRUE;
  68. LPSTR pszCatalogFile = NULL;
  69. LPWSTR pwszCatalogFile = NULL;
  70. LPSTR pszFileName = NULL;
  71. LPSTR pszHash = NULL;
  72. LPWSTR pwszFileName = NULL;
  73. LPSTR pszAttrName = NULL;
  74. LPWSTR pwszAttrName = NULL;
  75. LPSTR pszAttrValue = NULL;
  76. LPWSTR pwszAttrValue = NULL;
  77. BOOL fAddEntry = FALSE;
  78. DWORD cch = 0;
  79. HANDLE hCatalog = NULL;
  80. BOOL fOptionChosen = FALSE;
  81. LPWSTR pwszSpAttr = NULL;
  82. CRYPTCATATTRIBUTE *pCatAttr = NULL;
  83. if ( argc < 2 )
  84. {
  85. Usage();
  86. return( 1 );
  87. }
  88. argv++;
  89. argc--;
  90. printf( "command line: %s\n", GetCommandLineA() );
  91. pszCatalogFile = argv[0];
  92. cch = strlen( pszCatalogFile );
  93. while ( --argc > 0 )
  94. {
  95. if ( **++argv == '-' )
  96. {
  97. switch( argv[0][1] )
  98. {
  99. case 'a':
  100. case 'A':
  101. if ( argc < 2 )
  102. {
  103. Usage();
  104. return( 1 );
  105. }
  106. pszFileName = argv[1];
  107. fAddEntry = TRUE;
  108. if (_strcmpi(&argv[0][1], "attr") == 0)
  109. {
  110. if ( argc < 4 )
  111. {
  112. Usage();
  113. return( 1 );
  114. }
  115. pszAttrName = argv[2];
  116. pszAttrValue = argv[3];
  117. }
  118. break;
  119. case 'd':
  120. case 'D':
  121. if ( argc < 2 )
  122. {
  123. Usage();
  124. return( 1 );
  125. }
  126. pszHash = argv[1];
  127. break;
  128. case 'r':
  129. case 'R':
  130. if ( argc < 3 )
  131. {
  132. Usage();
  133. return( 1 );
  134. }
  135. pszHash = argv[1];
  136. fAddEntry = TRUE;
  137. pszFileName = argv[2];
  138. break;
  139. case 'S':
  140. if (memcmp(&(argv[0][0]), (void *) PSZ_SPATTR_OPTION, strlen(PSZ_SPATTR_OPTION)) == 0)
  141. {
  142. DWORD dwNumChars;
  143. dwNumChars = MultiByteToWideChar(
  144. CP_ACP,
  145. 0,
  146. &(argv[0][strlen(PSZ_SPATTR_OPTION)]),
  147. -1,
  148. NULL,
  149. 0
  150. );
  151. if (dwNumChars == 0)
  152. {
  153. printf( "Error calling MultiByteToWideChar on %s\n", &(argv[0][strlen(PSZ_SPATTR_OPTION)]));
  154. return -1;
  155. }
  156. pwszSpAttr = new WCHAR [ dwNumChars ];
  157. if (pwszSpAttr == NULL)
  158. {
  159. printf("Out of memory error\n");
  160. return -1;
  161. }
  162. if ( MultiByteToWideChar(
  163. CP_ACP,
  164. 0,
  165. &(argv[0][strlen(PSZ_SPATTR_OPTION)]),
  166. -1,
  167. pwszSpAttr,
  168. dwNumChars
  169. ) == 0 )
  170. {
  171. delete pwszSpAttr;
  172. printf( "Error calling MultiByteToWideChar on %s\n", &(argv[0][strlen(PSZ_SPATTR_OPTION)]));
  173. return -1;
  174. }
  175. }
  176. else
  177. {
  178. Usage();
  179. return -1;
  180. }
  181. break;
  182. case 's':
  183. if ((argc < 2) || (argv[0][2] != '\0'))
  184. {
  185. Usage();
  186. return -1;
  187. }
  188. sizeLimit = strtol(*(argv+1), NULL, 10);
  189. if (errno || (sizeLimit == 0))
  190. {
  191. printf ("Invalid size specified with -s option: %s\n",*(argv+1));
  192. Usage();
  193. return -1;
  194. }
  195. break;
  196. default:
  197. Usage();
  198. return -1;
  199. }
  200. fOptionChosen = TRUE;
  201. argc -= 1;
  202. argv++;
  203. }
  204. }
  205. pwszCatalogFile = new WCHAR [ cch + 1 ];
  206. if ( pwszCatalogFile != NULL )
  207. {
  208. if ( MultiByteToWideChar(
  209. CP_ACP,
  210. 0,
  211. pszCatalogFile,
  212. -1,
  213. pwszCatalogFile,
  214. cch + 1
  215. ) == 0 )
  216. {
  217. delete pwszCatalogFile;
  218. return( 1 );
  219. }
  220. }
  221. if (!fOptionChosen)
  222. {
  223. Usage();
  224. delete pwszCatalogFile;
  225. return -1;
  226. }
  227. if (pszFileName != NULL)
  228. {
  229. cch = strlen( pszFileName );
  230. pwszFileName = new WCHAR [ cch + 1 ];
  231. if ( pwszFileName != NULL )
  232. {
  233. if ( MultiByteToWideChar(
  234. CP_ACP,
  235. 0,
  236. pszFileName,
  237. -1,
  238. pwszFileName,
  239. cch + 1
  240. ) == 0 )
  241. {
  242. delete pwszCatalogFile;
  243. delete pwszFileName;
  244. return( 1 );
  245. }
  246. }
  247. }
  248. if (pszAttrName != NULL)
  249. {
  250. cch = strlen( pszAttrName );
  251. pwszAttrName = new WCHAR [ cch + 1 ];
  252. if ( pwszAttrName != NULL )
  253. {
  254. if ( MultiByteToWideChar(
  255. CP_ACP,
  256. 0,
  257. pszAttrName,
  258. -1,
  259. pwszAttrName,
  260. cch + 1
  261. ) == 0 )
  262. {
  263. printf("Error converting AttrName to wchar\n");
  264. delete pwszCatalogFile;
  265. delete pwszFileName;
  266. delete pwszAttrName;
  267. return( 1 );
  268. }
  269. }
  270. }
  271. if (pszAttrValue != NULL)
  272. {
  273. cch = strlen( pszAttrValue );
  274. pwszAttrValue = new WCHAR [ cch + 1 ];
  275. if ( pwszAttrValue != NULL )
  276. {
  277. if ( MultiByteToWideChar(
  278. CP_ACP,
  279. 0,
  280. pszAttrValue,
  281. -1,
  282. pwszAttrValue,
  283. cch + 1
  284. ) == 0 )
  285. {
  286. printf("Error converting AttrValue to wchar\n");
  287. delete pwszCatalogFile;
  288. delete pwszFileName;
  289. delete pwszAttrName;
  290. delete pwszAttrValue;
  291. return( 1 );
  292. }
  293. }
  294. }
  295. if ( pszHash != NULL )
  296. {
  297. fResult = RemoveHashFromCatalog(pwszCatalogFile, pszHash);
  298. if ( fResult == FALSE )
  299. {
  300. printf("Error removing <%s> from catalog <%s>\n", pszHash, pszCatalogFile);
  301. }
  302. }
  303. //
  304. // If there haven't been any errors, and we are adding a hash
  305. //
  306. if (( fResult == TRUE ) && ( fAddEntry == TRUE ))
  307. {
  308. hCatalog = CryptCATOpen(
  309. pwszCatalogFile,
  310. CRYPTCAT_OPEN_ALWAYS,
  311. NULL,
  312. 0x00000001,
  313. 0x00010001
  314. );
  315. if ( hCatalog == NULL )
  316. {
  317. fResult = FALSE;
  318. }
  319. else
  320. {
  321. // If we're adding an attribute
  322. if (pwszAttrName && pwszAttrValue)
  323. {
  324. fResult = AddFileOrAuthAttrToCatalog( hCatalog, pwszFileName,
  325. 0x10010001, pwszAttrName,
  326. pwszAttrValue );
  327. CryptCATClose( hCatalog );
  328. if ( fResult == FALSE )
  329. {
  330. printf("Error adding Attribute <%s> to catalog <%s>\n",
  331. pszAttrName, pszCatalogFile);
  332. }
  333. }
  334. else
  335. // If we're only adding the file by hash
  336. {
  337. fResult = AddFileToCatalog( hCatalog, pwszFileName );
  338. CryptCATClose( hCatalog );
  339. if ( fResult == FALSE )
  340. {
  341. printf("Error adding <%s> to catalog <%s>\n",
  342. pszFileName, pszCatalogFile);
  343. }
  344. }
  345. }
  346. }
  347. if ( pwszSpAttr != NULL )
  348. {
  349. hCatalog = CryptCATOpen(
  350. pwszCatalogFile,
  351. CRYPTCAT_OPEN_ALWAYS,
  352. NULL,
  353. 0x00000001,
  354. 0x00010001
  355. );
  356. if ( hCatalog == NULL )
  357. {
  358. fResult = FALSE;
  359. goto Return;
  360. }
  361. //
  362. // Check to see if it already has an SpAttr
  363. //
  364. pCatAttr = CryptCATGetCatAttrInfo(hCatalog, PWSZ_SPATTR);
  365. if ( pCatAttr == NULL )
  366. {
  367. if (NULL == CryptCATPutCatAttrInfo(
  368. hCatalog,
  369. PWSZ_SPATTR,
  370. 0x10010001,
  371. (wcslen(pwszSpAttr) + 1) * sizeof(WCHAR),
  372. (BYTE *) pwszSpAttr))
  373. {
  374. printf("Error adding SpAttr to catalog <%s>\n", pszCatalogFile);
  375. fResult = FALSE;
  376. goto Return;
  377. }
  378. }
  379. else
  380. {
  381. if (NULL == CryptCATPutCatAttrInfo(
  382. hCatalog,
  383. PWSZ_SPATTR,
  384. 0x10040001,
  385. (wcslen(pwszSpAttr) + 1) * sizeof(WCHAR),
  386. (BYTE *) pwszSpAttr))
  387. {
  388. if (GetLastError() == ERROR_INVALID_PARAMETER)
  389. {
  390. printf("The SpAttr modification failed, it is likely due to an old wintrust.dll\n");
  391. }
  392. else
  393. {
  394. printf("Error changing SpAttr in catalog <%s>\n", pszCatalogFile);
  395. }
  396. fResult = FALSE;
  397. goto Return;
  398. }
  399. }
  400. CryptCATPersistStore(hCatalog);
  401. CryptCATClose( hCatalog );
  402. }
  403. Return:
  404. return( !fResult );
  405. }
  406. typedef BOOL (WINAPI *PFN_CRYPTSIP_RETRIEVE_SUBJECT_GUID_FOR_CATALOG_FILE) (
  407. IN LPCWSTR FileName,
  408. IN HANDLE hFileIn,
  409. OUT GUID *pgSubject
  410. );
  411. //+---------------------------------------------------------------------------
  412. //
  413. // Function: AddFileOrAuthAttrToCatalog
  414. //
  415. // Synopsis: add a file as an entry to the catalog. The tag will be the
  416. // hash
  417. // additionally, you can add an authenticated attribute.
  418. //
  419. //----------------------------------------------------------------------------
  420. BOOL AddFileOrAuthAttrToCatalog (IN HANDLE hCatalog,
  421. IN LPWSTR pwszFileName,
  422. IN DWORD dwAttrFlags,
  423. IN LPWSTR pwszAttrName,
  424. IN LPWSTR pwszAttrValue)
  425. {
  426. BOOL fResult;
  427. GUID FlatSubject = CRYPT_SUBJTYPE_FLAT_IMAGE;
  428. GUID SubjectType;
  429. SIP_SUBJECTINFO SubjectInfo;
  430. SIP_DISPATCH_INFO DispatchInfo;
  431. DWORD cbIndirectData;
  432. SIP_INDIRECT_DATA* pIndirectData = NULL;
  433. CRYPTCATSTORE* pCatStore = CryptCATStoreFromHandle( hCatalog );
  434. CRYPTCATMEMBER* pMember;
  435. CRYPTCATATTRIBUTE* pAttr;
  436. LPWSTR pwszHashTag = NULL;
  437. HMODULE hMod = NULL;
  438. PFN_CRYPTSIP_RETRIEVE_SUBJECT_GUID_FOR_CATALOG_FILE pSIPFunc = NULL;
  439. memset( &SubjectInfo, 0, sizeof( SubjectInfo ) );
  440. memset( &DispatchInfo, 0, sizeof( DispatchInfo ) );
  441. if (sizeLimit)
  442. {
  443. // Check that we do not add the hash for a file whose
  444. // size if less than the specified lower limit
  445. if ( !CheckFileSize(pwszFileName, sizeLimit) )
  446. {
  447. printf ("Error: %S is smaller than the specified minimum size (%d)\n",
  448. pwszFileName, sizeLimit);
  449. return FALSE;
  450. }
  451. }
  452. //
  453. // NOTE!!!!!
  454. //
  455. // Try to use the function that only retrieves SIPs for hashing files
  456. // that are to be included in catalog files. This function is new and
  457. // only exists post win2k, so if it isn't there, then fall back to the
  458. // win2k function... which should be OK since Win2k didn't SHIP
  459. // with any SIPs that caused problems (although SIPs could be installed on
  460. // a win2k system after the fact that do cause problems)
  461. //
  462. if (NULL != (hMod = LoadLibrary("crypt32.dll")))
  463. {
  464. pSIPFunc = (PFN_CRYPTSIP_RETRIEVE_SUBJECT_GUID_FOR_CATALOG_FILE)
  465. GetProcAddress(hMod, "CryptSIPRetrieveSubjectGuidForCatalogFile");
  466. if (pSIPFunc != NULL)
  467. {
  468. if ( pSIPFunc(pwszFileName, NULL, &SubjectType) == FALSE )
  469. {
  470. memcpy( &SubjectType, &FlatSubject, sizeof( GUID ) );
  471. }
  472. }
  473. }
  474. if (pSIPFunc == NULL)
  475. {
  476. //
  477. // Fall back to old SIP resolver
  478. //
  479. if ( CryptSIPRetrieveSubjectGuid(
  480. pwszFileName,
  481. NULL,
  482. &SubjectType
  483. ) == FALSE )
  484. {
  485. memcpy( &SubjectType, &FlatSubject, sizeof( GUID ) );
  486. }
  487. }
  488. if (hMod != NULL)
  489. {
  490. FreeLibrary(hMod);
  491. }
  492. if ( CryptSIPLoad( &SubjectType, 0, &DispatchInfo ) == FALSE )
  493. {
  494. return( FALSE );
  495. }
  496. // Some of this subject info stuff should be configurable but
  497. // since the CDF API does not allow it, we won't worry about it
  498. // yet.
  499. SubjectInfo.cbSize = sizeof( SubjectInfo );
  500. SubjectInfo.hProv = pCatStore->hProv;
  501. SubjectInfo.DigestAlgorithm.pszObjId = (char *)CertAlgIdToOID( CALG_SHA1 );
  502. SubjectInfo.dwFlags = SPC_INC_PE_RESOURCES_FLAG |
  503. SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG |
  504. MSSIP_FLAGS_PROHIBIT_RESIZE_ON_CREATE;
  505. SubjectInfo.dwEncodingType = pCatStore->dwEncodingType;
  506. SubjectInfo.pgSubjectType = &SubjectType;
  507. SubjectInfo.pwsFileName = pwszFileName;
  508. fResult = DispatchInfo.pfCreate( &SubjectInfo, &cbIndirectData, NULL );
  509. if ( fResult == TRUE )
  510. {
  511. pIndirectData = (SIP_INDIRECT_DATA *)new BYTE [ cbIndirectData ];
  512. if ( pIndirectData != NULL )
  513. {
  514. fResult = DispatchInfo.pfCreate(
  515. &SubjectInfo,
  516. &cbIndirectData,
  517. pIndirectData
  518. );
  519. }
  520. else
  521. {
  522. SetLastError( E_OUTOFMEMORY );
  523. fResult = FALSE;
  524. }
  525. }
  526. if ( fResult == TRUE )
  527. {
  528. fResult = MsCatConstructHashTag(
  529. pIndirectData->Digest.cbData,
  530. pIndirectData->Digest.pbData,
  531. &pwszHashTag
  532. );
  533. }
  534. if ( fResult == FALSE )
  535. {
  536. goto Return;
  537. }
  538. if (pwszAttrName && pwszAttrValue)
  539. {
  540. // We're adding an Attribute
  541. if (dwAttrFlags != 0x10010001)
  542. {
  543. printf("Error: Unsupported flag specified\n");
  544. fResult = FALSE;
  545. goto Return;
  546. }
  547. // Find the member in the catalog.
  548. pMember = CryptCATGetMemberInfo(hCatalog, pwszHashTag);
  549. if (pMember == NULL)
  550. {
  551. // Catalog member was not found. Adding it...
  552. pMember = CryptCATPutMemberInfo(
  553. hCatalog,
  554. pwszFileName,
  555. pwszHashTag,
  556. &SubjectType,
  557. SubjectInfo.dwIntVersion,
  558. cbIndirectData,
  559. (LPBYTE)pIndirectData
  560. );
  561. }
  562. if (pMember == NULL)
  563. {
  564. printf("Error: Could not find file hash, and could not add it.\n");
  565. fResult = FALSE;
  566. }
  567. else
  568. {
  569. if (pAttr = CryptCATGetAttrInfo(hCatalog, pMember, pwszAttrName))
  570. {
  571. if (wcscmp(pwszAttrValue, LPCWSTR(pAttr->pbValue)) == 0)
  572. {
  573. printf("Attribute already exists with the same value\n");
  574. fResult = FALSE;
  575. }
  576. else
  577. {
  578. pAttr->cbValue = (wcslen(pwszAttrValue) + 1) * sizeof(WCHAR);
  579. delete(pAttr->pbValue);
  580. pAttr->pbValue = (BYTE *)pwszAttrValue;
  581. pAttr->pbValue = new BYTE[pAttr->cbValue];
  582. if (pAttr->pbValue)
  583. {
  584. memcpy(pAttr->pbValue, pwszAttrValue, pAttr->cbValue);
  585. fResult = CryptCATPersistStore(hCatalog);
  586. }
  587. else
  588. {
  589. pAttr->cbValue = 0;
  590. fResult = FALSE;
  591. }
  592. }
  593. }
  594. else
  595. {
  596. pAttr = CryptCATPutAttrInfo(hCatalog,
  597. pMember,
  598. pwszAttrName,
  599. dwAttrFlags,
  600. (wcslen(pwszAttrValue) + 1) * sizeof(WCHAR),
  601. (BYTE *)pwszAttrValue);
  602. if (pAttr != NULL)
  603. {
  604. fResult = CryptCATPersistStore(hCatalog);
  605. }
  606. else
  607. {
  608. fResult = FALSE;
  609. }
  610. }
  611. }
  612. }
  613. else
  614. {
  615. // We're just adding a catalog member
  616. // Does this member already exist?
  617. pMember = CryptCATGetMemberInfo(hCatalog, pwszHashTag);
  618. if (pMember == NULL)
  619. {
  620. // it does not exist in the catalog yet. Add it.
  621. pMember = CryptCATPutMemberInfo(
  622. hCatalog,
  623. pwszFileName,
  624. pwszHashTag,
  625. &SubjectType,
  626. SubjectInfo.dwIntVersion,
  627. cbIndirectData,
  628. (LPBYTE)pIndirectData
  629. );
  630. if ( pMember != NULL )
  631. {
  632. fResult = CryptCATPersistStore( hCatalog );
  633. }
  634. else
  635. {
  636. fResult = FALSE;
  637. }
  638. }
  639. else
  640. {
  641. // It already exists in the catalog.
  642. printf("This file's hash is already present in the catalog.\n");
  643. fResult = FALSE;
  644. }
  645. }
  646. Return:
  647. if ( pwszHashTag != NULL )
  648. {
  649. MsCatFreeHashTag( pwszHashTag );
  650. }
  651. delete (LPBYTE)pIndirectData;
  652. return( fResult );
  653. }
  654. //+---------------------------------------------------------------------------
  655. //
  656. // Function: RemoveHashFromCatalog
  657. //
  658. // Synopsis: removes a hash entry from the catalog.
  659. //
  660. //----------------------------------------------------------------------------
  661. BOOL
  662. RemoveHashFromCatalog(IN LPWSTR pwszCatalogFile, IN LPSTR pszHash)
  663. {
  664. BOOL fRet = TRUE;
  665. LPSTR pChar = NULL;
  666. int i, j;
  667. DWORD dwContentType;
  668. PCTL_CONTEXT pCTLContext = NULL;
  669. CTL_CONTEXT CTLContext;
  670. CTL_INFO CTLInfo;
  671. DWORD cbEncodedCTL = 0;
  672. BYTE *pbEncodedCTL = NULL;
  673. DWORD cbWritten = 0;
  674. HANDLE hFile = INVALID_HANDLE_VALUE;
  675. DWORD cch = 0;
  676. LPWSTR pwszHash = NULL;
  677. BOOL fHashFound = FALSE;
  678. CMSG_SIGNED_ENCODE_INFO signedInfo;
  679. memset(&signedInfo, 0, sizeof(signedInfo));
  680. signedInfo.cbSize = sizeof(signedInfo);
  681. CTLInfo.rgCTLEntry = NULL;
  682. cch = strlen( pszHash );
  683. pwszHash = new WCHAR [ cch + 1 ];
  684. if ( pwszHash == NULL )
  685. {
  686. goto ErrorReturn;
  687. }
  688. if ( MultiByteToWideChar(
  689. CP_ACP,
  690. 0,
  691. pszHash,
  692. -1,
  693. pwszHash,
  694. cch + 1
  695. ) == 0 )
  696. {
  697. goto ErrorReturn;
  698. }
  699. //
  700. // Get rid of all the ' ' chars
  701. //
  702. i = 0;
  703. j = 0;
  704. for (i=0; i<(int)wcslen(pwszHash); i++)
  705. {
  706. if (pwszHash[i] != ' ')
  707. {
  708. pwszHash[j++] = pwszHash[i];
  709. }
  710. }
  711. pwszHash[j] = '\0';
  712. //
  713. // Open the cat file as a CTL
  714. //
  715. if (!CryptQueryObject(
  716. CERT_QUERY_OBJECT_FILE,
  717. pwszCatalogFile,
  718. CERT_QUERY_CONTENT_FLAG_CTL,
  719. CERT_QUERY_FORMAT_FLAG_BINARY,
  720. 0, //flags
  721. NULL,
  722. &dwContentType,
  723. NULL,
  724. NULL,
  725. NULL,
  726. (const void **) &pCTLContext))
  727. {
  728. goto ErrorReturn;
  729. }
  730. if (dwContentType != CERT_QUERY_CONTENT_CTL)
  731. {
  732. goto ErrorReturn;
  733. }
  734. //
  735. // Create another CTL context just like pCTLContext
  736. //
  737. CTLInfo = *(pCTLContext->pCtlInfo);
  738. CTLInfo.rgCTLEntry = (PCTL_ENTRY) new CTL_ENTRY[pCTLContext->pCtlInfo->cCTLEntry];
  739. if (CTLInfo.rgCTLEntry == NULL)
  740. {
  741. goto ErrorReturn;
  742. }
  743. //
  744. // Loop through all the ctl entries and remove the entry
  745. // that corresponds to the hash given
  746. //
  747. CTLInfo.cCTLEntry = 0;
  748. for (i=0; i<(int)pCTLContext->pCtlInfo->cCTLEntry; i++)
  749. {
  750. if (wcscmp(
  751. (LPWSTR) pCTLContext->pCtlInfo->rgCTLEntry[i].SubjectIdentifier.pbData,
  752. pwszHash) != 0)
  753. {
  754. CTLInfo.rgCTLEntry[CTLInfo.cCTLEntry++] = pCTLContext->pCtlInfo->rgCTLEntry[i];
  755. }
  756. else
  757. {
  758. fHashFound = TRUE;
  759. }
  760. }
  761. if (!fHashFound)
  762. {
  763. printf("<%S> not found in <%S>\n", pwszHash, pwszCatalogFile);
  764. goto ErrorReturn;
  765. }
  766. //
  767. // now save the CTL which is exactly the same as the previous one,
  768. // except it doesn't doesn't have the hash being removed, back to
  769. // the original filename
  770. //
  771. if (!CryptMsgEncodeAndSignCTL(
  772. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  773. &CTLInfo,
  774. &signedInfo,
  775. 0,
  776. NULL,
  777. &cbEncodedCTL))
  778. {
  779. goto ErrorReturn;
  780. }
  781. if (NULL == (pbEncodedCTL = new BYTE[cbEncodedCTL]))
  782. {
  783. goto ErrorReturn;
  784. }
  785. if (!CryptMsgEncodeAndSignCTL(
  786. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  787. &CTLInfo,
  788. &signedInfo,
  789. 0,
  790. pbEncodedCTL,
  791. &cbEncodedCTL))
  792. {
  793. goto ErrorReturn;
  794. }
  795. if (INVALID_HANDLE_VALUE == (hFile = CreateFileW(
  796. pwszCatalogFile,
  797. GENERIC_READ | GENERIC_WRITE,
  798. 0,
  799. NULL,
  800. CREATE_ALWAYS,
  801. FILE_ATTRIBUTE_NORMAL,
  802. NULL)))
  803. {
  804. goto ErrorReturn;
  805. }
  806. if (!WriteFile(
  807. hFile,
  808. pbEncodedCTL,
  809. cbEncodedCTL,
  810. &cbWritten,
  811. NULL))
  812. {
  813. printf("WriteFile of <%S> failed with %x\n", pwszCatalogFile, GetLastError());
  814. goto ErrorReturn;
  815. }
  816. if (cbWritten != cbEncodedCTL)
  817. {
  818. goto ErrorReturn;
  819. }
  820. CloseHandle(hFile);
  821. hFile = INVALID_HANDLE_VALUE;
  822. CommonReturn:
  823. if (pwszHash != NULL)
  824. {
  825. delete (pwszHash);
  826. }
  827. if (pCTLContext != NULL)
  828. {
  829. CertFreeCTLContext(pCTLContext);
  830. }
  831. if (CTLInfo.rgCTLEntry != NULL)
  832. {
  833. delete (CTLInfo.rgCTLEntry);
  834. }
  835. if (pbEncodedCTL != NULL)
  836. {
  837. delete (pbEncodedCTL);
  838. }
  839. if (hFile != INVALID_HANDLE_VALUE)
  840. {
  841. if (!CloseHandle(hFile))
  842. {
  843. fRet = FALSE;
  844. }
  845. }
  846. return fRet;
  847. ErrorReturn:
  848. fRet = FALSE;
  849. goto CommonReturn;
  850. }
  851. //+---------------------------------------------------------------------------
  852. //
  853. // Function: CheckFileSize
  854. //
  855. // Synopsis: Checks that a file meets the minumum size requirement.
  856. //
  857. //----------------------------------------------------------------------------
  858. BOOL
  859. CheckFileSize (LPWSTR fileName, ULONG sizeLimit)
  860. {
  861. HANDLE hFile;
  862. LARGE_INTEGER sizeFile = {0};
  863. // Attempt to open the specified file
  864. hFile = CreateFileW( fileName,
  865. GENERIC_READ,
  866. FILE_SHARE_READ,
  867. NULL,
  868. OPEN_EXISTING,
  869. FILE_FLAG_SEQUENTIAL_SCAN,
  870. NULL );
  871. if (INVALID_HANDLE_VALUE == hFile)
  872. {
  873. printf("Error opening %S (%lu)\n", fileName, GetLastError() );
  874. return FALSE;
  875. }
  876. // Get the file size
  877. if (!GetFileSizeEx(hFile, &sizeFile))
  878. {
  879. printf("Error determining size of %S (%lu)\n", fileName, GetLastError());
  880. return FALSE;
  881. }
  882. if ((!sizeFile.HighPart) && (sizeFile.LowPart < sizeLimit))
  883. {
  884. // File is too small
  885. return FALSE;
  886. }
  887. // Success. File is not too small.
  888. return TRUE;
  889. }