windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/pkitrust/wintrust/wthelper.cpp

500 lines
12 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: wthelper.cpp
//
// Contents: Microsoft Internet Security Trust Provider
//
// Functions: WTHelperGetProvPrivateDataFromChain
// WTHelperGetProvSignerFromChain
// WTHelperGetFileHandle
// WTHelperGetFileName
// WTHelperOpenKnownStores
// WTHelperGetProvCertFromChain
// WTHelperCheckCertUsage
// WTHelperIsInRootStore
// WTHelperProvDataFromStateData
// WTHelperGetAgencyInfo
//
// *** local functions ***
// _FindKeyUsage
//
// History: 01-Jun-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include "pkialloc.h"
BOOL _FindKeyUsage(PCERT_ENHKEY_USAGE pUsage, LPCSTR pszRequestedUsageOID);
CRYPT_PROVIDER_PRIVDATA * WINAPI WTHelperGetProvPrivateDataFromChain(CRYPT_PROVIDER_DATA *pProvData,
GUID *pgProviderID)
{
if (!(pProvData) ||
!(pgProviderID))
{
return(NULL);
}
for (int i = 0; i < (int)pProvData->csProvPrivData; i++)
{
if (memcmp(&pProvData->pasProvPrivData[i].gProviderID, pgProviderID, sizeof(GUID)) == 0)
{
return(&pProvData->pasProvPrivData[i]);
}
}
return(NULL);
}
CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(CRYPT_PROVIDER_DATA *pProvData,
DWORD idxSigner,
BOOL fCounterSigner,
DWORD idxCounterSigner)
{
if (!(pProvData) ||
(idxSigner >= pProvData->csSigners))
{
return(NULL);
}
if (fCounterSigner)
{
if (idxCounterSigner >= pProvData->pasSigners[idxSigner].csCounterSigners)
{
return(NULL);
}
return(&pProvData->pasSigners[idxSigner].pasCounterSigners[idxCounterSigner]);
}
return(&pProvData->pasSigners[idxSigner]);
}
CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(CRYPT_PROVIDER_SGNR *pSgnr,
DWORD idxCert)
{
if (!(pSgnr) ||
(idxCert >= pSgnr->csCertChain))
{
return(NULL);
}
return(&pSgnr->pasCertChain[idxCert]);
}
HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *pWintrustData)
{
switch (pWintrustData->dwUnionChoice)
{
case WTD_CHOICE_FILE:
return(pWintrustData->pFile->hFile);
case WTD_CHOICE_CATALOG:
return(pWintrustData->pCatalog->hMemberFile);
}
return(INVALID_HANDLE_VALUE);
}
WCHAR * WINAPI WTHelperGetFileName(WINTRUST_DATA *pWintrustData)
{
switch (pWintrustData->dwUnionChoice)
{
case WTD_CHOICE_FILE:
return((WCHAR *)pWintrustData->pFile->pcwszFilePath);
case WTD_CHOICE_CATALOG:
if (!(pWintrustData->pCatalog->pcwszCatalogFilePath) ||
!(pWintrustData->pCatalog->pcwszMemberTag))
{
return(NULL);
}
return((WCHAR *)pWintrustData->pCatalog->pcwszMemberFilePath);
case WTD_CHOICE_CERT:
if (pWintrustData->pCert->pcwszDisplayName)
return (WCHAR *) pWintrustData->pCert->pcwszDisplayName;
else
return L"Certificate";
case WTD_CHOICE_BLOB:
if (pWintrustData->pBlob->pcwszDisplayName)
return (WCHAR *) pWintrustData->pBlob->pcwszDisplayName;
else
return L"Blob";
}
return(NULL);
}
BOOL WINAPI WTHelperOpenKnownStores(CRYPT_PROVIDER_DATA *pProvData)
{
DWORD i;
DWORD cs;
HCERTSTORE *pas;
if ((pProvData->pWintrustData) &&
(pProvData->pWintrustData->dwUnionChoice == WTD_CHOICE_CERT) &&
(_ISINSTRUCT(WINTRUST_CERT_INFO, pProvData->pWintrustData->pCert->cbStruct, dwFlags)))
{
HCERTSTORE hStore;
if (pProvData->pWintrustData->pCert->dwFlags & WTCI_DONT_OPEN_STORES)
{
if (hStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL))
{
AddToStoreChain(hStore, &pProvData->chStores, &pProvData->pahStores);
return(TRUE);
}
return(FALSE);
}
if (pProvData->pWintrustData->pCert->dwFlags & WTCI_OPEN_ONLY_ROOT)
{
if (hStore = StoreProviderGetStore(pProvData->hProv, WVT_STOREID_ROOT))
{
AddToStoreChain(hStore, &pProvData->chStores, &pProvData->pahStores);
return(TRUE);
}
return(FALSE);
}
}
cs = 0;
TrustOpenStores(pProvData->hProv, &cs, NULL, 0);
if (cs > 0)
{
if (!(pas = new HCERTSTORE[cs]))
{
pProvData->dwError = ERROR_NOT_ENOUGH_MEMORY;
pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_INITPROV] = TRUST_E_SYSTEM_ERROR;
return(FALSE);
}
if (TrustOpenStores(pProvData->hProv, &cs, pas, 0))
{
for (i = 0; i < cs; i++)
{
AddToStoreChain(pas[i], &pProvData->chStores, &pProvData->pahStores);
}
}
else
{
cs = 0;
}
delete pas;
}
if (cs > 0)
{
return(TRUE);
}
return(FALSE);
}
BOOL WINAPI WTHelperGetAgencyInfo(PCCERT_CONTEXT pCert, DWORD *pcbAgencyInfo, SPC_SP_AGENCY_INFO *pAgencyInfo)
{
PCERT_EXTENSION pExt;
PSPC_SP_AGENCY_INFO pInfo;
DWORD cbInfo;
if (!(pCert) || !(pcbAgencyInfo))
{
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
*pcbAgencyInfo = 0;
if (!(pExt = CertFindExtension(SPC_SP_AGENCY_INFO_OBJID, pCert->pCertInfo->cExtension,
pCert->pCertInfo->rgExtension)))
{
return(FALSE);
}
CryptDecodeObject(X509_ASN_ENCODING, SPC_SP_AGENCY_INFO_STRUCT,
pExt->Value.pbData, pExt->Value.cbData, 0, NULL,
pcbAgencyInfo);
if (*pcbAgencyInfo == 0)
{
return(FALSE);
}
if (!(pAgencyInfo))
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return(FALSE);
}
if (!(CryptDecodeObject(X509_ASN_ENCODING, SPC_SP_AGENCY_INFO_STRUCT,
pExt->Value.pbData, pExt->Value.cbData, 0, pAgencyInfo,
pcbAgencyInfo)))
{
return(FALSE);
}
return(TRUE);
}
BOOL WINAPI WTHelperCheckCertUsage(PCCERT_CONTEXT pCertContext, LPCSTR pszRequestedUsageOID)
{
PCERT_ENHKEY_USAGE pUsage;
DWORD cbUsage;
int i;
cbUsage = 0;
CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &cbUsage);
if (cbUsage > 0)
{
if (!(pUsage = (PCERT_ENHKEY_USAGE)new BYTE[cbUsage]))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(FALSE);
}
if (!(CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
pUsage, &cbUsage)))
{
delete pUsage;
return(FALSE);
}
//
// the cert has enhanced key usage extensions, check if we find ours
//
if (!(_FindKeyUsage(pUsage, pszRequestedUsageOID)))
{
SetLastError(CERT_E_WRONG_USAGE);
delete pUsage;
return(FALSE);
}
delete pUsage;
}
//
// OK... either we have NO EXTENSION or we found our OID in the list in the EXTENSION.
// now, make sure if we have properties that it has been enabled.
//
cbUsage = 0;
CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &cbUsage);
if (cbUsage > 0)
{
if (!(pUsage = (PCERT_ENHKEY_USAGE)new BYTE[cbUsage]))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(FALSE);
}
if (!(CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG,
pUsage, &cbUsage)))
{
delete pUsage;
return(FALSE);
}
//
// the cert has properties, first check if we're disabled
//
if (_FindKeyUsage(pUsage, szOID_YESNO_TRUST_ATTR))
{
SetLastError(CERT_E_WRONG_USAGE);
delete pUsage;
return(FALSE);
}
if (!(_FindKeyUsage(pUsage, pszRequestedUsageOID)))
{
SetLastError(CERT_E_WRONG_USAGE);
delete pUsage;
return(FALSE);
}
delete pUsage;
}
return(TRUE);
}
BOOL _FindKeyUsage(PCERT_ENHKEY_USAGE pUsage, LPCSTR pszRequestedUsageOID)
{
int i;
for (i = 0; i < (int)pUsage->cUsageIdentifier; i++)
{
if (strcmp(pUsage->rgpszUsageIdentifier[i], pszRequestedUsageOID) == 0)
{
return(TRUE); // OK found it!
}
}
return(FALSE);
}
BOOL WINAPI WTHelperIsInRootStore(CRYPT_PROVIDER_DATA *pProvData, PCCERT_CONTEXT pCertContext)
{
if (pProvData->chStores < 1)
{
return(FALSE);
}
//
// check the fast way first!
//
if (pCertContext->hCertStore == pProvData->pahStores[0])
{
//
// it's in the root store!
//
return(TRUE);
}
//
// can't do it the fast way -- do it the slow way!
//
BYTE *pbHash;
DWORD cbHash;
CRYPT_HASH_BLOB sBlob;
PCCERT_CONTEXT pWorkContext;
cbHash = 0;
if (!(CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, NULL, &cbHash)))
{
return(FALSE);
}
if (cbHash < 1)
{
return(FALSE);
}
if (!(pbHash = (BYTE *)WVTNew(cbHash)))
{
return(FALSE);
}
if (!(CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, pbHash, &cbHash)))
{
delete pbHash;
return(FALSE);
}
sBlob.cbData = cbHash;
sBlob.pbData = pbHash;
pWorkContext = CertFindCertificateInStore(pProvData->pahStores[0], pProvData->dwEncoding, 0,
CERT_FIND_SHA1_HASH, &sBlob, NULL);
delete pbHash;
if (pWorkContext)
{
CertFreeCertificateContext(pWorkContext);
return(TRUE);
}
return(FALSE);
}
typedef struct _ENUM_OID_INFO_ARG {
DWORD cOidInfo;
PCCRYPT_OID_INFO *ppOidInfo;
} ENUM_OID_INFO_ARG, *PENUM_OID_INFO_ARG;
static BOOL WINAPI EnumOidInfoCallback(
IN PCCRYPT_OID_INFO pOidInfo,
IN void *pvArg
)
{
PENUM_OID_INFO_ARG pEnumOidInfoArg = (PENUM_OID_INFO_ARG) pvArg;
PCCRYPT_OID_INFO *ppNewOidInfo;
DWORD cOidInfo = pEnumOidInfoArg->cOidInfo;
// DSIE: Bug 152473.
for (DWORD i = 0; i < cOidInfo; i++)
{
if (0 == wcscmp(pOidInfo->pwszName, pEnumOidInfoArg->ppOidInfo[i]->pwszName))
{
return TRUE;
}
}
if (ppNewOidInfo = (PCCRYPT_OID_INFO *) PkiRealloc(
pEnumOidInfoArg->ppOidInfo,
(cOidInfo + 2) * sizeof(PCCRYPT_OID_INFO))) {
ppNewOidInfo[cOidInfo] = pOidInfo;
ppNewOidInfo[cOidInfo + 1] = NULL;
pEnumOidInfoArg->cOidInfo = cOidInfo + 1;
pEnumOidInfoArg->ppOidInfo = ppNewOidInfo;
}
return TRUE;
}
BOOL WINAPI WTHelperGetKnownUsages(DWORD fdwAction, PCCRYPT_OID_INFO **pppOidInfo)
{
if (!(pppOidInfo))
{
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
if (fdwAction == WTH_FREE)
{
PkiFree(*pppOidInfo);
*pppOidInfo = NULL;
return(TRUE);
}
if (fdwAction == WTH_ALLOC)
{
ENUM_OID_INFO_ARG EnumOidInfoArg;
memset(&EnumOidInfoArg, 0, sizeof(EnumOidInfoArg));
CryptEnumOIDInfo(
CRYPT_ENHKEY_USAGE_OID_GROUP_ID,
0, // dwFlags
&EnumOidInfoArg,
EnumOidInfoCallback
);
return (NULL != (*pppOidInfo = EnumOidInfoArg.ppOidInfo));
}
SetLastError(ERROR_INVALID_PARAMETER);
*pppOidInfo = NULL;
return(FALSE);
}
CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
{
return((CRYPT_PROVIDER_DATA *)hStateData);
}