|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: chainprv.cpp
//
// Contents: Microsoft Internet Security Generic Chain Policy Provider
//
// Functions: GenericChainRegisterServer
// GenericChainUnregisterServer
// GenericChainCertificateTrust
// GenericChainFinalProv
//
// History: 21-Feb-1998 philh created
//
//--------------------------------------------------------------------------
#include "global.hxx"
//////////////////////////////////////////////////////////////////////////////
//
// GenericChainRegisterServer
//----------------------------------------------------------------------------
// Register the GenericChain provider
//
STDAPI GenericChainRegisterServer(void) { GUID gGenericChainProv = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY; BOOL fRet; CRYPT_REGISTER_ACTIONID sRegAID;
fRet = TRUE;
memset(&sRegAID, 0x00, sizeof(CRYPT_REGISTER_ACTIONID));
sRegAID.cbStruct = sizeof(CRYPT_REGISTER_ACTIONID);
// Authenticode initialization provider
sRegAID.sInitProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); sRegAID.sInitProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME; sRegAID.sInitProvider.pwszFunctionName = SP_INIT_FUNCTION;
// Authenticode object provider
sRegAID.sObjectProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); sRegAID.sObjectProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME; sRegAID.sObjectProvider.pwszFunctionName = SP_OBJTRUST_FUNCTION;
// Authenticode signature provider
sRegAID.sSignatureProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); sRegAID.sSignatureProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME; sRegAID.sSignatureProvider.pwszFunctionName = SP_SIGTRUST_FUNCTION;
//------------------------------------------------------------------------
// Our Generic Chain certificate provider (builds the chain)
//+-----------------------------------------------------------------------
sRegAID.sCertificateProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); sRegAID.sCertificateProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME; sRegAID.sCertificateProvider.pwszFunctionName = GENERIC_CHAIN_CERTTRUST_FUNCTION;
// authenticode cert policy
sRegAID.sCertificatePolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); sRegAID.sCertificatePolicyProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME; sRegAID.sCertificatePolicyProvider.pwszFunctionName = SP_CHKCERT_FUNCTION;
//------------------------------------------------------------------------
// Our Generic Chain final provider (chain policy callback)
//+-----------------------------------------------------------------------
sRegAID.sFinalPolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); sRegAID.sFinalPolicyProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME; sRegAID.sFinalPolicyProvider.pwszFunctionName = GENERIC_CHAIN_FINALPOLICY_FUNCTION;
// Authenticode cleanup -- we don't store any data.
sRegAID.sCleanupProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY); sRegAID.sCleanupProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME; sRegAID.sCleanupProvider.pwszFunctionName = SP_CLEANUPPOLICY_FUNCTION;
fRet &= WintrustAddActionID(&gGenericChainProv, 0, &sRegAID); return((fRet) ? S_OK : S_FALSE); }
//////////////////////////////////////////////////////////////////////////////
//
// DllUnregisterServer
//----------------------------------------------------------------------------
// unregisters GenericChain provider
//
STDAPI GenericChainUnregisterServer(void) { GUID gGenericChainProv = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
WintrustRemoveActionID(&gGenericChainProv); return(S_OK); }
//////////////////////////////////////////////////////////////////////////////
//
// GenericChainCertificateTrust
//----------------------------------------------------------------------------
// Creates the chains for the signers and counter signers
//
void GenericChainWalkSigner( IN OUT PCRYPT_PROVIDER_DATA pProvData, IN OUT PCRYPT_PROVIDER_SGNR pSgnr, IN PWTD_GENERIC_CHAIN_POLICY_CREATE_INFO pChainInfo );
HRESULT WINAPI GenericChainCertificateTrust( IN OUT PCRYPT_PROVIDER_DATA pProvData ) { HRESULT hr; WTD_GENERIC_CHAIN_POLICY_DATA DefaultPolicyData; PWTD_GENERIC_CHAIN_POLICY_DATA pPolicyData;
if (_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, fRecallWithState) && pProvData->fRecallWithState == TRUE) return S_OK;
pPolicyData = (PWTD_GENERIC_CHAIN_POLICY_DATA) pProvData->pWintrustData->pPolicyCallbackData;
if (NULL == pPolicyData) { memset(&DefaultPolicyData, 0, sizeof(DefaultPolicyData)); DefaultPolicyData.cbSize = sizeof(DefaultPolicyData); pPolicyData = &DefaultPolicyData; }
if (!_ISINSTRUCT(WTD_GENERIC_CHAIN_POLICY_DATA, pPolicyData->cbSize, pvPolicyArg) || !_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, dwProvFlags) || (pProvData->dwProvFlags & WTD_USE_IE4_TRUST_FLAG)) { pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = ERROR_INVALID_PARAMETER; return S_FALSE; }
if (pProvData->csSigners < 1) { pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = TRUST_E_NOSIGNATURE; return S_FALSE; }
pProvData->dwProvFlags |= CPD_USE_NT5_CHAIN_FLAG; hr = S_OK; //
// loop through all signers
//
for (DWORD i = 0; i < pProvData->csSigners; i++) { PCRYPT_PROVIDER_SGNR pSgnr;
pSgnr = WTHelperGetProvSignerFromChain(pProvData, i, FALSE, 0); if (pSgnr->csCertChain < 1) { pSgnr->dwError = TRUST_E_NO_SIGNER_CERT; pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = TRUST_E_NO_SIGNER_CERT; hr = S_FALSE; continue; }
GenericChainWalkSigner( pProvData, pSgnr, pPolicyData->pSignerChainInfo );
//
// loop through all counter signers
//
for (DWORD j = 0; j < pSgnr->csCounterSigners; j++) { PCRYPT_PROVIDER_SGNR pCounterSgnr;
pCounterSgnr = WTHelperGetProvSignerFromChain( pProvData, i, TRUE, j); if (pCounterSgnr->csCertChain < 1) { pCounterSgnr->dwError = TRUST_E_NO_SIGNER_CERT; pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = TRUST_E_COUNTER_SIGNER; hr = S_FALSE; continue; }
GenericChainWalkSigner( pProvData, pCounterSgnr, pPolicyData->pCounterSignerChainInfo ); } }
return hr; }
HCERTSTORE GenericChainGetAdditionalStore( IN CRYPT_PROVIDER_DATA *pProvData ) { if (0 == pProvData->chStores) return NULL;
if (1 < pProvData->chStores) { HCERTSTORE hCollectionStore;
if (hCollectionStore = CertOpenStore( CERT_STORE_PROV_COLLECTION, 0, // dwEncodingType
0, // hCryptProv
0, // dwFlags
NULL // pvPara
)) { DWORD i; for (i = 0; i < pProvData->chStores; i++) CertAddStoreToCollection( hCollectionStore, pProvData->pahStores[i], CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0 // dwPriority
); } return hCollectionStore; } else return CertDuplicateStore(pProvData->pahStores[0]); }
void GenericChainWalkSigner( IN OUT PCRYPT_PROVIDER_DATA pProvData, IN OUT PCRYPT_PROVIDER_SGNR pSgnr, IN PWTD_GENERIC_CHAIN_POLICY_CREATE_INFO pChainInfo ) { DWORD dwSgnrError; WTD_GENERIC_CHAIN_POLICY_CREATE_INFO DefaultChainInfo; CERT_CHAIN_PARA ChainPara; HCERTSTORE hAdditionalStore = NULL; PCCERT_CHAIN_CONTEXT pChainContext; PCRYPT_PROVIDER_CERT pCert = NULL;
if (pChainInfo) { if (!_ISINSTRUCT(WTD_GENERIC_CHAIN_POLICY_CREATE_INFO, pChainInfo->cbSize, pvReserved)) { dwSgnrError = ERROR_INVALID_PARAMETER; goto InvalidParameter; } } else { memset(&ChainPara, 0, sizeof(ChainPara)); ChainPara.cbSize = sizeof(ChainPara);
memset(&DefaultChainInfo, 0, sizeof(DefaultChainInfo)); DefaultChainInfo.cbSize = sizeof(DefaultChainInfo); DefaultChainInfo.pChainPara = &ChainPara; pChainInfo = &DefaultChainInfo; }
hAdditionalStore = GenericChainGetAdditionalStore(pProvData); pCert = WTHelperGetProvCertFromChain(pSgnr, 0); if (pCert == NULL) { // Not really sure what error to put here
pProvData->dwError = E_UNEXPECTED; dwSgnrError = E_UNEXPECTED; goto ErrorReturn; }
if (!CertGetCertificateChain ( pChainInfo->hChainEngine, pCert->pCert, &pSgnr->sftVerifyAsOf, hAdditionalStore, pChainInfo->pChainPara, pChainInfo->dwFlags, pChainInfo->pvReserved, &pChainContext )) { pProvData->dwError = GetLastError(); dwSgnrError = TRUST_E_SYSTEM_ERROR; goto GetChainError; }
pSgnr->pChainContext = pChainContext;
CommonReturn: if (hAdditionalStore) CertCloseStore(hAdditionalStore, 0); return;
ErrorReturn: pSgnr->dwError = dwSgnrError; pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = dwSgnrError; goto CommonReturn; TRACE_ERROR_EX(DBG_SS, InvalidParameter) TRACE_ERROR_EX(DBG_SS, GetChainError) }
//////////////////////////////////////////////////////////////////////////////
//
// Final Policy Provider function: GenericChainFinalProv
//----------------------------------------------------------------------------
// Check the outcome of the previous functions and display UI based on this.
//
DWORD GenericChainGetErrorBasedOnStepErrors( IN PCRYPT_PROVIDER_DATA pProvData );
HRESULT WINAPI GenericChainDefaultPolicyCallback( IN PCRYPT_PROVIDER_DATA pProvData, IN DWORD dwStepError, IN DWORD dwRegPolicySettings, IN DWORD cSigner, IN PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO *rgpSigner, IN void *pvPolicyArg );
HRESULT WINAPI GenericChainFinalProv( IN OUT PCRYPT_PROVIDER_DATA pProvData ) { HRESULT hr;
WTD_GENERIC_CHAIN_POLICY_DATA DefaultPolicyData; PWTD_GENERIC_CHAIN_POLICY_DATA pPolicyData; DWORD dwStepError; DWORD cSigner = 0; DWORD i; PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO *ppSignerInfo = NULL; PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO pSignerInfo; // not allocated
PFN_WTD_GENERIC_CHAIN_POLICY_CALLBACK pfnPolicyCallback;
pPolicyData = (PWTD_GENERIC_CHAIN_POLICY_DATA) pProvData->pWintrustData->pPolicyCallbackData; if (NULL == pPolicyData) { memset(&DefaultPolicyData, 0, sizeof(DefaultPolicyData)); DefaultPolicyData.cbSize = sizeof(DefaultPolicyData); pPolicyData = &DefaultPolicyData; }
if (!_ISINSTRUCT(WTD_GENERIC_CHAIN_POLICY_DATA, pPolicyData->cbSize, pvPolicyArg) || !_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, dwFinalError) || (pProvData->dwProvFlags & WTD_USE_IE4_TRUST_FLAG) || 0 == (pProvData->dwProvFlags & CPD_USE_NT5_CHAIN_FLAG)) goto InvalidParameter;
dwStepError = GenericChainGetErrorBasedOnStepErrors(pProvData);
cSigner = pProvData->csSigners; if (0 == cSigner) goto NoSignature;
if (NULL == (ppSignerInfo = (PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO *) malloc( sizeof(PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO) * cSigner + sizeof(WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO) * cSigner))) goto OutOfMemory; memset(ppSignerInfo, 0, sizeof(PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO) * cSigner + sizeof(WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO) * cSigner);
//
// Update allocated info for each signer
//
pSignerInfo = (PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO) &ppSignerInfo[cSigner]; i = 0; for ( ; i < cSigner; i++, pSignerInfo++) { CRYPT_PROVIDER_SGNR *pSgnr; DWORD cCounterSigner;
ppSignerInfo[i] = pSignerInfo; pSignerInfo->cbSize = sizeof(WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO);
pSgnr = WTHelperGetProvSignerFromChain(pProvData, i, FALSE, 0); pSignerInfo->pChainContext = pSgnr->pChainContext; pSignerInfo->dwSignerType = pSgnr->dwSignerType; pSignerInfo->pMsgSignerInfo = pSgnr->psSigner; pSignerInfo->dwError = pSgnr->dwError;
cCounterSigner = pSgnr->csCounterSigners; if (cCounterSigner) { DWORD j; PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO *ppCounterSignerInfo; PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO pCounterSignerInfo;
if (NULL == (ppCounterSignerInfo = (PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO *) malloc( sizeof(PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO) * cCounterSigner + sizeof(WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO) * cCounterSigner))) goto OutOfMemory; memset(ppCounterSignerInfo, 0, sizeof(PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO) * cCounterSigner + sizeof(WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO) * cCounterSigner); pSignerInfo->cCounterSigner = cCounterSigner; pSignerInfo->rgpCounterSigner = ppCounterSignerInfo;
//
// Update allocated info for each counter signer
//
pCounterSignerInfo = (PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO) &ppCounterSignerInfo[cCounterSigner]; j = 0; for ( ; j < cCounterSigner; j++, pCounterSignerInfo++) { PCRYPT_PROVIDER_SGNR pCounterSgnr;
ppCounterSignerInfo[j] = pCounterSignerInfo; pCounterSignerInfo->cbSize = sizeof(WTD_GENERIC_CHAIN_POLICY_SIGNER_INFO);
pCounterSgnr = WTHelperGetProvSignerFromChain(pProvData, i, TRUE, j); pCounterSignerInfo->pChainContext = pCounterSgnr->pChainContext; pCounterSignerInfo->dwSignerType = pCounterSgnr->dwSignerType; pCounterSignerInfo->pMsgSignerInfo = pCounterSgnr->psSigner; pCounterSignerInfo->dwError = pCounterSgnr->dwError; } } }
if (pPolicyData->pfnPolicyCallback) pfnPolicyCallback = pPolicyData->pfnPolicyCallback; else pfnPolicyCallback = GenericChainDefaultPolicyCallback;
hr = pfnPolicyCallback( pProvData, dwStepError, pProvData->dwRegPolicySettings, cSigner, ppSignerInfo, pPolicyData->pvPolicyArg );
CommonReturn: if (ppSignerInfo) { while (cSigner--) { pSignerInfo = ppSignerInfo[cSigner]; if (pSignerInfo && pSignerInfo->rgpCounterSigner) free(pSignerInfo->rgpCounterSigner); } free(ppSignerInfo); } pProvData->dwFinalError = (DWORD) hr; return hr;
ErrorReturn: hr = (HRESULT) GetLastError(); if (S_OK == hr) hr = E_UNEXPECTED; goto CommonReturn;
SET_ERROR_EX(DBG_SS, InvalidParameter, ERROR_INVALID_PARAMETER) SET_ERROR_EX(DBG_SS, OutOfMemory, ERROR_NOT_ENOUGH_MEMORY) SET_ERROR_EX(DBG_SS, NoSignature, TRUST_E_NOSIGNATURE); }
DWORD GenericChainGetErrorBasedOnStepErrors( IN PCRYPT_PROVIDER_DATA pProvData ) { //
// initial allocation of the step errors?
//
if (NULL == pProvData->padwTrustStepErrors) return ERROR_NOT_ENOUGH_MEMORY;
// problem with file
if ((pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FILEIO] != 0) || (pProvData->padwTrustStepErrors[TRUSTERROR_STEP_CATALOGFILE] != 0)) { return(CRYPT_E_FILE_ERROR); }
//
// did we fail in one of the last steps?
//
if (pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_INITPROV] != 0) { return(pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_INITPROV]); }
if (pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] != 0) { return(pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]); }
if (pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV] != 0) { return(pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_SIGPROV]); }
if (pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] != 0) { return(pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV]); }
if (pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTCHKPROV] != 0) { return(pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTCHKPROV]); }
if (pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV] != 0) { return(pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_POLICYPROV]); }
return(ERROR_SUCCESS); }
HRESULT WINAPI GenericChainDefaultPolicyCallback( IN PCRYPT_PROVIDER_DATA pProvData, IN DWORD dwStepError, IN DWORD dwRegPolicySettings, IN DWORD cSigner, IN PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO *rgpSigner, IN void *pvPolicyArg ) { HRESULT hr; DWORD i;
AUTHENTICODE_EXTRA_CERT_CHAIN_POLICY_PARA ExtraPolicyPara; memset(&ExtraPolicyPara, 0, sizeof(ExtraPolicyPara)); ExtraPolicyPara.cbSize = sizeof(ExtraPolicyPara); ExtraPolicyPara.dwRegPolicySettings = dwRegPolicySettings;
CERT_CHAIN_POLICY_PARA PolicyPara; memset(&PolicyPara, 0, sizeof(PolicyPara)); PolicyPara.cbSize = sizeof(PolicyPara); PolicyPara.pvExtraPolicyPara = (void *) &ExtraPolicyPara;
AUTHENTICODE_EXTRA_CERT_CHAIN_POLICY_STATUS ExtraPolicyStatus; memset(&ExtraPolicyStatus, 0, sizeof(ExtraPolicyStatus)); ExtraPolicyStatus.cbSize = sizeof(ExtraPolicyStatus);
CERT_CHAIN_POLICY_STATUS PolicyStatus; memset(&PolicyStatus, 0, sizeof(PolicyStatus)); PolicyStatus.cbSize = sizeof(PolicyStatus); PolicyStatus.pvExtraPolicyStatus = (void *) &ExtraPolicyStatus;
//
// check the high level error codes.
//
if (0 != dwStepError) { hr = (HRESULT) dwStepError; goto CommonReturn; }
//
// check each signer
//
for (i = 0; i < cSigner; i++) { PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO pSigner = rgpSigner[i]; ExtraPolicyPara.pSignerInfo = pSigner->pMsgSignerInfo;
if (!CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_AUTHENTICODE, pSigner->pChainContext, &PolicyPara, &PolicyStatus )) { hr = TRUST_E_SYSTEM_ERROR; goto CommonReturn; }
if (0 != PolicyStatus.dwError) { hr = (HRESULT) PolicyStatus.dwError; goto CommonReturn; }
if (pSigner->cCounterSigner) { AUTHENTICODE_TS_EXTRA_CERT_CHAIN_POLICY_PARA TSExtraPolicyPara; memset(&TSExtraPolicyPara, 0, sizeof(TSExtraPolicyPara)); TSExtraPolicyPara.cbSize = sizeof(TSExtraPolicyPara); TSExtraPolicyPara.dwRegPolicySettings = dwRegPolicySettings; TSExtraPolicyPara.fCommercial = ExtraPolicyStatus.fCommercial;
CERT_CHAIN_POLICY_PARA TSPolicyPara; memset(&TSPolicyPara, 0, sizeof(TSPolicyPara)); TSPolicyPara.cbSize = sizeof(TSPolicyPara); TSPolicyPara.pvExtraPolicyPara = (void *) &TSExtraPolicyPara;
CERT_CHAIN_POLICY_STATUS TSPolicyStatus; memset(&TSPolicyStatus, 0, sizeof(TSPolicyStatus)); TSPolicyStatus.cbSize = sizeof(TSPolicyStatus);
//
// check counter signers
//
for (DWORD j = 0; j < pSigner->cCounterSigner; j++) { PWTD_GENERIC_CHAIN_POLICY_SIGNER_INFO pCounterSigner = pSigner->rgpCounterSigner[j];
//
// do we care about this counter signer?
//
if (pCounterSigner->dwSignerType != SGNR_TYPE_TIMESTAMP) continue;
if (!CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_AUTHENTICODE_TS, pCounterSigner->pChainContext, &TSPolicyPara, &TSPolicyStatus )) { hr = TRUST_E_SYSTEM_ERROR; goto CommonReturn; } else if (0 != TSPolicyStatus.dwError) { hr = (HRESULT) TSPolicyStatus.dwError; goto CommonReturn; } } } } hr = S_OK; CommonReturn: return hr; }
|