diff options
author | Ladislav Zezula <ladislav.zezula@avg.com> | 2013-12-05 15:59:00 +0100 |
---|---|---|
committer | Ladislav Zezula <ladislav.zezula@avg.com> | 2013-12-05 15:59:00 +0100 |
commit | c34c37b3418f1e5ab3678ce65d46f81803dec91d (patch) | |
tree | 4a9cf4c61634691981f9dc367b53dac4070f8d0d /src/SFileVerify.cpp | |
parent | ff0c25952a28a927c48738ab5207b9bda69e588a (diff) |
+ StormLib 9.0 BETA
Diffstat (limited to 'src/SFileVerify.cpp')
-rw-r--r-- | src/SFileVerify.cpp | 162 |
1 files changed, 75 insertions, 87 deletions
diff --git a/src/SFileVerify.cpp b/src/SFileVerify.cpp index 4509388..219e187 100644 --- a/src/SFileVerify.cpp +++ b/src/SFileVerify.cpp @@ -20,25 +20,8 @@ //----------------------------------------------------------------------------- // Local defines -#define SIGNATURE_TYPE_NONE 0 -#define SIGNATURE_TYPE_WEAK 1 -#define SIGNATURE_TYPE_STRONG 2 - #define MPQ_DIGEST_UNIT_SIZE 0x10000 -typedef struct _MPQ_SIGNATURE_INFO -{ - ULONGLONG BeginMpqData; // File offset where the hashing starts - ULONGLONG BeginExclude; // Begin of the excluded area (used for (signature) file) - ULONGLONG EndExclude; // End of the excluded area (used for (signature) file) - ULONGLONG EndMpqData; // File offset where the hashing ends - ULONGLONG EndOfFile; // Size of the entire file - BYTE Signature[MPQ_STRONG_SIGNATURE_SIZE + 0x10]; - DWORD cbSignatureSize; // Length of the signature - int nSignatureType; // See SIGNATURE_TYPE_XXX - -} MPQ_SIGNATURE_INFO, *PMPQ_SIGNATURE_INFO; - //----------------------------------------------------------------------------- // Known Blizzard public keys // Created by Jean-Francois Roy using OpenSSL @@ -156,7 +139,7 @@ static void GetPlainAnsiFileName( const TCHAR * szFileName, char * szPlainName) { - const TCHAR * szPlainNameT = GetPlainFileNameT(szFileName); + const TCHAR * szPlainNameT = GetPlainFileName(szFileName); // Convert the plain name to ANSI while(*szPlainNameT != 0) @@ -186,67 +169,13 @@ static void CalculateArchiveRange( } } - // Get the MPQ data end. This is stored in our MPQ header, - // and it's been already prepared by SFileOpenArchive, + // Get the MPQ data end. This is stored in the MPQ header pSI->EndMpqData = ha->MpqPos + ha->pHeader->ArchiveSize64; // Get the size of the entire file FileStream_GetSize(ha->pStream, &pSI->EndOfFile); } -static bool QueryMpqSignatureInfo( - TMPQArchive * ha, - PMPQ_SIGNATURE_INFO pSI) -{ - ULONGLONG ExtraBytes; - TMPQFile * hf; - HANDLE hFile; - DWORD dwFileSize; - - // Calculate the range of the MPQ - CalculateArchiveRange(ha, pSI); - - // If there is "(signature)" file in the MPQ, it has a weak signature - if(SFileOpenFileEx((HANDLE)ha, SIGNATURE_NAME, SFILE_OPEN_BASE_FILE, &hFile)) - { - // Get the content of the signature - SFileReadFile(hFile, pSI->Signature, sizeof(pSI->Signature), &pSI->cbSignatureSize, NULL); - - // Verify the size of the signature - hf = (TMPQFile *)hFile; - - // We have to exclude the signature file from the digest - pSI->BeginExclude = ha->MpqPos + hf->pFileEntry->ByteOffset; - pSI->EndExclude = pSI->BeginExclude + hf->pFileEntry->dwCmpSize; - dwFileSize = hf->dwDataSize; - - // Close the file - SFileCloseFile(hFile); - pSI->nSignatureType = SIGNATURE_TYPE_WEAK; - return (dwFileSize == (MPQ_WEAK_SIGNATURE_SIZE + 8)) ? true : false; - } - - // If there is extra bytes beyond the end of the archive, - // it's the strong signature - ExtraBytes = pSI->EndOfFile - pSI->EndMpqData; - if(ExtraBytes >= (MPQ_STRONG_SIGNATURE_SIZE + 4)) - { - // Read the strong signature - if(!FileStream_Read(ha->pStream, &pSI->EndMpqData, pSI->Signature, (MPQ_STRONG_SIGNATURE_SIZE + 4))) - return false; - - // Check the signature header "NGIS" - if(pSI->Signature[0] != 'N' || pSI->Signature[1] != 'G' || pSI->Signature[2] != 'I' || pSI->Signature[3] != 'S') - return false; - - pSI->nSignatureType = SIGNATURE_TYPE_STRONG; - return true; - } - - // Succeeded, but no known signature found - return true; -} - static bool CalculateMpqHashMd5( TMPQArchive * ha, PMPQ_SIGNATURE_INFO pSI, @@ -723,7 +652,7 @@ static DWORD VerifyFile( if(dwTotalBytes == 0) { // Check CRC32 and MD5 only if there is no patches - if(hf->hfPatchFile == NULL) + if(hf->hfPatch == NULL) { // Check if the CRC32 matches. if(dwFlags & SFILE_VERIFY_FILE_CRC) @@ -781,6 +710,63 @@ static DWORD VerifyFile( return dwVerifyResult; } +// Used in SFileGetFileInfo +bool QueryMpqSignatureInfo( + TMPQArchive * ha, + PMPQ_SIGNATURE_INFO pSI) +{ + ULONGLONG ExtraBytes; + TMPQFile * hf; + HANDLE hFile; + DWORD dwFileSize; + + // Make sure it's all zeroed + memset(pSI, 0, sizeof(MPQ_SIGNATURE_INFO)); + + // Calculate the range of the MPQ + CalculateArchiveRange(ha, pSI); + + // If there is "(signature)" file in the MPQ, it has a weak signature + if(SFileOpenFileEx((HANDLE)ha, SIGNATURE_NAME, SFILE_OPEN_BASE_FILE, &hFile)) + { + // Get the content of the signature + SFileReadFile(hFile, pSI->Signature, sizeof(pSI->Signature), &pSI->cbSignatureSize, NULL); + + // Verify the size of the signature + hf = (TMPQFile *)hFile; + + // We have to exclude the signature file from the digest + pSI->BeginExclude = ha->MpqPos + hf->pFileEntry->ByteOffset; + pSI->EndExclude = pSI->BeginExclude + hf->pFileEntry->dwCmpSize; + dwFileSize = hf->dwDataSize; + + // Close the file + SFileCloseFile(hFile); + pSI->SignatureTypes |= SIGNATURE_TYPE_WEAK; + return (dwFileSize == (MPQ_WEAK_SIGNATURE_SIZE + 8)) ? true : false; + } + + // If there is extra bytes beyond the end of the archive, + // it's the strong signature + ExtraBytes = pSI->EndOfFile - pSI->EndMpqData; + if(ExtraBytes >= (MPQ_STRONG_SIGNATURE_SIZE + 4)) + { + // Read the strong signature + if(!FileStream_Read(ha->pStream, &pSI->EndMpqData, pSI->Signature, (MPQ_STRONG_SIGNATURE_SIZE + 4))) + return false; + + // Check the signature header "NGIS" + if(pSI->Signature[0] != 'N' || pSI->Signature[1] != 'G' || pSI->Signature[2] != 'I' || pSI->Signature[3] != 'S') + return false; + + pSI->SignatureTypes |= SIGNATURE_TYPE_STRONG; + return true; + } + + // Succeeded, but no known signature found + return true; +} + //----------------------------------------------------------------------------- // Public (exported) functions @@ -828,7 +814,7 @@ int WINAPI SFileVerifyRawData(HANDLE hMpq, DWORD dwWhatToVerify, const char * sz TMPQHeader * pHeader; // Verify input parameters - if(!IsValidMpqHandle(ha)) + if(!IsValidMpqHandle(hMpq)) return ERROR_INVALID_PARAMETER; pHeader = ha->pHeader; @@ -900,7 +886,7 @@ DWORD WINAPI SFileVerifyArchive(HANDLE hMpq) TMPQArchive * ha = (TMPQArchive *)hMpq; // Verify input parameters - if(!IsValidMpqHandle(ha)) + if(!IsValidMpqHandle(hMpq)) return ERROR_VERIFY_FAILED; // Get the MPQ signature and signature type @@ -908,18 +894,20 @@ DWORD WINAPI SFileVerifyArchive(HANDLE hMpq) if(!QueryMpqSignatureInfo(ha, &si)) return ERROR_VERIFY_FAILED; - // Verify the signature - switch(si.nSignatureType) - { - case SIGNATURE_TYPE_NONE: - return ERROR_NO_SIGNATURE; + // If there is no signature + if(si.SignatureTypes == 0) + return ERROR_NO_SIGNATURE; - case SIGNATURE_TYPE_WEAK: - return VerifyWeakSignature(ha, &si); + // We haven't seen a MPQ with both signatures + assert(si.SignatureTypes == SIGNATURE_TYPE_WEAK || si.SignatureTypes == SIGNATURE_TYPE_STRONG); - case SIGNATURE_TYPE_STRONG: - return VerifyStrongSignature(ha, &si); - } + // Verify the strong signature, if present + if(si.SignatureTypes & SIGNATURE_TYPE_STRONG) + return VerifyStrongSignature(ha, &si); + + // Verify the weak signature, if present + if(si.SignatureTypes & SIGNATURE_TYPE_WEAK) + return VerifyWeakSignature(ha, &si); - return ERROR_VERIFY_FAILED; + return ERROR_NO_SIGNATURE; } |