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/payload.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/payload.cpp')
| -rw-r--r-- | src/burn/engine/payload.cpp | 127 |
1 files changed, 77 insertions, 50 deletions
diff --git a/src/burn/engine/payload.cpp b/src/burn/engine/payload.cpp index 72eb3476..392a3dd4 100644 --- a/src/burn/engine/payload.cpp +++ b/src/burn/engine/payload.cpp | |||
| @@ -27,6 +27,8 @@ extern "C" HRESULT PayloadsParseFromXml( | |||
| 27 | IXMLDOMNode* pixnNode = NULL; | 27 | IXMLDOMNode* pixnNode = NULL; |
| 28 | DWORD cNodes = 0; | 28 | DWORD cNodes = 0; |
| 29 | LPWSTR scz = NULL; | 29 | LPWSTR scz = NULL; |
| 30 | BOOL fChainPayload = pContainers && pLayoutPayloads; // These are required when parsing chain payloads. | ||
| 31 | BOOL fValidFileSize = FALSE; | ||
| 30 | 32 | ||
| 31 | // select payload nodes | 33 | // select payload nodes |
| 32 | hr = XmlSelectNodes(pixnBundle, L"Payload", &pixnNodes); | 34 | hr = XmlSelectNodes(pixnBundle, L"Payload", &pixnNodes); |
| @@ -51,6 +53,7 @@ extern "C" HRESULT PayloadsParseFromXml( | |||
| 51 | for (DWORD i = 0; i < cNodes; ++i) | 53 | for (DWORD i = 0; i < cNodes; ++i) |
| 52 | { | 54 | { |
| 53 | BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i]; | 55 | BURN_PAYLOAD* pPayload = &pPayloads->rgPayloads[i]; |
| 56 | fValidFileSize = FALSE; | ||
| 54 | 57 | ||
| 55 | hr = XmlNextElement(pixnNodes, &pixnNode, NULL); | 58 | hr = XmlNextElement(pixnNodes, &pixnNode, NULL); |
| 56 | ExitOnFailure(hr, "Failed to get next node."); | 59 | ExitOnFailure(hr, "Failed to get next node."); |
| @@ -63,27 +66,36 @@ extern "C" HRESULT PayloadsParseFromXml( | |||
| 63 | hr = XmlGetAttributeEx(pixnNode, L"FilePath", &pPayload->sczFilePath); | 66 | hr = XmlGetAttributeEx(pixnNode, L"FilePath", &pPayload->sczFilePath); |
| 64 | ExitOnFailure(hr, "Failed to get @FilePath."); | 67 | ExitOnFailure(hr, "Failed to get @FilePath."); |
| 65 | 68 | ||
| 66 | // @Packaging | 69 | // @SourcePath |
| 67 | hr = XmlGetAttributeEx(pixnNode, L"Packaging", &scz); | 70 | hr = XmlGetAttributeEx(pixnNode, L"SourcePath", &pPayload->sczSourcePath); |
| 68 | ExitOnFailure(hr, "Failed to get @Packaging."); | 71 | ExitOnFailure(hr, "Failed to get @SourcePath."); |
| 69 | 72 | ||
| 70 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"embedded", -1)) | 73 | if (!fChainPayload) |
| 71 | { | 74 | { |
| 75 | // All non-chain payloads are embedded in the UX container. | ||
| 72 | pPayload->packaging = BURN_PAYLOAD_PACKAGING_EMBEDDED; | 76 | pPayload->packaging = BURN_PAYLOAD_PACKAGING_EMBEDDED; |
| 73 | } | 77 | } |
| 74 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"external", -1)) | ||
| 75 | { | ||
| 76 | pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL; | ||
| 77 | } | ||
| 78 | else | 78 | else |
| 79 | { | 79 | { |
| 80 | hr = E_INVALIDARG; | 80 | // @Packaging |
| 81 | ExitOnFailure(hr, "Invalid value for @Packaging: %ls", scz); | 81 | hr = XmlGetAttributeEx(pixnNode, L"Packaging", &scz); |
| 82 | } | 82 | ExitOnFailure(hr, "Failed to get @Packaging."); |
| 83 | 83 | ||
| 84 | // @Container | 84 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"embedded", -1)) |
| 85 | if (pContainers) | 85 | { |
| 86 | { | 86 | pPayload->packaging = BURN_PAYLOAD_PACKAGING_EMBEDDED; |
| 87 | } | ||
| 88 | else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, scz, -1, L"external", -1)) | ||
| 89 | { | ||
| 90 | pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL; | ||
| 91 | } | ||
| 92 | else | ||
| 93 | { | ||
| 94 | hr = E_INVALIDARG; | ||
| 95 | ExitOnFailure(hr, "Invalid value for @Packaging: %ls", scz); | ||
| 96 | } | ||
| 97 | |||
| 98 | // @Container | ||
| 87 | hr = XmlGetAttributeEx(pixnNode, L"Container", &scz); | 99 | hr = XmlGetAttributeEx(pixnNode, L"Container", &scz); |
| 88 | if (E_NOTFOUND != hr || BURN_PAYLOAD_PACKAGING_EMBEDDED == pPayload->packaging) | 100 | if (E_NOTFOUND != hr || BURN_PAYLOAD_PACKAGING_EMBEDDED == pPayload->packaging) |
| 89 | { | 101 | { |
| @@ -93,52 +105,67 @@ extern "C" HRESULT PayloadsParseFromXml( | |||
| 93 | hr = ContainerFindById(pContainers, scz, &pPayload->pContainer); | 105 | hr = ContainerFindById(pContainers, scz, &pPayload->pContainer); |
| 94 | ExitOnFailure(hr, "Failed to to find container: %ls", scz); | 106 | ExitOnFailure(hr, "Failed to to find container: %ls", scz); |
| 95 | } | 107 | } |
| 96 | } | ||
| 97 | 108 | ||
| 98 | // @LayoutOnly | 109 | // @LayoutOnly |
| 99 | hr = XmlGetYesNoAttribute(pixnNode, L"LayoutOnly", &pPayload->fLayoutOnly); | 110 | hr = XmlGetYesNoAttribute(pixnNode, L"LayoutOnly", &pPayload->fLayoutOnly); |
| 100 | if (E_NOTFOUND != hr) | 111 | if (E_NOTFOUND != hr) |
| 101 | { | 112 | { |
| 102 | ExitOnFailure(hr, "Failed to get @LayoutOnly."); | 113 | ExitOnFailure(hr, "Failed to get @LayoutOnly."); |
| 103 | } | 114 | } |
| 104 | 115 | ||
| 105 | // @SourcePath | 116 | // @DownloadUrl |
| 106 | hr = XmlGetAttributeEx(pixnNode, L"SourcePath", &pPayload->sczSourcePath); | 117 | hr = XmlGetAttributeEx(pixnNode, L"DownloadUrl", &pPayload->downloadSource.sczUrl); |
| 107 | ExitOnFailure(hr, "Failed to get @SourcePath."); | 118 | if (E_NOTFOUND != hr) |
| 119 | { | ||
| 120 | ExitOnFailure(hr, "Failed to get @DownloadUrl."); | ||
| 121 | } | ||
| 108 | 122 | ||
| 109 | // @DownloadUrl | 123 | // @FileSize |
| 110 | hr = XmlGetAttributeEx(pixnNode, L"DownloadUrl", &pPayload->downloadSource.sczUrl); | 124 | hr = XmlGetAttributeEx(pixnNode, L"FileSize", &scz); |
| 111 | if (E_NOTFOUND != hr) | 125 | if (E_NOTFOUND != hr) |
| 112 | { | 126 | { |
| 113 | ExitOnFailure(hr, "Failed to get @DownloadUrl."); | 127 | ExitOnFailure(hr, "Failed to get @FileSize."); |
| 114 | } | ||
| 115 | 128 | ||
| 116 | // @FileSize | 129 | hr = StrStringToUInt64(scz, 0, &pPayload->qwFileSize); |
| 117 | hr = XmlGetAttributeEx(pixnNode, L"FileSize", &scz); | 130 | ExitOnFailure(hr, "Failed to parse @FileSize."); |
| 118 | if (E_NOTFOUND != hr) | ||
| 119 | { | ||
| 120 | ExitOnFailure(hr, "Failed to get @FileSize."); | ||
| 121 | 131 | ||
| 122 | hr = StrStringToUInt64(scz, 0, &pPayload->qwFileSize); | 132 | fValidFileSize = TRUE; |
| 123 | ExitOnFailure(hr, "Failed to parse @FileSize."); | 133 | } |
| 124 | } | 134 | |
| 135 | // @Hash | ||
| 136 | hr = XmlGetAttributeEx(pixnNode, L"Hash", &scz); | ||
| 137 | if (E_NOTFOUND != hr) | ||
| 138 | { | ||
| 139 | ExitOnFailure(hr, "Failed to get @Hash."); | ||
| 125 | 140 | ||
| 126 | // @Hash | 141 | hr = StrAllocHexDecode(scz, &pPayload->pbHash, &pPayload->cbHash); |
| 127 | hr = XmlGetAttributeEx(pixnNode, L"Hash", &scz); | 142 | ExitOnFailure(hr, "Failed to hex decode the Payload/@Hash."); |
| 128 | ExitOnFailure(hr, "Failed to get @Hash."); | ||
| 129 | 143 | ||
| 130 | hr = StrAllocHexDecode(scz, &pPayload->pbHash, &pPayload->cbHash); | 144 | if (BURN_PAYLOAD_VERIFICATION_NONE == pPayload->verification) |
| 131 | ExitOnFailure(hr, "Failed to hex decode the Payload/@Hash."); | 145 | { |
| 146 | pPayload->verification = BURN_PAYLOAD_VERIFICATION_HASH; | ||
| 147 | } | ||
| 148 | } | ||
| 132 | 149 | ||
| 133 | if (pPayload->fLayoutOnly && pLayoutPayloads) | 150 | if (BURN_PAYLOAD_VERIFICATION_NONE == pPayload->verification) |
| 134 | { | 151 | { |
| 135 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pLayoutPayloads->rgItems), pLayoutPayloads->cItems + 1, sizeof(BURN_PAYLOAD_GROUP_ITEM), 5); | 152 | ExitOnRootFailure(hr = E_INVALIDDATA, "There was no verification information for payload: %ls", pPayload->sczKey); |
| 136 | ExitOnFailure(hr, "Failed to allocate memory for layout payloads."); | 153 | } |
| 154 | else if (BURN_PAYLOAD_VERIFICATION_HASH == pPayload->verification && !fValidFileSize) | ||
| 155 | { | ||
| 156 | ExitOnRootFailure(hr = E_INVALIDDATA, "File size is required when verifying by hash for payload: %ls", pPayload->sczKey); | ||
| 157 | } | ||
| 137 | 158 | ||
| 138 | pLayoutPayloads->rgItems[pLayoutPayloads->cItems].pPayload = pPayload; | 159 | if (pPayload->fLayoutOnly) |
| 139 | ++pLayoutPayloads->cItems; | 160 | { |
| 161 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pLayoutPayloads->rgItems), pLayoutPayloads->cItems + 1, sizeof(BURN_PAYLOAD_GROUP_ITEM), 5); | ||
| 162 | ExitOnFailure(hr, "Failed to allocate memory for layout payloads."); | ||
| 140 | 163 | ||
| 141 | pLayoutPayloads->qwTotalSize += pPayload->qwFileSize; | 164 | pLayoutPayloads->rgItems[pLayoutPayloads->cItems].pPayload = pPayload; |
| 165 | ++pLayoutPayloads->cItems; | ||
| 166 | |||
| 167 | pLayoutPayloads->qwTotalSize += pPayload->qwFileSize; | ||
| 168 | } | ||
| 142 | } | 169 | } |
| 143 | 170 | ||
| 144 | // prepare next iteration | 171 | // prepare next iteration |
