958 lines
29 KiB
C++
958 lines
29 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
||
|
//
|
||
|
// File: winvtrst.cpp
|
||
|
//
|
||
|
// Contents: Microsoft Internet Security Trust Provider
|
||
|
//
|
||
|
// Functions: WinVerifyTrustEx
|
||
|
// WinVerifyTrust
|
||
|
// WTHelperGetFileHash
|
||
|
//
|
||
|
// *** local functions ***
|
||
|
// _VerifyTrust
|
||
|
// _FillProviderData
|
||
|
// _CleanupProviderData
|
||
|
// _CleanupProviderNonStateData
|
||
|
// _WVTSipFreeSubjectInfo
|
||
|
// _WVTSipFreeSubjectInfoKeepState
|
||
|
// _WVTSetupProviderData
|
||
|
//
|
||
|
// History: 31-May-1997 pberkman created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
#include "global.hxx"
|
||
|
|
||
|
#include "wvtver1.h"
|
||
|
#include "softpub.h"
|
||
|
#include "imagehlp.h"
|
||
|
|
||
|
LONG _VerifyTrust(
|
||
|
IN HWND hWnd,
|
||
|
IN GUID *pgActionID,
|
||
|
IN OUT PWINTRUST_DATA pWinTrustData,
|
||
|
OUT OPTIONAL BYTE *pbSubjectHash,
|
||
|
IN OPTIONAL OUT DWORD *pcbSubjectHash,
|
||
|
OUT OPTIONAL ALG_ID *pHashAlgid
|
||
|
);
|
||
|
|
||
|
BOOL _FillProviderData(CRYPT_PROVIDER_DATA *pProvData, HWND hWnd, WINTRUST_DATA *pWinTrustData);
|
||
|
void _CleanupProviderData(CRYPT_PROVIDER_DATA *pProvData);
|
||
|
void _CleanupProviderNonStateData(CRYPT_PROVIDER_DATA *ProvData);
|
||
|
|
||
|
BOOL _WVTSipFreeSubjectInfo(SIP_SUBJECTINFO *pSubj);
|
||
|
BOOL _WVTSetupProviderData(CRYPT_PROVIDER_DATA *psProvData,
|
||
|
CRYPT_PROVIDER_DATA *psStateProvData);
|
||
|
BOOL _WVTSipFreeSubjectInfoKeepState(SIP_SUBJECTINFO *pSubj);
|
||
|
|
||
|
|
||
|
VOID FreeWintrustStateData (WINTRUST_DATA* pWintrustData);
|
||
|
|
||
|
extern CCatalogCache g_CatalogCache;
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// WinVerifyTrustEx
|
||
|
//
|
||
|
//
|
||
|
extern "C" HRESULT WINAPI WinVerifyTrustEx(HWND hWnd, GUID *pgActionID, WINTRUST_DATA *pWinTrustData)
|
||
|
{
|
||
|
return((HRESULT)WinVerifyTrust(hWnd, pgActionID, pWinTrustData));
|
||
|
}
|
||
|
|
||
|
#define PE_EXE_HEADER_TAG "MZ"
|
||
|
#define PE_EXE_HEADER_TAG_LEN 2
|
||
|
|
||
|
BOOL _IsUnsignedPEFile(
|
||
|
PWINTRUST_FILE_INFO pFileInfo
|
||
|
)
|
||
|
{
|
||
|
BOOL fIsUnsignedPEFile = FALSE;
|
||
|
HANDLE hFile = NULL;
|
||
|
BOOL fCloseFile = FALSE;
|
||
|
BYTE rgbHeader[PE_EXE_HEADER_TAG_LEN];
|
||
|
DWORD dwBytesRead;
|
||
|
DWORD dwCertCnt;
|
||
|
|
||
|
|
||
|
hFile = pFileInfo->hFile;
|
||
|
if (NULL == hFile || INVALID_HANDLE_VALUE == hFile) {
|
||
|
hFile = CreateFileU(
|
||
|
pFileInfo->pcwszFilePath,
|
||
|
GENERIC_READ,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL, // lpsa
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL // hTemplateFile
|
||
|
);
|
||
|
if (INVALID_HANDLE_VALUE == hFile)
|
||
|
goto CreateFileError;
|
||
|
fCloseFile = TRUE;
|
||
|
}
|
||
|
|
||
|
if (0 != SetFilePointer(
|
||
|
hFile,
|
||
|
0, // lDistanceToMove
|
||
|
NULL, // lpDistanceToMoveHigh
|
||
|
FILE_BEGIN
|
||
|
))
|
||
|
goto SetFilePointerError;
|
||
|
|
||
|
dwBytesRead = 0;
|
||
|
if (!ReadFile(
|
||
|
hFile,
|
||
|
rgbHeader,
|
||
|
PE_EXE_HEADER_TAG_LEN,
|
||
|
&dwBytesRead,
|
||
|
NULL // lpOverlapped
|
||
|
) || PE_EXE_HEADER_TAG_LEN != dwBytesRead)
|
||
|
goto ReadFileError;
|
||
|
|
||
|
if (0 != memcmp(rgbHeader, PE_EXE_HEADER_TAG, PE_EXE_HEADER_TAG_LEN))
|
||
|
goto NotPEFile;
|
||
|
|
||
|
|
||
|
// Now see if the PE file is signed
|
||
|
dwCertCnt = 0;
|
||
|
if (!ImageEnumerateCertificates(
|
||
|
hFile,
|
||
|
CERT_SECTION_TYPE_ANY,
|
||
|
&dwCertCnt,
|
||
|
NULL, // Indices
|
||
|
0 // IndexCount
|
||
|
) || 0 == dwCertCnt)
|
||
|
fIsUnsignedPEFile = TRUE;
|
||
|
|
||
|
CommonReturn:
|
||
|
if (fCloseFile)
|
||
|
CloseHandle(hFile);
|
||
|
return fIsUnsignedPEFile;
|
||
|
|
||
|
ErrorReturn:
|
||
|
goto CommonReturn;
|
||
|
|
||
|
TRACE_ERROR(CreateFileError)
|
||
|
TRACE_ERROR(SetFilePointerError)
|
||
|
TRACE_ERROR(ReadFileError)
|
||
|
TRACE_ERROR(NotPEFile)
|
||
|
}
|
||
|
|
||
|
extern "C" LONG WINAPI WinVerifyTrust(HWND hWnd, GUID *pgActionID, LPVOID pOld)
|
||
|
{
|
||
|
PWINTRUST_DATA pWinTrustData = (PWINTRUST_DATA) pOld;
|
||
|
|
||
|
// For SAFER, see if this is a unsigned PE file
|
||
|
if (_ISINSTRUCT(WINTRUST_DATA, pWinTrustData->cbStruct, dwProvFlags) &&
|
||
|
(pWinTrustData->dwProvFlags & WTD_SAFER_FLAG) &&
|
||
|
(WTD_STATEACTION_IGNORE == pWinTrustData->dwStateAction) &&
|
||
|
(WTD_CHOICE_FILE == pWinTrustData->dwUnionChoice)) {
|
||
|
if (_IsUnsignedPEFile(pWinTrustData->pFile)) {
|
||
|
SetLastError((DWORD) TRUST_E_NOSIGNATURE);
|
||
|
return (LONG) TRUST_E_NOSIGNATURE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return _VerifyTrust(
|
||
|
hWnd,
|
||
|
pgActionID,
|
||
|
pWinTrustData,
|
||
|
NULL, // pbSubjectHash
|
||
|
NULL, // pcbSubjectHash
|
||
|
NULL // pHashAlgid
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Returns S_OK and the hash if the file was signed and contains a valid
|
||
|
// hash
|
||
|
extern "C" LONG WINAPI WTHelperGetFileHash(
|
||
|
IN LPCWSTR pwszFilename,
|
||
|
IN DWORD dwFlags,
|
||
|
IN OUT OPTIONAL PVOID *pvReserved,
|
||
|
OUT OPTIONAL BYTE *pbFileHash,
|
||
|
IN OUT OPTIONAL DWORD *pcbFileHash,
|
||
|
OUT OPTIONAL ALG_ID *pHashAlgid
|
||
|
)
|
||
|
{
|
||
|
GUID wvtFileActionID = WINTRUST_ACTION_GENERIC_VERIFY_V2;
|
||
|
WINTRUST_FILE_INFO wvtFileInfo;
|
||
|
WINTRUST_DATA wvtData;
|
||
|
|
||
|
//
|
||
|
// Initialize the _VerifyTrust input data structure
|
||
|
//
|
||
|
memset(&wvtData, 0, sizeof(wvtData)); // default all fields to 0
|
||
|
wvtData.cbStruct = sizeof(wvtData);
|
||
|
// wvtData.pPolicyCallbackData = // use default code signing EKU
|
||
|
// wvtData.pSIPClientData = // no data to pass to SIP
|
||
|
|
||
|
wvtData.dwUIChoice = WTD_UI_NONE;
|
||
|
|
||
|
// wvtData.fdwRevocationChecks = // do revocation checking if
|
||
|
// enabled by admin policy or
|
||
|
// IE advanced user options
|
||
|
wvtData.dwUnionChoice = WTD_CHOICE_FILE;
|
||
|
wvtData.pFile = &wvtFileInfo;
|
||
|
|
||
|
// wvtData.dwStateAction = // default verification
|
||
|
// wvtData.hWVTStateData = // not applicable for default
|
||
|
// wvtData.pwszURLReference = // not used
|
||
|
|
||
|
// Only want to get the hash
|
||
|
wvtData.dwProvFlags = WTD_HASH_ONLY_FLAG;
|
||
|
|
||
|
//
|
||
|
// Initialize the WinVerifyTrust file info data structure
|
||
|
//
|
||
|
memset(&wvtFileInfo, 0, sizeof(wvtFileInfo)); // default all fields to 0
|
||
|
wvtFileInfo.cbStruct = sizeof(wvtFileInfo);
|
||
|
wvtFileInfo.pcwszFilePath = pwszFilename;
|
||
|
// wvtFileInfo.hFile = // allow WVT to open
|
||
|
// wvtFileInfo.pgKnownSubject // allow WVT to determine
|
||
|
|
||
|
//
|
||
|
// Call _VerifyTrust
|
||
|
//
|
||
|
return _VerifyTrust(
|
||
|
NULL, // hWnd
|
||
|
&wvtFileActionID,
|
||
|
&wvtData,
|
||
|
pbFileHash,
|
||
|
pcbFileHash,
|
||
|
pHashAlgid
|
||
|
);
|
||
|
}
|
||
|
|
||
|
LONG _VerifyTrust(
|
||
|
IN HWND hWnd,
|
||
|
IN GUID *pgActionID,
|
||
|
IN OUT PWINTRUST_DATA pWinTrustData,
|
||
|
OUT OPTIONAL BYTE *pbSubjectHash,
|
||
|
IN OPTIONAL OUT DWORD *pcbSubjectHash,
|
||
|
OUT OPTIONAL ALG_ID *pHashAlgid
|
||
|
)
|
||
|
{
|
||
|
CRYPT_PROVIDER_DATA sProvData;
|
||
|
CRYPT_PROVIDER_DATA *pStateProvData;
|
||
|
HRESULT hr;
|
||
|
BOOL fVersion1;
|
||
|
BOOL fCacheableCall;
|
||
|
PCATALOG_CACHED_STATE pCachedState = NULL;
|
||
|
BOOL fVersion1WVTCalled = FALSE;
|
||
|
DWORD cbInSubjectHash;
|
||
|
DWORD dwLastError = 0;
|
||
|
|
||
|
hr = TRUST_E_PROVIDER_UNKNOWN;
|
||
|
pStateProvData = NULL;
|
||
|
|
||
|
if (pcbSubjectHash)
|
||
|
{
|
||
|
cbInSubjectHash = *pcbSubjectHash;
|
||
|
*pcbSubjectHash = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cbInSubjectHash = 0;
|
||
|
}
|
||
|
|
||
|
if (pHashAlgid)
|
||
|
*pHashAlgid = 0;
|
||
|
|
||
|
fCacheableCall = g_CatalogCache.IsCacheableWintrustCall( pWinTrustData );
|
||
|
|
||
|
if ( fCacheableCall == TRUE )
|
||
|
{
|
||
|
g_CatalogCache.LockCache();
|
||
|
|
||
|
if ( pWinTrustData->dwStateAction == WTD_STATEACTION_AUTO_CACHE_FLUSH )
|
||
|
{
|
||
|
g_CatalogCache.FlushCache();
|
||
|
g_CatalogCache.UnlockCache();
|
||
|
|
||
|
return( ERROR_SUCCESS );
|
||
|
}
|
||
|
|
||
|
pCachedState = g_CatalogCache.FindCachedState( pWinTrustData );
|
||
|
|
||
|
g_CatalogCache.AdjustWintrustDataToCachedState(
|
||
|
pWinTrustData,
|
||
|
pCachedState,
|
||
|
FALSE
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (WintrustIsVersion1ActionID(pgActionID))
|
||
|
{
|
||
|
fVersion1 = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fVersion1 = FALSE;
|
||
|
|
||
|
if (_ISINSTRUCT(WINTRUST_DATA, pWinTrustData->cbStruct, hWVTStateData))
|
||
|
{
|
||
|
if ((pWinTrustData->dwStateAction == WTD_STATEACTION_VERIFY) ||
|
||
|
(pWinTrustData->dwStateAction == WTD_STATEACTION_CLOSE))
|
||
|
{
|
||
|
pStateProvData = WTHelperProvDataFromStateData(pWinTrustData->hWVTStateData);
|
||
|
|
||
|
if (pWinTrustData->dwStateAction == WTD_STATEACTION_CLOSE)
|
||
|
{
|
||
|
if (pWinTrustData->hWVTStateData)
|
||
|
{
|
||
|
_CleanupProviderData(pStateProvData);
|
||
|
DELETE_OBJECT(pWinTrustData->hWVTStateData);
|
||
|
}
|
||
|
|
||
|
assert( fCacheableCall == FALSE );
|
||
|
|
||
|
return(ERROR_SUCCESS);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (_WVTSetupProviderData(&sProvData, pStateProvData))
|
||
|
{
|
||
|
sProvData.pgActionID = pgActionID;
|
||
|
|
||
|
|
||
|
if (!(pStateProvData))
|
||
|
{
|
||
|
if (!(WintrustLoadFunctionPointers(pgActionID, sProvData.psPfns)))
|
||
|
{
|
||
|
//
|
||
|
// it may be that we are looking for a version 1 trust provider.
|
||
|
//
|
||
|
hr = Version1_WinVerifyTrust(hWnd, pgActionID, pWinTrustData);
|
||
|
fVersion1WVTCalled = TRUE;
|
||
|
}
|
||
|
|
||
|
if ( fVersion1WVTCalled == FALSE )
|
||
|
{
|
||
|
if (fVersion1)
|
||
|
{
|
||
|
//
|
||
|
// backwards compatibility with IE3.x and previous
|
||
|
//
|
||
|
WINTRUST_DATA sWinTrustData;
|
||
|
WINTRUST_FILE_INFO sWinTrustFileInfo;
|
||
|
|
||
|
pWinTrustData = ConvertDataFromVersion1(hWnd, pgActionID, &sWinTrustData, &sWinTrustFileInfo,
|
||
|
pWinTrustData);
|
||
|
}
|
||
|
|
||
|
if (!_FillProviderData(&sProvData, hWnd, pWinTrustData))
|
||
|
{
|
||
|
hr = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
goto ErrorCase;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// On July 27, 2000 removed support for the IE4 way of chain building.
|
||
|
sProvData.dwProvFlags |= CPD_USE_NT5_CHAIN_FLAG;
|
||
|
|
||
|
if ( fVersion1WVTCalled == FALSE )
|
||
|
{
|
||
|
if (sProvData.psPfns->pfnInitialize)
|
||
|
{
|
||
|
(*sProvData.psPfns->pfnInitialize)(&sProvData);
|
||
|
}
|
||
|
|
||
|
if (sProvData.psPfns->pfnObjectTrust)
|
||
|
{
|
||
|
(*sProvData.psPfns->pfnObjectTrust)(&sProvData);
|
||
|
}
|
||
|
|
||
|
if (sProvData.psPfns->pfnSignatureTrust)
|
||
|
{
|
||
|
(*sProvData.psPfns->pfnSignatureTrust)(&sProvData);
|
||
|
}
|
||
|
|
||
|
if (sProvData.psPfns->pfnCertificateTrust)
|
||
|
{
|
||
|
(*sProvData.psPfns->pfnCertificateTrust)(&sProvData);
|
||
|
}
|
||
|
|
||
|
if (sProvData.psPfns->pfnFinalPolicy)
|
||
|
{
|
||
|
hr = (*sProvData.psPfns->pfnFinalPolicy)(&sProvData);
|
||
|
}
|
||
|
|
||
|
if (sProvData.psPfns->pfnTestFinalPolicy)
|
||
|
{
|
||
|
(*sProvData.psPfns->pfnTestFinalPolicy)(&sProvData);
|
||
|
}
|
||
|
|
||
|
if (sProvData.psPfns->pfnCleanupPolicy)
|
||
|
{
|
||
|
(*sProvData.psPfns->pfnCleanupPolicy)(&sProvData);
|
||
|
}
|
||
|
|
||
|
dwLastError = sProvData.dwFinalError;
|
||
|
if (0 == dwLastError)
|
||
|
{
|
||
|
dwLastError = (DWORD) hr;
|
||
|
}
|
||
|
|
||
|
if (pcbSubjectHash && hr != TRUST_E_NOSIGNATURE)
|
||
|
{
|
||
|
// Return the subject's hash
|
||
|
|
||
|
DWORD cbHash;
|
||
|
if (sProvData.pPDSip && sProvData.pPDSip->psIndirectData)
|
||
|
{
|
||
|
cbHash = sProvData.pPDSip->psIndirectData->Digest.cbData;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
cbHash = 0;
|
||
|
}
|
||
|
|
||
|
if (cbHash > 0)
|
||
|
{
|
||
|
*pcbSubjectHash = cbHash;
|
||
|
if (pbSubjectHash)
|
||
|
{
|
||
|
if (cbInSubjectHash >= cbHash)
|
||
|
{
|
||
|
memcpy(pbSubjectHash,
|
||
|
sProvData.pPDSip->psIndirectData->Digest.pbData,
|
||
|
cbHash);
|
||
|
}
|
||
|
else if (S_OK == hr)
|
||
|
{
|
||
|
hr = ERROR_MORE_DATA;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pHashAlgid)
|
||
|
{
|
||
|
*pHashAlgid = CertOIDToAlgId(
|
||
|
sProvData.pPDSip->psIndirectData->DigestAlgorithm.pszObjId);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!(pStateProvData))
|
||
|
{
|
||
|
//
|
||
|
// no previous state saved
|
||
|
//
|
||
|
if ((_ISINSTRUCT(WINTRUST_DATA, pWinTrustData->cbStruct, hWVTStateData)) &&
|
||
|
(pWinTrustData->dwStateAction == WTD_STATEACTION_VERIFY))
|
||
|
{
|
||
|
//
|
||
|
// first time call and asking to maintain state...
|
||
|
//
|
||
|
if (!(pWinTrustData->hWVTStateData = (HANDLE)WVTNew(sizeof(CRYPT_PROVIDER_DATA))))
|
||
|
{
|
||
|
_CleanupProviderData(&sProvData);
|
||
|
hr = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_CleanupProviderNonStateData(&sProvData);
|
||
|
|
||
|
memcpy(pWinTrustData->hWVTStateData, &sProvData, sizeof(CRYPT_PROVIDER_DATA));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_CleanupProviderData(&sProvData);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// only free up memory specific to this object/member
|
||
|
//
|
||
|
_CleanupProviderNonStateData(&sProvData);
|
||
|
memcpy(pWinTrustData->hWVTStateData, &sProvData, sizeof(CRYPT_PROVIDER_DATA));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// in version 1, when called by IE3.x and earlier, if security level is HIGH,
|
||
|
// then the no bad UI is set. If we had an error, we want to
|
||
|
// set the error to TRUST_E_FAIL. If we do not trust the object, every other
|
||
|
// case sets it to TRUST_E_SUBJECT_NOT_TRUSTED and IE throws NO UI....
|
||
|
//
|
||
|
if (fVersion1)
|
||
|
{
|
||
|
if (hr != ERROR_SUCCESS)
|
||
|
{
|
||
|
if ((pWinTrustData) &&
|
||
|
(_ISINSTRUCT(WINTRUST_DATA, pWinTrustData->cbStruct, dwUIChoice)))
|
||
|
{
|
||
|
if (pWinTrustData->dwUIChoice == WTD_UI_NOBAD)
|
||
|
{
|
||
|
hr = TRUST_E_FAIL; // ie throws UI.
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = TRUST_E_SUBJECT_NOT_TRUSTED; // ie throws no UI.
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = TRUST_E_SUBJECT_NOT_TRUSTED; // ie throws no UI.
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = TRUST_E_SYSTEM_ERROR;
|
||
|
}
|
||
|
|
||
|
ErrorCase:
|
||
|
|
||
|
if ( fCacheableCall == TRUE )
|
||
|
{
|
||
|
if ( pCachedState == NULL )
|
||
|
{
|
||
|
if ( g_CatalogCache.CreateCachedStateFromWintrustData(
|
||
|
pWinTrustData,
|
||
|
&pCachedState
|
||
|
) == TRUE )
|
||
|
{
|
||
|
g_CatalogCache.AddCachedState( pCachedState );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( pCachedState == NULL )
|
||
|
{
|
||
|
FreeWintrustStateData( pWinTrustData );
|
||
|
}
|
||
|
|
||
|
g_CatalogCache.AdjustWintrustDataToCachedState(
|
||
|
pWinTrustData,
|
||
|
pCachedState,
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
g_CatalogCache.ReleaseCachedState( pCachedState );
|
||
|
|
||
|
g_CatalogCache.UnlockCache();
|
||
|
}
|
||
|
|
||
|
SetLastError(dwLastError);
|
||
|
|
||
|
return (LONG) hr;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// local utility functions
|
||
|
//
|
||
|
//
|
||
|
BOOL _FillProviderData(CRYPT_PROVIDER_DATA *pProvData, HWND hWnd, WINTRUST_DATA *pWinTrustData)
|
||
|
{
|
||
|
BOOL fHasTrustPubFlags;
|
||
|
|
||
|
//
|
||
|
// remember: we do NOT want to return FALSE unless it is an absolutely
|
||
|
// catastrophic error! Let the Trust provider handle (eg: none!)
|
||
|
//
|
||
|
|
||
|
if (pWinTrustData && _ISINSTRUCT(WINTRUST_DATA,
|
||
|
pWinTrustData->cbStruct, dwProvFlags))
|
||
|
pProvData->dwProvFlags = pWinTrustData->dwProvFlags &
|
||
|
WTD_PROV_FLAGS_MASK;
|
||
|
|
||
|
if ((hWnd == INVALID_HANDLE_VALUE) || !(hWnd))
|
||
|
{
|
||
|
if (pWinTrustData->dwUIChoice != WTD_UI_NONE)
|
||
|
{
|
||
|
hWnd = GetDesktopWindow();
|
||
|
}
|
||
|
}
|
||
|
pProvData->hWndParent = hWnd;
|
||
|
pProvData->hProv = I_CryptGetDefaultCryptProv(0); // get the default and DONT RELEASE IT!!!!
|
||
|
pProvData->dwEncoding = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
|
||
|
pProvData->pWintrustData = pWinTrustData;
|
||
|
pProvData->dwError = ERROR_SUCCESS;
|
||
|
|
||
|
// allocate errors
|
||
|
if (!(pProvData->padwTrustStepErrors))
|
||
|
{
|
||
|
if (!(pProvData->padwTrustStepErrors = (DWORD *)WVTNew(TRUSTERROR_MAX_STEPS * sizeof(DWORD))))
|
||
|
{
|
||
|
pProvData->dwError = GetLastError();
|
||
|
//
|
||
|
// NOTE!! this is currently the only FALSE return, so the caller will
|
||
|
// assume ERROR_NOT_ENOUGH_MEMORY if FALSE is returned from this function
|
||
|
//
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
pProvData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
|
||
|
}
|
||
|
|
||
|
memset(pProvData->padwTrustStepErrors, 0x00, sizeof(DWORD) * TRUSTERROR_MAX_STEPS);
|
||
|
|
||
|
WintrustGetRegPolicyFlags(&pProvData->dwRegPolicySettings);
|
||
|
GetRegSecuritySettings(&pProvData->dwRegSecuritySettings);
|
||
|
|
||
|
fHasTrustPubFlags = I_CryptReadTrustedPublisherDWORDValueFromRegistry(
|
||
|
CERT_TRUST_PUB_AUTHENTICODE_FLAGS_VALUE_NAME,
|
||
|
&pProvData->dwTrustPubSettings
|
||
|
);
|
||
|
|
||
|
if (fHasTrustPubFlags)
|
||
|
{
|
||
|
if (pProvData->dwTrustPubSettings &
|
||
|
(CERT_TRUST_PUB_ALLOW_MACHINE_ADMIN_TRUST |
|
||
|
CERT_TRUST_PUB_ALLOW_ENTERPRISE_ADMIN_TRUST))
|
||
|
{
|
||
|
// End User trust not allowed
|
||
|
pProvData->dwRegPolicySettings =
|
||
|
WTPF_IGNOREREVOKATION |
|
||
|
WTPF_IGNOREREVOCATIONONTS |
|
||
|
WTPF_OFFLINEOK_IND |
|
||
|
WTPF_OFFLINEOK_COM |
|
||
|
WTPF_OFFLINEOKNBU_IND |
|
||
|
WTPF_OFFLINEOKNBU_COM |
|
||
|
WTPF_ALLOWONLYPERTRUST;
|
||
|
}
|
||
|
|
||
|
// Allow the safer UI to enable revocation checking
|
||
|
|
||
|
if (pProvData->dwTrustPubSettings &
|
||
|
CERT_TRUST_PUB_CHECK_PUBLISHER_REV_FLAG)
|
||
|
{
|
||
|
pProvData->dwRegPolicySettings &= ~WTPF_IGNOREREVOKATION;
|
||
|
pProvData->dwRegPolicySettings |=
|
||
|
WTPF_OFFLINEOK_IND |
|
||
|
WTPF_OFFLINEOK_COM |
|
||
|
WTPF_OFFLINEOKNBU_IND |
|
||
|
WTPF_OFFLINEOKNBU_COM;
|
||
|
}
|
||
|
|
||
|
if (pProvData->dwTrustPubSettings &
|
||
|
CERT_TRUST_PUB_CHECK_TIMESTAMP_REV_FLAG)
|
||
|
{
|
||
|
pProvData->dwRegPolicySettings &= ~WTPF_IGNOREREVOCATIONONTS;
|
||
|
pProvData->dwRegPolicySettings |=
|
||
|
WTPF_OFFLINEOK_IND |
|
||
|
WTPF_OFFLINEOK_COM |
|
||
|
WTPF_OFFLINEOKNBU_IND |
|
||
|
WTPF_OFFLINEOKNBU_COM;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if (!(pWinTrustData) ||
|
||
|
!(_ISINSTRUCT(WINTRUST_DATA, pWinTrustData->cbStruct, dwUIChoice)))
|
||
|
|
||
|
{
|
||
|
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT] = (DWORD)ERROR_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
void _CleanupProviderData(CRYPT_PROVIDER_DATA *pProvData)
|
||
|
{
|
||
|
// pProvData->hProv: we're using crypt32's default
|
||
|
|
||
|
// pProvData->pWintrustData->xxx->hFile
|
||
|
if ((pProvData->fOpenedFile) && (pProvData->pWintrustData != NULL))
|
||
|
{
|
||
|
HANDLE *phFile;
|
||
|
|
||
|
phFile = NULL;
|
||
|
|
||
|
switch (pProvData->pWintrustData->dwUnionChoice)
|
||
|
{
|
||
|
case WTD_CHOICE_FILE:
|
||
|
phFile = &pProvData->pWintrustData->pFile->hFile;
|
||
|
break;
|
||
|
|
||
|
case WTD_CHOICE_CATALOG:
|
||
|
phFile = &pProvData->pWintrustData->pCatalog->hMemberFile;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ((phFile) && (*phFile) && (*phFile != INVALID_HANDLE_VALUE))
|
||
|
{
|
||
|
CloseHandle(*phFile);
|
||
|
*phFile = INVALID_HANDLE_VALUE;
|
||
|
pProvData->fOpenedFile = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pProvData->dwSubjectChoice == CPD_CHOICE_SIP)
|
||
|
{
|
||
|
DELETE_OBJECT(pProvData->pPDSip->pSip);
|
||
|
DELETE_OBJECT(pProvData->pPDSip->pCATSip);
|
||
|
|
||
|
_WVTSipFreeSubjectInfo(pProvData->pPDSip->psSipSubjectInfo);
|
||
|
DELETE_OBJECT(pProvData->pPDSip->psSipSubjectInfo);
|
||
|
|
||
|
_WVTSipFreeSubjectInfo(pProvData->pPDSip->psSipCATSubjectInfo);
|
||
|
DELETE_OBJECT(pProvData->pPDSip->psSipCATSubjectInfo);
|
||
|
|
||
|
TrustFreeDecode(WVT_MODID_WINTRUST, (BYTE **)&pProvData->pPDSip->psIndirectData);
|
||
|
|
||
|
DELETE_OBJECT(pProvData->pPDSip);
|
||
|
}
|
||
|
|
||
|
|
||
|
if (pProvData->hMsg)
|
||
|
{
|
||
|
CryptMsgClose(pProvData->hMsg);
|
||
|
pProvData->hMsg = NULL;
|
||
|
}
|
||
|
|
||
|
// signer structure
|
||
|
for (int i = 0; i < (int)pProvData->csSigners; i++)
|
||
|
{
|
||
|
TrustFreeDecode(WVT_MODID_WINTRUST, (BYTE **)&pProvData->pasSigners[i].psSigner);
|
||
|
|
||
|
DeallocateCertChain(pProvData->pasSigners[i].csCertChain,
|
||
|
&pProvData->pasSigners[i].pasCertChain);
|
||
|
|
||
|
DELETE_OBJECT(pProvData->pasSigners[i].pasCertChain);
|
||
|
|
||
|
if (_ISINSTRUCT(CRYPT_PROVIDER_SGNR,
|
||
|
pProvData->pasSigners[i].cbStruct, pChainContext) &&
|
||
|
pProvData->pasSigners[i].pChainContext)
|
||
|
CertFreeCertificateChain(pProvData->pasSigners[i].pChainContext);
|
||
|
|
||
|
// counter signers
|
||
|
for (int i2 = 0; i2 < (int)pProvData->pasSigners[i].csCounterSigners; i2++)
|
||
|
{
|
||
|
TrustFreeDecode(WVT_MODID_WINTRUST, (BYTE **)&pProvData->pasSigners[i].pasCounterSigners[i2].psSigner);
|
||
|
|
||
|
DeallocateCertChain(pProvData->pasSigners[i].pasCounterSigners[i2].csCertChain,
|
||
|
&pProvData->pasSigners[i].pasCounterSigners[i2].pasCertChain);
|
||
|
|
||
|
DELETE_OBJECT(pProvData->pasSigners[i].pasCounterSigners[i2].pasCertChain);
|
||
|
if (_ISINSTRUCT(CRYPT_PROVIDER_SGNR,
|
||
|
pProvData->pasSigners[i].pasCounterSigners[i2].cbStruct,
|
||
|
pChainContext) &&
|
||
|
pProvData->pasSigners[i].pasCounterSigners[i2].pChainContext)
|
||
|
CertFreeCertificateChain(
|
||
|
pProvData->pasSigners[i].pasCounterSigners[i2].pChainContext);
|
||
|
}
|
||
|
|
||
|
DELETE_OBJECT(pProvData->pasSigners[i].pasCounterSigners);
|
||
|
}
|
||
|
|
||
|
DELETE_OBJECT(pProvData->pasSigners);
|
||
|
|
||
|
// MUST BE DONE LAST!!! Using the force flag!!!
|
||
|
if (pProvData->pahStores)
|
||
|
{
|
||
|
DeallocateStoreChain(pProvData->chStores, pProvData->pahStores);
|
||
|
|
||
|
DELETE_OBJECT(pProvData->pahStores);
|
||
|
}
|
||
|
|
||
|
pProvData->chStores = 0;
|
||
|
|
||
|
// pProvData->padwTrustStepErrors
|
||
|
DELETE_OBJECT(pProvData->padwTrustStepErrors);
|
||
|
|
||
|
// pProvData->pasProvPrivData
|
||
|
DELETE_OBJECT(pProvData->pasProvPrivData);
|
||
|
pProvData->csProvPrivData = 0;
|
||
|
|
||
|
// pProvData->psPfns
|
||
|
if (pProvData->psPfns)
|
||
|
{
|
||
|
if (pProvData->psPfns->psUIpfns)
|
||
|
{
|
||
|
DELETE_OBJECT(pProvData->psPfns->psUIpfns->psUIData);
|
||
|
DELETE_OBJECT(pProvData->psPfns->psUIpfns);
|
||
|
}
|
||
|
|
||
|
DELETE_OBJECT(pProvData->psPfns);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void _CleanupProviderNonStateData(CRYPT_PROVIDER_DATA *pProvData)
|
||
|
{
|
||
|
// pProvData->hProv: we're using default!
|
||
|
|
||
|
// pProvData->pWintrustData->xxx->hFile: close!
|
||
|
if ((pProvData->fOpenedFile) && (pProvData->pWintrustData != NULL))
|
||
|
{
|
||
|
HANDLE *phFile;
|
||
|
|
||
|
phFile = NULL;
|
||
|
|
||
|
switch (pProvData->pWintrustData->dwUnionChoice)
|
||
|
{
|
||
|
case WTD_CHOICE_FILE:
|
||
|
phFile = &pProvData->pWintrustData->pFile->hFile;
|
||
|
break;
|
||
|
|
||
|
case WTD_CHOICE_CATALOG:
|
||
|
phFile = &pProvData->pWintrustData->pCatalog->hMemberFile;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ((phFile) && (*phFile) && (*phFile != INVALID_HANDLE_VALUE))
|
||
|
{
|
||
|
CloseHandle(*phFile);
|
||
|
*phFile = INVALID_HANDLE_VALUE;
|
||
|
pProvData->fOpenedFile = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pProvData->dwSubjectChoice == CPD_CHOICE_SIP)
|
||
|
{
|
||
|
DELETE_OBJECT(pProvData->pPDSip->pSip);
|
||
|
|
||
|
_WVTSipFreeSubjectInfoKeepState(pProvData->pPDSip->psSipSubjectInfo);
|
||
|
|
||
|
// pProvData->pPDSip->psSipSubjectInfo: keep
|
||
|
|
||
|
// pProvData->pPDSip->pCATSip: keep
|
||
|
|
||
|
// pProvData->pPDSip->psSipCATSubjectInfo: keep
|
||
|
|
||
|
TrustFreeDecode(WVT_MODID_WINTRUST, (BYTE **)&pProvData->pPDSip->psIndirectData);
|
||
|
|
||
|
// pProvData->pPDSip: keep
|
||
|
}
|
||
|
|
||
|
|
||
|
// pProvData->hMsg: keep
|
||
|
|
||
|
// signer structure: keep
|
||
|
|
||
|
// pProvData->pahStores: keep
|
||
|
|
||
|
// pProvData->padwTrustStepErrors: keep
|
||
|
|
||
|
// pProvData->pasProvPrivData: keep
|
||
|
|
||
|
// pProvData->psPfns: keep
|
||
|
}
|
||
|
|
||
|
BOOL _WVTSipFreeSubjectInfo(SIP_SUBJECTINFO *pSubj)
|
||
|
{
|
||
|
if (!(pSubj))
|
||
|
{
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
DELETE_OBJECT(pSubj->pgSubjectType);
|
||
|
|
||
|
switch(pSubj->dwUnionChoice)
|
||
|
{
|
||
|
case MSSIP_ADDINFO_BLOB:
|
||
|
DELETE_OBJECT(pSubj->psBlob);
|
||
|
break;
|
||
|
|
||
|
case MSSIP_ADDINFO_CATMEMBER:
|
||
|
if (pSubj->psCatMember)
|
||
|
{
|
||
|
// The following APIs are in DELAYLOAD'ed mscat32.dll. If the
|
||
|
// DELAYLOAD fails an exception is raised.
|
||
|
__try {
|
||
|
CryptCATClose(
|
||
|
CryptCATHandleFromStore(pSubj->psCatMember->pStore));
|
||
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||
|
DWORD dwExceptionCode = GetExceptionCode();
|
||
|
}
|
||
|
|
||
|
DELETE_OBJECT(pSubj->psCatMember);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
BOOL _WVTSipFreeSubjectInfoKeepState(SIP_SUBJECTINFO *pSubj)
|
||
|
{
|
||
|
if (!(pSubj))
|
||
|
{
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
DELETE_OBJECT(pSubj->pgSubjectType);
|
||
|
|
||
|
switch(pSubj->dwUnionChoice)
|
||
|
{
|
||
|
case MSSIP_ADDINFO_BLOB:
|
||
|
DELETE_OBJECT(pSubj->psBlob);
|
||
|
break;
|
||
|
|
||
|
case MSSIP_ADDINFO_CATMEMBER:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
BOOL _WVTSetupProviderData(CRYPT_PROVIDER_DATA *psProvData, CRYPT_PROVIDER_DATA *psState)
|
||
|
{
|
||
|
if (psState)
|
||
|
{
|
||
|
memcpy(psProvData, psState, sizeof(CRYPT_PROVIDER_DATA));
|
||
|
|
||
|
if (_ISINSTRUCT(CRYPT_PROVIDER_DATA, psProvData->cbStruct, fRecallWithState))
|
||
|
{
|
||
|
psProvData->fRecallWithState = TRUE;
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
memset(psProvData, 0x00, sizeof(CRYPT_PROVIDER_DATA));
|
||
|
|
||
|
psProvData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
|
||
|
|
||
|
if (!(psProvData->psPfns = (CRYPT_PROVIDER_FUNCTIONS *)WVTNew(sizeof(CRYPT_PROVIDER_FUNCTIONS))))
|
||
|
{
|
||
|
return(FALSE);
|
||
|
}
|
||
|
memset(psProvData->psPfns, 0x00, sizeof(CRYPT_PROVIDER_FUNCTIONS));
|
||
|
psProvData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
|
||
|
|
||
|
if (!(psProvData->psPfns->psUIpfns = (CRYPT_PROVUI_FUNCS *)WVTNew(sizeof(CRYPT_PROVUI_FUNCS))))
|
||
|
{
|
||
|
return(FALSE);
|
||
|
}
|
||
|
memset(psProvData->psPfns->psUIpfns, 0x00, sizeof(CRYPT_PROVUI_FUNCS));
|
||
|
psProvData->psPfns->psUIpfns->cbStruct = sizeof(CRYPT_PROVUI_FUNCS);
|
||
|
|
||
|
if (!(psProvData->psPfns->psUIpfns->psUIData = (CRYPT_PROVUI_DATA *)WVTNew(sizeof(CRYPT_PROVUI_DATA))))
|
||
|
{
|
||
|
return(FALSE);
|
||
|
}
|
||
|
memset(psProvData->psPfns->psUIpfns->psUIData, 0x00, sizeof(CRYPT_PROVUI_DATA));
|
||
|
psProvData->psPfns->psUIpfns->psUIData->cbStruct = sizeof(CRYPT_PROVUI_DATA);
|
||
|
|
||
|
GetSystemTimeAsFileTime(&psProvData->sftSystemTime);
|
||
|
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
VOID FreeWintrustStateData (WINTRUST_DATA* pWintrustData)
|
||
|
{
|
||
|
PCRYPT_PROVIDER_DATA pStateProvData;
|
||
|
|
||
|
pStateProvData = WTHelperProvDataFromStateData(
|
||
|
pWintrustData->hWVTStateData
|
||
|
);
|
||
|
|
||
|
if ( pStateProvData != NULL )
|
||
|
{
|
||
|
_CleanupProviderData( pStateProvData );
|
||
|
DELETE_OBJECT( pWintrustData->hWVTStateData );
|
||
|
}
|
||
|
}
|
||
|
|