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.

757 lines
20 KiB

  1. /*
  2. Copyright (c) Microsoft Corporation
  3. */
  4. #include "stdinc.h"
  5. #include "sxsp.h"
  6. #include "imagehlp.h"
  7. #include "windows.h"
  8. #include "hashfile.h"
  9. #include "wincrypt.h"
  10. #include "winbase.h"
  11. #include "softpub.h"
  12. #include "strongname.h"
  13. #include "fusioneventlog.h"
  14. #include "sxsp.h"
  15. BOOL SxspImageDigesterFunc( DIGEST_HANDLE hSomething, PBYTE pbDataBlock, DWORD dwLength);
  16. BOOL SxspSimpleHashRoutine(CFusionHash &rhHash, HANDLE hFile);
  17. BOOL SxspImageHashRoutine(CFusionHash &rhHash, HANDLE hFile, BOOL &bInvalidImage);
  18. CRITICAL_SECTION g_csHashFile;
  19. struct _HASH_ALG_NAME_MAP
  20. {
  21. PWSTR wsName;
  22. ULONG cchName;
  23. ALG_ID cId;
  24. } HashAlgNameMap[] =
  25. {
  26. { L"SHA1", 4, CALG_SHA1 },
  27. { L"SHA", 3, CALG_SHA },
  28. { L"MD5", 3, CALG_MD5 },
  29. { L"MD4", 3, CALG_MD4 },
  30. { L"MD2", 3, CALG_MD2 },
  31. { L"MAC", 3, CALG_MAC },
  32. { L"HMAC", 4, CALG_HMAC }
  33. };
  34. BOOL
  35. SxspEnumKnownHashTypes(
  36. DWORD dwIndex,
  37. OUT CBaseStringBuffer &rbuffHashTypeName,
  38. BOOL &rbNoMoreItems
  39. )
  40. {
  41. FN_PROLOG_WIN32
  42. rbNoMoreItems = FALSE;
  43. if ( dwIndex >= NUMBER_OF( HashAlgNameMap ) )
  44. {
  45. rbNoMoreItems = TRUE;
  46. }
  47. else
  48. {
  49. IFW32FALSE_EXIT( rbuffHashTypeName.Win32Assign(
  50. HashAlgNameMap[dwIndex].wsName,
  51. HashAlgNameMap[dwIndex].cchName ) );
  52. }
  53. FN_EPILOG
  54. }
  55. BOOL
  56. SxspHashAlgFromString(
  57. const CBaseStringBuffer &strAlgName,
  58. ALG_ID &algId
  59. )
  60. {
  61. FN_PROLOG_WIN32
  62. SIZE_T idx;
  63. for (idx = 0; idx < NUMBER_OF(HashAlgNameMap); idx++)
  64. {
  65. if (::FusionpCompareStrings(
  66. strAlgName, strAlgName.Cch(),
  67. HashAlgNameMap[idx].wsName, HashAlgNameMap[idx].cchName,
  68. false) == 0)
  69. {
  70. algId = HashAlgNameMap[idx].cId;
  71. break;
  72. }
  73. }
  74. if (idx == NUMBER_OF(HashAlgNameMap))
  75. ORIGINATE_WIN32_FAILURE_AND_EXIT(HashAlgDoesNotMatch, ERROR_SXS_MANIFEST_PARSE_ERROR);
  76. FN_EPILOG
  77. }
  78. BOOL
  79. SxspHashStringFromAlg(
  80. ALG_ID algId,
  81. CBaseStringBuffer &strAlgName
  82. )
  83. {
  84. FN_PROLOG_WIN32
  85. SIZE_T idx;
  86. strAlgName.Clear();
  87. for (idx = 0; idx < NUMBER_OF(HashAlgNameMap); idx++)
  88. {
  89. if (HashAlgNameMap[idx].cId == algId)
  90. {
  91. IFW32FALSE_EXIT(strAlgName.Win32Assign(HashAlgNameMap[idx].wsName, HashAlgNameMap[idx].cchName));
  92. break;
  93. }
  94. }
  95. PARAMETER_CHECK(idx != NUMBER_OF(HashAlgNameMap));
  96. FN_EPILOG
  97. }
  98. BOOL
  99. SxspCheckHashDuringInstall(
  100. BOOL fHasHashData,
  101. const CBaseStringBuffer &rbuffFile,
  102. const CBaseStringBuffer &rbuffHashDataString,
  103. ALG_ID HashAlgId,
  104. HashValidateResult &rHashValid
  105. )
  106. {
  107. FN_PROLOG_WIN32
  108. rHashValid = HashValidate_OtherProblems;
  109. #if DBG
  110. ::FusionpDbgPrintEx(
  111. FUSION_DBG_LEVEL_INFO,
  112. "SXS.DLL: %s - Validating install-time hash: File=%ls tHasHash=%s tAlgId=0x%08x\n\tHash=%ls\n",
  113. __FUNCTION__,
  114. static_cast<PCWSTR>(rbuffFile),
  115. fHasHashData ? "yes" : "no",
  116. HashAlgId,
  117. static_cast<PCWSTR>(rbuffHashDataString));
  118. #endif
  119. if (fHasHashData)
  120. {
  121. CFusionArray<BYTE> rgbHashData;
  122. IFW32FALSE_EXIT(rgbHashData.Win32Initialize());
  123. IFW32FALSE_EXIT(
  124. ::SxspHashStringToBytes(
  125. rbuffHashDataString,
  126. rbuffHashDataString.Cch(),
  127. rgbHashData));
  128. IFW32FALSE_EXIT(
  129. ::SxspVerifyFileHash(
  130. 0,
  131. rbuffFile,
  132. rgbHashData,
  133. HashAlgId,
  134. rHashValid));
  135. }
  136. else
  137. {
  138. //
  139. // If there's no hash data, or we're in OS setup mode, then the hash of the
  140. // file is "implicitly" correct.
  141. //
  142. rHashValid = HashValidate_Matches;
  143. }
  144. FN_EPILOG
  145. }
  146. BOOL
  147. SxspCreateFileHash(
  148. DWORD dwFlags,
  149. ALG_ID PreferredAlgorithm,
  150. const CBaseStringBuffer &pwsFileName,
  151. CFusionArray<BYTE> &rgbHashDestination
  152. )
  153. /*++
  154. Purpose:
  155. Parameters:
  156. Returns:
  157. --*/
  158. {
  159. FN_PROLOG_WIN32
  160. CFusionFile hFile;
  161. CFusionHash hCurrentHash;
  162. // Initialization
  163. hFile = INVALID_HANDLE_VALUE;
  164. PARAMETER_CHECK((dwFlags & ~HASHFLAG_VALID_PARAMS) == 0);
  165. //
  166. // First try and open the file. No sense in doing anything else if we
  167. // can't get to the data to start with. Use a very friendly set of
  168. // rights to check the file. Future users might want to be sure that
  169. // you're in the right security context before doing this - system
  170. // level to check system files, etc.
  171. //
  172. IFW32FALSE_EXIT(hFile.Win32CreateFile(pwsFileName, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING));
  173. //
  174. // We'll be using SHA1 for the file hash
  175. //
  176. IFW32FALSE_EXIT(hCurrentHash.Win32Initialize(CALG_SHA1));
  177. //
  178. // So first try hashing it via the image, and if that fails, try the
  179. // normal file-reading hash routine instead.
  180. //
  181. if (dwFlags & HASHFLAG_AUTODETECT)
  182. {
  183. BOOL fInvalidImage;
  184. IFW32FALSE_EXIT(::SxspImageHashRoutine(hCurrentHash, hFile, fInvalidImage));
  185. if (fInvalidImage)
  186. IFW32FALSE_EXIT(::SxspSimpleHashRoutine(hCurrentHash, hFile));
  187. }
  188. else if (dwFlags & HASHFLAG_STRAIGHT_HASH)
  189. {
  190. IFW32FALSE_EXIT(::SxspSimpleHashRoutine(hCurrentHash, hFile));
  191. }
  192. else if (dwFlags & HASHFLAG_PROCESS_IMAGE)
  193. {
  194. BOOL fInvalidImage;
  195. IFW32FALSE_EXIT(::SxspImageHashRoutine(hCurrentHash, hFile, fInvalidImage));
  196. if (fInvalidImage)
  197. ORIGINATE_WIN32_FAILURE_AND_EXIT(SxspCreateFileHash, ERROR_INVALID_PARAMETER);
  198. }
  199. //
  200. // We know the buffer is the right size, so we just call down to the hash parameter
  201. // getter, which will be smart and bop out (setting the pdwDestinationSize parameter)
  202. // if the user passed an incorrect parameter.
  203. //
  204. IFW32FALSE_EXIT(hCurrentHash.Win32GetValue(rgbHashDestination));
  205. FN_EPILOG
  206. }
  207. BOOL
  208. SxspImageDigesterFunc(
  209. DIGEST_HANDLE hSomething,
  210. PBYTE pbDataBlock,
  211. DWORD dwLength
  212. )
  213. {
  214. FN_PROLOG_WIN32
  215. CFusionHash* pHashObject = reinterpret_cast<CFusionHash*>(hSomething);
  216. if (pHashObject != NULL)
  217. IFW32FALSE_EXIT(pHashObject->Win32HashData(pbDataBlock, dwLength));
  218. FN_EPILOG
  219. }
  220. BOOL
  221. SxspSimpleHashRoutine(
  222. CFusionHash &rhHash,
  223. HANDLE hFile
  224. )
  225. {
  226. FN_PROLOG_WIN32
  227. DWORD dwDataRead;
  228. BOOL fKeepReading = TRUE;
  229. BOOL b = FALSE;
  230. CFusionArray<BYTE> srgbBuffer;
  231. IFW32FALSE_EXIT( srgbBuffer.Win32SetSize( 64 * 1024 ) );
  232. while (fKeepReading)
  233. {
  234. IFW32FALSE_ORIGINATE_AND_EXIT(::ReadFile(hFile, srgbBuffer.GetArrayPtr(), srgbBuffer.GetSizeAsDWORD(), &dwDataRead, NULL));
  235. //
  236. // if we're out of data, quit.
  237. //
  238. if (dwDataRead == 0)
  239. {
  240. fKeepReading = FALSE;
  241. continue;
  242. }
  243. //
  244. // If we've gotten this far, we need to add the data found
  245. // to our existing hash
  246. //
  247. IFW32FALSE_EXIT(rhHash.Win32HashData(srgbBuffer.GetArrayPtr(), dwDataRead));
  248. }
  249. FN_EPILOG
  250. }
  251. BOOL
  252. SxspImageHashRoutine(
  253. CFusionHash &rhHash,
  254. HANDLE hFile,
  255. BOOL &rfInvalidImage
  256. )
  257. {
  258. FN_PROLOG_WIN32
  259. CSxsLockCriticalSection lock(g_csHashFile);
  260. rfInvalidImage = FALSE;
  261. PARAMETER_CHECK((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE));
  262. // The ImageGetDigestStream() function is not thread safe, so we have to ensure that it's
  263. // not called by other threads while we're using it.
  264. IFW32FALSE_EXIT(lock.Lock());
  265. IFW32FALSE_EXIT_UNLESS(
  266. ::ImageGetDigestStream(
  267. hFile,
  268. CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO,
  269. &SxspImageDigesterFunc,
  270. (DIGEST_HANDLE)(&rhHash)),
  271. (::FusionpGetLastWin32Error() == ERROR_INVALID_PARAMETER),
  272. rfInvalidImage);
  273. lock.Unlock();
  274. FN_EPILOG
  275. }
  276. BOOL
  277. SxspVerifyFileHash(
  278. const DWORD dwFlags,
  279. const CBaseStringBuffer &hsFullFilePath,
  280. const CFusionArray<BYTE> &rsrgbTheoreticalHash,
  281. ALG_ID whichAlg,
  282. HashValidateResult &HashValid
  283. )
  284. {
  285. FN_PROLOG_WIN32
  286. CFusionArray<BYTE> bGotHash;
  287. HashValid = HashValidate_OtherProblems;
  288. BOOL fFileNotFoundError;
  289. LONG ulRetriesLeft = 0;
  290. LONG ulBackoffAmount = 1000;
  291. LONG ulBackoffAmountCap = 3000;
  292. float ulBackoffRate = 1.5f;
  293. PARAMETER_CHECK( (dwFlags == SVFH_DEFAULT_ACTION) ||
  294. (dwFlags == SVFH_RETRY_LOGIC_SIMPLE) ||
  295. (dwFlags == SVFH_RETRY_WAIT_UNTIL));
  296. if ( dwFlags == SVFH_RETRY_LOGIC_SIMPLE )
  297. ulRetriesLeft = 10;
  298. TryAgain:
  299. IFW32FALSE_EXIT_UNLESS2(
  300. ::SxspCreateFileHash(
  301. HASHFLAG_AUTODETECT,
  302. whichAlg,
  303. hsFullFilePath,
  304. bGotHash),
  305. LIST_5( ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, ERROR_BAD_NETPATH, ERROR_BAD_NET_NAME, ERROR_SHARING_VIOLATION),
  306. fFileNotFoundError);
  307. //
  308. // If this was a sharing violation and we've got retries left, then try again.
  309. //
  310. if (fFileNotFoundError && (::FusionpGetLastWin32Error() == ERROR_SHARING_VIOLATION) && (ulRetriesLeft > 0))
  311. {
  312. ulRetriesLeft--;
  313. ::Sleep( ulBackoffAmount );
  314. if (ulBackoffAmount < ulBackoffAmountCap)
  315. ulBackoffAmount = (ULONG)((float)ulBackoffAmount * ulBackoffRate);
  316. if (dwFlags == SVFH_RETRY_WAIT_UNTIL)
  317. ulRetriesLeft = 1;
  318. goto TryAgain;
  319. }
  320. //
  321. // If the file was able to be hashed, and the return error isn't "file not found",
  322. // then compare the hashes
  323. //
  324. if (!fFileNotFoundError &&(rsrgbTheoreticalHash.GetSize() == bGotHash.GetSize()))
  325. {
  326. HashValid =
  327. (::memcmp(
  328. bGotHash.GetArrayPtr(),
  329. rsrgbTheoreticalHash.GetArrayPtr(),
  330. bGotHash.GetSize()) == 0) ? HashValidate_Matches : HashValidate_HashNotMatched;
  331. }
  332. else
  333. {
  334. HashValid = HashValidate_HashesCantBeMatched;
  335. }
  336. FN_EPILOG
  337. }
  338. BOOL
  339. SxspGetStrongNameFromManifestName(
  340. PCWSTR pszManifestName,
  341. CBaseStringBuffer &rbuffStrongName,
  342. BOOL &rfHasPublicKey
  343. )
  344. {
  345. BOOL fSuccess = TRUE;
  346. FN_TRACE_WIN32(fSuccess);
  347. PCWSTR wsCursor;
  348. SIZE_T cchJump, cchPubKey;
  349. rfHasPublicKey = FALSE;
  350. rbuffStrongName.Clear();
  351. wsCursor = pszManifestName;
  352. //
  353. // Tricky: Zips through the name of the manifest to find the strong name string.
  354. //
  355. for (int i = 0; i < 2; i++)
  356. {
  357. cchJump = ::wcscspn(wsCursor, L"_");
  358. PARAMETER_CHECK(cchJump != 0);
  359. wsCursor += (cchJump + 1); // x86_foo_strongname -> foo_strongname
  360. }
  361. //
  362. // Are we mysteriously at the end of the string?
  363. //
  364. PARAMETER_CHECK(wsCursor[0] != L'\0');
  365. //
  366. // Find the length of the public key string
  367. //
  368. cchPubKey = wcscspn(wsCursor, L"_");
  369. PARAMETER_CHECK(cchPubKey != 0);
  370. IFW32FALSE_EXIT(rbuffStrongName.Win32Assign(wsCursor, cchPubKey));
  371. rfHasPublicKey = (::FusionpCompareStrings(
  372. rbuffStrongName,
  373. rbuffStrongName.Cch(),
  374. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_PUBLICKEY_MISSING_VALUE,
  375. NUMBER_OF(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_PUBLICKEY_MISSING_VALUE) - 1,
  376. false) != 0);
  377. FN_EPILOG
  378. }
  379. static GUID p_WintrustVerifyGenericV2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  380. BOOL
  381. SxspValidateManifestAgainstCatalog(
  382. const CBaseStringBuffer &rbuffManifestName, // "c:\foo\x86_comctl32_6.0.0.0_0000.manifest"
  383. ManifestValidationResult &rResult,
  384. DWORD dwOptionsFlags
  385. )
  386. {
  387. FN_PROLOG_WIN32
  388. CStringBuffer sbCatalogName;
  389. //
  390. // Take the manifest name (which should be c:\foo\bar\blort.manifest) and switch
  391. // it to contain the catalog name instead:
  392. //
  393. // c:\foo\bar\blort.cat
  394. //
  395. IFW32FALSE_EXIT(sbCatalogName.Win32Assign(rbuffManifestName));
  396. IFW32FALSE_EXIT(
  397. sbCatalogName.Win32ChangePathExtension(
  398. FILE_EXTENSION_CATALOG,
  399. FILE_EXTENSION_CATALOG_CCH,
  400. eAddIfNoExtension));
  401. IFW32FALSE_EXIT(::SxspValidateManifestAgainstCatalog(rbuffManifestName, sbCatalogName, rResult, dwOptionsFlags));
  402. FN_EPILOG
  403. }
  404. void
  405. SxspCertFreeCtlContext(
  406. PCCTL_CONTEXT CtlContext
  407. )
  408. {
  409. if (CtlContext != NULL)
  410. ::CertFreeCTLContext(CtlContext);
  411. }
  412. void
  413. SxspCertFreeCertContext(
  414. PCCERT_CONTEXT CertContext
  415. )
  416. {
  417. if (CertContext != NULL)
  418. ::CertFreeCertificateContext(CertContext);
  419. }
  420. BOOL
  421. SxspValidateCatalogAndFindManifestHash(
  422. IN HANDLE hCatalogFile,
  423. IN PBYTE prgbHash,
  424. IN SIZE_T cbHash,
  425. OUT BOOL &rfCatalogOk,
  426. OUT BOOL &rfHashInCatalog
  427. )
  428. {
  429. FN_PROLOG_WIN32
  430. CFileMapping fmCatalogMapping;
  431. CMappedViewOfFile mvCatalogView;
  432. LARGE_INTEGER liCatalogFile;
  433. ULONGLONG ullCatalogFile;
  434. PVOID pvCatalogData;
  435. CRYPT_VERIFY_MESSAGE_PARA vfmParameters;
  436. //
  437. // Default value
  438. //
  439. rfHashInCatalog = FALSE;
  440. rfCatalogOk = FALSE;
  441. //
  442. // Create a CTL context from the catalog file.
  443. //
  444. IFW32FALSE_ORIGINATE_AND_EXIT(::GetFileSizeEx(hCatalogFile, &liCatalogFile));
  445. ullCatalogFile = liCatalogFile.QuadPart;
  446. IFW32FALSE_EXIT(fmCatalogMapping.Win32CreateFileMapping(hCatalogFile, PAGE_READONLY, ullCatalogFile, NULL));
  447. IFW32FALSE_EXIT(mvCatalogView.Win32MapViewOfFile(fmCatalogMapping, FILE_MAP_READ, 0, (SIZE_T)ullCatalogFile));
  448. pvCatalogData = mvCatalogView;
  449. //
  450. // First, validate that the message (catalog) is OK
  451. //
  452. ZeroMemory(&vfmParameters, sizeof(vfmParameters));
  453. vfmParameters.cbSize = sizeof(vfmParameters);
  454. vfmParameters.dwMsgAndCertEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
  455. // NTRAID#NTBUG9 - 591808 - 2002/04/01 - mgrier - Missing error check (well, missing
  456. // handling of the error case). And no, returning the "failure" via
  457. // rfCatalogOk == NULL does not count.
  458. rfCatalogOk = ::CryptVerifyMessageSignature(
  459. &vfmParameters,
  460. 0,
  461. static_cast<PBYTE>(pvCatalogData),
  462. static_cast<DWORD>(ullCatalogFile),
  463. NULL,
  464. NULL,
  465. NULL);
  466. if (rfCatalogOk)
  467. {
  468. CSmartPtrWithNamedDestructor<const CERT_CONTEXT, &::SxspCertFreeCertContext> pCertContext;
  469. CSmartPtrWithNamedDestructor<const CTL_CONTEXT, &::SxspCertFreeCtlContext> pCtlContext;
  470. PCTL_ENTRY pFoundCtlEntry;
  471. CSmallStringBuffer buffStringizedHash;
  472. CTL_ANY_SUBJECT_INFO ctlSubjectInfo;
  473. //
  474. // The search routine needs a string to find, says the crypto guys.
  475. //
  476. IFW32FALSE_EXIT(::SxspHashBytesToString( prgbHash, cbHash, buffStringizedHash));
  477. IFW32FALSE_EXIT(buffStringizedHash.Win32ConvertCase(eConvertToUpperCase));
  478. //
  479. // If this failed, something bad happened with the CTL - maybe the catalog
  480. // was invalid, maybe something else happened. Whatever it was, let the
  481. // caller decide.
  482. //
  483. // NTRAID#NTBUG9 - 591808 - 2002/04/01 - mgrier - Missing error check (well, missing
  484. // handling of the error case).
  485. pCtlContext.AttachForDelete(
  486. ::CertCreateCTLContext(
  487. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  488. static_cast<PBYTE>(pvCatalogData),
  489. static_cast<DWORD>(ullCatalogFile)));
  490. if (pCtlContext != NULL)
  491. {
  492. //
  493. // Fill out this data with the string information.
  494. //
  495. CStringBufferAccessor sba;
  496. sba.Attach(&buffStringizedHash);
  497. ZeroMemory(&ctlSubjectInfo, sizeof(ctlSubjectInfo));
  498. ctlSubjectInfo.SubjectAlgorithm.pszObjId = NULL;
  499. ctlSubjectInfo.SubjectIdentifier.pbData = static_cast<PBYTE>(static_cast<PVOID>(sba.GetBufferPtr()));
  500. ctlSubjectInfo.SubjectIdentifier.cbData = static_cast<DWORD>((sba.Cch() + 1) * sizeof(WCHAR));
  501. sba.Detach();
  502. //
  503. // Look for it in the CTL
  504. //
  505. pFoundCtlEntry = CertFindSubjectInCTL(
  506. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  507. CTL_ANY_SUBJECT_TYPE,
  508. &ctlSubjectInfo,
  509. pCtlContext,
  510. 0);
  511. rfHashInCatalog = ( pFoundCtlEntry != NULL );
  512. }
  513. }
  514. FN_EPILOG
  515. }
  516. class CSxspValidateManifestAgainstCatalogLocals
  517. {
  518. public:
  519. CSxspValidateManifestAgainstCatalogLocals() { }
  520. ~CSxspValidateManifestAgainstCatalogLocals() { }
  521. CSmallStringBuffer rbuffStrongNameString;
  522. CPublicKeyInformation pkiCatalogInfo;
  523. };
  524. BOOL
  525. SxspValidateManifestAgainstCatalog(
  526. IN const CBaseStringBuffer &rbuffManifestName,
  527. IN const CBaseStringBuffer &rbuffCatalogName,
  528. OUT ManifestValidationResult &rResult,
  529. IN DWORD dwOptionsFlags
  530. )
  531. {
  532. FN_PROLOG_WIN32
  533. CFusionArray<BYTE> ManifestHash;
  534. BOOL fTempFlag = FALSE;
  535. BOOL fCatalogOk = FALSE;
  536. BOOL fHashFound = FALSE;
  537. CFusionFile ffCatalogFile;
  538. CSmartPtr<CSxspValidateManifestAgainstCatalogLocals> Locals;
  539. IFW32FALSE_EXIT(Locals.Win32Allocate(__FILE__, __LINE__));
  540. CSmallStringBuffer &rbuffStrongNameString = Locals->rbuffStrongNameString;
  541. CPublicKeyInformation &pkiCatalogInfo = Locals->pkiCatalogInfo;
  542. //
  543. // Generate the hash of the manifest first
  544. //
  545. IFW32FALSE_EXIT_UNLESS2(
  546. ::SxspCreateFileHash(
  547. HASHFLAG_STRAIGHT_HASH,
  548. CALG_SHA1,
  549. rbuffManifestName,
  550. ManifestHash),
  551. LIST_4(ERROR_PATH_NOT_FOUND, ERROR_FILE_NOT_FOUND, ERROR_BAD_NET_NAME, ERROR_BAD_NETPATH),
  552. fTempFlag);
  553. if (fTempFlag)
  554. {
  555. rResult = ManifestValidate_ManifestMissing;
  556. FN_SUCCESSFUL_EXIT();
  557. }
  558. //
  559. // Open the catalog file for now, we'll use it later.
  560. //
  561. IFW32FALSE_EXIT_UNLESS2(
  562. ffCatalogFile.Win32CreateFile(
  563. rbuffCatalogName,
  564. GENERIC_READ,
  565. FILE_SHARE_READ,
  566. OPEN_EXISTING),
  567. LIST_4(ERROR_PATH_NOT_FOUND, ERROR_FILE_NOT_FOUND, ERROR_BAD_NET_NAME, ERROR_BAD_NETPATH),
  568. fTempFlag);
  569. if (fTempFlag)
  570. {
  571. rResult = ManifestValidate_CatalogMissing;
  572. FN_SUCCESSFUL_EXIT();
  573. }
  574. //
  575. // Now look in the file to see if the catalog contains the hash of the manifest
  576. // in the CTL
  577. //
  578. IFW32FALSE_EXIT(
  579. ::SxspValidateCatalogAndFindManifestHash(
  580. ffCatalogFile,
  581. ManifestHash.GetArrayPtr(),
  582. ManifestHash.GetSize(),
  583. fCatalogOk,
  584. fHashFound));
  585. if (!fCatalogOk)
  586. {
  587. rResult = ManifestValidate_OtherProblems;
  588. FN_SUCCESSFUL_EXIT();
  589. }
  590. else if (!fHashFound)
  591. {
  592. rResult = ManifestValidate_NotCertified;
  593. FN_SUCCESSFUL_EXIT();
  594. }
  595. //
  596. // Are we supposed to validate the strong name of this catalog?
  597. //
  598. if ((dwOptionsFlags & MANIFESTVALIDATE_MODE_NO_STRONGNAME) == 0)
  599. {
  600. IFW32FALSE_EXIT(::SxspGetStrongNameFromManifestName(
  601. rbuffManifestName,
  602. rbuffStrongNameString,
  603. fTempFlag));
  604. if (!fTempFlag)
  605. {
  606. rResult = ManifestValidate_OtherProblems;
  607. FN_SUCCESSFUL_EXIT();
  608. }
  609. IFW32FALSE_EXIT(pkiCatalogInfo.Initialize(rbuffCatalogName));
  610. }
  611. //
  612. // Huzzah!
  613. //
  614. rResult = ManifestValidate_IsIntact;
  615. FN_EPILOG
  616. }
  617. bool
  618. SxspIsFullHexString(
  619. PCWSTR wsString,
  620. SIZE_T Cch
  621. )
  622. {
  623. for (SIZE_T i = 0; i < Cch; i++)
  624. {
  625. WCHAR ch = wsString[i];
  626. if (!::SxspIsHexDigit(ch))
  627. return false;
  628. }
  629. return true;
  630. }