diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2021-05-03 12:23:31 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-05-11 19:11:19 -0500 |
commit | cd921db764df9578733c85c29e8c6c368f4c7e78 (patch) | |
tree | 8c04087da4430101afa9c065cc5c6555335d4b32 /src/burn/engine/cache.cpp | |
parent | 67dd3ced3b383eb8423156cdabd3f9ce037caba8 (diff) | |
download | wix-cd921db764df9578733c85c29e8c6c368f4c7e78.tar.gz wix-cd921db764df9578733c85c29e8c6c368f4c7e78.tar.bz2 wix-cd921db764df9578733c85c29e8c6c368f4c7e78.zip |
Enforce payload and container verification.
Diffstat (limited to 'src/burn/engine/cache.cpp')
-rw-r--r-- | src/burn/engine/cache.cpp | 95 |
1 files changed, 80 insertions, 15 deletions
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp index 02cad4a5..44267cbc 100644 --- a/src/burn/engine/cache.cpp +++ b/src/burn/engine/cache.cpp | |||
@@ -114,10 +114,16 @@ static HRESULT RemoveBundleOrPackage( | |||
114 | __in_z LPCWSTR wzBundleOrPackageId, | 114 | __in_z LPCWSTR wzBundleOrPackageId, |
115 | __in_z LPCWSTR wzCacheId | 115 | __in_z LPCWSTR wzCacheId |
116 | ); | 116 | ); |
117 | static HRESULT VerifyFileSize( | ||
118 | __in HANDLE hFile, | ||
119 | __in DWORD64 qwFileSize, | ||
120 | __in_z LPCWSTR wzUnverifiedPayloadPath | ||
121 | ); | ||
117 | static HRESULT VerifyHash( | 122 | static HRESULT VerifyHash( |
118 | __in BYTE* pbHash, | 123 | __in BYTE* pbHash, |
119 | __in DWORD cbHash, | 124 | __in DWORD cbHash, |
120 | __in DWORD64 qwFileSize, | 125 | __in DWORD64 qwFileSize, |
126 | __in BOOL fVerifyFileSize, | ||
121 | __in_z LPCWSTR wzUnverifiedPayloadPath, | 127 | __in_z LPCWSTR wzUnverifiedPayloadPath, |
122 | __in HANDLE hFile, | 128 | __in HANDLE hFile, |
123 | __in BURN_CACHE_STEP cacheStep, | 129 | __in BURN_CACHE_STEP cacheStep, |
@@ -1513,11 +1519,16 @@ static HRESULT VerifyThenTransferContainer( | |||
1513 | ExitWithLastError(hr, "Failed to open container in working path: %ls", wzUnverifiedContainerPath); | 1519 | ExitWithLastError(hr, "Failed to open container in working path: %ls", wzUnverifiedContainerPath); |
1514 | } | 1520 | } |
1515 | 1521 | ||
1516 | // Container should have a hash we can use to verify with. | 1522 | |
1517 | if (pContainer->pbHash) | 1523 | switch (pContainer->verification) |
1518 | { | 1524 | { |
1519 | hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, wzUnverifiedContainerPath, hFile, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext); | 1525 | case BURN_CONTAINER_VERIFICATION_HASH: |
1526 | hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, TRUE, wzUnverifiedContainerPath, hFile, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext); | ||
1520 | ExitOnFailure(hr, "Failed to verify container hash: %ls", wzCachedPath); | 1527 | ExitOnFailure(hr, "Failed to verify container hash: %ls", wzCachedPath); |
1528 | break; | ||
1529 | default: | ||
1530 | ExitOnRootFailure(hr = E_INVALIDARG, "Container has no verification information: %ls", pContainer->sczId); | ||
1531 | break; | ||
1521 | } | 1532 | } |
1522 | 1533 | ||
1523 | LogStringLine(REPORT_STANDARD, "%ls container from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedContainerPath, wzCachedPath); | 1534 | LogStringLine(REPORT_STANDARD, "%ls container from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedContainerPath, wzCachedPath); |
@@ -1550,10 +1561,16 @@ static HRESULT VerifyThenTransferPayload( | |||
1550 | ExitWithLastError(hr, "Failed to open payload in working path: %ls", wzUnverifiedPayloadPath); | 1561 | ExitWithLastError(hr, "Failed to open payload in working path: %ls", wzUnverifiedPayloadPath); |
1551 | } | 1562 | } |
1552 | 1563 | ||
1553 | if (pPayload->pbHash) // the payload should have a hash we can use to verify it. | 1564 | switch (pPayload->verification) |
1554 | { | 1565 | { |
1555 | hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzUnverifiedPayloadPath, hFile, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext); | 1566 | case BURN_PAYLOAD_VERIFICATION_HASH: |
1567 | hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, TRUE, wzUnverifiedPayloadPath, hFile, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext); | ||
1556 | ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath); | 1568 | ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath); |
1569 | break; | ||
1570 | case BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE: __fallthrough; | ||
1571 | default: | ||
1572 | ExitOnRootFailure(hr = E_INVALIDARG, "Payload has no verification information: %ls", pPayload->sczKey); | ||
1573 | break; | ||
1557 | } | 1574 | } |
1558 | 1575 | ||
1559 | LogStringLine(REPORT_STANDARD, "%ls payload from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedPayloadPath, wzCachedPath); | 1576 | LogStringLine(REPORT_STANDARD, "%ls payload from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedPayloadPath, wzCachedPath); |
@@ -1627,10 +1644,15 @@ static HRESULT VerifyFileAgainstContainer( | |||
1627 | ExitOnRootFailure(hr, "Failed to open container at path: %ls", wzVerifyPath); | 1644 | ExitOnRootFailure(hr, "Failed to open container at path: %ls", wzVerifyPath); |
1628 | } | 1645 | } |
1629 | 1646 | ||
1630 | if (pContainer->pbHash) // the container should have a hash we can use to verify it. | 1647 | switch (pContainer->verification) |
1631 | { | 1648 | { |
1632 | hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext); | 1649 | case BURN_CONTAINER_VERIFICATION_HASH: |
1650 | hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, TRUE, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext); | ||
1633 | ExitOnFailure(hr, "Failed to verify hash of container: %ls", pContainer->sczId); | 1651 | ExitOnFailure(hr, "Failed to verify hash of container: %ls", pContainer->sczId); |
1652 | break; | ||
1653 | default: | ||
1654 | ExitOnRootFailure(hr = E_INVALIDARG, "Container has no verification information: %ls", pContainer->sczId); | ||
1655 | break; | ||
1634 | } | 1656 | } |
1635 | 1657 | ||
1636 | if (fAlreadyCached) | 1658 | if (fAlreadyCached) |
@@ -1667,6 +1689,7 @@ static HRESULT VerifyFileAgainstPayload( | |||
1667 | { | 1689 | { |
1668 | HRESULT hr = S_OK; | 1690 | HRESULT hr = S_OK; |
1669 | HANDLE hFile = INVALID_HANDLE_VALUE; | 1691 | HANDLE hFile = INVALID_HANDLE_VALUE; |
1692 | BOOL fVerifyFileSize = FALSE; | ||
1670 | 1693 | ||
1671 | // Get the payload on disk actual hash. | 1694 | // Get the payload on disk actual hash. |
1672 | hFile = ::CreateFileW(wzVerifyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); | 1695 | hFile = ::CreateFileW(wzVerifyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); |
@@ -1680,10 +1703,33 @@ static HRESULT VerifyFileAgainstPayload( | |||
1680 | ExitOnRootFailure(hr, "Failed to open payload at path: %ls", wzVerifyPath); | 1703 | ExitOnRootFailure(hr, "Failed to open payload at path: %ls", wzVerifyPath); |
1681 | } | 1704 | } |
1682 | 1705 | ||
1683 | if (pPayload->pbHash) // the payload should have a hash we can use to verify it. | 1706 | switch (pPayload->verification) |
1684 | { | 1707 | { |
1685 | hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext); | 1708 | case BURN_PAYLOAD_VERIFICATION_HASH: |
1709 | fVerifyFileSize = TRUE; | ||
1710 | |||
1711 | hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, fVerifyFileSize, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext); | ||
1686 | ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey); | 1712 | ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey); |
1713 | |||
1714 | break; | ||
1715 | case BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE: | ||
1716 | fVerifyFileSize = 0 != pPayload->qwFileSize; | ||
1717 | |||
1718 | if (pPayload->pbHash) | ||
1719 | { | ||
1720 | hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, fVerifyFileSize, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext); | ||
1721 | ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey); | ||
1722 | } | ||
1723 | else if (fVerifyFileSize) | ||
1724 | { | ||
1725 | hr = VerifyFileSize(hFile, pPayload->qwFileSize, wzVerifyPath); | ||
1726 | ExitOnFailure(hr, "Failed to verify file size for path: %ls", wzVerifyPath); | ||
1727 | } | ||
1728 | |||
1729 | break; | ||
1730 | default: | ||
1731 | ExitOnRootFailure(hr = E_INVALIDARG, "Payload has no verification information: %ls", pPayload->sczKey); | ||
1732 | break; | ||
1687 | } | 1733 | } |
1688 | 1734 | ||
1689 | if (fAlreadyCached) | 1735 | if (fAlreadyCached) |
@@ -2015,10 +2061,32 @@ LExit: | |||
2015 | return hr; | 2061 | return hr; |
2016 | } | 2062 | } |
2017 | 2063 | ||
2064 | static HRESULT VerifyFileSize( | ||
2065 | __in HANDLE hFile, | ||
2066 | __in DWORD64 qwFileSize, | ||
2067 | __in_z LPCWSTR wzUnverifiedPayloadPath | ||
2068 | ) | ||
2069 | { | ||
2070 | HRESULT hr = S_OK; | ||
2071 | LONGLONG llSize = 0; | ||
2072 | |||
2073 | hr = FileSizeByHandle(hFile, &llSize); | ||
2074 | ExitOnFailure(hr, "Failed to get file size for path: %ls", wzUnverifiedPayloadPath); | ||
2075 | |||
2076 | if (static_cast<DWORD64>(llSize) != qwFileSize) | ||
2077 | { | ||
2078 | ExitOnRootFailure(hr = ERROR_FILE_CORRUPT, "File size mismatch for path: %ls, expected: %llu, actual: %lld", wzUnverifiedPayloadPath, qwFileSize, llSize); | ||
2079 | } | ||
2080 | |||
2081 | LExit: | ||
2082 | return hr; | ||
2083 | } | ||
2084 | |||
2018 | static HRESULT VerifyHash( | 2085 | static HRESULT VerifyHash( |
2019 | __in BYTE* pbHash, | 2086 | __in BYTE* pbHash, |
2020 | __in DWORD cbHash, | 2087 | __in DWORD cbHash, |
2021 | __in DWORD64 qwFileSize, | 2088 | __in DWORD64 qwFileSize, |
2089 | __in BOOL fVerifyFileSize, | ||
2022 | __in_z LPCWSTR wzUnverifiedPayloadPath, | 2090 | __in_z LPCWSTR wzUnverifiedPayloadPath, |
2023 | __in HANDLE hFile, | 2091 | __in HANDLE hFile, |
2024 | __in BURN_CACHE_STEP cacheStep, | 2092 | __in BURN_CACHE_STEP cacheStep, |
@@ -2032,19 +2100,16 @@ static HRESULT VerifyHash( | |||
2032 | HRESULT hr = S_OK; | 2100 | HRESULT hr = S_OK; |
2033 | BYTE rgbActualHash[SHA512_HASH_LEN] = { }; | 2101 | BYTE rgbActualHash[SHA512_HASH_LEN] = { }; |
2034 | DWORD64 qwHashedBytes = 0; | 2102 | DWORD64 qwHashedBytes = 0; |
2035 | LONGLONG llSize = 0; | ||
2036 | LPWSTR pszExpected = NULL; | 2103 | LPWSTR pszExpected = NULL; |
2037 | LPWSTR pszActual = NULL; | 2104 | LPWSTR pszActual = NULL; |
2038 | 2105 | ||
2039 | hr = SendCacheBeginMessage(pfnCacheMessageHandler, pContext, cacheStep); | 2106 | hr = SendCacheBeginMessage(pfnCacheMessageHandler, pContext, cacheStep); |
2040 | ExitOnFailure(hr, "Aborted cache verify hash begin."); | 2107 | ExitOnFailure(hr, "Aborted cache verify hash begin."); |
2041 | 2108 | ||
2042 | hr = FileSizeByHandle(hFile, &llSize); | 2109 | if (fVerifyFileSize) |
2043 | ExitOnFailure(hr, "Failed to get file size for path: %ls", wzUnverifiedPayloadPath); | ||
2044 | |||
2045 | if (static_cast<DWORD64>(llSize) != qwFileSize) | ||
2046 | { | 2110 | { |
2047 | ExitOnFailure(hr = ERROR_FILE_CORRUPT, "File size mismatch for path: %ls, expected: %llu, actual: %lld", wzUnverifiedPayloadPath, qwFileSize, llSize); | 2111 | hr = VerifyFileSize(hFile, qwFileSize, wzUnverifiedPayloadPath); |
2112 | ExitOnFailure(hr, "Failed to verify file size for path: %ls", wzUnverifiedPayloadPath); | ||
2048 | } | 2113 | } |
2049 | 2114 | ||
2050 | // TODO: create a cryp hash file that sends progress. | 2115 | // TODO: create a cryp hash file that sends progress. |