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.
462 lines
12 KiB
462 lines
12 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
//
|
|
// File: callui.cpp
|
|
//
|
|
// Contents: Microsoft Internet Security Authenticode Policy Provider
|
|
//
|
|
// Functions: SoftpubCallUI
|
|
//
|
|
// *** local functions ***
|
|
// _AllocGetOpusInfo
|
|
//
|
|
// History: 06-Jun-1997 pberkman created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "global.hxx"
|
|
#include "trustdb.h"
|
|
#include "acui.h"
|
|
#include "winsafer.h"
|
|
|
|
SPC_SP_OPUS_INFO *_AllocGetOpusInfo(CRYPT_PROVIDER_DATA *pProvData, CRYPT_PROVIDER_SGNR *pSigner,
|
|
DWORD *pcbOpusInfo);
|
|
|
|
|
|
|
|
#define MIN_HASH_LEN 16
|
|
#define MAX_HASH_LEN 20
|
|
|
|
// Returns:
|
|
// S_FALSE
|
|
// not found in the database
|
|
// TRUST_E_SYSTEM_ERROR
|
|
// system errors while attempting to do the check
|
|
// S_OK
|
|
// found in the database
|
|
// TRUST_E_EXPLICIT_DISTRUST
|
|
// explicitly disallowed in the database or revoked
|
|
HRESULT _CheckTrustedPublisher(
|
|
CRYPT_PROVIDER_DATA *pProvData,
|
|
DWORD dwError,
|
|
BOOL fOnlyDisallowed
|
|
)
|
|
{
|
|
CRYPT_PROVIDER_SGNR *pSigner;
|
|
PCCERT_CONTEXT pPubCert;
|
|
BYTE rgbHash[MAX_HASH_LEN];
|
|
CRYPT_DATA_BLOB HashBlob;
|
|
HCERTSTORE hStore;
|
|
|
|
if (CERT_E_REVOKED == dwError)
|
|
{
|
|
return TRUST_E_EXPLICIT_DISTRUST;
|
|
}
|
|
|
|
pSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0);
|
|
|
|
if (NULL == pSigner || pSigner->csCertChain <= 0)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
pPubCert = WTHelperGetProvCertFromChain(pSigner, 0)->pCert;
|
|
|
|
// Check if disallowed.
|
|
|
|
// Since the signature component can be altered, must use the signature
|
|
// hash
|
|
|
|
HashBlob.pbData = rgbHash;
|
|
HashBlob.cbData = MAX_HASH_LEN;
|
|
if (!CertGetCertificateContextProperty(
|
|
pPubCert,
|
|
CERT_SIGNATURE_HASH_PROP_ID,
|
|
rgbHash,
|
|
&HashBlob.cbData
|
|
) || MIN_HASH_LEN > HashBlob.cbData)
|
|
{
|
|
return TRUST_E_SYSTEM_ERROR;
|
|
}
|
|
|
|
hStore = OpenDisallowedStore();
|
|
|
|
if (hStore)
|
|
{
|
|
PCCERT_CONTEXT pFoundCert;
|
|
|
|
pFoundCert = CertFindCertificateInStore(
|
|
hStore,
|
|
0, // dwCertEncodingType
|
|
0, // dwFindFlags
|
|
CERT_FIND_SIGNATURE_HASH,
|
|
(const void *) &HashBlob,
|
|
NULL //pPrevCertContext
|
|
);
|
|
|
|
CertCloseStore(hStore, 0);
|
|
if (pFoundCert)
|
|
{
|
|
CertFreeCertificateContext(pFoundCert);
|
|
return TRUST_E_EXPLICIT_DISTRUST;
|
|
}
|
|
}
|
|
|
|
if (fOnlyDisallowed)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
if (S_OK != dwError)
|
|
{
|
|
// Everything must be valid to allow a trusted publisher
|
|
return S_FALSE;
|
|
}
|
|
|
|
// Check if trusted publisher
|
|
|
|
hStore = OpenTrustedPublisherStore();
|
|
|
|
if (hStore)
|
|
{
|
|
PCCERT_CONTEXT pFoundCert;
|
|
|
|
pFoundCert = CertFindCertificateInStore(
|
|
hStore,
|
|
0, // dwCertEncodingType
|
|
0, // dwFindFlags
|
|
CERT_FIND_SIGNATURE_HASH,
|
|
(const void *) &HashBlob,
|
|
NULL //pPrevCertContext
|
|
);
|
|
|
|
CertCloseStore(hStore, 0);
|
|
if (pFoundCert)
|
|
{
|
|
CertFreeCertificateContext(pFoundCert);
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
typedef BOOL (WINAPI *PFN_SAFERI_SEARCH_MATCHING_HASH_RULES)(
|
|
IN ALG_ID HashAlgorithm OPTIONAL,
|
|
IN PBYTE pHashBytes,
|
|
IN DWORD dwHashSize,
|
|
IN DWORD dwOriginalImageSize OPTIONAL,
|
|
OUT PDWORD pdwFoundLevel,
|
|
OUT PDWORD pdwUIFlags
|
|
);
|
|
|
|
// Returns:
|
|
// S_FALSE
|
|
// not found in the database
|
|
// S_OK
|
|
// fully trusted in the database
|
|
// TRUST_E_EXPLICIT_DISTRUST
|
|
// explicitly disallowed in the database
|
|
HRESULT _CheckTrustedCodeHash(CRYPT_PROVIDER_DATA *pProvData)
|
|
{
|
|
static BOOL fGotProcAddr = FALSE;
|
|
static PFN_SAFERI_SEARCH_MATCHING_HASH_RULES
|
|
pfnCodeAuthzSearchMatchingHashRules = NULL;
|
|
|
|
DWORD cbHash;
|
|
|
|
if (pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] == 0 &&
|
|
pProvData->pPDSip && pProvData->pPDSip->psIndirectData)
|
|
{
|
|
cbHash = pProvData->pPDSip->psIndirectData->Digest.cbData;
|
|
}
|
|
else
|
|
{
|
|
cbHash = 0;
|
|
}
|
|
|
|
if (0 == cbHash)
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
|
|
// wintrust.dll has a static dependency on advapi32.dll. However, not
|
|
// all advapi32.dll's will export "SaferiSearchMatchingHashRules"
|
|
if (!fGotProcAddr)
|
|
{
|
|
HMODULE hModule;
|
|
|
|
hModule = GetModuleHandleA("advapi32.dll");
|
|
if (NULL != hModule)
|
|
{
|
|
pfnCodeAuthzSearchMatchingHashRules =
|
|
(PFN_SAFERI_SEARCH_MATCHING_HASH_RULES) GetProcAddress(
|
|
hModule, "SaferiSearchMatchingHashRules");
|
|
}
|
|
|
|
fGotProcAddr = TRUE;
|
|
}
|
|
|
|
if (NULL != pfnCodeAuthzSearchMatchingHashRules)
|
|
{
|
|
__try
|
|
{
|
|
DWORD dwFoundLevel = 0xFFFFFFFF;
|
|
DWORD dwUIFlags = 0;
|
|
|
|
if (pfnCodeAuthzSearchMatchingHashRules(
|
|
CertOIDToAlgId(pProvData->pPDSip->psIndirectData->DigestAlgorithm.pszObjId),
|
|
pProvData->pPDSip->psIndirectData->Digest.pbData,
|
|
cbHash,
|
|
0, // dwOriginalImageSize
|
|
&dwFoundLevel,
|
|
&dwUIFlags
|
|
))
|
|
{
|
|
switch (dwFoundLevel)
|
|
{
|
|
case SAFER_LEVELID_FULLYTRUSTED:
|
|
return S_OK;
|
|
case SAFER_LEVELID_DISALLOWED:
|
|
return TRUST_E_EXPLICIT_DISTRUST;
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
}
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
HRESULT SoftpubCallUI(CRYPT_PROVIDER_DATA *pProvData, DWORD dwError, BOOL fFinalCall)
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwUIChoice;
|
|
|
|
if (!(fFinalCall))
|
|
{
|
|
// TBDTBD: if we want the user to get involved along the way???
|
|
return(ERROR_SUCCESS);
|
|
}
|
|
|
|
if (0 == (pProvData->dwProvFlags & WTD_SAFER_FLAG))
|
|
{
|
|
if (!(pProvData->dwRegPolicySettings & WTPF_ALLOWONLYPERTRUST) &&
|
|
(pProvData->pWintrustData->dwUIChoice == WTD_UI_NONE))
|
|
{
|
|
if (S_OK == dwError || ((DWORD) CERT_E_REVOKED) == dwError)
|
|
{
|
|
//
|
|
// Check for explicitly trusted or disallowed code
|
|
//
|
|
hr = _CheckTrustedCodeHash(pProvData);
|
|
if (S_FALSE != hr)
|
|
{
|
|
if (S_OK == hr)
|
|
{
|
|
// Ensure we always indicate trust.
|
|
pProvData->dwFinalError = 0;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Check for untrusted publisher
|
|
//
|
|
hr = _CheckTrustedPublisher(pProvData, dwError, TRUE);
|
|
if (TRUST_E_EXPLICIT_DISTRUST == hr)
|
|
{
|
|
return TRUST_E_EXPLICIT_DISTRUST;
|
|
}
|
|
}
|
|
|
|
return(dwError);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Check for trusted or disallowed subject hash
|
|
//
|
|
hr = _CheckTrustedCodeHash(pProvData);
|
|
if (S_FALSE != hr)
|
|
{
|
|
if (S_OK == hr)
|
|
{
|
|
// Ensure we always indicate trust.
|
|
pProvData->dwFinalError = 0;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Check for trusted or disallowed publisher
|
|
//
|
|
hr = _CheckTrustedPublisher(pProvData, dwError, FALSE);
|
|
if (S_FALSE != hr)
|
|
{
|
|
if (S_OK == hr)
|
|
{
|
|
// Ensure we always indicate trust.
|
|
pProvData->dwFinalError = 0;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
if (pProvData->dwRegPolicySettings & WTPF_ALLOWONLYPERTRUST)
|
|
{
|
|
if (0 == dwError)
|
|
{
|
|
return CRYPT_E_SECURITY_SETTINGS;
|
|
}
|
|
return dwError;
|
|
}
|
|
|
|
dwUIChoice = pProvData->pWintrustData->dwUIChoice;
|
|
|
|
if ((dwUIChoice == WTD_UI_NONE) ||
|
|
((dwUIChoice == WTD_UI_NOBAD) && (dwError != ERROR_SUCCESS)) ||
|
|
((dwUIChoice == WTD_UI_NOGOOD) && (dwError == ERROR_SUCCESS)))
|
|
{
|
|
if (0 == dwError)
|
|
{
|
|
// No explicit trust
|
|
pProvData->dwFinalError = TRUST_E_SUBJECT_NOT_TRUSTED;
|
|
}
|
|
return dwError;
|
|
}
|
|
|
|
//
|
|
// call the ui
|
|
//
|
|
HINSTANCE hModule = NULL;
|
|
IPersonalTrustDB *pTrustDB = NULL;
|
|
ACUI_INVOKE_INFO aii;
|
|
pfnACUIProviderInvokeUI pfn = NULL;
|
|
DWORD cbOpusInfo;
|
|
CRYPT_PROVIDER_SGNR *pRootSigner;
|
|
|
|
pRootSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0);
|
|
|
|
OpenTrustDB(NULL, IID_IPersonalTrustDB, (LPVOID*)&pTrustDB);
|
|
|
|
memset(&aii, 0x00, sizeof(ACUI_INVOKE_INFO));
|
|
|
|
//
|
|
// Setup the UI invokation
|
|
//
|
|
|
|
aii.cbSize = sizeof(ACUI_INVOKE_INFO);
|
|
aii.hDisplay = pProvData->hWndParent;
|
|
aii.pProvData = pProvData;
|
|
aii.hrInvokeReason = dwError;
|
|
aii.pwcsAltDisplayName = WTHelperGetFileName(pProvData->pWintrustData);
|
|
aii.pPersonalTrustDB = (IUnknown *)pTrustDB;
|
|
|
|
if (pRootSigner)
|
|
{
|
|
aii.pOpusInfo = _AllocGetOpusInfo(pProvData, pRootSigner, &cbOpusInfo);
|
|
}
|
|
|
|
//
|
|
// Load the default authenticode UI.
|
|
//
|
|
if (hModule = LoadLibraryA(CVP_DLL))
|
|
{
|
|
pfn = (pfnACUIProviderInvokeUI)GetProcAddress(hModule, "ACUIProviderInvokeUI");
|
|
}
|
|
|
|
//
|
|
// Invoke the UI
|
|
//
|
|
if (pfn)
|
|
{
|
|
hr = (*pfn)(&aii);
|
|
}
|
|
else
|
|
{
|
|
hr = TRUST_E_PROVIDER_UNKNOWN;
|
|
pProvData->dwError = hr;
|
|
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_UIPROV] = hr;
|
|
|
|
DBG_PRINTF((DBG_SS, "Unable to load CRYPTUI.DLL\n"));
|
|
|
|
}
|
|
|
|
//
|
|
// Return the appropriate code
|
|
//
|
|
|
|
if (pTrustDB)
|
|
{
|
|
pTrustDB->Release();
|
|
}
|
|
|
|
if (aii.pOpusInfo)
|
|
{
|
|
TrustFreeDecode(WVT_MODID_SOFTPUB, (BYTE **)&aii.pOpusInfo);
|
|
}
|
|
|
|
if (hModule)
|
|
{
|
|
FreeLibrary(hModule);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
SPC_SP_OPUS_INFO *_AllocGetOpusInfo(CRYPT_PROVIDER_DATA *pProvData, CRYPT_PROVIDER_SGNR *pSigner,
|
|
DWORD *pcbOpusInfo)
|
|
{
|
|
PCRYPT_ATTRIBUTE pAttr;
|
|
PSPC_SP_OPUS_INFO pInfo;
|
|
|
|
pInfo = NULL;
|
|
|
|
if (!(pSigner->psSigner))
|
|
{
|
|
goto NoSigner;
|
|
}
|
|
|
|
if (pSigner->psSigner->AuthAttrs.cAttr == 0)
|
|
{
|
|
goto NoOpusAttribute;
|
|
}
|
|
|
|
if (!(pAttr = CertFindAttribute(SPC_SP_OPUS_INFO_OBJID,
|
|
pSigner->psSigner->AuthAttrs.cAttr,
|
|
pSigner->psSigner->AuthAttrs.rgAttr)))
|
|
{
|
|
goto NoOpusAttribute;
|
|
}
|
|
|
|
if (!(pAttr->rgValue))
|
|
{
|
|
goto NoOpusAttribute;
|
|
}
|
|
|
|
if (!(TrustDecode(WVT_MODID_SOFTPUB, (BYTE **)&pInfo, pcbOpusInfo, 200,
|
|
pProvData->dwEncoding, SPC_SP_OPUS_INFO_STRUCT,
|
|
pAttr->rgValue->pbData, pAttr->rgValue->cbData, CRYPT_DECODE_NOCOPY_FLAG)))
|
|
{
|
|
goto DecodeError;
|
|
}
|
|
|
|
return(pInfo);
|
|
|
|
ErrorReturn:
|
|
return(NULL);
|
|
|
|
TRACE_ERROR_EX(DBG_SS, NoSigner);
|
|
TRACE_ERROR_EX(DBG_SS, NoOpusAttribute);
|
|
TRACE_ERROR_EX(DBG_SS, DecodeError);
|
|
}
|
|
|