From 8c77de737aaea1b4857c724c730446bca8da2dd0 Mon Sep 17 00:00:00 2001 From: Sean Hall Date: Fri, 16 Apr 2021 10:48:38 -0500 Subject: Elevate for CacheVerifyContainer/Payload. --- src/engine/apply.cpp | 15 +++--- src/engine/cache.cpp | 68 ++++++++++++++++-------- src/engine/elevation.cpp | 136 ++++++++++++++++++++++++++++++++++++++++++++++- src/engine/elevation.h | 7 +++ src/engine/engine.mc | 14 +++++ 5 files changed, 209 insertions(+), 31 deletions(-) diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp index f40b3841..0eb8a710 100644 --- a/src/engine/apply.cpp +++ b/src/engine/apply.cpp @@ -538,6 +538,9 @@ extern "C" HRESULT ApplyCache( if (!pPackage->fPerMachine && !cacheContext.wzLayoutDirectory) { + hr = CacheGetCompletedPath(FALSE, pPackage->sczCacheId, &pPackage->sczCacheFolder); + ExitOnFailure(hr, "Failed to get cached path for package with cache id: %ls", pPackage->sczCacheId); + cacheContext.hPipe = INVALID_HANDLE_VALUE; } @@ -800,12 +803,6 @@ static HRESULT ApplyCachePackage( HRESULT hr = S_OK; BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION cachePackageCompleteAction = BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE; - if (!pPackage->sczCacheFolder && !pContext->wzLayoutDirectory) - { - hr = CacheGetCompletedPath(pPackage->fPerMachine, pPackage->sczCacheId, &pPackage->sczCacheFolder); - ExitOnFailure(hr, "Failed to get cached path for package with cache id: %ls", pPackage->sczCacheId); - } - for (;;) { hr = UserExperienceOnCachePackageBegin(pContext->pUX, pPackage->sczId, pPackage->payloads.cPayloads, pPackage->payloads.qwTotalSize); @@ -1038,7 +1035,11 @@ static HRESULT ApplyCacheVerifyContainerOrPayload( hr = UserExperienceOnCacheContainerOrPayloadVerifyBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId); ExitOnRootFailure(hr, "BA aborted cache container or payload verify begin."); - if (pContainer) + if (INVALID_HANDLE_VALUE != pContext->hPipe) + { + hr = ElevationCacheVerifyContainerOrPayload(pContext->hPipe, pContainer, pPackage, pPayload, pContext->wzLayoutDirectory); + } + else if (pContainer) { hr = CacheVerifyContainer(pContainer, pContext->wzLayoutDirectory); } diff --git a/src/engine/cache.cpp b/src/engine/cache.cpp index 2299d26d..9aa94d1d 100644 --- a/src/engine/cache.cpp +++ b/src/engine/cache.cpp @@ -59,11 +59,13 @@ static HRESULT TransferWorkingPathToUnverifiedPath( ); static HRESULT VerifyFileAgainstContainer( __in BURN_CONTAINER* pContainer, - __in_z LPCWSTR wzVerifyPath + __in_z LPCWSTR wzVerifyPath, + __in BOOL fAlreadyCached ); static HRESULT VerifyFileAgainstPayload( __in BURN_PAYLOAD* pPayload, - __in_z LPCWSTR wzVerifyPath + __in_z LPCWSTR wzVerifyPath, + __in BOOL fAlreadyCached ); static HRESULT ResetPathPermissions( __in BOOL fPerMachine, @@ -896,19 +898,11 @@ extern "C" HRESULT CacheCompletePayload( ExitOnFailure(hr, "Failed to concat complete cached path."); // If the cached file matches what we expected, we're good. - hr = VerifyFileAgainstPayload(pPayload, sczCachedPath); + hr = VerifyFileAgainstPayload(pPayload, sczCachedPath, TRUE); if (SUCCEEDED(hr)) { - ::DecryptFileW(sczCachedPath, 0); // Let's try to make sure it's not encrypted. - LogId(REPORT_STANDARD, MSG_VERIFIED_EXISTING_PAYLOAD, pPayload->sczKey, sczCachedPath); ExitFunction(); } - else if (E_PATHNOTFOUND != hr && E_FILENOTFOUND != hr) - { - LogErrorId(hr, MSG_FAILED_VERIFY_PAYLOAD, pPayload->sczKey, sczCachedPath, NULL); - - FileEnsureDelete(sczCachedPath); // if the file existed but did not verify correctly, make it go away. - } hr = CreateUnverifiedPath(fPerMachine, pPayload->sczKey, &sczUnverifiedPayloadPath); ExitOnFailure(hr, "Failed to create unverified path."); @@ -928,14 +922,8 @@ extern "C" HRESULT CacheCompletePayload( hr = ResetPathPermissions(fPerMachine, sczUnverifiedPayloadPath); ExitOnFailure(hr, "Failed to reset permissions on unverified cached payload: %ls", pPayload->sczKey); - hr = VerifyFileAgainstPayload(pPayload, sczUnverifiedPayloadPath); - if (FAILED(hr)) - { - LogErrorId(hr, MSG_FAILED_VERIFY_PAYLOAD, pPayload->sczKey, sczUnverifiedPayloadPath, NULL); - - FileEnsureDelete(sczUnverifiedPayloadPath); // if the file did not verify correctly, make it go away. - ExitFunction(); - } + hr = VerifyFileAgainstPayload(pPayload, sczUnverifiedPayloadPath, FALSE); + LogExitOnFailure(hr, MSG_FAILED_VERIFY_PAYLOAD, "Failed to verify payload: %ls at path: %ls", pPayload->sczKey, sczUnverifiedPayloadPath, NULL); LogId(REPORT_STANDARD, MSG_VERIFIED_ACQUIRED_PAYLOAD, pPayload->sczKey, sczUnverifiedPayloadPath, fMove ? "moving" : "copying", sczCachedPath); @@ -963,7 +951,7 @@ extern "C" HRESULT CacheVerifyContainer( hr = PathConcat(wzCachedDirectory, pContainer->sczFilePath, &sczCachedPath); ExitOnFailure(hr, "Failed to concat complete cached path."); - hr = VerifyFileAgainstContainer(pContainer, sczCachedPath); + hr = VerifyFileAgainstContainer(pContainer, sczCachedPath, TRUE); LExit: ReleaseStr(sczCachedPath); @@ -982,7 +970,7 @@ extern "C" HRESULT CacheVerifyPayload( hr = PathConcat(wzCachedDirectory, pPayload->sczFilePath, &sczCachedPath); ExitOnFailure(hr, "Failed to concat complete cached path."); - hr = VerifyFileAgainstPayload(pPayload, sczCachedPath); + hr = VerifyFileAgainstPayload(pPayload, sczCachedPath, TRUE); LExit: ReleaseStr(sczCachedPath); @@ -1460,7 +1448,8 @@ LExit: static HRESULT VerifyFileAgainstContainer( __in BURN_CONTAINER* pContainer, - __in_z LPCWSTR wzVerifyPath + __in_z LPCWSTR wzVerifyPath, + __in BOOL fAlreadyCached ) { HRESULT hr = S_OK; @@ -1484,15 +1473,32 @@ static HRESULT VerifyFileAgainstContainer( ExitOnFailure(hr, "Failed to verify hash of container: %ls", pContainer->sczId); } + if (fAlreadyCached) + { + LogId(REPORT_STANDARD, MSG_VERIFIED_EXISTING_CONTAINER, pContainer->sczId, wzVerifyPath); + ::DecryptFileW(wzVerifyPath, 0); // Let's try to make sure it's not encrypted. + } + LExit: ReleaseFileHandle(hFile); + if (FAILED(hr) && E_PATHNOTFOUND != hr && E_FILENOTFOUND != hr) + { + if (fAlreadyCached) + { + LogErrorId(hr, MSG_FAILED_VERIFY_CONTAINER, pContainer->sczId, wzVerifyPath, NULL); + } + + FileEnsureDelete(wzVerifyPath); // if the file existed but did not verify correctly, make it go away. + } + return hr; } static HRESULT VerifyFileAgainstPayload( __in BURN_PAYLOAD* pPayload, - __in_z LPCWSTR wzVerifyPath + __in_z LPCWSTR wzVerifyPath, + __in BOOL fAlreadyCached ) { HRESULT hr = S_OK; @@ -1516,9 +1522,25 @@ static HRESULT VerifyFileAgainstPayload( ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey); } + if (fAlreadyCached) + { + LogId(REPORT_STANDARD, MSG_VERIFIED_EXISTING_PAYLOAD, pPayload->sczKey, wzVerifyPath); + ::DecryptFileW(wzVerifyPath, 0); // Let's try to make sure it's not encrypted. + } + LExit: ReleaseFileHandle(hFile); + if (FAILED(hr) && E_PATHNOTFOUND != hr && E_FILENOTFOUND != hr) + { + if (fAlreadyCached) + { + LogErrorId(hr, MSG_FAILED_VERIFY_PAYLOAD, pPayload->sczKey, wzVerifyPath, NULL); + } + + FileEnsureDelete(wzVerifyPath); // if the file existed but did not verify correctly, make it go away. + } + return hr; } diff --git a/src/engine/elevation.cpp b/src/engine/elevation.cpp index d37907cf..2dd61a81 100644 --- a/src/engine/elevation.cpp +++ b/src/engine/elevation.cpp @@ -16,6 +16,7 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE BURN_ELEVATION_MESSAGE_TYPE_SAVE_STATE, BURN_ELEVATION_MESSAGE_TYPE_LAYOUT_BUNDLE, BURN_ELEVATION_MESSAGE_TYPE_CACHE_OR_LAYOUT_CONTAINER_OR_PAYLOAD, + BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_CONTAINER_OR_PAYLOAD, BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP, BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, @@ -176,6 +177,13 @@ static HRESULT OnCacheOrLayoutContainerOrPayload( __in BYTE* pbData, __in DWORD cbData ); +static HRESULT OnCacheVerifyContainerOrPayload( + __in BURN_CONTAINERS* pContainers, + __in BURN_PACKAGES* pPackages, + __in BURN_PAYLOADS* pPayloads, + __in BYTE* pbData, + __in DWORD cbData + ); static void OnCacheCleanup( __in_z LPCWSTR wzBundleId ); @@ -657,6 +665,44 @@ LExit: return hr; } +extern "C" HRESULT ElevationCacheVerifyContainerOrPayload( + __in HANDLE hPipe, + __in_opt BURN_CONTAINER* pContainer, + __in_opt BURN_PACKAGE* pPackage, + __in_opt BURN_PAYLOAD* pPayload, + __in_z_opt LPCWSTR wzLayoutDirectory + ) +{ + HRESULT hr = S_OK; + BYTE* pbData = NULL; + SIZE_T cbData = 0; + DWORD dwResult = 0; + + // serialize message data + hr = BuffWriteString(&pbData, &cbData, pContainer ? pContainer->sczId : NULL); + ExitOnFailure(hr, "Failed to write container id to message buffer."); + + hr = BuffWriteString(&pbData, &cbData, pPackage ? pPackage->sczId : NULL); + ExitOnFailure(hr, "Failed to write package id to message buffer."); + + hr = BuffWriteString(&pbData, &cbData, pPayload ? pPayload->sczKey : NULL); + ExitOnFailure(hr, "Failed to write payload id to message buffer."); + + hr = BuffWriteString(&pbData, &cbData, wzLayoutDirectory); + ExitOnFailure(hr, "Failed to write layout directory to message buffer."); + + // send message + hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_CONTAINER_OR_PAYLOAD, pbData, cbData, NULL, NULL, &dwResult); + ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_CONTAINER_OR_PAYLOAD message to per-machine process."); + + hr = (HRESULT)dwResult; + +LExit: + ReleaseBuffer(pbData); + + return hr; +} + /******************************************************************* ElevationCacheCleanup - @@ -1724,6 +1770,10 @@ static HRESULT ProcessElevatedChildCacheMessage( hrResult = OnCacheOrLayoutContainerOrPayload(pContext->pContainers, pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData); break; + case BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_CONTAINER_OR_PAYLOAD: + hrResult = OnCacheVerifyContainerOrPayload(pContext->pContainers, pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData); + break; + case BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP: OnCacheCleanup(pContext->pRegistration->sczId); hrResult = S_OK; @@ -2062,7 +2112,7 @@ static HRESULT OnCacheOrLayoutContainerOrPayload( // Deserialize message data. hr = BuffReadString(pbData, cbData, &iData, &scz); - ExitOnFailure(hr, "Failed to read package id."); + ExitOnFailure(hr, "Failed to read container id."); if (scz && *scz) { @@ -2135,6 +2185,90 @@ LExit: return hr; } +static HRESULT OnCacheVerifyContainerOrPayload( + __in BURN_CONTAINERS* pContainers, + __in BURN_PACKAGES* pPackages, + __in BURN_PAYLOADS* pPayloads, + __in BYTE* pbData, + __in DWORD cbData + ) +{ + HRESULT hr = S_OK; + SIZE_T iData = 0; + LPWSTR scz = NULL; + BURN_CONTAINER* pContainer = NULL; + BURN_PACKAGE* pPackage = NULL; + BURN_PAYLOAD* pPayload = NULL; + LPWSTR sczCacheDirectory = NULL; + + // Deserialize message data. + hr = BuffReadString(pbData, cbData, &iData, &scz); + ExitOnFailure(hr, "Failed to read container id."); + + if (scz && *scz) + { + hr = ContainerFindById(pContainers, scz, &pContainer); + ExitOnFailure(hr, "Failed to find container: %ls", scz); + } + + hr = BuffReadString(pbData, cbData, &iData, &scz); + ExitOnFailure(hr, "Failed to read package id."); + + if (scz && *scz) + { + hr = PackageFindById(pPackages, scz, &pPackage); + ExitOnFailure(hr, "Failed to find package: %ls", scz); + } + + hr = BuffReadString(pbData, cbData, &iData, &scz); + ExitOnFailure(hr, "Failed to read payload id."); + + if (scz && *scz) + { + hr = PayloadFindById(pPayloads, scz, &pPayload); + ExitOnFailure(hr, "Failed to find payload: %ls", scz); + } + + hr = BuffReadString(pbData, cbData, &iData, &sczCacheDirectory); + ExitOnFailure(hr, "Failed to read layout directory."); + + if (!sczCacheDirectory || !*sczCacheDirectory) + { + if (!pPackage) + { + hr = E_INVALIDARG; + ExitOnRootFailure(hr, "Invalid data passed to cache verify payload."); + } + + hr = CacheGetCompletedPath(TRUE, pPackage->sczCacheId, &sczCacheDirectory); + ExitOnFailure(hr, "Failed to get cached path for package with cache id: %ls", pPackage->sczCacheId); + } + + if (pContainer) + { + Assert(!pPackage); + Assert(!pPayload); + + hr = CacheVerifyContainer(pContainer, sczCacheDirectory); + } + else if (pPayload) + { + hr = CacheVerifyPayload(pPayload, sczCacheDirectory); + } + else + { + hr = E_INVALIDARG; + ExitOnRootFailure(hr, "Invalid data passed to cache or layout payload."); + } + // Nothing should be logged on failure. + +LExit: + ReleaseStr(sczCacheDirectory); + ReleaseStr(scz); + + return hr; +} + static void OnCacheCleanup( __in_z LPCWSTR wzBundleId ) diff --git a/src/engine/elevation.h b/src/engine/elevation.h index 9ce8cef9..da67e3f3 100644 --- a/src/engine/elevation.h +++ b/src/engine/elevation.h @@ -64,6 +64,13 @@ HRESULT ElevationCacheOrLayoutContainerOrPayload( __in_z LPCWSTR wzUnverifiedPath, __in BOOL fMove ); +HRESULT ElevationCacheVerifyContainerOrPayload( + __in HANDLE hPipe, + __in_opt BURN_CONTAINER* pContainer, + __in_opt BURN_PACKAGE* pPackage, + __in_opt BURN_PAYLOAD* pPayload, + __in_z_opt LPCWSTR wzLayoutDirectory + ); HRESULT ElevationCacheCleanup( __in HANDLE hPipe ); diff --git a/src/engine/engine.mc b/src/engine/engine.mc index 0e19d3bb..6e0695bc 100644 --- a/src/engine/engine.mc +++ b/src/engine/engine.mc @@ -478,6 +478,13 @@ Language=English Acquired payload: %1!ls! to working path: %2!ls! from: %4!ls!. . +MessageId=303 +Severity=Success +SymbolicName=MSG_VERIFIED_EXISTING_CONTAINER +Language=English +Verified existing container: %1!ls! at path: %2!ls!. +. + MessageId=304 Severity=Success SymbolicName=MSG_VERIFIED_EXISTING_PAYLOAD @@ -724,6 +731,13 @@ Language=English Acquiring package: %1!ls!, payload: %2!ls!, %3!hs! from: %4!ls! . +MessageId=339 +Severity=Error +SymbolicName=MSG_FAILED_VERIFY_CONTAINER +Language=English +Failed to verify container: %2!ls! at path: %3!ls!, error: %1!ls!. Deleting file. +. + MessageId=347 Severity=Warning SymbolicName=MSG_APPLY_RETRYING_CONTAINER -- cgit v1.2.3-55-g6feb