522 lines
17 KiB
C++
522 lines
17 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
|