Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

978 lines
33 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: gettrst.cpp
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include <dbgdef.h>
#include "wintrustp.h"
#include "crypthlp.h"
extern HINSTANCE HinstDll;
extern HMODULE HmodRichEdit;
//////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////
static BOOL IsUntrustedRootProblem(WINTRUST_DATA *pWTD)
{
CRYPT_PROVIDER_DATA *pProvData = NULL;
CRYPT_PROVIDER_SGNR *pProvSigner = NULL;
CRYPT_PROVIDER_CERT *pCryptProviderCert;
DWORD i;
pProvData = WTHelperProvDataFromStateData(pWTD->hWVTStateData);
pProvSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0);
if (pProvSigner)
{
// get all certs in the chain
for (i=0; i<pProvSigner->csCertChain; i++)
{
pCryptProviderCert = WTHelperGetProvCertFromChain(pProvSigner, i);
if (pCryptProviderCert != NULL)
{
if (pCryptProviderCert->dwError != ERROR_SUCCESS)
{
return FALSE;
}
}
else
{
return FALSE;
}
}
}
else
{
return FALSE;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////
static DWORD GetFinalErrorFromChain(PCERT_VIEW_HELPER pviewhelp)
{
int i;
DWORD dwErr = 0;
for (i=((int)pviewhelp->cpCryptProviderCerts)-1; i>= 0; i--)
{
dwErr = pviewhelp->rgpCryptProviderCerts[i]->dwError;
if (((dwErr == CERT_E_UNTRUSTEDROOT) || (dwErr == CERT_E_UNTRUSTEDTESTROOT)) &&
(pviewhelp->fIgnoreUntrustedRoot))
{
dwErr = 0;
}
else if (dwErr != 0)
{
break;
}
}
return dwErr;
}
//////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////
static void GetCertChainErrorString(PCERT_VIEW_HELPER pviewhelp)
{
WCHAR szErrorString[CRYPTUI_MAX_STRING_SIZE];
DWORD i;
DWORD dwChainError;
//
// free the error string if one already exists
//
if (pviewhelp->pwszErrorString != NULL)
{
free(pviewhelp->pwszErrorString);
pviewhelp->pwszErrorString = NULL;
}
// If they ask to be warned about local/remote differences,
// always display this warning
if (pviewhelp->fWarnRemoteTrust)
{
LoadStringU(HinstDll, IDS_WARNREMOTETRUST_ERROR, szErrorString, ARRAYSIZE(szErrorString));
goto StringLoaded;
}
//
// if there was no over all chain error, then the only problem,
// is if there are no usages
//
if (pviewhelp->dwChainError == 0)
{
if (pviewhelp->cUsages == NULL)
{
LoadStringU(HinstDll, IDS_NOVALIDUSAGES_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
else
{
return;
}
}
if ((pviewhelp->dwChainError == CERT_E_UNTRUSTEDROOT) ||
(pviewhelp->dwChainError == CERT_E_UNTRUSTEDTESTROOT))
{
//
// if we are ignoring untrusted roots, then just return
//
if (pviewhelp->fIgnoreUntrustedRoot)
{
return;
}
//
// if we are just warning the user about untrusted root AND the root
// cert is in the remote root store then load that string
//
if (pviewhelp->fWarnUntrustedRoot && pviewhelp->fRootInRemoteStore)
{
//
// if this is a root cert then show the error for a root
//
if (pviewhelp->cpCryptProviderCerts == 1 && (pviewhelp->rgpCryptProviderCerts[0])->fSelfSigned)
{
LoadStringU(HinstDll, IDS_WARNUNTRUSTEDROOT_ERROR_ROOTCERT, szErrorString, ARRAYSIZE(szErrorString));
}
else
{
LoadStringU(HinstDll, IDS_WARNUNTRUSTEDROOT_ERROR, szErrorString, ARRAYSIZE(szErrorString));
}
}
else
{
//
// if this is a root cert then show the error for a root
//
if (pviewhelp->cpCryptProviderCerts == 1 && (pviewhelp->rgpCryptProviderCerts[0])->fSelfSigned)
{
LoadStringU(HinstDll, IDS_UNTRUSTEDROOT_ROOTCERT_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
else
{
LoadStringU(HinstDll, IDS_UNTRUSTEDROOT_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
}
}
else if (pviewhelp->dwChainError == CERT_E_REVOKED)
{
LoadStringU(HinstDll, IDS_CERTREVOKED_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
else if (pviewhelp->dwChainError == TRUST_E_CERT_SIGNATURE)
{
LoadStringU(HinstDll, IDS_CERTBADSIGNATURE_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
else if (pviewhelp->dwChainError == CERT_E_EXPIRED)
{
LoadStringU(HinstDll, IDS_CERTEXPIRED_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
else if (pviewhelp->dwChainError == CERT_E_VALIDITYPERIODNESTING)
{
LoadStringU(HinstDll, IDS_TIMENESTING_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
else if (pviewhelp->dwChainError == CERT_E_WRONG_USAGE)
{
LoadStringU(HinstDll, IDS_WRONG_USAGE_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
else if (pviewhelp->dwChainError == TRUST_E_BASIC_CONSTRAINTS)
{
LoadStringU(HinstDll, IDS_BASIC_CONSTRAINTS_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
else if (pviewhelp->dwChainError == CERT_E_PURPOSE)
{
LoadStringU(HinstDll, IDS_PURPOSE_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
else if (pviewhelp->dwChainError == CERT_E_REVOCATION_FAILURE)
{
LoadStringU(HinstDll, IDS_REVOCATION_FAILURE_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
else if (pviewhelp->dwChainError == CERT_E_CHAINING)
{
LoadStringU(HinstDll, IDS_CANTBUILDCHAIN_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
}
else if (pviewhelp->dwChainError == TRUST_E_EXPLICIT_DISTRUST)
{
LoadStringU(HinstDll, IDS_EXPLICITDISTRUST_ERROR, szErrorString, ARRAYSIZE(szErrorString));
}
else if (pviewhelp->dwChainError != 0)
{
//
// this is not an error we know about, so call the general
// error string function
//
GetUnknownErrorString(&(pviewhelp->pwszErrorString), pviewhelp->dwChainError);
}
StringLoaded:
if (pviewhelp->pwszErrorString == NULL)
{
pviewhelp->pwszErrorString = AllocAndCopyWStr(szErrorString);
}
}
// Returned string must be freed via LocalFree()
LPWSTR
FormatRevocationStatus(
IN PCERT_CHAIN_ELEMENT pElement
)
{
LPWSTR pwszRevStatus = NULL;
UINT ids = IDS_REV_STATUS_UNKNOWN_ERROR;
static const WCHAR wszNoTime[] = L"...";
LPWSTR pwszArg1 = (LPWSTR) wszNoTime;
LPWSTR pwszArg2 = (LPWSTR) wszNoTime;
LPWSTR pwszTime1 = NULL;
LPWSTR pwszTime2 = NULL;
LPWSTR pwszErrStr = NULL;
DWORD dwRevResult;
PCERT_REVOCATION_INFO pRevInfo;
PCERT_REVOCATION_CRL_INFO pCrlInfo;
pRevInfo = pElement->pRevocationInfo;
if (NULL == pRevInfo)
return NULL;
dwRevResult = pRevInfo->dwRevocationResult;
pCrlInfo = pRevInfo->pCrlInfo;
switch (dwRevResult) {
case ERROR_SUCCESS:
ids = IDS_REV_STATUS_OK;
// Fall through
case CRYPT_E_REVOCATION_OFFLINE:
if (pCrlInfo) {
PCCRL_CONTEXT pCrl;
pCrl = pCrlInfo->pDeltaCrlContext;
if (NULL == pCrl)
pCrl = pCrlInfo->pBaseCrlContext;
if (pCrl) {
BOOL fFormatDate;
fFormatDate = FormatDateString(
&pwszTime1,
pCrl->pCrlInfo->ThisUpdate,
TRUE, // fIncludeTime
TRUE, // fLongFormat
NULL // hwnd
);
if (fFormatDate) {
pwszArg1 = pwszTime1;
if (I_CryptIsZeroFileTime(&pCrl->pCrlInfo->NextUpdate))
pwszArg2 = (LPWSTR) wszNoTime;
else {
fFormatDate = FormatDateString(
&pwszTime2,
pCrl->pCrlInfo->NextUpdate,
TRUE, // fIncludeTime
TRUE, // fLongFormat
NULL // hwnd
);
if (fFormatDate)
pwszArg2 = pwszTime2;
}
}
if (fFormatDate) {
switch (dwRevResult) {
case ERROR_SUCCESS:
ids = IDS_REV_STATUS_OK_WITH_CRL;
break;
case CRYPT_E_REVOCATION_OFFLINE:
ids = IDS_REV_STATUS_OFFLINE_WITH_CRL;
break;
}
}
}
}
break;
case CRYPT_E_REVOKED:
if (pCrlInfo && pCrlInfo->pCrlEntry) {
if (FormatDateString(
&pwszTime1,
pCrlInfo->pCrlEntry->RevocationDate,
TRUE, // fIncludeTime
TRUE, // fLongFormat
NULL // hwnd
)) {
ids = IDS_REV_STATUS_REVOKED_ON;
pwszArg1 = pwszTime1;
}
}
break;
default:
break;
}
if (IDS_REV_STATUS_UNKNOWN_ERROR == ids) {
GetUnknownErrorString(&pwszErrStr, dwRevResult);
if (NULL == pwszErrStr)
goto CommonReturn;
pwszArg1 = pwszErrStr;
}
pwszRevStatus = FormatMessageUnicodeIds(ids, pwszArg1, pwszArg2);
CommonReturn:
if (pwszTime1)
free(pwszTime1);
if (pwszTime2)
free(pwszTime2);
if (pwszErrStr)
free(pwszErrStr);
return pwszRevStatus;
}
//////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////
BOOL BuildChain(
PCERT_VIEW_HELPER pviewhelp,
LPSTR pszUsage)
{
CRYPT_PROVIDER_DATA const * pProvData = NULL;
CRYPT_PROVIDER_SGNR * pProvSigner = NULL;
DWORD i;
GUID defaultProviderGUID = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
HRESULT hr = ERROR_SUCCESS;
BOOL fInternalError = FALSE;
DWORD dwStartIndex;
BOOL fRet = TRUE;
PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pcvp = pviewhelp->pcvp;
WCHAR szErrorString[CRYPTUI_MAX_STRING_SIZE];
//
// if there was previous chain state then free that before building
// the new chain
//
if (pviewhelp->fFreeWTD)
{
pviewhelp->sWTD.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrustEx(NULL, &defaultProviderGUID, &(pviewhelp->sWTD));
}
pviewhelp->cpCryptProviderCerts = 0;
pviewhelp->fFreeWTD = FALSE;
//
// initialize structs that are used with WinVerifyTrust()
//
memset(&(pviewhelp->sWTD), 0x00, sizeof(WINTRUST_DATA));
pviewhelp->sWTD.cbStruct = sizeof(WINTRUST_DATA);
pviewhelp->sWTD.dwUIChoice = WTD_UI_NONE;
pviewhelp->sWTD.dwUnionChoice = WTD_CHOICE_CERT;
pviewhelp->sWTD.pCert = &(pviewhelp->sWTCI);
pviewhelp->sWTD.dwProvFlags = (pszUsage == NULL) ? WTD_NO_POLICY_USAGE_FLAG : 0;
if ((pcvp->dwFlags & CRYPTUI_ENABLE_REVOCATION_CHECKING) == 0)
{
pviewhelp->sWTD.dwProvFlags |= WTD_REVOCATION_CHECK_NONE;
}
else
{
pviewhelp->sWTD.dwProvFlags |= WTD_REVOCATION_CHECK_CHAIN;
}
memset(&(pviewhelp->sWTCI), 0x00, sizeof(WINTRUST_CERT_INFO));
pviewhelp->sWTCI.cbStruct = sizeof(WINTRUST_CERT_INFO);
pviewhelp->sWTCI.pcwszDisplayName = L"CryptUI";
pviewhelp->sWTCI.psCertContext = (CERT_CONTEXT *)pcvp->pCertContext;
pviewhelp->sWTCI.chStores = pcvp->cStores;
pviewhelp->sWTCI.pahStores = pcvp->rghStores;
pviewhelp->sWTCI.dwFlags |= (pcvp->dwFlags & CRYPTUI_DONT_OPEN_STORES) ? WTCI_DONT_OPEN_STORES : 0;
pviewhelp->sWTCI.dwFlags |= (pcvp->dwFlags & CRYPTUI_ONLY_OPEN_ROOT_STORE) ? WTCI_OPEN_ONLY_ROOT : 0;
//
// if a provider was passed in, then use it to build the chain,
// otherwise use the default provider to build the chain
//
if (pcvp->pCryptProviderData != NULL)
{
pProvData = pcvp->pCryptProviderData;
}
else
{
pviewhelp->sWTD.dwStateAction = WTD_STATEACTION_VERIFY;
//
// the default default provider requires the policycallback data to point
// to the usage oid you are validating for, so set it to the usage passed in
//
pviewhelp->sWTD.pPolicyCallbackData = pszUsage;
pviewhelp->sWTD.pSIPClientData = NULL;
hr = WinVerifyTrustEx(NULL, &defaultProviderGUID, &(pviewhelp->sWTD));
pProvData = WTHelperProvDataFromStateData(pviewhelp->sWTD.hWVTStateData);
if (WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA) pProvData, 0, FALSE, 0) != NULL)
{
pviewhelp->fFreeWTD = TRUE;
fInternalError = FALSE;
}
else
{
pviewhelp->fFreeWTD = FALSE;
pviewhelp->sWTD.dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrustEx(NULL, &defaultProviderGUID, &(pviewhelp->sWTD));
fInternalError = TRUE;
}
}
if (pProvData && !fInternalError)
{
//
// set the chain error in the helper struct
//
pviewhelp->dwChainError = pProvData->dwFinalError;
//
// This is to catch internal WinVerifyTrust errors
//
if ((pviewhelp->dwChainError == 0) && (FAILED(hr)))
{
pviewhelp->dwChainError = (DWORD) hr;
}
//
// if the WinTrust state was passed into the certUI then use that for
// the chain, else, get it from the state that was just built
//
if (pcvp->pCryptProviderData != NULL)
{
pProvSigner = WTHelperGetProvSignerFromChain(
(PCRYPT_PROVIDER_DATA) pProvData,
pcvp->idxSigner,
pcvp->fCounterSigner,
pcvp->idxCounterSigner);
dwStartIndex = pcvp->idxCert;
}
else
{
pProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA) pProvData, 0, FALSE, 0);
dwStartIndex = 0;
}
if (pProvSigner)
{
//
// get all certs in the chain
//
for (i=dwStartIndex; i<pProvSigner->csCertChain && (i<dwStartIndex+MAX_CERT_CHAIN_LENGTH); i++)
{
pviewhelp->rgpCryptProviderCerts[pviewhelp->cpCryptProviderCerts] = WTHelperGetProvCertFromChain(pProvSigner, i);
if (pviewhelp->rgpCryptProviderCerts[pviewhelp->cpCryptProviderCerts] != NULL)
{
// Note, only modify this property when creating the
// chain for the original end cert. Subsequent CA
// chains won't have the ExtendedErrorInfo.
if ((pcvp->dwFlags & CRYPTUI_TREEVIEW_PAGE_FLAG) == 0)
{
// Either delete or set the
// CERT_EXTENDED_ERROR_INFO_PROP_ID
// This is used in cvdetail.cpp when displaying
// property details
PCRYPT_PROVIDER_CERT pProvCert =
pviewhelp->rgpCryptProviderCerts[
pviewhelp->cpCryptProviderCerts];
LPWSTR pwszExtErrorInfo = NULL; // not allocated
LPWSTR pwszRevStatus = NULL; // LocalAlloc()'ed
if (pProvCert->cbStruct >
offsetof(CRYPT_PROVIDER_CERT, pChainElement)
&&
NULL != pProvCert->pChainElement)
{
pwszExtErrorInfo = (LPWSTR)
pProvCert->pChainElement->pwszExtendedErrorInfo;
pwszRevStatus = FormatRevocationStatus(
pProvCert->pChainElement);
if (NULL == pwszExtErrorInfo)
{
pwszExtErrorInfo = pwszRevStatus;
}
else if (pwszRevStatus)
{
LPWSTR pwszReAlloc;
DWORD cchRevStatus;
DWORD cchExtErrorInfo;
cchRevStatus = wcslen(pwszRevStatus);
cchExtErrorInfo = wcslen(pwszExtErrorInfo);
pwszReAlloc = (LPWSTR) LocalReAlloc(
pwszRevStatus,
(cchRevStatus + cchExtErrorInfo + 1) *
sizeof(WCHAR),
LMEM_MOVEABLE);
if (pwszReAlloc)
{
memcpy(&pwszReAlloc[cchRevStatus],
pwszExtErrorInfo,
(cchExtErrorInfo + 1) * sizeof(WCHAR));
pwszExtErrorInfo = pwszRevStatus =
pwszReAlloc;
}
}
}
if (pwszExtErrorInfo)
{
CRYPT_DATA_BLOB ExtErrorInfoBlob;
ExtErrorInfoBlob.pbData = (BYTE *) pwszExtErrorInfo;
ExtErrorInfoBlob.cbData =
(wcslen(pwszExtErrorInfo) + 1) * sizeof(WCHAR);
CertSetCertificateContextProperty(
pProvCert->pCert,
CERT_EXTENDED_ERROR_INFO_PROP_ID,
CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG,
&ExtErrorInfoBlob
);
}
else
{
CertSetCertificateContextProperty(
pProvCert->pCert,
CERT_EXTENDED_ERROR_INFO_PROP_ID,
CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG,
NULL // pvData, NULL implies delete
);
}
if (pwszRevStatus)
LocalFree(pwszRevStatus);
}
pviewhelp->cpCryptProviderCerts++;
}
}
}
}
CalculateUsages(pviewhelp);
//
// if the cert we are looking at is not the leaf cert, then we can't just take the
// dwFinalError as the overall chain error, so find the over all chain error by
// walking the chain and looking at the errors
//
if ((pcvp->pCryptProviderData != NULL) && (pcvp->idxCert != 0))
{
pviewhelp->dwChainError = GetFinalErrorFromChain(pviewhelp);
}
//
// if we are in the fWarnUntrustedRoot then check to see if the root cert is in the
// remote machine's root store
//
if (pviewhelp->fWarnUntrustedRoot)
{
PCCERT_CONTEXT pCertContext = NULL;
CRYPT_HASH_BLOB cryptHashBlob;
BYTE hash[20];
DWORD cb = 20;
pviewhelp->fRootInRemoteStore = FALSE;
cryptHashBlob.cbData = 20;
cryptHashBlob.pbData = &(hash[0]);
if (CertGetCertificateContextProperty(
pviewhelp->rgpCryptProviderCerts[pviewhelp->cpCryptProviderCerts-1]->pCert,
CERT_SHA1_HASH_PROP_ID,
&(hash[0]),
&cb))
{
pCertContext = CertFindCertificateInStore(
pviewhelp->pcvp->rghStores[0],
X509_ASN_ENCODING || PKCS_7_ASN_ENCODING,
0,
CERT_FIND_SHA1_HASH,
&cryptHashBlob,
NULL);
if (pCertContext != NULL)
{
CertFreeCertificateContext(pCertContext);
pviewhelp->fRootInRemoteStore = TRUE;
}
}
}
//
// get the error string for the whole cert chain
//
if (!fInternalError)
{
GetCertChainErrorString(pviewhelp);
}
else
{
LoadStringU(HinstDll, IDS_INTERNAL_ERROR, szErrorString, ARRAYSIZE(szErrorString));
pviewhelp->pwszErrorString = AllocAndCopyWStr(szErrorString);
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////
BOOL CalculateUsages(PCERT_VIEW_HELPER pviewhelp)
{
DWORD cLocalArrayOfUsages = 0;
LPSTR * localArrayOfUsages = NULL;
BOOL fLocalUsagesAllocated = FALSE;
DWORD i;
HRESULT hr;
BOOL fRet = TRUE;
PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pcvp = pviewhelp->pcvp;
void *pTemp;
//
// if there are already usages, then clean them up before recalculating them,
// or just return if state was passed into CertUI
//
if (pviewhelp->cUsages != 0)
{
//
// state was passed into the CertUI, so just return
//
if (pcvp->pCryptProviderData != NULL)
{
return TRUE;
}
//
// cleanup usages that were generated prior to this call
//
for (i=0; i<pviewhelp->cUsages; i++)
{
free(pviewhelp->rgUsages[i]);
}
free(pviewhelp->rgUsages);
}
//
// initialize usage variables
//
pviewhelp->cUsages = 0;
pviewhelp->rgUsages = NULL;
//
// if a provider was passed in, then we just look at it for the usage and structure
// passed in for the trust of that usage,
// otherwise we need to look at each usage and validate trust for all of them
//
if (pcvp->pCryptProviderData != NULL)
{
//
// allocate an array of 1 LPSTR
//
if (NULL == (pviewhelp->rgUsages = (LPSTR *) malloc(sizeof(LPSTR))))
{
SetLastError(E_OUTOFMEMORY);
return FALSE;
}
//
// copy either the 1 purpose that was passed in, or the purpose out of WinTrust state
//
if (pcvp->cPurposes == 1)
{
if (NULL == (pviewhelp->rgUsages[0] = (LPSTR) malloc(strlen(pcvp->rgszPurposes[0])+1)))
{
SetLastError(E_OUTOFMEMORY);
return FALSE;
}
strcpy(pviewhelp->rgUsages[0], pcvp->rgszPurposes[0]);
}
else
{
if (NULL == (pviewhelp->rgUsages[0] = (LPSTR) malloc(strlen(pcvp->pCryptProviderData->pszUsageOID)+1)))
{
SetLastError(E_OUTOFMEMORY);
return FALSE;
}
strcpy(pviewhelp->rgUsages[0], pcvp->pCryptProviderData->pszUsageOID);
}
pviewhelp->cUsages = 1;
}
else
{
//
// check to see if usages where passed in, if so, then intersect those with
// available usages in the cert, otherwise, get the available usages in the cert
// and use them as is
//
if (pcvp->cPurposes != 0)
{
//
// get the array of possible usages for the cert chain
//
// DSIE: Switch over to using pChainElement from philh's new chain building code.
AllocAndReturnKeyUsageList(pviewhelp->rgpCryptProviderCerts[0], &localArrayOfUsages, &cLocalArrayOfUsages);
if (cLocalArrayOfUsages != 0)
fLocalUsagesAllocated = TRUE;
//
// for each usage that was passed in check to see if it is in the list of possible usages
//
for (i=0; i<pcvp->cPurposes; i++)
{
if (OIDinArray(pcvp->rgszPurposes[i], localArrayOfUsages, cLocalArrayOfUsages))
{
//
// if an array hasn't yet been allocated, then allocate space for an array of
// 1 LPSTR, otherwise use realloc to add one more element
//
if (pviewhelp->rgUsages == NULL)
{
pviewhelp->rgUsages = (LPSTR *) malloc(sizeof(LPSTR));
}
else
{
pTemp = realloc(pviewhelp->rgUsages, sizeof(LPSTR) * (pviewhelp->cUsages+1));
if (pTemp == NULL)
{
free(pviewhelp->rgUsages);
pviewhelp->rgUsages = NULL;
}
else
{
pviewhelp->rgUsages = (LPSTR *) pTemp;
}
}
if (pviewhelp->rgUsages == NULL)
{
goto ErrorCleanUp;
}
//
// allocate space for the usage string, then copy it, and increment number of usages
//
if (NULL == (pviewhelp->rgUsages[pviewhelp->cUsages] = (LPSTR) malloc(strlen(pcvp->rgszPurposes[i])+1)))
{
SetLastError(E_OUTOFMEMORY);
goto ErrorCleanUp;
}
strcpy(pviewhelp->rgUsages[pviewhelp->cUsages], pcvp->rgszPurposes[i]);
pviewhelp->cUsages++;
}
}
}
else
{
AllocAndReturnKeyUsageList(pviewhelp->rgpCryptProviderCerts[0], &(pviewhelp->rgUsages), &(pviewhelp->cUsages));
}
}
CleanUp:
if (fLocalUsagesAllocated)
{
i = 0;
while ((i < cLocalArrayOfUsages) && (localArrayOfUsages[i] != NULL))
{
free(localArrayOfUsages[i]);
i++;
}
free(localArrayOfUsages);
}
return fRet;
ErrorCleanUp:
if (pviewhelp->rgUsages != NULL)
{
i = 0;
while ((i < pviewhelp->cUsages) && (pviewhelp->rgUsages[i] != NULL))
{
free(pviewhelp->rgUsages[i]);
i++;
}
free(pviewhelp->rgUsages);
}
fRet = FALSE;
goto CleanUp;
}
//////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////
BOOL BuildWinVTrustState(
LPCWSTR szFileName,
CMSG_SIGNER_INFO const *pSignerInfo,
DWORD cStores,
HCERTSTORE *rghStores,
LPCSTR pszOID,
PCERT_VIEWSIGNERINFO_PRIVATE pcvsiPrivate,
CRYPT_PROVIDER_DEFUSAGE *pCryptProviderDefUsage,
WINTRUST_DATA *pWTD)
{
WINTRUST_FILE_INFO WTFI;
WINTRUST_SGNR_INFO WTSI;
HRESULT hr;
GUID defaultProviderGUID = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
//
// initialize structs that are used locally with WinVerifyTrust()
//
memset(pWTD, 0x00, sizeof(WINTRUST_DATA));
pWTD->cbStruct = sizeof(WINTRUST_DATA);
pWTD->dwUIChoice = WTD_UI_NONE;
//
// if the szFileName parameter is non NULL then this for a file,
// otherwise it is for a signer info
//
if (szFileName != NULL)
{
pWTD->dwUnionChoice = WTD_CHOICE_FILE;
pWTD->pFile = &WTFI;
pWTD->pPolicyCallbackData = (void *) pszOID;
memset(&WTFI, 0x00, sizeof(WINTRUST_FILE_INFO));
WTFI.cbStruct = sizeof(WINTRUST_FILE_INFO);
WTFI.pcwszFilePath = szFileName;
}
else
{
pWTD->dwUnionChoice = WTD_CHOICE_SIGNER;
pWTD->pSgnr = &WTSI;
pWTD->pPolicyCallbackData = (void *) pszOID;
memset(&WTSI, 0x00, sizeof(WINTRUST_SGNR_INFO));
WTSI.cbStruct = sizeof(WINTRUST_SGNR_INFO);
WTSI.pcwszDisplayName = L"CryptUI";
WTSI.psSignerInfo = (CMSG_SIGNER_INFO *) pSignerInfo;
WTSI.chStores = cStores;
WTSI.pahStores = rghStores;
//WTSI.pszOID = pszOID;
}
pWTD->pSIPClientData = NULL;
pWTD->dwStateAction = WTD_STATEACTION_VERIFY;
hr = WinVerifyTrustEx(NULL, &defaultProviderGUID, pWTD);
if (hr == ERROR_SUCCESS)
{
pcvsiPrivate->fpCryptProviderDataTrustedUsage = TRUE;
}
else
{
pcvsiPrivate->fpCryptProviderDataTrustedUsage = FALSE;
}
pcvsiPrivate->pCryptProviderData = WTHelperProvDataFromStateData(pWTD->hWVTStateData);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////
BOOL FreeWinVTrustState(
LPCWSTR szFileName,
CMSG_SIGNER_INFO const *pSignerInfo,
DWORD cStores,
HCERTSTORE *rghStores,
LPCSTR pszOID,
CRYPT_PROVIDER_DEFUSAGE *pCryptProviderDefUsage,
WINTRUST_DATA *pWTD)//,
//BOOL *pfUseDefaultProvider)
{
WINTRUST_FILE_INFO WTFI;
WINTRUST_SGNR_INFO WTSI;
HRESULT hr;
GUID defaultProviderGUID = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
// initialize structs that are used locally with WinVerifyTrust()
memset(pWTD, 0x00, sizeof(WINTRUST_DATA));
pWTD->cbStruct = sizeof(WINTRUST_DATA);
pWTD->dwUIChoice = WTD_UI_NONE;
//
// if the szFileName parameter is non NULL then this for a file,
// otherwise it is for a signer info
//
if (szFileName != NULL)
{
pWTD->dwUnionChoice = WTD_CHOICE_FILE;
pWTD->pFile = &WTFI;
memset(&WTFI, 0x00, sizeof(WINTRUST_FILE_INFO));
WTFI.cbStruct = sizeof(WINTRUST_FILE_INFO);
WTFI.pcwszFilePath = szFileName;
}
else
{
pWTD->dwUnionChoice = WTD_CHOICE_SIGNER;
pWTD->pSgnr = &WTSI;
memset(&WTSI, 0x00, sizeof(WINTRUST_SGNR_INFO));
WTSI.cbStruct = sizeof(WINTRUST_SGNR_INFO);
WTSI.psSignerInfo = (CMSG_SIGNER_INFO *) pSignerInfo;
WTSI.chStores = cStores;
WTSI.pahStores = rghStores;
}
/*if (*pfUseDefaultProvider)
{
pWTD->dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrustEx(NULL, &defaultProviderGUID, pWTD);
}
else
{*/
pWTD->dwStateAction = WTD_STATEACTION_CLOSE;
WinVerifyTrustEx(NULL, &(pCryptProviderDefUsage->gActionID), pWTD);
WintrustGetDefaultForUsage(DWACTION_FREE, pszOID, pCryptProviderDefUsage);
//}
return TRUE;
}