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