WindowsXP-SP1/admin/pchealth/sysinfo/control/chkdev.cpp
2020-09-30 16:53:49 +02:00

1206 lines
34 KiB
C++

#include "stdafx.h"
#include <chkdev.h>
BOOL testCatAPIs(LPWSTR lpwzCatName, HCATADMIN hCatAdmin, HCATINFO hCatInfo);
HCATADMIN hCatAdmin = 0;
extern Classes_Provided eClasses;
#define NumberTestCerts 7
BYTE TestCertHashes[NumberTestCerts][20] =
{
{0xBB, 0x11, 0x81, 0xF2, 0xB0, 0xC5, 0xE3, 0x2F, 0x7F, 0x2D, 0x62, 0x3B, 0x9C, 0x87, 0xE8, 0x55, 0x26, 0xF9, 0xCF, 0x2F},
{0xBA, 0x9E, 0x3C, 0x32, 0x56, 0x2A, 0x67, 0x12, 0x8C, 0xAA, 0xBD, 0x4A, 0xB0, 0xC5, 0x00, 0xBE, 0xE1, 0xD0, 0xC2, 0x56},
{0xA4, 0x34, 0x89, 0x15, 0x9A, 0x52, 0x0F, 0x0D, 0x93, 0xD0, 0x32, 0xCC, 0xAF, 0x37, 0xE7, 0xFE, 0x20, 0xA8, 0xB4, 0x19},
{0x73, 0xA9, 0x01, 0x93, 0x83, 0x4C, 0x5B, 0x16, 0xB4, 0x3F, 0x0C, 0xE0, 0x5E, 0xB4, 0xA3, 0xEF, 0x6F, 0x2C, 0x08, 0x2F},
{0xD2, 0xC3, 0x78, 0xCE, 0x42, 0xBC, 0x93, 0xA0, 0x3D, 0xD5, 0xA4, 0x2E, 0x8E, 0x08, 0xB1, 0x71, 0xB6, 0x27, 0x90, 0x1D},
{0xFC, 0x94, 0x4A, 0x1F, 0xA0, 0xDC, 0x8A, 0xC7, 0x78, 0x4A, 0xAC, 0x36, 0x9D, 0x14, 0x46, 0x02, 0x24, 0x08, 0xFF, 0x5D},
{0x92, 0x6A, 0xF1, 0x27, 0x25, 0x37, 0xE0, 0x73, 0x32, 0x6F, 0x12, 0xF7, 0xA7, 0x11, 0xE7, 0x55, 0xE6, 0x4E, 0x78, 0x4C}
};
CheckDevice::CheckDevice()
{
m_FileList = NULL;
lpszServiceName = NULL;
lpszServiceImage = NULL;
m_hDevInfo = SetupDiCreateDeviceInfoListEx(NULL, NULL, NULL, NULL);
}
CheckDevice::~CheckDevice(void)
{
if ( m_FileList )
{
delete m_FileList;
}
if ( lpszServiceName )
{
delete lpszServiceName;
lpszServiceName = NULL;
}
if ( lpszServiceImage )
{
delete lpszServiceImage;
lpszServiceImage = NULL;
}
m_FileList = NULL;
SetupDiDestroyDeviceInfoList(m_hDevInfo);
}
CheckDevice::CheckDevice(DEVNODE hDevice, DEVNODE hParent) : InfnodeClass (hDevice, hParent)
{
m_FileList = NULL;
lpszServiceName = NULL;
lpszServiceImage = NULL;
m_hDevInfo = SetupDiCreateDeviceInfoListEx(NULL, NULL, NULL, NULL);
if(eClasses == Class_Win32_PnPSignedDriverCIMDataFile)
CreateFileNode();
}
BOOL CheckDevice::AddFileNode(TCHAR *szFileName , UINT uiWin32Error /*= 0 */, LPCTSTR szSigner /*= NULL*/)
{
FileNode *pThisFile;
if ( !szFileName || !strlen(szFileName) )
{
return(FALSE);
}
_strlwr(szFileName);
// need to check that this file exists, if it doesn't, need to munge it so that it does
HANDLE hFile;
TCHAR cMungedName[_MAX_PATH];
TCHAR *pStrPos;
hFile = CreateFile(szFileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (BADHANDLE(hFile))
{
// file does not exist, need to search for it
if (pStrPos = strstr(szFileName, _T("\\system\\")))
{
// this may have been placed in the system32 dir instead
*pStrPos = '\0';
pStrPos++;
pStrPos = strchr(pStrPos, '\\');
sprintf(cMungedName, _T("%s\\system32%s"), szFileName, pStrPos);
szFileName = cMungedName;
hFile = CreateFile(szFileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (BADHANDLE(hFile))
{
return FALSE;
}
}
else if (pStrPos = strstr(szFileName, _T(".inf")))
{
// might be that an inf got caught in the other directory
pStrPos = _tcsrchr(szFileName, '\\');
//a-kjaw. to fix prefix bug# 259380.
if(NULL == pStrPos)
return FALSE;
*pStrPos = '\0';
pStrPos++;
sprintf(cMungedName, _T("%s\\other\\%s"),szFileName, pStrPos);
szFileName = cMungedName;
hFile = CreateFile(szFileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (BADHANDLE(hFile))
{
return FALSE;
}
}
else
return FALSE;
}
CloseHandle(hFile);
// first scan the file list for duplicates
pThisFile = m_FileList;
while ( pThisFile )
{
if ( !strcmp(pThisFile->FilePath(), szFileName) )
{
return(TRUE); // no copy, no add
}
pThisFile = pThisFile->pNext;
}
pThisFile = NULL;
pThisFile = new FileNode;
if ( !pThisFile )
{
return(FALSE);
}
pThisFile->pDevnode = this;
pThisFile->lpszFilePath = new TCHAR[strlen(szFileName) + 1];
if ( !pThisFile->lpszFilePath )
{
delete pThisFile;
return(FALSE);
}
strcpy(pThisFile->lpszFilePath, szFileName);
// copyed the data
pThisFile->lpszFileName = _tcsrchr(pThisFile->lpszFilePath, '\\');
pThisFile->lpszFileName++;
pThisFile->lpszFileExt = _tcsrchr(pThisFile->lpszFilePath, '.');
pThisFile->lpszFileExt++;
// get the version information
//pThisFile->GetFileInformation();
if(uiWin32Error == NO_ERROR)
pThisFile->bSigned = TRUE;
else
pThisFile->bSigned = FALSE;
if(szSigner != NULL)
{
pThisFile->lpszSignedBy = new TCHAR[(_tcslen(szSigner) + 1) * sizeof(TCHAR)];
_tcscpy(pThisFile->lpszSignedBy, szSigner);
}
//else
// pThisFile->bSigned = FALSE;
// now perform the LL patch
pThisFile->pNext = m_FileList;
m_FileList = pThisFile;
return(TRUE);
}
BOOL CheckDevice::GetServiceNameAndDriver(void)
{
/**********
Get service Name
***********/
ULONG ulSize;
CONFIGRET retval;
ulSize = 0;
retval = CM_Get_DevNode_Registry_Property (hDevnode,
CM_DRP_SERVICE,
NULL,
NULL,
&ulSize,
0);
if ( retval )
if ( (retval == CR_BUFFER_SMALL) )
{
if ( !ulSize )
ulSize = 511;
}
else
return(retval);
lpszServiceName = new TCHAR [ulSize+1];
if ( !lpszServiceName ) return(CR_OUT_OF_MEMORY);
//Now get value
retval = CM_Get_DevNode_Registry_Property (hDevnode,
CM_DRP_SERVICE,
NULL,
lpszServiceName,
&ulSize,
0);
if ( retval )
return(retval);
TCHAR KeyName[BUFFSIZE];
TCHAR KeyValue[BUFFSIZE];
HKEY SrvcKey;
sprintf(KeyName, _T("SYSTEM\\CurrentControlSet\\Services\\%s"), lpszServiceName);
if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE,
KeyName,
0,
KEY_READ,
&SrvcKey) != ERROR_SUCCESS )
return(FALSE);
if ( RegQueryValueEx(SrvcKey,
_T("ImagePath"),
0,
NULL,
NULL,
&ulSize) != ERROR_SUCCESS )
{
RegCloseKey(SrvcKey);
return(FALSE);
}
if ( RegQueryValueEx(SrvcKey,
_T("ImagePath"),
0,
NULL,
(PBYTE)KeyValue,
&ulSize) != ERROR_SUCCESS )
{
RegCloseKey(SrvcKey);
return(FALSE);
}
else
{
// sometimes the service path is assumed
// z.b. system32\foo
// or %system32%\foo
if ( !_tcsncmp(KeyValue, _T("System32\\"), _tcslen(_T("System32\\"))) )
{
sprintf(KeyName, _T("%%WINDIR%%\\%s"), KeyValue);
ExpandEnvironmentStrings(KeyName, KeyValue, BUFFSIZE);
lpszServiceImage = new TCHAR[strlen(KeyValue) + 1];
if ( lpszServiceImage )
strcpy(lpszServiceImage, KeyValue);
}
}
// should be everything
RegCloseKey(SrvcKey);
return(TRUE);
}
BOOL CheckDevice::CreateFileNode(void)
{
// also going to add the inf as a file
TCHAR infname[512];
TCHAR tempname[512];
if ( InfName() )
{
// BUGBUG is this correct, or in some subdir??
sprintf(tempname, _T("%%WINDIR%%\\inf\\%s"), InfName());
ExpandEnvironmentStrings(tempname, infname, 512);
AddFileNode(infname);
}
else
return(FALSE);
if ( GetServiceNameAndDriver() )
AddFileNode(lpszServiceImage);
//CreateFileNode_Class();
CreateFileNode_Driver();
return(TRUE);
}
BOOL CheckDevice::CreateFileNode_Class(void)
{
SP_DEVINSTALL_PARAMS DevInstallParams, DevTemp;
SP_DEVINFO_DATA DevInfoData;
SP_DRVINFO_DATA DrvInfoData;
DWORD dwScanResult;
HDEVINFO hDevInfo;
HSPFILEQ hFileQueue;
BOOL bProceed = TRUE;
// Reset all structures to empty
memset(&DevInstallParams, 0, sizeof(DevInstallParams));
memset(&DevInfoData, 0, sizeof(DevInfoData));
memset(&DrvInfoData, 0, sizeof(DrvInfoData));
memset(&DevTemp, 0, sizeof(DevInstallParams));
DrvInfoData.cbSize = sizeof(DrvInfoData);
DevInfoData.cbSize = sizeof(DevInfoData);
DevInstallParams.cbSize = sizeof(DevInstallParams);
hFileQueue = SetupOpenFileQueue();
// We need to build a driver node for the devnode
hDevInfo = m_hDevInfo;
if ( INVALID_HANDLE_VALUE == hDevInfo )
return(0);
DevInfoData.Reserved = 0;
if ( !SetupDiOpenDeviceInfo(hDevInfo, DeviceID(), NULL, NULL , &DevInfoData) )
{
SetupDiDestroyDeviceInfoList(hDevInfo);
return(FALSE);
}
/*
if (SetupDiGetDeviceInstallParams(hDevInfo,
&DevInfoData,
&DevInstallParams
))
{
DevInstallParams.FlagsEx = (DI_FLAGSEX_INSTALLEDDRIVER |
DI_FLAGSEX_ALLOWEXCLUDEDDRVS);
SetupDiSetDeviceInstallParams(hDevInfo,
&DevInfoData,
&DevInstallParams
);
}
*/
if ( !SetupDiBuildDriverInfoList(hDevInfo, &DevInfoData, SPDIT_CLASSDRIVER) )
{
SetupDiDestroyDeviceInfoList(hDevInfo);
return(FALSE);
}
// select a driver
if ( DeviceName() )
strcpy(DrvInfoData.Description, DeviceName());
if ( MFG() )
strcpy(DrvInfoData.MfgName, MFG());
if ( InfProvider() )
strcpy(DrvInfoData.ProviderName, InfProvider());
DrvInfoData.DriverType = SPDIT_CLASSDRIVER;
if ( !SetupDiSetSelectedDriver(hDevInfo,
&DevInfoData,
&DrvInfoData) )
{
//BUGBUG put goo here
DWORD err = GetLastError();
return(FALSE);
}
if ( SetupDiGetDeviceInstallParams(hDevInfo, &DevInfoData, &DevInstallParams) )
{
memcpy(&DevTemp, &DevInfoData, sizeof(DevInfoData));
}
DevInstallParams.FileQueue = hFileQueue;
DevInstallParams.Flags |= (DI_NOVCP | DI_ENUMSINGLEINF | DI_DONOTCALLCONFIGMG | DI_NOFILECOPY | DI_NOWRITE_IDS) ;
DevInstallParams.Flags &= ~(DI_NODI_DEFAULTACTION);
DevInstallParams.FlagsEx |= DI_FLAGSEX_NO_DRVREG_MODIFY;
DevInstallParams.InstallMsgHandler = ScanQueueCallback;
DevInstallParams.InstallMsgHandlerContext = this;
strcpy(DevInstallParams.DriverPath, InfName());
SetLastError(0);
SetupDiSetDeviceInstallParams(hDevInfo, &DevInfoData, &DevInstallParams);
if ( !SetupDiCallClassInstaller(DIF_INSTALLCLASSDRIVERS, hDevInfo, &DevInfoData) )
{
DWORD err = GetLastError();
}
SetupScanFileQueue(hFileQueue,
SPQ_SCAN_USE_CALLBACKEX,
NULL,
ScanQueueCallback,
this,
&dwScanResult);
if ( DevTemp.cbSize )
{
SetupDiSetDeviceInstallParams(hDevInfo, &DevInfoData, &DevTemp);
}
return(FALSE);
}
BOOL CheckDevice::CreateFileNode_Driver(void)
{
SP_DEVINSTALL_PARAMS DevInstallParams, DevTemp;
SP_DEVINFO_DATA DevInfoData;
SP_DRVINFO_DATA DrvInfoData;
DWORD dwScanResult;
HDEVINFO hDevInfo;
HSPFILEQ hFileQueue;
BOOL bProceed = TRUE;
// Reset all structures to empty
memset(&DevInstallParams, 0, sizeof(DevInstallParams));
memset(&DevInfoData, 0, sizeof(DevInfoData));
memset(&DrvInfoData, 0, sizeof(DrvInfoData));
memset(&DevTemp, 0, sizeof(DevInstallParams));
DrvInfoData.cbSize = sizeof(DrvInfoData);
DevInfoData.cbSize = sizeof(DevInfoData);
DevInstallParams.cbSize = sizeof(DevInstallParams);
hFileQueue = SetupOpenFileQueue();
// We need to build a driver node for the devnode
hDevInfo = m_hDevInfo;
if ( INVALID_HANDLE_VALUE == hDevInfo )
return(0);
DevInfoData.Reserved = 0;
if ( !SetupDiOpenDeviceInfo(hDevInfo, DeviceID(), NULL, NULL , &DevInfoData) )
{
SetupDiDestroyDeviceInfoList(hDevInfo);
return(FALSE);
}
if ( !SetupDiBuildDriverInfoList(hDevInfo, &DevInfoData, SPDIT_COMPATDRIVER) )
{
SetupDiDestroyDeviceInfoList(hDevInfo);
return(FALSE);
}
// select a driver
if ( DeviceName() )
strcpy(DrvInfoData.Description, DeviceName());
if ( MFG() )
strcpy(DrvInfoData.MfgName, MFG());
if ( InfProvider() )
strcpy(DrvInfoData.ProviderName, InfProvider());
DrvInfoData.DriverType = SPDIT_COMPATDRIVER;
if ( !SetupDiSetSelectedDriver(hDevInfo,
&DevInfoData,
&DrvInfoData) )
{
DWORD err = GetLastError();
return(FALSE);
}
if ( SetupDiGetDeviceInstallParams(hDevInfo, &DevInfoData, &DevInstallParams) )
{
memcpy(&DevTemp, &DevInfoData, sizeof(DevInfoData));
}
DevInstallParams.FileQueue = hFileQueue;
DevInstallParams.Flags |= (DI_NOVCP /*| DI_ENUMSINGLEINF | DI_DONOTCALLCONFIGMG | DI_NOFILECOPY | DI_NOWRITE_IDS*/) ;
//DevInstallParams.Flags &= ~(DI_NODI_DEFAULTACTION);
//DevInstallParams.FlagsEx |= DI_FLAGSEX_NO_DRVREG_MODIFY;
//DevInstallParams.InstallMsgHandler = ScanQueueCallback;
//DevInstallParams.InstallMsgHandlerContext = this;
strcpy(DevInstallParams.DriverPath, InfName());
SetLastError(0);
SetupDiSetDeviceInstallParams(hDevInfo, &DevInfoData, &DevInstallParams);
if ( !SetupDiCallClassInstaller(DIF_INSTALLDEVICEFILES, hDevInfo, &DevInfoData) )
{
DWORD err = GetLastError();
}
SetupScanFileQueue(hFileQueue,
SPQ_SCAN_USE_CALLBACKEX,
NULL,
ScanQueueCallback,
this,
&dwScanResult);
if ( DevTemp.cbSize )
{
SetupDiSetDeviceInstallParams(hDevInfo, &DevInfoData, &DevTemp);
}
return(FALSE);
}
FileNode * CheckDevice::GetFileList(void)
{
return(m_FileList);
}
FileNode::FileNode()
{
lpszFileName = NULL;
lpszFilePath = NULL;
lpszFileExt = NULL;
baHashValue = NULL;
dwHashSize = 0;
pNext = NULL;
FileSize = 0;
lpszCatalogPath = NULL;
lpszCatalogName = NULL;
lpszSignedBy = NULL;
m_pCatAttrib = NULL;
bSigned = FALSE;
}
FileNode::~FileNode()
{
if ( lpszFilePath )
{
delete lpszFilePath;
}
lpszFileName = NULL;
lpszFilePath = NULL;
lpszFileExt = NULL;
if ( baHashValue )
{
delete baHashValue;
}
baHashValue = NULL;
dwHashSize = 0;
if ( lpszCatalogPath )
{
delete lpszCatalogPath;
}
lpszCatalogPath = NULL;
lpszCatalogName = NULL;
if ( pNext )
{
delete pNext;
}
pNext = NULL;
if ( m_pCatAttrib )
{
delete m_pCatAttrib;
}
m_pCatAttrib = NULL;
}
BOOL FileNode::GetFileInformation(void)
{
UINT dwSize;
DWORD dwHandle;
BYTE *pBuf;
VS_FIXEDFILEINFO *lpVerData;
HANDLE hFile;
BY_HANDLE_FILE_INFORMATION FileInfo;
// get version of the file
dwSize = GetFileVersionInfoSize(lpszFilePath, &dwHandle);
pBuf = new BYTE[dwSize];
if ( GetFileVersionInfo(lpszFilePath, dwHandle, dwSize, pBuf) )
{
if ( VerQueryValue(pBuf, _T("\\"), (void **)&lpVerData, &dwSize) )
{
Version.dwProductVersionLS = lpVerData->dwProductVersionLS;
Version.dwProductVersionMS = lpVerData->dwProductVersionMS;
Version.dwFileVersionLS = lpVerData->dwFileVersionLS;
Version.dwFileVersionMS = lpVerData->dwFileVersionMS;
// while we're here get the file time as well)
TimeStamp.dwLowDateTime = lpVerData->dwFileDateLS;
TimeStamp.dwHighDateTime = lpVerData->dwFileDateMS;
}
}
delete pBuf;
// get file hash
if ( BADHANDLE(hCatAdmin) )
{
CryptCATAdminAcquireContext(&hCatAdmin, NULL, 0);
}
hFile = CreateFile(lpszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
// BUGBUG: on for win9x inf.s, they might be in the inf\other directory
// BUGBUG: for whatever reason, sometimes setupapi will give c:\windows\system\driver dir, and not the sytem32\drivers
if ( BADHANDLE(hFile) )
{
int foo = GetLastError();
return(FALSE);
}
if ( CryptCATAdminCalcHashFromFileHandle(hFile, &dwHashSize, NULL, 0) )
{
baHashValue = new BYTE[dwHashSize];
ZeroMemory(baHashValue, dwHashSize);
CryptCATAdminCalcHashFromFileHandle(hFile, &dwHashSize, baHashValue, 0);
}
else
{
baHashValue = 0;
}
// get file size
FileSize = GetFileSize(hFile, NULL);
// get time stamp
if ( GetFileInformationByHandle(hFile, &FileInfo) )
{
TimeStamp = FileInfo.ftCreationTime;
}
CloseHandle(hFile);
return(TRUE);
}
BOOL FileNode::VerifyFile(void)
{
USES_CONVERSION;
BOOL bRet;
HCATINFO hCatInfo = NULL;
HCATINFO PrevCat;
WINTRUST_DATA WinTrustData;
WINTRUST_CATALOG_INFO WinTrustCatalogInfo;
DRIVER_VER_INFO VerInfo;
GUID gSubSystemDriver = DRIVER_ACTION_VERIFY;
//GUID gSubSystemDriver = WINTRUST_ACTION_GENERIC_VERIFY_V2;
HRESULT hRes;
CATALOG_INFO CatInfo;
LPTSTR lpFilePart;
WCHAR UnicodeKey[MAX_PATH];
TCHAR szBuffer[MAX_PATH];
// make sure that we can find the file
if ( !baHashValue || !dwHashSize || !FileSize )
{
// seems that there is no file to check, or couldn't find it
return(FALSE);
}
//
// Need to lower case file tag for old-style catalog files
//
lstrcpy(szBuffer, lpszFilePath);
CharLowerBuff(szBuffer, lstrlen(szBuffer));
#ifdef _UNICODE
CopyMemory(UnicodeKey, szBuffer, MAX_PATH * sizeof(WCHAR));
#else
MultiByteToWideChar(CP_ACP, 0, szBuffer, -1, UnicodeKey, MAX_PATH);
#endif
ZeroMemory(&VerInfo, sizeof(DRIVER_VER_INFO));
VerInfo.cbStruct = sizeof(DRIVER_VER_INFO);
//
// Now we have the file's hash. Initialize the structures that
// will be used later on in calls to WinVerifyTrust.
//
ZeroMemory(&WinTrustData, sizeof(WINTRUST_DATA));
WinTrustData.cbStruct = sizeof(WINTRUST_DATA);
WinTrustData.dwUIChoice = WTD_UI_NONE;
WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
WinTrustData.dwUnionChoice = WTD_CHOICE_CATALOG;
WinTrustData.dwStateAction = WTD_STATEACTION_VERIFY;
WinTrustData.pPolicyCallbackData = (LPVOID)&VerInfo;
WinTrustData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
WinTrustData.pCatalog = &WinTrustCatalogInfo;
ZeroMemory(&WinTrustCatalogInfo, sizeof(WINTRUST_CATALOG_INFO));
WinTrustCatalogInfo.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
WinTrustCatalogInfo.pbCalculatedFileHash = baHashValue;
WinTrustCatalogInfo.cbCalculatedFileHash = dwHashSize;
WinTrustCatalogInfo.pcwszMemberTag = UnicodeKey;
WinTrustCatalogInfo.pcwszMemberFilePath = UnicodeKey;
//
// Now we try to find the file hash in the catalog list, via CryptCATAdminEnumCatalogFromHash
//
PrevCat = NULL;
hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin, baHashValue, dwHashSize, 0, &PrevCat);
//
// We want to cycle through the matching catalogs until we find one that matches both hash and member tag
//
bRet = FALSE;
while ( hCatInfo && !bRet )
{
ZeroMemory(&CatInfo, sizeof(CATALOG_INFO));
CatInfo.cbStruct = sizeof(CATALOG_INFO);
if ( CryptCATCatalogInfoFromContext(hCatInfo, &CatInfo, 0) )
{
WinTrustCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
// Now verify that the file is an actual member of the catalog.
hRes = WinVerifyTrust(NULL, &gSubSystemDriver, &WinTrustData);
if ( hRes == ERROR_SUCCESS )
{
#ifdef _UNICODE
CopyMemory(szBuffer, CatInfo.wszCatalogFile, MAX_PATH * sizeof(TCHAR));
#else
WideCharToMultiByte(CP_ACP, 0, CatInfo.wszCatalogFile, -1, szBuffer, MAX_PATH, NULL, NULL);
#endif
//Commented because of some weird prob!!
//GetFullPathName(szBuffer, MAX_PATH, szBuffer, &lpFilePart);
lpszCatalogPath = new TCHAR[(lstrlen(szBuffer) + 1) * sizeof(TCHAR)];
lstrcpy(lpszCatalogPath, szBuffer);
lpszCatalogName = _tcsrchr(lpszCatalogPath, '\\');
lpszCatalogName++;
bRet = TRUE;
if ( VerInfo.pcSignerCertContext != NULL )
{
CertFreeCertificateContext(VerInfo.pcSignerCertContext);
VerInfo.pcSignerCertContext = NULL;
}
// file is signed, so need to walk the cert chain to see who signed it
bSigned = WalkCertChain(WinTrustData.hWVTStateData);
}
}
if ( !bRet )
{
// The hash was in this catalog, but the file wasn't a member... so off to the next catalog
PrevCat = hCatInfo;
hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin, baHashValue, dwHashSize, 0, &PrevCat);
}
}
if ( !hCatInfo )
{
//
// If it wasn't found in the catalogs, check if the file is individually signed.
//
bRet = VerifyIsFileSigned(lpszFilePath, (PDRIVER_VER_INFO) &VerInfo);
if ( bRet )
{
// If so, mark the file as being signed.
bSigned = TRUE;
}
}
else
{
GetCatalogInfo(CatInfo.wszCatalogFile, hCatAdmin, hCatInfo);
// The file was verified in the catalogs, so mark it as signed and free the catalog context.
CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
}
if ( hRes == ERROR_SUCCESS )
{
#ifdef _UNICODE
CopyMemory(szBuffer, VerInfo.wszSignedBy, MAX_PATH * sizeof(TCHAR));
#else
WideCharToMultiByte(CP_ACP, 0, VerInfo.wszSignedBy, -1, szBuffer, sizeof(szBuffer), NULL, NULL);
#endif
lpszSignedBy = new TCHAR[(lstrlen(szBuffer) + 1) * sizeof(TCHAR)];
lstrcpy(lpszSignedBy, szBuffer);
}
//
// close wintrust state
//
WinTrustData.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrust(NULL,
&gSubSystemDriver,
&WinTrustData);
return(bSigned);
}
/*************************************************************************
* Function : VerifyIsFileSigned
* Purpose : Calls WinVerifyTrust with Policy Provider GUID to
* verify if an individual file is signed.
**************************************************************************/
BOOL FileNode::VerifyIsFileSigned(LPTSTR pcszMatchFile, PDRIVER_VER_INFO lpVerInfo)
{
USES_CONVERSION;
INT iRet;
HRESULT hRes;
WINTRUST_DATA WinTrustData;
WINTRUST_FILE_INFO WinTrustFile;
GUID gOSVerCheck = DRIVER_ACTION_VERIFY;
GUID gPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WCHAR wszFileName[MAX_PATH];
ZeroMemory(&WinTrustData, sizeof(WINTRUST_DATA));
WinTrustData.cbStruct = sizeof(WINTRUST_DATA);
WinTrustData.dwUIChoice = WTD_UI_NONE;
WinTrustData.fdwRevocationChecks = WTD_REVOKE_NONE;
WinTrustData.dwUnionChoice = WTD_CHOICE_FILE;
WinTrustData.dwStateAction = WTD_STATEACTION_AUTO_CACHE;
WinTrustData.pFile = &WinTrustFile;
WinTrustData.pPolicyCallbackData = (LPVOID)lpVerInfo;
ZeroMemory(lpVerInfo, sizeof(DRIVER_VER_INFO));
lpVerInfo->cbStruct = sizeof(DRIVER_VER_INFO);
ZeroMemory(&WinTrustFile, sizeof(WINTRUST_FILE_INFO));
WinTrustFile.cbStruct = sizeof(WINTRUST_FILE_INFO);
#ifdef _UNICODE
CopyMemory(wszFileName, pcszMatchFile, MAX_PATH * sizeof(WCHAR));
#else
iRet = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pcszMatchFile, -1, (LPWSTR)&wszFileName, wcslen(wszFileName));
#endif
WinTrustFile.pcwszFilePath = wszFileName;
hRes = WinVerifyTrust((HWND__ *)INVALID_HANDLE_VALUE, &gOSVerCheck, &WinTrustData);
if ( hRes != ERROR_SUCCESS )
hRes = WinVerifyTrust((HWND__ *)INVALID_HANDLE_VALUE, &gPublishedSoftware, &WinTrustData);
return(hRes == ERROR_SUCCESS);
}
LogoFileVersion::LogoFileVersion()
{
dwProductVersionLS = 0;
dwProductVersionMS = 0;
dwFileVersionLS = 0;
dwFileVersionMS = 0;
}
CatalogAttribute::CatalogAttribute()
{
Attrib = NULL;
Value = NULL;
pNext = NULL;
}
CatalogAttribute::~CatalogAttribute()
{
if ( Attrib ) delete Attrib;
if ( Value ) delete Value;
if ( pNext ) delete pNext;
Attrib = NULL;
Value = NULL;
pNext = NULL;
}
// Function: ScanQueueCallback
// Parameters:
// pvContext: Pointer to a context that contains any data needed
// Notify: The type of message received
// Param1: The pointer to the string containing the filename
// Param2: Not used
// Purpose: This function gets called when you tell the setup environment to scan
// through the file queue. Basically it receives the filenames and copies
// them into a string.
// Returns: NO_ERROR if nothing went wrong and ERROR_NOT_ENOUGH_MEMORY if their is no
// free memory
UINT __stdcall ScanQueueCallback(PVOID pvContext, UINT Notify, UINT_PTR Param1, UINT_PTR Param2)
{
CheckDevice *pDevice = (CheckDevice *)pvContext;
PFILEPATHS pfilepaths;
if ( (SPFILENOTIFY_QUEUESCAN == Notify) && Param1 )
{
pDevice->AddFileNode((TCHAR *)Param1);
}
if ( (SPFILENOTIFY_QUEUESCAN_EX == Notify) && Param1 )
{
pfilepaths = (PFILEPATHS)Param1;
////////////////Put Signer in the 3rd param whenever its available!
pDevice->AddFileNode((LPTSTR)pfilepaths->Target , pfilepaths->Win32Error , /*pfilepaths->csSigner*/ NULL);
}
return(NO_ERROR);
}
BOOL FileNode::GetCatalogInfo(LPWSTR lpwzCatName, HCATADMIN hCatAdmin, HCATINFO hCatInfo)
{
USES_CONVERSION;
HANDLE hCat;
CRYPTCATATTRIBUTE *pCatAttrib;
TCHAR szBuffer[512];
CRYPTCATMEMBER *pMember = NULL;
PSIP_INDIRECT_DATA pSipData;
CatalogAttribute *CatAttribute;
hCat = CryptCATOpen(lpwzCatName, CRYPTCAT_OPEN_EXISTING, NULL, 0, 0);
if ( BADHANDLE(hCat) )
{
return(FALSE);
}
pCatAttrib = NULL;
while ( pCatAttrib = CryptCATEnumerateCatAttr(hCat, pCatAttrib) )
{
if ( pCatAttrib->dwAttrTypeAndAction | CRYPTCAT_ATTR_NAMEASCII )
{
#ifdef _UNICODE
CopyMemory(szBuffer, pCatAttrib->pwszReferenceTag, 511 * sizeof(TCHAR));
#else
WideCharToMultiByte(CP_ACP, 0, pCatAttrib->pwszReferenceTag, -1, szBuffer, 511, NULL, NULL);
#endif
CatAttribute = new CatalogAttribute;
if ( !CatAttribute )
{
return(FALSE);
}
CatAttribute->Attrib = new TCHAR[strlen(szBuffer) +1];
if ( !CatAttribute->Attrib )
{
delete CatAttribute;
return(FALSE);
}
_tcscpy(CatAttribute->Attrib, szBuffer);
#ifdef _UNICODE
CopyMemory(szBuffer, (PUSHORT)pCatAttrib->pbValue, 511 * sizeof(TCHAR));
#else
WideCharToMultiByte(CP_ACP, 0, (PUSHORT)pCatAttrib->pbValue, -1, szBuffer, 511, NULL, NULL);
#endif
CatAttribute->Value = new TCHAR[strlen(szBuffer) + 1];
if ( !CatAttribute->Value )
{
delete CatAttribute;
return(FALSE);
}
_tcscpy(CatAttribute->Value, szBuffer);
// add to node
CatAttribute->pNext = (void *)m_pCatAttrib;
m_pCatAttrib = CatAttribute;
}
}
while ( pMember = CryptCATEnumerateMember(hCat, pMember) )
{
pSipData = pMember->pIndirectData;
}
CryptCATClose(hCat);
return(TRUE);
}
BOOL CheckFile (TCHAR *szFileName)
{
FileNode *pThisFile = NULL;
BOOL bRet = FALSE; // v-jammar; fix prefix bug 427999
try //v-stlowe: 3/20/2001: to fix prefix bug where memory was leaking on out-of-mem throw
{
pThisFile = new FileNode;
if ( !pThisFile )
{
return(FALSE);
}
pThisFile->lpszFilePath = new TCHAR[strlen(szFileName) + 1];
if ( !pThisFile->lpszFilePath )
{
delete pThisFile;
return(FALSE);
}
_tcscpy(pThisFile->lpszFilePath, szFileName);
// copyed the data
pThisFile->lpszFileName = _tcsrchr(pThisFile->lpszFilePath, '\\');
pThisFile->lpszFileName++;
pThisFile->lpszFileExt = _tcsrchr(pThisFile->lpszFilePath, '.');
pThisFile->lpszFileExt++;
// get the version information
pThisFile->GetFileInformation();
bRet = pThisFile->VerifyFile();
}
catch(...)
{
}
// BUGBUG, need to check out the signer of this file to determine
// who actually signed it.
if(pThisFile)
{
delete pThisFile;
pThisFile = NULL;
}
return(bRet);
}
BOOL Share_CloseHandle(void)
{
if ( !BADHANDLE(hCatAdmin) )
{
CryptCATAdminReleaseContext(hCatAdmin, 0);
hCatAdmin = 0;
}
return(TRUE);
}
BOOL FileNode::GetCertInfo(PCCERT_CONTEXT pCertContext)
{
DWORD Size = 200;
#if 0
Size = 200;
if ( CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, pArray, &Size) )
{
printf("\nSH1 Hash (%u):", Size);
for ( UINT index = 0; index < Size; index++ )
{
printf("%s0x%02X", index == 0 ? " " : ", ", pArray[index]);
}
printf("\n");
}
Size = 200;
if ( CertGetCertificateContextProperty(pCertContext, CERT_SIGNATURE_HASH_PROP_ID, pArray, &Size) )
{
printf("\nCert Hash (%u):", Size);
for ( UINT index = 0; index < Size; index++ )
{
printf("%s0x%02X", index == 0 ? " " : ", ", pArray[index]);
}
printf("\n");
}
// Get Chain information
CERT_CHAIN_PARA ChainPara;
PCCERT_CHAIN_CONTEXT pChainContext = NULL;
memset (&CharinPara, 0, sizeof (CERT_CHAIN_PARA));
ChainPara.cbSize = sizeof (CERT_CHAIN_PARA);
ChainPara.RequestedUsage.
if ( CertGetCertificateChain(NULL, pCertContext, NULL, NULL, ) )
{
}
#endif
return(TRUE);
}
BOOL WalkCertChain(HANDLE hWVTStateData)
{
CRYPT_PROVIDER_DATA * pProvData;
CRYPT_PROVIDER_SGNR * pProvSigner = NULL;
CRYPT_PROVIDER_CERT * pCryptProviderCert;
BYTE pArray[21];
UINT i;
DWORD size;
pProvData = WTHelperProvDataFromStateData(hWVTStateData);
// did it work?
if ( !pProvData )
{
return(FALSE);
}
pProvSigner = WTHelperGetProvSignerFromChain(
(PCRYPT_PROVIDER_DATA) pProvData,
0, // first signer
FALSE, //not counter signature
0); // index of counter sig, obviously not used
if ( pProvSigner == NULL )
{
return(FALSE);
}
//
// walk all certs, the leaf cert is index 0, the root is the last index
//
pCryptProviderCert = NULL;
for ( i = 0; i < pProvSigner->csCertChain; i++ )
{
pCryptProviderCert = WTHelperGetProvCertFromChain(pProvSigner, i);
if ( pCryptProviderCert == NULL )
{
// error
}
size = 20;
if ( CertGetCertificateContextProperty(
pCryptProviderCert->pCert,
CERT_SHA1_HASH_PROP_ID,
pArray,
&size) )
{
/*
printf("\nSH1 Hash (%u):{", size);
for ( UINT index = 0; index < size; index++ )
{
printf("%s0x%02X", index == 0 ? " " : ", ", pArray[index]);
}
printf("}\n");
*/
for ( UINT j = 0; j < NumberTestCerts; j++ )
{
if ( !memcmp(pArray, TestCertHashes[j], 20) )
{
// This cert is a test cert, not a real one, fail
//printf("This file is signed by the testcert, and is therefor not trusted\n");
//pritnf("please check the certification for this device");
return (TRUE);
}
}
}
}
return(FALSE);
}