windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/pkitrust/softpub/httpsprv.cpp

522 lines
17 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: httpsprv.cpp
//
// Contents: Microsoft Internet Security Authenticode Policy Provider
//
// Functions: HTTPSRegisterServer
// HTTPSUnregisterServer
// HTTPSCertificateTrust
// HTTPSFinalProv
//
// History: 29-Jul-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include <wininet.h>
DWORD GetErrorBasedOnStepErrors(CRYPT_PROVIDER_DATA *pProvData);
//////////////////////////////////////////////////////////////////////////////
//
// HTTPSRegisterServer
//----------------------------------------------------------------------------
// Register the HTTPS provider
//
STDAPI HTTPSRegisterServer(void)
{
GUID gHTTPSProv = HTTPSPROV_ACTION;
BOOL fRet;
CRYPT_REGISTER_ACTIONID sRegAID;
CRYPT_PROVIDER_REGDEFUSAGE sDefUsage;
fRet = TRUE;
//
// set the usages we want
//
memset(&sDefUsage, 0x00, sizeof(CRYPT_PROVIDER_REGDEFUSAGE));
sDefUsage.cbStruct = sizeof(CRYPT_PROVIDER_REGDEFUSAGE);
sDefUsage.pgActionID = &gHTTPSProv;
sDefUsage.pwszDllName = SP_POLICY_PROVIDER_DLL_NAME;
sDefUsage.pwszLoadCallbackDataFunctionName = "SoftpubLoadDefUsageCallData";
sDefUsage.pwszFreeCallbackDataFunctionName = "SoftpubFreeDefUsageCallData";
fRet &= WintrustAddDefaultForUsage(szOID_PKIX_KP_SERVER_AUTH, &sDefUsage);
fRet &= WintrustAddDefaultForUsage(szOID_PKIX_KP_CLIENT_AUTH, &sDefUsage);
fRet &= WintrustAddDefaultForUsage(szOID_SERVER_GATED_CRYPTO, &sDefUsage);
fRet &= WintrustAddDefaultForUsage(szOID_SGC_NETSCAPE, &sDefUsage);
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;
// wintrust's certificate provider
sRegAID.sCertificateProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
#if 0
sRegAID.sCertificateProvider.pwszDLLName = WT_PROVIDER_DLL_NAME; // set to wintrust.dll
sRegAID.sCertificateProvider.pwszFunctionName = WT_PROVIDER_CERTTRUST_FUNCTION; // use wintrust's standard!
#else
// philh changed on Feb 19, 1998 to use HTTPS
sRegAID.sCertificateProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME;
sRegAID.sCertificateProvider.pwszFunctionName = HTTPS_CERTTRUST_FUNCTION;
#endif
// 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;
// custom final ...
sRegAID.sFinalPolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
sRegAID.sFinalPolicyProvider.pwszDLLName = SP_POLICY_PROVIDER_DLL_NAME;
sRegAID.sFinalPolicyProvider.pwszFunctionName = HTTPS_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(&gHTTPSProv, 0, &sRegAID);
return((fRet) ? S_OK : S_FALSE);
}
//////////////////////////////////////////////////////////////////////////////
//
// DllUnregisterServer
//----------------------------------------------------------------------------
// unregisters schannel provider
//
STDAPI HTTPSUnregisterServer(void)
{
GUID gHTTPSProv = HTTPSPROV_ACTION;
WintrustRemoveActionID(&gHTTPSProv);
return(S_OK);
}
HCERTCHAINENGINE HTTPSGetChainEngine(
IN CRYPT_PROVIDER_DATA *pProvData
)
{
CERT_CHAIN_ENGINE_CONFIG Config;
HCERTSTORE hStore = NULL;
HCERTCHAINENGINE hChainEngine = NULL;
if (NULL == pProvData->pWintrustData ||
pProvData->pWintrustData->dwUnionChoice != WTD_CHOICE_CERT ||
!_ISINSTRUCT(WINTRUST_CERT_INFO,
pProvData->pWintrustData->pCert->cbStruct, dwFlags) ||
0 == (pProvData->pWintrustData->pCert->dwFlags &
(WTCI_DONT_OPEN_STORES | WTCI_OPEN_ONLY_ROOT)))
return NULL;
memset(&Config, 0, sizeof(Config));
Config.cbSize = sizeof(Config);
if (NULL == (hStore = CertOpenStore(
CERT_STORE_PROV_MEMORY,
0, // dwEncodingType
0, // hCryptProv
0, // dwFlags
NULL // pvPara
)))
goto OpenMemoryStoreError;
if (pProvData->pWintrustData->pCert->dwFlags & WTCI_DONT_OPEN_STORES)
Config.hRestrictedRoot = hStore;
Config.hRestrictedTrust = hStore;
Config.hRestrictedOther = hStore;
if (!CertCreateCertificateChainEngine(
&Config,
&hChainEngine
))
goto CreateChainEngineError;
CommonReturn:
CertCloseStore(hStore, 0);
return hChainEngine;
ErrorReturn:
hChainEngine = NULL;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS, OpenMemoryStoreError)
TRACE_ERROR_EX(DBG_SS, CreateChainEngineError)
}
HCERTSTORE HTTPSGetChainAdditionalStore(
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]);
}
// Following is in ..\wintrust\certtrst.cpp
extern
BOOL UpdateCertProvChain(
IN OUT PCRYPT_PROVIDER_DATA pProvData,
IN DWORD idxSigner,
OUT DWORD *pdwError,
IN BOOL fCounterSigner,
IN DWORD idxCounterSigner,
IN PCRYPT_PROVIDER_SGNR pSgnr,
IN PCCERT_CHAIN_CONTEXT pChainContext
);
// Following is in .\authcode.cpp
extern
void UpdateCertError(
IN PCRYPT_PROVIDER_SGNR pSgnr,
IN PCERT_CHAIN_POLICY_STATUS pPolicyStatus
);
HRESULT WINAPI HTTPSCertificateTrust(CRYPT_PROVIDER_DATA *pProvData)
{
HTTPSPolicyCallbackData *pHTTPS;
CRYPT_PROVIDER_SGNR *pSgnr;
CRYPT_PROVIDER_CERT *pProvCert;
DWORD dwError;
DWORD dwSgnrError;
DWORD dwCreateChainFlags;
CERT_CHAIN_PARA ChainPara;
HCERTCHAINENGINE hChainEngine = NULL;
HCERTSTORE hAdditionalStore = NULL;
PCCERT_CHAIN_CONTEXT pChainContext = NULL;
LPSTR rgpszClientUsage[] = {
szOID_PKIX_KP_CLIENT_AUTH,
};
#define CLIENT_USAGE_COUNT (sizeof(rgpszClientUsage) / \
sizeof(rgpszClientUsage[0]))
LPSTR rgpszServerUsage[] = {
szOID_PKIX_KP_SERVER_AUTH,
szOID_SERVER_GATED_CRYPTO,
szOID_SGC_NETSCAPE,
};
#define SERVER_USAGE_COUNT (sizeof(rgpszServerUsage) / \
sizeof(rgpszServerUsage[0]))
if ((_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, fRecallWithState)) &&
(pProvData->fRecallWithState == TRUE))
{
return(S_OK);
}
pSgnr = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0);
if (pSgnr)
pProvCert = WTHelperGetProvCertFromChain(pSgnr, 0);
if (NULL == pSgnr || NULL == pProvCert) {
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
TRUST_E_NOSIGNATURE;
return S_FALSE;
}
pHTTPS = (HTTPSPolicyCallbackData *) pProvData->pWintrustData->pPolicyCallbackData;
if (!pHTTPS || !WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(
HTTPSPolicyCallbackData, pHTTPS->cbStruct, pwszServerName) ||
!_ISINSTRUCT(CRYPT_PROVIDER_DATA, pProvData->cbStruct, dwProvFlags) ||
(pProvData->dwProvFlags & WTD_USE_IE4_TRUST_FLAG) ||
!_ISINSTRUCT(CRYPT_PROVIDER_SGNR, pSgnr->cbStruct, pChainContext))
{
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
ERROR_INVALID_PARAMETER;
return S_FALSE;
}
pProvData->dwProvFlags |= CPD_USE_NT5_CHAIN_FLAG;
dwCreateChainFlags = 0;
memset(&ChainPara, 0, sizeof(ChainPara));
ChainPara.cbSize = sizeof(ChainPara);
ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
if (pHTTPS->dwAuthType == AUTHTYPE_CLIENT) {
ChainPara.RequestedUsage.Usage.cUsageIdentifier = CLIENT_USAGE_COUNT;
ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgpszClientUsage;
} else {
ChainPara.RequestedUsage.Usage.cUsageIdentifier = SERVER_USAGE_COUNT;
ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = rgpszServerUsage;
}
if (0 == (pHTTPS->fdwChecks & SECURITY_FLAG_IGNORE_REVOCATION)) {
if (pProvData->pWintrustData->fdwRevocationChecks != WTD_REVOKE_NONE)
// On 4-16-01 changed from END_CERT to EXCLUDE_ROOT
dwCreateChainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
}
hChainEngine = HTTPSGetChainEngine(pProvData);
hAdditionalStore = HTTPSGetChainAdditionalStore(pProvData);
if (!CertGetCertificateChain (
hChainEngine,
pProvCert->pCert,
&pSgnr->sftVerifyAsOf,
hAdditionalStore,
&ChainPara,
dwCreateChainFlags,
NULL, // pvReserved,
&pChainContext
)) {
pProvData->dwError = GetLastError();
dwSgnrError = TRUST_E_SYSTEM_ERROR;
goto GetChainError;
}
if (WTD_STATEACTION_VERIFY == pProvData->pWintrustData->dwStateAction) {
DWORD dwUpdateError;
UpdateCertProvChain(
pProvData,
0, // idxSigner
&dwUpdateError,
FALSE, // fCounterSigner
0, // idxCounterSigner
pSgnr,
pChainContext
);
dwSgnrError = pSgnr->dwError;
if (CERT_E_REVOKED == dwSgnrError ||
CERT_E_REVOCATION_FAILURE == dwSgnrError) {
// Clear the updated errors. Will be updated in the final policy
pSgnr->dwError = 0;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] = 0;
if (CERT_E_REVOKED == pProvCert->dwError ||
CERT_E_REVOCATION_FAILURE == pProvCert->dwError) {
pProvCert->dwError = 0;
}
}
}
dwError = S_OK;
CommonReturn:
if (hChainEngine)
CertFreeCertificateChainEngine(hChainEngine);
if (hAdditionalStore)
CertCloseStore(hAdditionalStore, 0);
pSgnr->pChainContext = pChainContext;
return dwError;
ErrorReturn:
pSgnr->dwError = dwSgnrError;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_CERTPROV] =
dwSgnrError;
dwError = S_FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS, GetChainError)
}
//////////////////////////////////////////////////////////////////////////////
//
// Final Policy Provider function: HTTPSFinalProv
//----------------------------------------------------------------------------
// Check the outcome of the previous functions and display UI based on this.
//
// On July 26, 2000, disabled the use of the test root
#if 0
void MapHTTPSRegPolicySettingsToBaseChainPolicyFlags(
IN DWORD dwRegPolicySettings,
IN OUT DWORD *pdwFlags
)
{
DWORD dwFlags;
if (0 == dwRegPolicySettings)
return;
dwFlags = *pdwFlags;
if (dwRegPolicySettings & WTPF_TRUSTTEST)
dwFlags |= CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG;
if (dwRegPolicySettings & WTPF_TESTCANBEVALID)
dwFlags |= CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG;
*pdwFlags = dwFlags;
}
#endif
HRESULT WINAPI HTTPSFinalProv(CRYPT_PROVIDER_DATA *pProvData)
{
HTTPSPolicyCallbackData *pHTTPS;
pHTTPS = (HTTPSPolicyCallbackData *)
pProvData->pWintrustData->pPolicyCallbackData;
if (!(pHTTPS) ||
!(WVT_IS_CBSTRUCT_GT_MEMBEROFFSET(HTTPSPolicyCallbackData,
pHTTPS->cbStruct, pwszServerName)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return(ERROR_INVALID_PARAMETER);
}
DWORD dwError;
CRYPT_PROVIDER_SGNR *pSgnr;
CERT_CHAIN_POLICY_PARA PolicyPara;
memset(&PolicyPara, 0, sizeof(PolicyPara));
PolicyPara.cbSize = sizeof(PolicyPara);
PolicyPara.pvExtraPolicyPara = (void *) pHTTPS;
CERT_CHAIN_POLICY_STATUS PolicyStatus;
memset(&PolicyStatus, 0, sizeof(PolicyStatus));
PolicyStatus.cbSize = sizeof(PolicyStatus);
//
// check the high level error codes.
//
if (0 != (dwError = GetErrorBasedOnStepErrors(pProvData)))
goto CommonReturn;
pSgnr = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0);
if (pSgnr == NULL) {
dwError = TRUST_E_SYSTEM_ERROR;
goto CommonReturn;
}
// On July 26, 2000, disabled the use of the test root
#if 0
MapHTTPSRegPolicySettingsToBaseChainPolicyFlags(
pProvData->dwRegPolicySettings,
&PolicyPara.dwFlags
);
#endif
if (!CertVerifyCertificateChainPolicy(
CERT_CHAIN_POLICY_SSL,
pSgnr->pChainContext,
&PolicyPara,
&PolicyStatus
)) {
dwError = TRUST_E_SYSTEM_ERROR;
goto CommonReturn;
} else if (0 != PolicyStatus.dwError) {
dwError = PolicyStatus.dwError;
UpdateCertError(pSgnr, &PolicyStatus);
goto CommonReturn;
}
dwError = 0;
CommonReturn:
pProvData->dwFinalError = dwError;
return dwError;
}
///////////////////////////////////////////////////////////////////////////////////
//
// Local Functions
//
///////////////////////////////////////////////////////////////////////////////////
DWORD GetErrorBasedOnStepErrors(CRYPT_PROVIDER_DATA *pProvData)
{
//
// initial allocation of the step errors?
//
if (!(pProvData->padwTrustStepErrors))
{
return(ERROR_NOT_ENOUGH_MEMORY);
}
//
// 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);
}