diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2021-04-16 09:40:18 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-04-19 23:12:55 -0500 |
commit | 941c47e5a3f57ce9626b447a95740b1444e69343 (patch) | |
tree | 6225b78f5fc7c8f88a2abf187a6a76d45b36ec26 /src/engine/cache.cpp | |
parent | d32f770ca05748df9e356444c7e617d5eeedb60c (diff) | |
download | wix-941c47e5a3f57ce9626b447a95740b1444e69343.tar.gz wix-941c47e5a3f57ce9626b447a95740b1444e69343.tar.bz2 wix-941c47e5a3f57ce9626b447a95740b1444e69343.zip |
Detect a package as cached if any of its payloads exist.
Detect is supposed to be fast, so it can't fully verify every payload for every package. The engine was wasting its time by trying to verify file sizes without the hash. Even worse, it was making decisions during planning based on that insufficient verification.
Contributes to #3640
Diffstat (limited to 'src/engine/cache.cpp')
-rw-r--r-- | src/engine/cache.cpp | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/src/engine/cache.cpp b/src/engine/cache.cpp index 2349a357..667ca9e0 100644 --- a/src/engine/cache.cpp +++ b/src/engine/cache.cpp | |||
@@ -91,6 +91,7 @@ static HRESULT RemoveBundleOrPackage( | |||
91 | static HRESULT VerifyHash( | 91 | static HRESULT VerifyHash( |
92 | __in BYTE* pbHash, | 92 | __in BYTE* pbHash, |
93 | __in DWORD cbHash, | 93 | __in DWORD cbHash, |
94 | __in DWORD64 qwFileSize, | ||
94 | __in_z LPCWSTR wzUnverifiedPayloadPath, | 95 | __in_z LPCWSTR wzUnverifiedPayloadPath, |
95 | __in HANDLE hFile | 96 | __in HANDLE hFile |
96 | ); | 97 | ); |
@@ -1288,7 +1289,7 @@ static HRESULT VerifyThenTransferContainer( | |||
1288 | // Container should have a hash we can use to verify with. | 1289 | // Container should have a hash we can use to verify with. |
1289 | if (pContainer->pbHash) | 1290 | if (pContainer->pbHash) |
1290 | { | 1291 | { |
1291 | hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, wzUnverifiedContainerPath, hFile); | 1292 | hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, wzUnverifiedContainerPath, hFile); |
1292 | ExitOnFailure(hr, "Failed to verify container hash: %ls", wzCachedPath); | 1293 | ExitOnFailure(hr, "Failed to verify container hash: %ls", wzCachedPath); |
1293 | } | 1294 | } |
1294 | 1295 | ||
@@ -1330,7 +1331,7 @@ static HRESULT VerifyThenTransferPayload( | |||
1330 | 1331 | ||
1331 | if (pPayload->pbHash) // the payload should have a hash we can use to verify it. | 1332 | if (pPayload->pbHash) // the payload should have a hash we can use to verify it. |
1332 | { | 1333 | { |
1333 | hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, wzUnverifiedPayloadPath, hFile); | 1334 | hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzUnverifiedPayloadPath, hFile); |
1334 | ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath); | 1335 | ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath); |
1335 | } | 1336 | } |
1336 | 1337 | ||
@@ -1398,7 +1399,7 @@ static HRESULT VerifyFileAgainstPayload( | |||
1398 | 1399 | ||
1399 | if (pPayload->pbHash) // the payload should have a hash we can use to verify it. | 1400 | if (pPayload->pbHash) // the payload should have a hash we can use to verify it. |
1400 | { | 1401 | { |
1401 | hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, wzVerifyPath, hFile); | 1402 | hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzVerifyPath, hFile); |
1402 | ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey); | 1403 | ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey); |
1403 | } | 1404 | } |
1404 | 1405 | ||
@@ -1712,7 +1713,7 @@ static HRESULT RemoveBundleOrPackage( | |||
1712 | } | 1713 | } |
1713 | } | 1714 | } |
1714 | 1715 | ||
1715 | if (FAILED(hr)) | 1716 | if (E_PATHNOTFOUND != hr && FAILED(hr)) |
1716 | { | 1717 | { |
1717 | LogId(REPORT_STANDARD, fBundle ? MSG_UNABLE_UNCACHE_BUNDLE : MSG_UNABLE_UNCACHE_PACKAGE, wzBundleOrPackageId, sczDirectory, hr); | 1718 | LogId(REPORT_STANDARD, fBundle ? MSG_UNABLE_UNCACHE_BUNDLE : MSG_UNABLE_UNCACHE_PACKAGE, wzBundleOrPackageId, sczDirectory, hr); |
1718 | hr = S_OK; | 1719 | hr = S_OK; |
@@ -1743,6 +1744,7 @@ LExit: | |||
1743 | static HRESULT VerifyHash( | 1744 | static HRESULT VerifyHash( |
1744 | __in BYTE* pbHash, | 1745 | __in BYTE* pbHash, |
1745 | __in DWORD cbHash, | 1746 | __in DWORD cbHash, |
1747 | __in DWORD64 qwFileSize, | ||
1746 | __in_z LPCWSTR wzUnverifiedPayloadPath, | 1748 | __in_z LPCWSTR wzUnverifiedPayloadPath, |
1747 | __in HANDLE hFile | 1749 | __in HANDLE hFile |
1748 | ) | 1750 | ) |
@@ -1751,22 +1753,31 @@ static HRESULT VerifyHash( | |||
1751 | 1753 | ||
1752 | HRESULT hr = S_OK; | 1754 | HRESULT hr = S_OK; |
1753 | BYTE rgbActualHash[SHA512_HASH_LEN] = { }; | 1755 | BYTE rgbActualHash[SHA512_HASH_LEN] = { }; |
1754 | DWORD64 qwHashedBytes; | 1756 | DWORD64 qwHashedBytes = 0; |
1757 | LONGLONG llSize = 0; | ||
1755 | LPWSTR pszExpected = NULL; | 1758 | LPWSTR pszExpected = NULL; |
1756 | LPWSTR pszActual = NULL; | 1759 | LPWSTR pszActual = NULL; |
1757 | 1760 | ||
1761 | hr = FileSizeByHandle(hFile, &llSize); | ||
1762 | ExitOnFailure(hr, "Failed to get file size for path: %ls", wzUnverifiedPayloadPath); | ||
1763 | |||
1764 | if (static_cast<DWORD64>(llSize) != qwFileSize) | ||
1765 | { | ||
1766 | ExitOnFailure(hr = ERROR_FILE_CORRUPT, "File size mismatch for path: %ls, expected: %llu, actual: %lld", wzUnverifiedPayloadPath, qwFileSize, llSize); | ||
1767 | } | ||
1768 | |||
1758 | // TODO: create a cryp hash file that sends progress. | 1769 | // TODO: create a cryp hash file that sends progress. |
1759 | hr = CrypHashFileHandle(hFile, PROV_RSA_AES, CALG_SHA_512, rgbActualHash, sizeof(rgbActualHash), &qwHashedBytes); | 1770 | hr = CrypHashFileHandle(hFile, PROV_RSA_AES, CALG_SHA_512, rgbActualHash, sizeof(rgbActualHash), &qwHashedBytes); |
1760 | ExitOnFailure(hr, "Failed to calculate hash for path: %ls", wzUnverifiedPayloadPath); | 1771 | ExitOnFailure(hr, "Failed to calculate hash for path: %ls", wzUnverifiedPayloadPath); |
1761 | 1772 | ||
1762 | // Compare hashes. | 1773 | // Compare hashes. |
1763 | if (cbHash != sizeof(rgbActualHash) || 0 != memcmp(pbHash, rgbActualHash, SHA512_HASH_LEN)) | 1774 | if (cbHash != sizeof(rgbActualHash) || 0 != memcmp(pbHash, rgbActualHash, sizeof(rgbActualHash))) |
1764 | { | 1775 | { |
1765 | hr = CRYPT_E_HASH_VALUE; | 1776 | hr = CRYPT_E_HASH_VALUE; |
1766 | 1777 | ||
1767 | // Best effort to log the expected and actual hash value strings. | 1778 | // Best effort to log the expected and actual hash value strings. |
1768 | if (SUCCEEDED(StrAllocHexEncode(pbHash, cbHash, &pszExpected)) && | 1779 | if (SUCCEEDED(StrAllocHexEncode(pbHash, cbHash, &pszExpected)) && |
1769 | SUCCEEDED(StrAllocHexEncode(rgbActualHash, (SIZE_T)qwHashedBytes, &pszActual))) | 1780 | SUCCEEDED(StrAllocHexEncode(rgbActualHash, sizeof(rgbActualHash), &pszActual))) |
1770 | { | 1781 | { |
1771 | ExitOnFailure(hr, "Hash mismatch for path: %ls, expected: %ls, actual: %ls", wzUnverifiedPayloadPath, pszExpected, pszActual); | 1782 | ExitOnFailure(hr, "Hash mismatch for path: %ls, expected: %ls, actual: %ls", wzUnverifiedPayloadPath, pszExpected, pszActual); |
1772 | } | 1783 | } |