//+------------------------------------------------------------------------- // // 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); }