Merge pull request #7564 from Robyt3/HTTP-Download-Check-Sha256

Check SHA256 of downloaded maps and community icons
This commit is contained in:
Dennis Felsing 2023-11-30 23:53:35 +00:00 committed by GitHub
commit 6a503cf9af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 4 deletions

View file

@ -1533,6 +1533,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
m_pMapdownloadTask = HttpGetFile(pMapUrl ? pMapUrl : aUrl, Storage(), m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE);
m_pMapdownloadTask->Timeout(CTimeout{g_Config.m_ClMapDownloadConnectTimeoutMs, 0, g_Config.m_ClMapDownloadLowSpeedLimit, g_Config.m_ClMapDownloadLowSpeedTime});
m_pMapdownloadTask->MaxResponseSize(1024 * 1024 * 1024); // 1 GiB
m_pMapdownloadTask->ExpectSha256(*pMapSha256);
Engine()->AddJob(m_pMapdownloadTask);
}
else

View file

@ -122,6 +122,7 @@ bool HttpHasIpresolveBug()
CHttpRequest::CHttpRequest(const char *pUrl)
{
str_copy(m_aUrl, pUrl);
sha256_init(&m_ActualSha256);
}
CHttpRequest::~CHttpRequest()
@ -311,6 +312,9 @@ size_t CHttpRequest::OnData(char *pData, size_t DataSize)
{
return 0;
}
sha256_update(&m_ActualSha256, pData, DataSize);
if(!m_WriteToFile)
{
if(DataSize == 0)
@ -358,6 +362,23 @@ int CHttpRequest::OnCompletion(int State)
if(m_Abort)
State = HTTP_ABORTED;
if(State == HTTP_DONE && m_ExpectedSha256 != SHA256_ZEROED)
{
const SHA256_DIGEST ActualSha256 = sha256_finish(&m_ActualSha256);
if(ActualSha256 != m_ExpectedSha256)
{
if(g_Config.m_DbgCurl || m_LogProgress >= HTTPLOG::FAILURE)
{
char aActualSha256[SHA256_MAXSTRSIZE];
sha256_str(ActualSha256, aActualSha256, sizeof(aActualSha256));
char aExpectedSha256[SHA256_MAXSTRSIZE];
sha256_str(m_ExpectedSha256, aExpectedSha256, sizeof(aExpectedSha256));
dbg_msg("http", "SHA256 mismatch: got=%s, expected=%s, url=%s", aActualSha256, aExpectedSha256, m_aUrl);
}
State = HTTP_ERROR;
}
}
if(m_WriteToFile)
{
if(m_File && io_close(m_File) != 0)

View file

@ -1,9 +1,12 @@
#ifndef ENGINE_SHARED_HTTP_H
#define ENGINE_SHARED_HTTP_H
#include <base/hash_ctxt.h>
#include <engine/shared/jobs.h>
#include <algorithm>
#include <atomic>
#include <engine/shared/jobs.h>
typedef struct _json_value json_value;
class IStorage;
@ -58,6 +61,9 @@ class CHttpRequest : public IJob
int64_t m_MaxResponseSize = -1;
REQUEST m_Type = REQUEST::GET;
SHA256_CTX m_ActualSha256;
SHA256_DIGEST m_ExpectedSha256 = SHA256_ZEROED;
bool m_WriteToFile = false;
uint64_t m_ResponseLength = 0;
@ -105,6 +111,7 @@ public:
void LogProgress(HTTPLOG LogProgress) { m_LogProgress = LogProgress; }
void IpResolve(IPRESOLVE IpResolve) { m_IpResolve = IpResolve; }
void WriteToFile(IStorage *pStorage, const char *pDest, int StorageType);
void ExpectSha256(const SHA256_DIGEST &Sha256) { m_ExpectedSha256 = Sha256; }
void Head() { m_Type = REQUEST::HEAD; }
void Post(const unsigned char *pData, size_t DataLength)
{

View file

@ -542,7 +542,7 @@ protected:
int OnCompletion(int State) override;
public:
CCommunityIconDownloadJob(CMenus *pMenus, const char *pCommunityId, const char *pUrl);
CCommunityIconDownloadJob(CMenus *pMenus, const char *pCommunityId, const char *pUrl, const SHA256_DIGEST &Sha256);
};
struct SCommunityIcon
{

View file

@ -1821,11 +1821,12 @@ int CMenus::CCommunityIconDownloadJob::OnCompletion(int State)
return State;
}
CMenus::CCommunityIconDownloadJob::CCommunityIconDownloadJob(CMenus *pMenus, const char *pCommunityId, const char *pUrl) :
CMenus::CCommunityIconDownloadJob::CCommunityIconDownloadJob(CMenus *pMenus, const char *pCommunityId, const char *pUrl, const SHA256_DIGEST &Sha256) :
CHttpRequest(pUrl),
CAbstractCommunityIconJob(pMenus, pCommunityId, IStorage::TYPE_SAVE)
{
WriteToFile(pMenus->Storage(), m_aPath, IStorage::TYPE_SAVE);
ExpectSha256(Sha256);
Timeout(CTimeout{0, 0, 0, 0});
LogProgress(HTTPLOG::FAILURE);
}
@ -2005,7 +2006,7 @@ void CMenus::UpdateCommunityIcons()
});
if(pExistingDownload == m_CommunityIconDownloadJobs.end() && (ExistingIcon == m_vCommunityIcons.end() || ExistingIcon->m_Sha256 != Community.IconSha256()))
{
std::shared_ptr<CCommunityIconDownloadJob> pJob = std::make_shared<CCommunityIconDownloadJob>(this, Community.Id(), Community.IconUrl());
std::shared_ptr<CCommunityIconDownloadJob> pJob = std::make_shared<CCommunityIconDownloadJob>(this, Community.Id(), Community.IconUrl(), Community.IconSha256());
Engine()->AddJob(pJob);
m_CommunityIconDownloadJobs.push_back(pJob);
}