Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 43 additions & 28 deletions src/verifySignedfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,24 @@ void SecurityGuard::writeSecurityError(const std::wstring& prefix, const std::ws
writeLog(expandedLogFileName.c_str(), prefix.c_str(), log2write.c_str());
}

bool SecurityGuard::verifySignedBinary(const std::wstring& filepath)
bool SecurityGuard::initFromSelfCertif()
{
wstring display_name;
wstring key_id_hex;
wstring subject;
wstring authority_key_id_hex;
wchar_t codeSigedBinPath[MAX_PATH]{};
::GetModuleFileName(NULL, codeSigedBinPath, MAX_PATH);

return verifySignatureAndGetInfo(codeSigedBinPath, _signer_display_name, _signer_key_id, _signer_subject, _authority_key_id);
}

bool SecurityGuard::verifySignatureAndGetInfo(const std::wstring& codeSigedBinPath, wstring& display_name, wstring& key_id_hex, wstring& subject, wstring& authority_key_id_hex)
{
//
// Signature verification
//

// Initialize the WINTRUST_FILE_INFO structure.
LPCWSTR pwszfilepath = filepath.c_str();
WINTRUST_FILE_INFO file_data = {};
file_data.cbStruct = sizeof(WINTRUST_FILE_INFO);
file_data.pcwszFilePath = pwszfilepath;
file_data.pcwszFilePath = codeSigedBinPath.c_str();

// Initialise WinTrust data
WINTRUST_DATA winTEXTrust_data = {};
Expand Down Expand Up @@ -121,13 +123,13 @@ bool SecurityGuard::verifySignedBinary(const std::wstring& filepath)

if (vtrust)
{
writeSecurityError(filepath.c_str(), L": chain of trust verification failed");
writeSecurityError(codeSigedBinPath, L": chain of trust verification failed");
return false;
}

if (t2)
{
writeSecurityError(filepath.c_str(), L": error encountered while cleaning up after WinVerifyTrust");
writeSecurityError(codeSigedBinPath, L": error encountered while cleaning up after WinVerifyTrust");
return false;
}
}
Expand All @@ -143,14 +145,14 @@ bool SecurityGuard::verifySignedBinary(const std::wstring& filepath)
bool status = true;

try {
BOOL result = ::CryptQueryObject(CERT_QUERY_OBJECT_FILE, filepath.c_str(),
BOOL result = ::CryptQueryObject(CERT_QUERY_OBJECT_FILE, codeSigedBinPath.c_str(),
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY, 0,
&dwEncoding, &dwContentType, &dwFormatType,
&hStore, &hMsg, NULL);

if (!result)
{
throw string("Checking certificate of ") + ws2s(filepath) + " : " + ws2s(GetLastErrorAsString(GetLastError()));
throw string("Checking certificate of ") + ws2s(codeSigedBinPath) + " : " + ws2s(GetLastErrorAsString(GetLastError()));
}

// Get signer information size.
Expand Down Expand Up @@ -235,13 +237,12 @@ bool SecurityGuard::verifySignedBinary(const std::wstring& filepath)


// --- Retrieve Authority Key Identifier (AKI) ---

PCERT_EXTENSION pExtension = ::CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2, // OID for Authority Key Identifier (2.5.29.35)
context->pCertInfo->cExtension, context->pCertInfo->rgExtension);
// OID for Authority Key Identifier (2.5.29.35)
PCERT_EXTENSION pExtension = ::CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2, context->pCertInfo->cExtension, context->pCertInfo->rgExtension);

if (!pExtension)
pExtension = ::CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER, // OID for Authority Key Identifier (2.5.29.1)
context->pCertInfo->cExtension, context->pCertInfo->rgExtension);
// OID for Authority Key Identifier (2.5.29.1)
pExtension = ::CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER, context->pCertInfo->cExtension, context->pCertInfo->rgExtension);

if (pExtension)
{
Expand Down Expand Up @@ -278,15 +279,35 @@ bool SecurityGuard::verifySignedBinary(const std::wstring& filepath)

}
catch (const string& s) {
writeSecurityError((filepath + L" - error while getting certificate information: ").c_str(), s2ws(s).c_str());
wstring msg = codeSigedBinPath;
msg += L" - error while getting certificate information: ";
writeSecurityError(msg, s2ws(s));
status = false;
}
catch (...) {
// Unknown error
writeSecurityError(filepath.c_str(), L": Unknow error while getting certificate information");
writeSecurityError(codeSigedBinPath, L": Unknow error while getting certificate information");
status = false;
}

// Clean up.

if (hStore != NULL) CertCloseStore(hStore, 0);
if (hMsg != NULL) CryptMsgClose(hMsg);
if (pSignerInfo != NULL) LocalFree(pSignerInfo);

return status;
}

bool SecurityGuard::verifySignedBinary(const std::wstring& filepath)
{
wstring display_name;
wstring key_id_hex;
wstring subject;
wstring authority_key_id_hex;

bool status = verifySignatureAndGetInfo(filepath, display_name, key_id_hex, subject, authority_key_id_hex);

//
// fields verifications - if status is true, and demaded parameter string to compare (from the parameter) is not empty, then do compare
//
Expand All @@ -298,7 +319,7 @@ bool SecurityGuard::verifySignedBinary(const std::wstring& filepath)
errMsg += _signer_display_name;
errMsg += L" vs unexpected ";
errMsg += display_name;
writeSecurityError(filepath.c_str(), errMsg);
writeSecurityError(filepath, errMsg);
}

