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