Enhance certificate check
This commit is contained in:
parent
f4228f5e52
commit
6b0a3c8e6b
@ -34,12 +34,8 @@
|
||||
#include "Common.h"
|
||||
#include "../Utf8.h"
|
||||
|
||||
|
||||
WcharMbcsConvertor* WcharMbcsConvertor::_pSelf = new WcharMbcsConvertor;
|
||||
|
||||
|
||||
|
||||
|
||||
void printInt(int int2print)
|
||||
{
|
||||
TCHAR str[32];
|
||||
|
259
PowerEditor/src/MISC/Common/verifySignedfile.cpp
Normal file
259
PowerEditor/src/MISC/Common/verifySignedfile.cpp
Normal file
@ -0,0 +1,259 @@
|
||||
// This file is part of Notepad++ project
|
||||
// Copyright (C)2003 Don HO <don.h@free.fr>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// Note that the GPL places important restrictions on "derived works", yet
|
||||
// it does not provide a detailed definition of that term. To avoid
|
||||
// misunderstandings, we consider an application to constitute a
|
||||
// "derivative work" for the purpose of this license if it does any of the
|
||||
// following:
|
||||
// 1. Integrates source code from Notepad++.
|
||||
// 2. Integrates/includes/aggregates Notepad++ into a proprietary executable
|
||||
// installer, such as those produced by InstallShield.
|
||||
// 3. Links to a library or executes a program that does any of the above.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
// VerifyDLL.cpp : Verification of an Authenticode signed DLL
|
||||
//
|
||||
|
||||
#include <memory>
|
||||
#include <windows.h>
|
||||
#include <wintrust.h>
|
||||
#include <softpub.h>
|
||||
#include <wincrypt.h>
|
||||
#include <sensapi.h>
|
||||
#include <iomanip>
|
||||
#include "VerifySignedFile.h"
|
||||
#include "Common.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool VerifySignedLibrary(const wstring& filepath,
|
||||
const wstring& cert_key_id_hex,
|
||||
const wstring& cert_subject,
|
||||
const wstring& cert_display_name)
|
||||
{
|
||||
wstring display_name;
|
||||
wstring key_id_hex;
|
||||
wstring subject;
|
||||
|
||||
wstring dmsg(TEXT("VerifyLibrary: "));
|
||||
dmsg += filepath;
|
||||
dmsg += TEXT("\n");
|
||||
|
||||
OutputDebugString(dmsg.c_str());
|
||||
|
||||
////////////////////// Signature verification
|
||||
|
||||
// Initialize the WINTRUST_FILE_INFO structure.
|
||||
LPCWSTR pwszfilepath = filepath.c_str();
|
||||
WINTRUST_FILE_INFO file_data = { 0 };
|
||||
file_data.cbStruct = sizeof(WINTRUST_FILE_INFO);
|
||||
file_data.pcwszFilePath = pwszfilepath;
|
||||
|
||||
// Initialise WinTrust data
|
||||
WINTRUST_DATA winTEXTrust_data = { 0 };
|
||||
winTEXTrust_data.cbStruct = sizeof(winTEXTrust_data);
|
||||
winTEXTrust_data.dwUIChoice = WTD_UI_NONE; // do not display optionnal dialog boxes
|
||||
winTEXTrust_data.dwUnionChoice = WTD_CHOICE_FILE; // we are not checking catalog signed files
|
||||
winTEXTrust_data.dwStateAction = WTD_STATEACTION_VERIFY; // only checking
|
||||
winTEXTrust_data.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN; // verify the whole certificate chain
|
||||
winTEXTrust_data.pFile = &file_data;
|
||||
|
||||
#if defined( VerifySignedLibrary_DISABLE_REVOCATION_CHECK )
|
||||
winTEXTrust_data.fdwRevocationChecks = WTD_REVOKE_NONE;
|
||||
OutputDebugString(TEXT("VerifyLibrary: certificate revocation disabled at compile time\n"));
|
||||
#else
|
||||
// if offline, revocation is not checked
|
||||
// depending of windows version, this may introduce a latency on offline systems
|
||||
DWORD netstatus;
|
||||
QOCINFO oci;
|
||||
oci.dwSize = sizeof(oci);
|
||||
CONST TCHAR* msftTEXTest_site = TEXT("http://www.msfncsi.com/ncsi.txt");
|
||||
bool online = false;
|
||||
online = (0 != IsNetworkAlive(&netstatus) );
|
||||
online = online && ( 0 == GetLastError());
|
||||
online = online && (0 == IsDestinationReachable(msftTEXTest_site, &oci));
|
||||
if (!online)
|
||||
{
|
||||
winTEXTrust_data.fdwRevocationChecks = WTD_REVOKE_NONE;
|
||||
OutputDebugString(TEXT("VerifyLibrary: system is offline - certificate revocation wont be checked\n"));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Verify signature and cert-chain validity
|
||||
GUID policy = WINTRUST_ACTION_GENERIC_VERIFY_V2;
|
||||
LONG vtrust = ::WinVerifyTrust(NULL, &policy, &winTEXTrust_data );
|
||||
|
||||
// Post check cleanup
|
||||
winTEXTrust_data.dwStateAction = WTD_STATEACTION_CLOSE;
|
||||
LONG t2 = ::WinVerifyTrust(NULL, &policy, &winTEXTrust_data);
|
||||
|
||||
if (vtrust)
|
||||
{
|
||||
OutputDebugString(TEXT("VerifyLibrary: trust verification failed\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (t2)
|
||||
{
|
||||
OutputDebugString(TEXT("VerifyLibrary: error encountered while cleaning up after WinVerifyTrust\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////// Certificate verification
|
||||
|
||||
HCERTSTORE hStore = nullptr;
|
||||
HCRYPTMSG hMsg = nullptr;
|
||||
PCMSG_SIGNER_INFO pSignerInfo = nullptr;
|
||||
DWORD dwEncoding, dwContentType, dwFormatType;
|
||||
DWORD dwSignerInfo = 0L;
|
||||
bool status = true;
|
||||
|
||||
try {
|
||||
BOOL result = ::CryptQueryObject(CERT_QUERY_OBJECT_FILE, filepath.c_str(),
|
||||
CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY, 0,
|
||||
&dwEncoding, &dwContentType, &dwFormatType,
|
||||
&hStore, &hMsg, NULL
|
||||
);
|
||||
if (!result)
|
||||
{
|
||||
throw wstring( TEXT("Checking certificate of ") ) + filepath + TEXT(" : ") + GetLastErrorAsString(GetLastError());
|
||||
}
|
||||
|
||||
// Get signer information size.
|
||||
result = ::CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo);
|
||||
if (!result)
|
||||
{
|
||||
throw wstring( TEXT("CryptMsgGetParam first call: ")) + GetLastErrorAsString(GetLastError());
|
||||
}
|
||||
|
||||
// Get Signer Information.
|
||||
pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo);
|
||||
if (NULL == pSignerInfo )
|
||||
{
|
||||
throw wstring( TEXT("Failed to allocate memory for signature processing"));
|
||||
}
|
||||
|
||||
result = CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, (PVOID)pSignerInfo, &dwSignerInfo);
|
||||
if (!result)
|
||||
{
|
||||
throw wstring( TEXT("CryptMsgGetParam: ")) + GetLastErrorAsString(GetLastError());
|
||||
}
|
||||
|
||||
// Get the signer certificate from temporary certificate store.
|
||||
CERT_INFO cert_info = { 0 };
|
||||
cert_info.Issuer = pSignerInfo->Issuer;
|
||||
cert_info.SerialNumber = pSignerInfo->SerialNumber;
|
||||
PCCERT_CONTEXT context = ::CertFindCertificateInStore( hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, (PVOID)&cert_info, NULL);
|
||||
if (!context)
|
||||
{
|
||||
throw wstring( TEXT("Certificate context: ")) + GetLastErrorAsString(GetLastError());
|
||||
}
|
||||
|
||||
// Getting the full subject
|
||||
auto subject_sze = ::CertNameToStr(X509_ASN_ENCODING, &context->pCertInfo->Subject, CERT_X500_NAME_STR, NULL, 0);
|
||||
if (subject_sze <= 1)
|
||||
{
|
||||
throw wstring(TEXT("Getting x509 field size problem."));
|
||||
}
|
||||
|
||||
std::unique_ptr<TCHAR[]> subject_buffer(new TCHAR[subject_sze]);
|
||||
if (::CertNameToStr(X509_ASN_ENCODING, &context->pCertInfo->Subject, CERT_X500_NAME_STR, subject_buffer.get(), subject_sze) <= 1)
|
||||
{
|
||||
throw wstring(TEXT("Failed to get x509 filed infos from certificate."));
|
||||
}
|
||||
subject = subject_buffer.get();
|
||||
|
||||
// Getting key_id
|
||||
DWORD key_id_sze = 0;
|
||||
if (!::CertGetCertificateContextProperty( context, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &key_id_sze))
|
||||
{
|
||||
throw wstring( TEXT("x509 property not found")) + GetLastErrorAsString(GetLastError());
|
||||
}
|
||||
|
||||
std::unique_ptr<BYTE[]> key_id_buff( new BYTE[key_id_sze] );
|
||||
if (!::CertGetCertificateContextProperty( context, CERT_KEY_IDENTIFIER_PROP_ID, key_id_buff.get(), &key_id_sze))
|
||||
{
|
||||
throw wstring( TEXT("Getting certificate property problem.")) + GetLastErrorAsString(GetLastError());
|
||||
}
|
||||
|
||||
wstringstream ss;
|
||||
for (unsigned i = 0; i < key_id_sze; i++)
|
||||
{
|
||||
ss << std::uppercase << std::setfill(TCHAR('0')) << std::setw(2) << std::hex
|
||||
<< key_id_buff[i];
|
||||
}
|
||||
key_id_hex = ss.str();
|
||||
wstring dbg = key_id_hex + TEXT("\n");
|
||||
OutputDebugString( dbg.c_str() );
|
||||
|
||||
// Getting the display name
|
||||
auto sze = ::CertGetNameString( context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0);
|
||||
if (sze <= 1)
|
||||
{
|
||||
throw wstring( TEXT("Getting data size problem.")) + GetLastErrorAsString(GetLastError());
|
||||
}
|
||||
|
||||
// Get display name.
|
||||
std::unique_ptr<TCHAR[]> display_name_buffer( new TCHAR[sze] );
|
||||
if (::CertGetNameString( context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, display_name_buffer.get(), sze) <= 1)
|
||||
{
|
||||
throw wstring( TEXT("Cannot get certificate info.")) + GetLastErrorAsString(GetLastError());
|
||||
}
|
||||
display_name = display_name_buffer.get();
|
||||
|
||||
} catch (wstring s) {
|
||||
::MessageBox(NULL, TEXT("DLL signature verification failed"), s.c_str(), MB_ICONERROR);
|
||||
OutputDebugString(TEXT("VerifyLibrary: error while getting certificate informations\n"));
|
||||
status = false;
|
||||
} catch (...) {
|
||||
// Unknown error
|
||||
OutputDebugString(TEXT("VerifyLibrary: error while getting certificate informations\n"));
|
||||
throw wstring( TEXT("Unknown exception occured. ")) + GetLastErrorAsString(GetLastError());
|
||||
}
|
||||
|
||||
// fields verifications
|
||||
if ( status && !cert_display_name.empty() && cert_display_name != display_name )
|
||||
{
|
||||
status = false;
|
||||
OutputDebugString(TEXT("VerifyLibrary: Invalid certificate display name\n"));
|
||||
}
|
||||
|
||||
if ( status && !cert_subject.empty() && subject != subject)
|
||||
{
|
||||
status = false;
|
||||
OutputDebugString(TEXT("VerifyLibrary: Invalid certificate subject\n"));
|
||||
}
|
||||
|
||||
if ( status && !cert_key_id_hex.empty() && cert_key_id_hex != key_id_hex )
|
||||
{
|
||||
status = false;
|
||||
OutputDebugString(TEXT("VerifyLibrary: Invalid certificate key id\n"));
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
|
||||
if (hStore != NULL) CertCloseStore(hStore, 0);
|
||||
if (hMsg != NULL) CryptMsgClose(hMsg);
|
||||
if (pSignerInfo != NULL) LocalFree(pSignerInfo);
|
||||
|
||||
return status;
|
||||
|
||||
////////////////////////
|
||||
}
|
||||
|
||||
#undef VerifySignedLibrary_DISABLE_REVOCATION_CHECK
|
39
PowerEditor/src/MISC/Common/verifySignedfile.h
Normal file
39
PowerEditor/src/MISC/Common/verifySignedfile.h
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
//#define VerifySignedLibrary_DISABLE_REVOCATION_CHECK "Dont check certificat revocation"
|
||||
|
||||
/*
|
||||
* Verifies an Authenticde DLL signature and ownership
|
||||
*
|
||||
* Parameters:
|
||||
* @param filepath path to the DLL file to examine
|
||||
* @param cert_display_name if specified, the signing certificate display name to compare to. Ignored if set to "", (weak comparison)
|
||||
* @param cert_subject if specified, the full signing certificate subject name. Ignored if set to "" (strong comparison)
|
||||
* @param cert_key_id_hex if specified, the signing certificate key id (fingerprint), Ignored if set to "" (very strong comparison)
|
||||
*
|
||||
* @return true if the verification was positive, false if it was negative of encountered some error
|
||||
*
|
||||
* Dependencies:
|
||||
* This function uses 3 APIs: WinTrust, CryptoAPI, SENS API
|
||||
* It requires to link on : wintrust.lib, crypt32.lib (or crypt64.lib depending on the compilation target) and sensapi.lib
|
||||
* Those functions are available on Windows starting with Windows-XP
|
||||
*
|
||||
* Limitations:
|
||||
* Certificate revocation checking requires an access to Internet.
|
||||
* The functions checks for connectivity and will disable revocation checking if the machine is offline or if Microsoft
|
||||
* connectivity checking site is not reachable (supposely implying we are on an airgapped network).
|
||||
* Depending on Windows version, this test will be instantaneous (Windows 8 and up) or may take a few seconds.
|
||||
* This behaviour can be disabled by setting a define at compilation time.
|
||||
* If macro VerifySignedLibrary_DISABLE_REVOCATION_CHECK is defined, the revocation
|
||||
* state of the certificates will *not* be checked.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
bool VerifySignedLibrary(const std::wstring& filepath,
|
||||
const std::wstring& key_id_hex,
|
||||
const std::wstring& cert_subject,
|
||||
const std::wstring& display_name);
|
@ -25,13 +25,13 @@
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <shlwapi.h>
|
||||
#include "ScintillaEditView.h"
|
||||
#include "Parameters.h"
|
||||
#include "Sorters.h"
|
||||
#include "tchar.h"
|
||||
#include <memory>
|
||||
#include "verifySignedFile.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -152,6 +152,11 @@ LanguageName ScintillaEditView::langNames[L_EXTERNAL+1] = {
|
||||
//const int MASK_GREEN = 0x00FF00;
|
||||
//const int MASK_BLUE = 0x0000FF;
|
||||
|
||||
const generic_string scintilla_signer_display_name = TEXT("Notepad++");
|
||||
const generic_string scintilla_signer_subject = TEXT("C=FR, S=Ile-de-France, L=Saint Cloud, O=\"Notepad++\", CN=\"Notepad++\"");
|
||||
const generic_string scintilla_signer_key_id = TEXT("42C4C5846BB675C74E2B2C90C69AB44366401093");
|
||||
|
||||
|
||||
int getNbDigits(int aNum, int base)
|
||||
{
|
||||
int nbChiffre = 1;
|
||||
@ -175,12 +180,20 @@ int getNbDigits(int aNum, int base)
|
||||
}
|
||||
|
||||
TCHAR moduleFileName[1024];
|
||||
|
||||
HMODULE loadSciLexerDll()
|
||||
{
|
||||
generic_string sciLexerPath = getSciLexerFullPathName(moduleFileName, 1024);
|
||||
|
||||
if (not isCertificateValidated(sciLexerPath, TEXT("Notepad++")))
|
||||
if (not VerifySignedLibrary(sciLexerPath, scintilla_signer_key_id, scintilla_signer_subject, scintilla_signer_display_name))
|
||||
{
|
||||
::MessageBox(NULL,
|
||||
TEXT("Authenticode check failed: signature or signing certificate are not recognized"),
|
||||
TEXT("Library verification failed"),
|
||||
MB_OK | MB_ICONERROR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ::LoadLibrary(sciLexerPath.c_str());
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalOptions>/fixed:no %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;shell32.lib;Oleacc.lib;Dbghelp.lib;Version.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;shell32.lib;Oleacc.lib;Dbghelp.lib;Version.lib;Crypt32.lib;wintrust.lib;Sensapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ShowProgress>LinkVerboseLib</ShowProgress>
|
||||
<OutputFile>$(OutDir)notepad++.exe</OutputFile>
|
||||
<Version>1.0</Version>
|
||||
@ -146,7 +146,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalOptions>/fixed:no %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;shell32.lib;Oleacc.lib;Dbghelp.lib;Version.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;shell32.lib;Oleacc.lib;Dbghelp.lib;Version.lib;Crypt32.lib;wintrust.lib;Sensapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ShowProgress>LinkVerboseLib</ShowProgress>
|
||||
<OutputFile>$(OutDir)notepad++.exe</OutputFile>
|
||||
<Version>1.0</Version>
|
||||
@ -188,7 +188,7 @@
|
||||
<WarningVersion>18</WarningVersion>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;shell32.lib;Oleacc.lib;Dbghelp.lib;Version.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;shell32.lib;Oleacc.lib;Dbghelp.lib;Version.lib;Crypt32.lib;wintrust.lib;Sensapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ShowProgress>LinkVerboseLib</ShowProgress>
|
||||
<OutputFile>$(OutDir)notepad++.exe</OutputFile>
|
||||
<Version>1.0</Version>
|
||||
@ -239,7 +239,7 @@ copy ..\src\contextMenu.xml ..\bin\contextMenu.xml
|
||||
<WarningVersion>18</WarningVersion>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;shell32.lib;Oleacc.lib;Dbghelp.lib;Version.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>comctl32.lib;shlwapi.lib;shell32.lib;Oleacc.lib;Dbghelp.lib;Version.lib;Crypt32.lib;wintrust.lib;Sensapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<ShowProgress>LinkVerboseLib</ShowProgress>
|
||||
<OutputFile>$(OutDir)notepad++.exe</OutputFile>
|
||||
<Version>1.0</Version>
|
||||
@ -269,6 +269,7 @@ copy ..\src\contextMenu.xml ..\bin64\contextMenu.xml
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\MISC\Common\LongRunningOperation.cpp" />
|
||||
<ClCompile Include="..\src\MISC\Common\mutex.cpp" />
|
||||
<ClCompile Include="..\src\MISC\Common\verifySignedfile.cpp" />
|
||||
<ClCompile Include="..\src\MISC\md5\md5Dlgs.cpp" />
|
||||
<ClCompile Include="..\src\WinControls\AboutDlg\AboutDlg.cpp" />
|
||||
<ClCompile Include="..\src\WinControls\AnsiCharPanel\ansiCharPanel.cpp" />
|
||||
@ -534,6 +535,7 @@ copy ..\src\contextMenu.xml ..\bin64\contextMenu.xml
|
||||
<ClInclude Include="..\src\MISC\Common\LongRunningOperation.h" />
|
||||
<ClInclude Include="..\src\MISC\Common\mutex.h" />
|
||||
<ClInclude Include="..\src\MISC\Common\mutex.hxx" />
|
||||
<ClInclude Include="..\src\MISC\Common\verifySignedfile.h" />
|
||||
<ClInclude Include="..\src\MISC\md5\md5.h" />
|
||||
<ClInclude Include="..\src\MISC\md5\md5Dlgs.h" />
|
||||
<ClInclude Include="..\src\MISC\md5\md5Dlgs_rc.h" />
|
||||
|
Loading…
Reference in New Issue
Block a user