if (status && (!_signer_subject.empty() && _signer_subject != subject))
Expand All @@ -309,7 +330,7 @@ bool SecurityGuard::verifySignedBinary(const std::wstring& filepath)
errMsg += _signer_subject;
errMsg += L" vs unexpected ";
errMsg += subject;
writeSecurityError(filepath.c_str(), errMsg);
writeSecurityError(filepath, errMsg);
}

if (status && (!_signer_key_id.empty() && stringToUpper(_signer_key_id) != key_id_hex))
Expand All @@ -320,7 +341,7 @@ bool SecurityGuard::verifySignedBinary(const std::wstring& filepath)
errMsg += _signer_key_id;
errMsg += L" vs unexpected ";
errMsg += key_id_hex;
writeSecurityError(filepath.c_str(), errMsg);
writeSecurityError(filepath, errMsg);
}

if (status && (!_authority_key_id.empty() && stringToUpper(_authority_key_id) != authority_key_id_hex))
Expand All @@ -331,14 +352,8 @@ bool SecurityGuard::verifySignedBinary(const std::wstring& filepath)
errMsg += _authority_key_id;
errMsg += L" vs unexpected ";
errMsg += authority_key_id_hex;
writeSecurityError(filepath.c_str(), errMsg);
writeSecurityError(filepath, errMsg);
}

// Clean up.

if (hStore != NULL) CertCloseStore(hStore, 0);
if (hMsg != NULL) CryptMsgClose(hMsg);
if (pSignerInfo != NULL) LocalFree(pSignerInfo);

return status;
}
5 changes: 4 additions & 1 deletion src/verifySignedfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@ class SecurityGuard final
{
public:
SecurityGuard(){};
bool verifySignedBinary(const std::wstring& filepath);
bool initFromSelfCertif();

bool verifySignatureAndGetInfo(const std::wstring& codeSigedBinPath, std::wstring& display_name, std::wstring& key_id_hex, std::wstring& subject, std::wstring& authority_key_id_hex);
bool verifySignedBinary(const std::wstring& filepath);

void enableChkRevoc() { _doCheckRevocation = true; }
void enableChkTrustChain() { _doCheckChainOfTrust = true; }
void setDisplayName(const std::wstring& signer_display_name) { _signer_display_name = signer_display_name; }
Expand Down
46 changes: 44 additions & 2 deletions src/winmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1461,7 +1461,28 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR lpszCmdLine, int)
deleteFileOrFolder(destPath);
}

::ShellExecute(NULL, L"open", L"explorer.exe", prog2Launch.c_str(), prog2LaunchDir, SW_SHOWNORMAL);


#ifdef _DEBUG
// Don't check any thing in debug mode
#else
// Check signature of the launched program, with the same certif as gup.exe
SecurityGuard securityGuard4PluginsInstall;

if (!securityGuard4PluginsInstall.initFromSelfCertif())
{
securityGuard.writeSecurityError(L"Above certificate init error from \"gup -clean\" (remove plugins)", L"");
return -1;
}

bool isSecured = securityGuard4PluginsInstall.verifySignedBinary(prog2Launch.c_str());
if (!isSecured)
{
securityGuard.writeSecurityError(L"Above certificate verification error from \"gup -clean\" (remove plugins)", L"");
return -1;
}
#endif
::ShellExecute(NULL, L"open", prog2Launch.c_str(), NULL, prog2LaunchDir, SW_SHOWNORMAL);

return 0;
}
Expand All @@ -1480,12 +1501,32 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR lpszCmdLine, int)
WRITE_LOG(GUP_LOG_FILENAME, L"-1 in plugin updater's part - if (isCleanUp && isUnzip) // update: ", L"nbParam < 3");
return -1;
}

wstring prog2Launch = params[0];
wchar_t prog2LaunchDir[MAX_PATH];
lstrcpy(prog2LaunchDir, prog2Launch.c_str());
::PathRemoveFileSpec(prog2LaunchDir);
wstring destPathRoot = params[1];

#ifdef _DEBUG
// Don't check any thing in debug mode
#else
// Check signature of the launched program, with the same certif as gup.exe
SecurityGuard securityGuard4PluginsInstall;

if (!securityGuard4PluginsInstall.initFromSelfCertif())
{
securityGuard.writeSecurityError(L"Above certificate init error from \"gup -unzip\" (install or update plugins)", L"");
return -1;
}

bool isSecured = securityGuard4PluginsInstall.verifySignedBinary(prog2Launch.c_str());
if (!isSecured)
{
securityGuard.writeSecurityError(L"Above certificate verification error from \"gup -unzip\" (install or update plugins)", L"");
return -1;
}
#endif
for (size_t i = 2; i < nbParam; ++i)
{
wstring destPath = destPathRoot;
Expand Down Expand Up @@ -1593,7 +1634,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR lpszCmdLine, int)
}
}

::ShellExecute(NULL, L"open", L"explorer.exe", prog2Launch.c_str(), prog2LaunchDir, SW_SHOWNORMAL);
::ShellExecute(NULL, L"open", prog2Launch.c_str(), NULL, prog2LaunchDir, SW_SHOWNORMAL);

return 0;
}

Expand Down