You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1108 lines
31 KiB
1108 lines
31 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
//
|
|
// File: chktrust.cpp
|
|
//
|
|
// Contents: Microsoft Internet Security Trust Checker
|
|
//
|
|
// History: 05-May-1997 pberkman created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include <stdio.h>
|
|
#include <windows.h>
|
|
#include <io.h>
|
|
#include <wchar.h>
|
|
|
|
#include "cryptreg.h"
|
|
#include "wincrypt.h"
|
|
#include "wintrust.h"
|
|
#include "softpub.h"
|
|
#include "mscat.h"
|
|
#include "unicode.h"
|
|
#include "dbgdef.h"
|
|
|
|
#include "gendefs.h"
|
|
#include "cwargv.hxx"
|
|
#include "printfu.hxx"
|
|
|
|
#include "mssip.h"
|
|
#include "resource.h"
|
|
|
|
HRESULT _CallWVT(WCHAR *pwszFilename);
|
|
HRESULT _ExplodeCatalog(WCHAR *pwszCatalogFile);
|
|
HRESULT _CallCatalogWVT(WCHAR *pwszCatalogFile, WCHAR *pwszMemberTag, WCHAR *pwszMemberFile);
|
|
int _ShowError(DWORD dwError, WCHAR *pwszFile);
|
|
void _ToLower(WCHAR *pwszInOut);
|
|
HRESULT _AddCatalogToDatabase(WCHAR *pwszFileIn);
|
|
HRESULT _DelCatalogFromDatabase(WCHAR *pwszFileIn);
|
|
|
|
|
|
GUID guidPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2;
|
|
GUID guidProviderTest = WINTRUST_ACTION_TRUSTPROVIDER_TEST;
|
|
GUID guidProviderDriver = DRIVER_ACTION_VERIFY;
|
|
GUID guidPassedIn;
|
|
GUID guidCatRoot;
|
|
|
|
GUID *pguidActionID = &guidPublishedSoftware;
|
|
GUID *pguidCatRoot = NULL;
|
|
|
|
DWORD dwExpectedError = ERROR_SUCCESS;
|
|
|
|
WCHAR *pwszCatalogFile = NULL;
|
|
WCHAR *pwszCatalogMember = NULL;
|
|
WCHAR *pwszOSVerLow = NULL;
|
|
WCHAR *pwszOSVerHigh = NULL;
|
|
BOOL fUseOldDriverVerInfoSize = FALSE;
|
|
|
|
PrintfU_ *pPrint = NULL;
|
|
|
|
HCATADMIN hCatAdmin = NULL;
|
|
|
|
BOOL fVerbose;
|
|
BOOL fQuiet;
|
|
BOOL fIECall;
|
|
BOOL fTestDump;
|
|
BOOL fCheckExpectedError = FALSE;
|
|
BOOL fProcessAllCatMembers;
|
|
BOOL fCatalogMemberVerify = FALSE;
|
|
BOOL fUseCatalogDatabase;
|
|
BOOL fAdd2CatalogDatabase;
|
|
BOOL fDelFromCatalogDatabase;
|
|
BOOL fReplaceCatfile;
|
|
BOOL fNT5;
|
|
BOOL fNoTimeStampWarning;
|
|
|
|
extern "C" int __cdecl wmain(int argc, WCHAR **wargv)
|
|
{
|
|
cWArgv_ *pArgs;
|
|
BOOL fFailed;
|
|
|
|
BOOL fFind;
|
|
HANDLE hFind;
|
|
WIN32_FIND_DATAW sFindData;
|
|
|
|
int iRet;
|
|
int iRetWorst;
|
|
HRESULT hr = ERROR_SUCCESS;
|
|
|
|
WCHAR *pwszFileIn;
|
|
WCHAR *pwszLastSlash;
|
|
WCHAR wszFile[MAX_PATH];
|
|
WCHAR wszDir[MAX_PATH];
|
|
char szFile[MAX_PATH * 2];
|
|
DWORD dwFiles;
|
|
DWORD dwDirLen;
|
|
|
|
iRet = 0;
|
|
pPrint = NULL;
|
|
hFind = INVALID_HANDLE_VALUE;
|
|
dwFiles = 0;
|
|
|
|
if (!(pPrint = new PrintfU_()))
|
|
{
|
|
goto MemoryError;
|
|
}
|
|
|
|
if (!(pArgs = new cWArgv_((HINSTANCE)GetModuleHandle(NULL), &fFailed, FALSE)))
|
|
{
|
|
goto MemoryError;
|
|
}
|
|
|
|
if (fFailed)
|
|
{
|
|
goto MemoryError;
|
|
}
|
|
|
|
pArgs->AddUsageText(IDS_USAGETEXT_USAGE, IDS_USAGETEXT_OPTIONS,
|
|
IDS_USAGETEXT_CMDFILE, IDS_USAGETEXT_ADD,
|
|
IDS_USAGETEXT_OPTPARAM);
|
|
|
|
pArgs->Add2List(IDS_PARAM_HELP, IDS_PARAMTEXT_HELP, WARGV_VALUETYPE_BOOL, (void *)FALSE, FALSE);
|
|
pArgs->Add2List(IDS_PARAM_VERBOSE, IDS_PARAMTEXT_VERBOSE, WARGV_VALUETYPE_BOOL, (void *)FALSE, FALSE);
|
|
pArgs->Add2List(IDS_PARAM_QUIET, IDS_PARAMTEXT_QUIET, WARGV_VALUETYPE_BOOL, (void *)FALSE, FALSE);
|
|
pArgs->Add2List(IDS_PARAM_TPROV, IDS_PARAMTEXT_TPROV, WARGV_VALUETYPE_WCHAR, NULL, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_IECALL, IDS_PARAMTEXT_IECALL, WARGV_VALUETYPE_BOOL, (void *)FALSE, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_TESTDUMP, IDS_PARAMTEXT_TESTDUMP, WARGV_VALUETYPE_BOOL, (void *)FALSE, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_EXPERROR, IDS_PARAMTEXT_EXPERROR, WARGV_VALUETYPE_DWORDH, NULL, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_TESTDRV, IDS_PARAMTEXT_TESTDRV, WARGV_VALUETYPE_BOOL, (void *)FALSE, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_CATFILE, IDS_PARAMTEXT_CATFILE, WARGV_VALUETYPE_WCHAR, NULL, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_CATMEMBER, IDS_PARAMTEXT_CATMEMBER, WARGV_VALUETYPE_WCHAR, NULL, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_ALLCATMEM, IDS_PARAMTEXT_ALLCATMEM, WARGV_VALUETYPE_BOOL, (void *)FALSE, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_CATUSELIST, IDS_PARAMTEXT_CATUSELIST, WARGV_VALUETYPE_BOOL, (void *)FALSE, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_CATADDLIST, IDS_PARAMTEXT_CATADDLIST, WARGV_VALUETYPE_BOOL, (void *)FALSE, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_CATDELLIST, IDS_PARAMTEXT_CATDELLIST, WARGV_VALUETYPE_BOOL, (void *)FALSE, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_REPLACECATFILE,IDS_PARAMTEXT_REPLACECATFILE, WARGV_VALUETYPE_BOOL, (void *)FALSE, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_CATROOT, IDS_PARAMTEXT_CATROOT, WARGV_VALUETYPE_WCHAR, NULL, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_NT5, IDS_PARAMTEXT_NT5, WARGV_VALUETYPE_BOOL, (void *)FALSE, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_TSWARN, IDS_PARAMTEXT_TSWARN, WARGV_VALUETYPE_BOOL, (void *)FALSE, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_OSVERLOW, IDS_PARAMTEXT_OSVERLOW, WARGV_VALUETYPE_WCHAR, NULL, TRUE);
|
|
pArgs->Add2List(IDS_PARAM_OSVERHIGH, IDS_PARAMTEXT_OSVERHIGH, WARGV_VALUETYPE_WCHAR, NULL, TRUE);
|
|
|
|
|
|
if (!(pArgs->Fill(argc, wargv)) ||
|
|
(pArgs->GetValue(IDS_PARAM_HELP)))
|
|
{
|
|
wprintf(L"%s", pArgs->GetUsageString());
|
|
goto NeededHelp;
|
|
}
|
|
|
|
pwszCatalogFile = (WCHAR *)pArgs->GetValue(IDS_PARAM_CATFILE);
|
|
pwszCatalogMember = (WCHAR *)pArgs->GetValue(IDS_PARAM_CATMEMBER);
|
|
fVerbose = (BOOL)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_VERBOSE));
|
|
fQuiet = (BOOL)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_QUIET));
|
|
fIECall = (BOOL)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_IECALL));
|
|
fTestDump = (BOOL)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_TESTDUMP));
|
|
fProcessAllCatMembers = (BOOL)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_ALLCATMEM));
|
|
fUseCatalogDatabase = (BOOL)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_CATUSELIST));
|
|
fAdd2CatalogDatabase = (BOOL)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_CATADDLIST));
|
|
fDelFromCatalogDatabase = (BOOL)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_CATDELLIST));
|
|
fReplaceCatfile = (BOOL)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_REPLACECATFILE));
|
|
fNT5 = (BOOL)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_NT5));
|
|
fNoTimeStampWarning = (BOOL)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_TSWARN));
|
|
pwszOSVerLow = (WCHAR *)pArgs->GetValue(IDS_PARAM_OSVERLOW);
|
|
pwszOSVerHigh = (WCHAR *)pArgs->GetValue(IDS_PARAM_OSVERHIGH);
|
|
|
|
|
|
//
|
|
// the win2k flag implies -q and -ucl (unless -acl or -del is used, then it just implies -q)
|
|
//
|
|
if (fNT5)
|
|
{
|
|
fQuiet = TRUE;
|
|
if (!fAdd2CatalogDatabase && !fDelFromCatalogDatabase)
|
|
{
|
|
fUseCatalogDatabase = TRUE;
|
|
}
|
|
}
|
|
|
|
if (fUseCatalogDatabase || fNT5)
|
|
{
|
|
fCatalogMemberVerify = TRUE;
|
|
}
|
|
|
|
if (pArgs->IsSet(IDS_PARAM_EXPERROR))
|
|
{
|
|
dwExpectedError = (DWORD)((DWORD_PTR)pArgs->GetValue(IDS_PARAM_EXPERROR));
|
|
fCheckExpectedError = TRUE;
|
|
}
|
|
|
|
if (!(pwszFileIn = pArgs->GetFileName()))
|
|
{
|
|
wprintf(L"%s", pArgs->GetUsageString());
|
|
goto ParamError;
|
|
}
|
|
|
|
if (((pwszCatalogFile) && !(pwszCatalogMember)) ||
|
|
(!(pwszCatalogFile) && (pwszCatalogMember)))
|
|
{
|
|
wprintf(L"%s", pArgs->GetUsageString());
|
|
goto ParamError;
|
|
}
|
|
|
|
if ((pwszCatalogFile) && (pwszCatalogMember))
|
|
{
|
|
fCatalogMemberVerify = TRUE;
|
|
}
|
|
|
|
//
|
|
// set the appropriete provider
|
|
//
|
|
if (pArgs->IsSet(IDS_PARAM_TPROV) || fNT5)
|
|
{
|
|
if (fNT5)
|
|
{
|
|
wstr2guid(L"{F750E6C3-38EE-11D1-85E5-00C04FC295EE}", &guidPassedIn);
|
|
}
|
|
else if (!(wstr2guid((WCHAR *)pArgs->GetValue(IDS_PARAM_TPROV), &guidPassedIn)))
|
|
{
|
|
goto GuidError;
|
|
}
|
|
|
|
pguidActionID = &guidPassedIn;
|
|
}
|
|
else if (fTestDump)
|
|
{
|
|
pguidActionID = &guidProviderTest;
|
|
}
|
|
else if (pArgs->GetValue(IDS_PARAM_TESTDRV))
|
|
{
|
|
pguidActionID = &guidProviderDriver;
|
|
}
|
|
else
|
|
{
|
|
pguidActionID = &guidPublishedSoftware;
|
|
}
|
|
|
|
//
|
|
// Get the catalog subsystem GUID to use
|
|
//
|
|
if (pArgs->IsSet(IDS_PARAM_CATROOT) || fNT5)
|
|
{
|
|
if (fNT5)
|
|
{
|
|
wstr2guid(L"{F750E6C3-38EE-11D1-85E5-00C04FC295EE}", &guidCatRoot);
|
|
}
|
|
else if (!(wstr2guid((WCHAR *)pArgs->GetValue(IDS_PARAM_CATROOT), &guidCatRoot)))
|
|
{
|
|
goto GuidError;
|
|
}
|
|
|
|
pguidCatRoot = &guidCatRoot;
|
|
}
|
|
|
|
//
|
|
// if we are calling just like IE, we only have one file and don't want to
|
|
// check if it exists or not... just call WVT.
|
|
//
|
|
if (fIECall)
|
|
{
|
|
dwFiles++;
|
|
|
|
hr = _CallWVT(pwszFileIn);
|
|
|
|
iRet = _ShowError(hr, pwszFileIn);
|
|
|
|
goto CommonReturn;
|
|
}
|
|
|
|
//
|
|
// Check to see if we are supposed to be using the old DRIVER_VER_INFO struct
|
|
//
|
|
while (--argc>0)
|
|
{
|
|
if (**++wargv == L'-')
|
|
{
|
|
if (wcscmp(*wargv, L"-UseOldDriverVerInfoStruct") == 0)
|
|
{
|
|
fUseOldDriverVerInfoSize = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If a delete is being done, then just execute that and get out
|
|
//
|
|
if (fDelFromCatalogDatabase)
|
|
{
|
|
hr = _DelCatalogFromDatabase(pwszFileIn);
|
|
iRet = _ShowError(hr, &wszFile[0]);
|
|
goto CommonReturn;
|
|
}
|
|
|
|
|
|
//
|
|
// OK.... go into a findfirst/next loop we could have been called with *.*
|
|
//
|
|
if (pwszLastSlash = wcsrchr(pwszFileIn, L'\\'))
|
|
{
|
|
*pwszLastSlash = NULL;
|
|
wcscpy(&wszDir[0], pwszFileIn);
|
|
wcscat(&wszDir[0], L"\\");
|
|
*pwszLastSlash = L'\\';
|
|
dwDirLen = wcslen(&wszDir[0]);
|
|
}
|
|
else
|
|
{
|
|
wszDir[0] = NULL;
|
|
dwDirLen = 0;
|
|
}
|
|
|
|
if ((hFind = FindFirstFileU(pwszFileIn, &sFindData)) == INVALID_HANDLE_VALUE)
|
|
{
|
|
pPrint->Display(IDS_CAN_NOT_OPEN_FILE, pwszFileIn);
|
|
goto FileNotFound;
|
|
}
|
|
|
|
fFind = TRUE;
|
|
dwFiles = 0;
|
|
iRetWorst = 0;
|
|
|
|
while (fFind)
|
|
{
|
|
if (!(sFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
if (dwDirLen > 0)
|
|
{
|
|
wcscpy(&wszFile[0], &wszDir[0]);
|
|
}
|
|
|
|
wszFile[dwDirLen] = NULL;
|
|
wcscat(wszFile, sFindData.cFileName);
|
|
|
|
if (wszFile[0])
|
|
{
|
|
if (fAdd2CatalogDatabase)
|
|
{
|
|
hr = _AddCatalogToDatabase(&wszFile[0]);
|
|
}
|
|
else
|
|
{
|
|
hr = _CallWVT(&wszFile[0]);
|
|
}
|
|
|
|
iRet = _ShowError(hr, &wszFile[0]);
|
|
|
|
switch (iRet)
|
|
{
|
|
case 0: // No Error
|
|
break;
|
|
|
|
case 1: // Error
|
|
iRetWorst = iRet;
|
|
break;
|
|
|
|
case 2: // Warning (no timestamp)
|
|
if (iRetWorst != 1)
|
|
{
|
|
iRetWorst = iRet;
|
|
}
|
|
// No other return values are possible from _ShowError
|
|
}
|
|
|
|
if (iRet == 0)
|
|
{
|
|
hr = ERROR_SUCCESS;
|
|
}
|
|
|
|
dwFiles++;
|
|
}
|
|
}
|
|
|
|
fFind = FindNextFileU(hFind, &sFindData);
|
|
}
|
|
|
|
iRet = iRetWorst;
|
|
|
|
if (dwFiles < 1)
|
|
{
|
|
pPrint->Display(IDS_CAN_NOT_OPEN_FILE, pwszFileIn);
|
|
goto FileNotFound;
|
|
}
|
|
|
|
|
|
CommonReturn:
|
|
|
|
DELETE_OBJECT(pArgs);
|
|
DELETE_OBJECT(pPrint);
|
|
|
|
if (hFind != INVALID_HANDLE_VALUE)
|
|
{
|
|
FindClose(hFind);
|
|
}
|
|
|
|
if (hCatAdmin)
|
|
{
|
|
CryptCATAdminReleaseContext(hCatAdmin, 0);
|
|
}
|
|
|
|
|
|
return(iRet);
|
|
|
|
ErrorReturn:
|
|
iRet = 1;
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR_EX(DBG_SS_APP, MemoryError);
|
|
TRACE_ERROR_EX(DBG_SS_APP, FileNotFound);
|
|
TRACE_ERROR_EX(DBG_SS_APP, ParamError);
|
|
TRACE_ERROR_EX(DBG_SS_APP, GuidError);
|
|
TRACE_ERROR_EX(DBG_SS_APP, NeededHelp);
|
|
}
|
|
|
|
HRESULT _CallWVT(WCHAR *pwszFilename)
|
|
{
|
|
if (fCatalogMemberVerify)
|
|
{
|
|
return(_CallCatalogWVT(pwszCatalogFile, pwszCatalogMember, pwszFilename));
|
|
}
|
|
|
|
HRESULT hr;
|
|
WINTRUST_DATA sWTD;
|
|
WINTRUST_FILE_INFO sWTFI;
|
|
|
|
memset(&sWTD, 0x00, sizeof(WINTRUST_DATA));
|
|
|
|
sWTD.cbStruct = sizeof(WINTRUST_DATA);
|
|
sWTD.dwUIChoice = (fQuiet) ? WTD_UI_NONE : WTD_UI_ALL;
|
|
sWTD.dwUnionChoice = WTD_CHOICE_FILE;
|
|
sWTD.pFile = &sWTFI;
|
|
|
|
memset(&sWTFI, 0x00, sizeof(WINTRUST_FILE_INFO));
|
|
|
|
sWTFI.cbStruct = sizeof(WINTRUST_FILE_INFO);
|
|
sWTFI.pcwszFilePath = pwszFilename;
|
|
sWTFI.hFile = CreateFileU(pwszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
hr = WinVerifyTrust(NULL, pguidActionID, &sWTD);
|
|
|
|
if (sWTFI.hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(sWTFI.hFile);
|
|
}
|
|
|
|
if ((fCheckExpectedError) && ((DWORD)hr == dwExpectedError) && (fProcessAllCatMembers))
|
|
{
|
|
if (IsCatalogFile(INVALID_HANDLE_VALUE, pwszFilename))
|
|
{
|
|
return(_ExplodeCatalog(pwszFilename));
|
|
}
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT _ExplodeCatalog(WCHAR *pwszCatalogFile)
|
|
{
|
|
HRESULT hrReturn;
|
|
HANDLE hCat;
|
|
CRYPTCATMEMBER *psMember;
|
|
|
|
hrReturn = ERROR_SUCCESS;
|
|
|
|
//
|
|
// open the catalog
|
|
//
|
|
if (!(hCat = CryptCATOpen(pwszCatalogFile, 0, NULL, 0, 0)))
|
|
{
|
|
goto ErrorCatOpen;
|
|
}
|
|
|
|
psMember = NULL;
|
|
|
|
while (psMember = CryptCATEnumerateMember(hCat, psMember))
|
|
{
|
|
hrReturn |= _CallCatalogWVT(pwszCatalogFile, psMember->pwszReferenceTag,
|
|
psMember->pwszReferenceTag);
|
|
}
|
|
|
|
CommonReturn:
|
|
if (hCat)
|
|
{
|
|
CryptCATClose(hCat);
|
|
}
|
|
|
|
return(hrReturn);
|
|
|
|
ErrorReturn:
|
|
hrReturn = GetLastError();
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR_EX(DBG_SS_APP, ErrorCatOpen);
|
|
}
|
|
|
|
HRESULT _CallCatalogWVT(WCHAR *pwszCatalogFile, WCHAR *pwszMemberTag, WCHAR *pwszMemberFile)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cbHash;
|
|
BYTE bHash[40];
|
|
WCHAR *pwsz;
|
|
WINTRUST_DATA sWTD;
|
|
WINTRUST_CATALOG_INFO sWTCI;
|
|
DRIVER_VER_INFO sDriverInfo;
|
|
|
|
memset(&sWTD, 0x00, sizeof(WINTRUST_DATA));
|
|
|
|
sWTD.cbStruct = sizeof(WINTRUST_DATA);
|
|
sWTD.dwUIChoice = (fQuiet) ? WTD_UI_NONE : WTD_UI_ALL;
|
|
sWTD.dwUnionChoice = WTD_CHOICE_CATALOG;
|
|
sWTD.pCatalog = &sWTCI;
|
|
|
|
memset(&sWTCI, 0x00, sizeof(WINTRUST_CATALOG_INFO));
|
|
|
|
sWTCI.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
|
|
sWTCI.pcwszCatalogFilePath = pwszCatalogFile;
|
|
sWTCI.pcwszMemberTag = pwszMemberTag;
|
|
sWTCI.pcwszMemberFilePath = pwszMemberFile;
|
|
sWTCI.hMemberFile = CreateFileU(pwszMemberFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (pwszOSVerLow != NULL)
|
|
{
|
|
WCHAR *pwszEnd;
|
|
WCHAR *pwszCurrent;
|
|
|
|
memset(&sDriverInfo, 0x00, sizeof(DRIVER_VER_INFO));
|
|
sDriverInfo.cbStruct = fUseOldDriverVerInfoSize ? _OFFSETOF(DRIVER_VER_INFO, dwBuildNumberLow) : sizeof(DRIVER_VER_INFO);
|
|
|
|
pwszEnd = wcschr(pwszOSVerLow, L':');
|
|
if (pwszEnd == NULL)
|
|
{
|
|
goto OSVerError;
|
|
}
|
|
*pwszEnd = L'\0';
|
|
sDriverInfo.dwPlatform = _wtol(pwszOSVerLow);
|
|
*pwszEnd = L':';
|
|
|
|
pwszCurrent = pwszEnd + 1;
|
|
pwszEnd = wcschr(pwszCurrent, L'.');
|
|
if (pwszEnd == NULL)
|
|
{
|
|
goto OSVerError;
|
|
}
|
|
*pwszEnd = L'\0';
|
|
sDriverInfo.sOSVersionLow.dwMajor = sDriverInfo.sOSVersionHigh.dwMajor = _wtol(pwszCurrent);
|
|
*pwszEnd = L'.';
|
|
|
|
pwszCurrent = pwszEnd + 1;
|
|
pwszEnd = wcschr(pwszCurrent, L'.');
|
|
if (pwszEnd == NULL)
|
|
{
|
|
sDriverInfo.sOSVersionLow.dwMinor = sDriverInfo.sOSVersionHigh.dwMinor = _wtol(pwszCurrent);
|
|
}
|
|
else
|
|
{
|
|
*pwszEnd = L'\0';
|
|
sDriverInfo.sOSVersionLow.dwMinor = sDriverInfo.sOSVersionHigh.dwMinor = _wtol(pwszCurrent);
|
|
*pwszEnd = L'.';
|
|
|
|
pwszCurrent = pwszEnd + 1;
|
|
sDriverInfo.dwBuildNumberLow = sDriverInfo.dwBuildNumberHigh = _wtol(pwszCurrent);
|
|
}
|
|
|
|
if (pwszOSVerHigh != NULL)
|
|
{
|
|
pwszEnd = wcschr(pwszOSVerHigh, L':');
|
|
if (pwszEnd == NULL)
|
|
{
|
|
goto OSVerError;
|
|
}
|
|
*pwszEnd = L'\0';
|
|
if (sDriverInfo.dwPlatform != (DWORD) _wtol(pwszOSVerHigh))
|
|
{
|
|
goto OSVerError;
|
|
}
|
|
*pwszEnd = L':';
|
|
|
|
pwszCurrent = pwszEnd + 1;
|
|
pwszEnd = wcschr(pwszCurrent, L'.');
|
|
if (pwszEnd == NULL)
|
|
{
|
|
goto OSVerError;
|
|
}
|
|
*pwszEnd = L'\0';
|
|
sDriverInfo.sOSVersionHigh.dwMajor = _wtol(pwszCurrent);
|
|
*pwszEnd = L'.';
|
|
|
|
pwszCurrent = pwszEnd + 1;
|
|
pwszEnd = wcschr(pwszCurrent, L'.');
|
|
if (pwszEnd == NULL)
|
|
{
|
|
sDriverInfo.sOSVersionHigh.dwMinor = _wtol(pwszCurrent);
|
|
}
|
|
else
|
|
{
|
|
*pwszEnd = L'\0';
|
|
sDriverInfo.sOSVersionHigh.dwMinor = _wtol(pwszCurrent);
|
|
*pwszEnd = L'.';
|
|
|
|
pwszCurrent = pwszEnd + 1;
|
|
sDriverInfo.dwBuildNumberHigh = _wtol(pwszCurrent);
|
|
}
|
|
}
|
|
|
|
sWTD.pPolicyCallbackData = &sDriverInfo;
|
|
}
|
|
|
|
cbHash = 40;
|
|
|
|
if (!(CryptCATAdminCalcHashFromFileHandle(sWTCI.hMemberFile, &cbHash, &bHash[0], 0)))
|
|
{
|
|
goto CatAdminCalcHashError;
|
|
}
|
|
|
|
sWTCI.pbCalculatedFileHash = &bHash[0];
|
|
sWTCI.cbCalculatedFileHash = cbHash;
|
|
|
|
if (fUseCatalogDatabase)
|
|
{
|
|
HCATINFO hCatInfo;
|
|
CATALOG_INFO sCatInfo;
|
|
|
|
if (!(hCatAdmin))
|
|
{
|
|
if (!(CryptCATAdminAcquireContext(&hCatAdmin, pguidCatRoot, 0)))
|
|
{
|
|
goto CatAdminAcquireError;
|
|
}
|
|
}
|
|
|
|
pwsz = NULL;
|
|
|
|
if (pwsz = wcsrchr(pwszMemberFile, L'\\'))
|
|
{
|
|
pwsz++;
|
|
}
|
|
else
|
|
{
|
|
pwsz = pwszMemberFile;
|
|
}
|
|
|
|
_ToLower(pwsz);
|
|
|
|
sWTCI.pcwszMemberTag = pwsz;
|
|
|
|
memset(&sCatInfo, 0x00, sizeof(CATALOG_INFO));
|
|
sCatInfo.cbStruct = sizeof(CATALOG_INFO);
|
|
|
|
hCatInfo = NULL;
|
|
|
|
while (hCatInfo = CryptCATAdminEnumCatalogFromHash(hCatAdmin, &bHash[0], cbHash, 0, &hCatInfo))
|
|
{
|
|
if (!(CryptCATCatalogInfoFromContext(hCatInfo, &sCatInfo, 0)))
|
|
{
|
|
// should do something (??)
|
|
continue;
|
|
}
|
|
|
|
sWTCI.pcwszCatalogFilePath = &sCatInfo.wszCatalogFile[0];
|
|
|
|
hr = WinVerifyTrust(NULL, pguidActionID, &sWTD);
|
|
|
|
if ((sWTD.pPolicyCallbackData != 0) && (sDriverInfo.pcSignerCertContext != NULL))
|
|
{
|
|
CertFreeCertificateContext(sDriverInfo.pcSignerCertContext);
|
|
}
|
|
|
|
if (hr == (HRESULT)dwExpectedError)
|
|
{
|
|
CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
|
|
|
|
goto CommonReturn;
|
|
}
|
|
}
|
|
|
|
goto CatMemberNotFound;
|
|
}
|
|
|
|
hr = WinVerifyTrust(NULL, pguidActionID, &sWTD);
|
|
|
|
CommonReturn:
|
|
if (sWTCI.hMemberFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(sWTCI.hMemberFile);
|
|
}
|
|
|
|
return(hr);
|
|
|
|
ErrorReturn:
|
|
hr = GetLastError();
|
|
goto CommonReturn;
|
|
|
|
OSVerError:
|
|
wprintf(L"Invalid osverl or osverh\n");
|
|
return S_FALSE;
|
|
|
|
TRACE_ERROR_EX(DBG_SS_APP, CatAdminCalcHashError);
|
|
TRACE_ERROR_EX(DBG_SS_APP, CatAdminAcquireError);
|
|
TRACE_ERROR_EX(DBG_SS_APP, CatMemberNotFound);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
OpenSIP(const WCHAR* pwsFileName,
|
|
SIP_SUBJECTINFO** ppSubjectInfo,
|
|
SIP_DISPATCH_INFO** ppDispatchInfo,
|
|
GUID* pgSubject)
|
|
{
|
|
|
|
if (pgSubject == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (NULL == (*ppSubjectInfo = (SIP_SUBJECTINFO*) new(BYTE[sizeof(SIP_SUBJECTINFO)])))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (NULL == (*ppDispatchInfo = (SIP_DISPATCH_INFO*) new(BYTE[sizeof(SIP_DISPATCH_INFO)])))
|
|
{
|
|
delete[] (*ppSubjectInfo);
|
|
return FALSE;
|
|
}
|
|
|
|
memset((void*)*ppSubjectInfo, 0, sizeof(SIP_SUBJECTINFO));
|
|
memset((void*)*ppDispatchInfo, 0, sizeof(SIP_DISPATCH_INFO));
|
|
memset((void*)pgSubject, 0, sizeof(GUID));
|
|
|
|
// Get the type of SIP
|
|
if (!CryptSIPRetrieveSubjectGuid(
|
|
pwsFileName,
|
|
NULL,
|
|
pgSubject))
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
(*ppDispatchInfo)->cbSize = sizeof(SIP_DISPATCH_INFO);
|
|
|
|
// Load the SIP
|
|
if (!CryptSIPLoad(
|
|
pgSubject,
|
|
0,
|
|
*ppDispatchInfo))
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
// Fill in the SIP_SUBJECTINFO struct
|
|
(*ppSubjectInfo)->cbSize = sizeof(SIP_SUBJECTINFO);
|
|
(*ppSubjectInfo)->pgSubjectType = pgSubject;
|
|
(*ppSubjectInfo)->pwsFileName = pwsFileName;
|
|
|
|
goto CommonReturn;
|
|
|
|
ErrorReturn:
|
|
delete[](*ppSubjectInfo);
|
|
delete[](*ppDispatchInfo);
|
|
return FALSE;
|
|
|
|
CommonReturn:
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ReadMsgBlob(const WCHAR* pwsFileName,
|
|
CRYPT_DATA_BLOB* pData)
|
|
{
|
|
if ((pwsFileName == NULL) ||
|
|
(pData == NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
SIP_SUBJECTINFO* pSubjectInfo = NULL;
|
|
SIP_DISPATCH_INFO* pDispatchInfo = NULL;
|
|
GUID gSubject;
|
|
|
|
memset((void*)&gSubject, 0, sizeof(gSubject));
|
|
|
|
// Get the SIP
|
|
if (!OpenSIP(
|
|
pwsFileName,
|
|
&pSubjectInfo,
|
|
&pDispatchInfo,
|
|
&gSubject))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Load the message blob
|
|
DWORD dwEncodingType = 0;
|
|
pData->cbData = 0;
|
|
|
|
if (!pDispatchInfo->pfGet(
|
|
pSubjectInfo,
|
|
&dwEncodingType,
|
|
0,
|
|
&(pData->cbData),
|
|
NULL))
|
|
{
|
|
delete[](pSubjectInfo);
|
|
delete[](pDispatchInfo);
|
|
return FALSE;
|
|
}
|
|
|
|
pData->pbData = (BYTE*)new(BYTE[pData->cbData]);
|
|
if (pData->pbData == NULL)
|
|
return FALSE;
|
|
|
|
memset((void*)pData->pbData, 0, pData->cbData);
|
|
|
|
if (!pDispatchInfo->pfGet(
|
|
pSubjectInfo,
|
|
&dwEncodingType,
|
|
0,
|
|
&(pData->cbData),
|
|
pData->pbData))
|
|
{
|
|
delete[](pData->pbData);
|
|
delete[](pSubjectInfo);
|
|
delete[](pDispatchInfo);
|
|
return FALSE;
|
|
}
|
|
|
|
delete[](pSubjectInfo);
|
|
delete[](pDispatchInfo);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CheckForTimeStamp(WCHAR *pwszFile)
|
|
{
|
|
BOOL fRet = TRUE;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
HCRYPTMSG hMsg = NULL;
|
|
BYTE *pb = NULL;
|
|
DWORD cb = 0;
|
|
DWORD cbRead = 0;
|
|
PCMSG_ATTR pMsgAttr = NULL;
|
|
DWORD cbMsgAttr = 0;
|
|
CRYPT_ATTRIBUTE *pAttr = NULL;
|
|
CRYPT_DATA_BLOB blob;
|
|
DWORD dwEncodingType;
|
|
|
|
if (!ReadMsgBlob(pwszFile, &blob))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If the encoded message was passed in the use CryptMsg to crack the encoded PKCS7 Signed Message
|
|
//
|
|
if (!(hMsg = CryptMsgOpenToDecode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL)))
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!CryptMsgUpdate(hMsg,
|
|
blob.pbData,
|
|
blob.cbData,
|
|
TRUE)) // fFinal
|
|
{
|
|
CryptMsgClose(hMsg);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// get the unauthenticated attributes because that is where the counter signer is
|
|
//
|
|
CryptMsgGetParam(hMsg,
|
|
CMSG_SIGNER_UNAUTH_ATTR_PARAM,
|
|
0,
|
|
NULL,
|
|
&cbMsgAttr);
|
|
|
|
if (cbMsgAttr == 0)
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (NULL == (pMsgAttr = (CMSG_ATTR *) new(BYTE[cbMsgAttr])))
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!CryptMsgGetParam(hMsg,
|
|
CMSG_SIGNER_UNAUTH_ATTR_PARAM,
|
|
0,
|
|
(void *) pMsgAttr,
|
|
&cbMsgAttr))
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// search for the counter signer in the unauthenticated attributes
|
|
//
|
|
if ((pAttr = CertFindAttribute(szOID_RSA_counterSign,
|
|
pMsgAttr->cAttr,
|
|
pMsgAttr->rgAttr)) == NULL)
|
|
{
|
|
//
|
|
// no counter signature
|
|
//
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
|
|
Cleanup:
|
|
|
|
delete[](blob.pbData);
|
|
|
|
if (pMsgAttr)
|
|
delete[](pMsgAttr);
|
|
|
|
if (hMsg != NULL)
|
|
CryptMsgClose(hMsg);
|
|
|
|
return fRet;
|
|
|
|
ErrorReturn:
|
|
fRet = FALSE;
|
|
goto Cleanup;
|
|
|
|
|
|
}
|
|
|
|
int _ShowError(DWORD dwError, WCHAR *pwszFile)
|
|
{
|
|
pPrint->Display(IDS_FILEREF, pwszFile);
|
|
|
|
if (fCheckExpectedError)
|
|
{
|
|
if (dwError == dwExpectedError)
|
|
{
|
|
pPrint->Display(IDS_SUCCEEDED);
|
|
return(0);
|
|
}
|
|
else
|
|
{
|
|
pPrint->Display(IDS_EXPECTED_HRESULT, dwExpectedError, dwError);
|
|
return(1);
|
|
}
|
|
}
|
|
|
|
switch(dwError)
|
|
{
|
|
case S_OK:
|
|
pPrint->Display(IDS_SUCCEEDED);
|
|
if (fNoTimeStampWarning)
|
|
{
|
|
if (!CheckForTimeStamp(pwszFile))
|
|
{
|
|
pPrint->Display(IDS_NO_TIMESTAMP_WARNING);
|
|
return(2);
|
|
}
|
|
}
|
|
return(0);
|
|
|
|
case TRUST_E_SUBJECT_FORM_UNKNOWN:
|
|
pPrint->Display(IDS_UNKNOWN_FILE_TYPE);
|
|
break;
|
|
|
|
case TRUST_E_PROVIDER_UNKNOWN:
|
|
pPrint->Display(IDS_UNKNOWN_PROVIDER);
|
|
break;
|
|
|
|
case TRUST_E_ACTION_UNKNOWN:
|
|
pPrint->Display(IDS_UNKNOWN_ACTION);
|
|
break;
|
|
|
|
case TRUST_E_SUBJECT_NOT_TRUSTED:
|
|
pPrint->Display(IDS_SUBJECT_NOT_TRUSTED);
|
|
break;
|
|
|
|
default:
|
|
pPrint->Display(IDS_FAIL, GetLastError());
|
|
|
|
break;
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
HRESULT _AddCatalogToDatabase(WCHAR *pwszFileIn)
|
|
{
|
|
HCATINFO hCatInfo;
|
|
WCHAR *pwszBaseName;
|
|
|
|
if (!(hCatAdmin))
|
|
{
|
|
if (!(CryptCATAdminAcquireContext(&hCatAdmin, pguidCatRoot, 0)))
|
|
{
|
|
return(GetLastError());
|
|
}
|
|
}
|
|
|
|
//
|
|
// set the base file name
|
|
//
|
|
if (!(pwszBaseName = wcsrchr(pwszFileIn, L'\\')))
|
|
{
|
|
pwszBaseName = wcsrchr(pwszFileIn, L':');
|
|
}
|
|
|
|
if (pwszBaseName)
|
|
{
|
|
*pwszBaseName++;
|
|
}
|
|
else
|
|
{
|
|
pwszBaseName = pwszFileIn;
|
|
}
|
|
|
|
if (hCatInfo = CryptCATAdminAddCatalog(hCatAdmin, pwszFileIn, fReplaceCatfile ? pwszBaseName : NULL, 0))
|
|
{
|
|
CryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfo, 0);
|
|
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
|
|
return(GetLastError());
|
|
}
|
|
|
|
HRESULT _DelCatalogFromDatabase(WCHAR *pwszFileIn)
|
|
{
|
|
HCATINFO hCatInfo;
|
|
WCHAR *pwszBaseName;
|
|
|
|
typedef BOOL (WINAPI * PCRYPTCATADMINREMOVECATALOG)(HCATADMIN, WCHAR *, DWORD);
|
|
|
|
HRESULT hr = S_OK;
|
|
HMODULE hDLL = NULL;
|
|
PCRYPTCATADMINREMOVECATALOG pCryptCATAdminRemoveCatalog = NULL;
|
|
|
|
if (!(hCatAdmin))
|
|
{
|
|
if (!(CryptCATAdminAcquireContext(&hCatAdmin, pguidCatRoot, 0)))
|
|
{
|
|
return(GetLastError());
|
|
}
|
|
}
|
|
|
|
//
|
|
// set the base file name
|
|
//
|
|
if (!(pwszBaseName = wcsrchr(pwszFileIn, L'\\')))
|
|
{
|
|
pwszBaseName = wcsrchr(pwszFileIn, L':');
|
|
}
|
|
|
|
if (pwszBaseName)
|
|
{
|
|
*pwszBaseName++;
|
|
}
|
|
else
|
|
{
|
|
pwszBaseName = pwszFileIn;
|
|
}
|
|
|
|
if (hDLL = LoadLibraryA("wintrust.dll"))
|
|
{
|
|
if (pCryptCATAdminRemoveCatalog = (PCRYPTCATADMINREMOVECATALOG)
|
|
GetProcAddress(hDLL,
|
|
"CryptCATAdminRemoveCatalog"))
|
|
{
|
|
if (!pCryptCATAdminRemoveCatalog(hCatAdmin, pwszBaseName, 0))
|
|
{
|
|
hr = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
FreeLibrary(hDLL);
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
void _ToLower(WCHAR *pwszInOut)
|
|
{
|
|
while (*pwszInOut)
|
|
{
|
|
*pwszInOut = towlower(*pwszInOut);
|
|
pwszInOut++;
|
|
}
|
|
}
|
|
|