737 lines
20 KiB
C++
737 lines
20 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
//
|
|
// File: trustapi.cpp
|
|
//
|
|
// Contents: Microsoft Internet Security Trust APIs
|
|
//
|
|
// Functions: TrustFindIssuerCertificate
|
|
// TrustOpenStores
|
|
// TrustDecode
|
|
// TrustFreeDecode
|
|
//
|
|
// *** local functions ***
|
|
// _CompareAuthKeyId
|
|
// _CompareAuthKeyId2
|
|
// _SetCertErrorAndHygiene
|
|
// _GetExternalIssuerCert
|
|
//
|
|
// History: 20-Nov-1997 pberkman created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "global.hxx"
|
|
|
|
|
|
BOOL _CompareAuthKeyId(DWORD dwEncoding, PCCERT_CONTEXT pChildContext,
|
|
PCCERT_CONTEXT pParentContext);
|
|
BOOL _CompareAuthKeyId2(DWORD dwEncoding, PCCERT_CONTEXT pChildContext,
|
|
PCCERT_CONTEXT pParentContext);
|
|
BOOL _SetCertErrorAndHygiene(PCCERT_CONTEXT pSubjectContext,
|
|
PCCERT_CONTEXT pIssuerContext,
|
|
DWORD dwCurrentConfidence, DWORD *pdwError);
|
|
PCCERT_CONTEXT _GetExternalIssuerCert(PCCERT_CONTEXT pContext,
|
|
DWORD dwEncoding,
|
|
DWORD *pdwRetError,
|
|
DWORD *pdwConfidence,
|
|
FILETIME *psftVerifyAsOf);
|
|
|
|
void _SetConfidenceOnIssuer(DWORD dwEncoding, PCCERT_CONTEXT pChildCert, PCCERT_CONTEXT pTestIssuerCert,
|
|
DWORD dwVerificationFlag, FILETIME *psftVerifyAsOf, DWORD *pdwConfidence,
|
|
DWORD *pdwError);
|
|
|
|
PCCERT_CONTEXT WINAPI TrustFindIssuerCertificate(PCCERT_CONTEXT pChildContext,
|
|
DWORD dwEncoding,
|
|
DWORD chStores,
|
|
HCERTSTORE *pahStores,
|
|
FILETIME *psftVerifyAsOf,
|
|
DWORD *pdwConfidence,
|
|
DWORD *pdwError,
|
|
DWORD dwFlags)
|
|
{
|
|
if (!(pChildContext) ||
|
|
!(pahStores) ||
|
|
!(psftVerifyAsOf) ||
|
|
(dwFlags != 0))
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return(NULL);
|
|
}
|
|
|
|
PCCERT_CONTEXT pCertContext;
|
|
DWORD fdwRetError;
|
|
DWORD fdwWork;
|
|
DWORD dwError;
|
|
PCCERT_CONTEXT pCertWithHighestConfidence;
|
|
DWORD dwHighestConfidence;
|
|
DWORD dwConfidence;
|
|
|
|
if (pdwError)
|
|
{
|
|
*pdwError = ERROR_SUCCESS;
|
|
}
|
|
|
|
dwConfidence = 0;
|
|
|
|
dwHighestConfidence = 0;
|
|
pCertWithHighestConfidence = NULL;
|
|
|
|
fdwRetError = 0;
|
|
fdwWork = 0;
|
|
|
|
for (int i = 0; i < (int)chStores; i++)
|
|
{
|
|
fdwWork = CERT_STORE_SIGNATURE_FLAG;
|
|
|
|
pCertContext = NULL;
|
|
|
|
while (pCertContext = CertGetIssuerCertificateFromStore(pahStores[i],
|
|
pChildContext,
|
|
pCertContext,
|
|
&fdwWork))
|
|
{
|
|
_SetConfidenceOnIssuer(dwEncoding, pChildContext, pCertContext, fdwWork,
|
|
psftVerifyAsOf, &dwConfidence, &dwError);
|
|
|
|
if (dwConfidence > dwHighestConfidence)
|
|
{
|
|
if (pCertWithHighestConfidence)
|
|
{
|
|
CertFreeCertificateContext(pCertWithHighestConfidence);
|
|
}
|
|
|
|
dwHighestConfidence = dwConfidence;
|
|
pCertWithHighestConfidence = CertDuplicateCertificateContext(pCertContext);
|
|
fdwRetError = dwError;
|
|
}
|
|
|
|
if (dwConfidence >= CERT_CONFIDENCE_HIGHEST)
|
|
{
|
|
if (pdwError)
|
|
{
|
|
*pdwError = dwError;
|
|
}
|
|
|
|
if (pdwConfidence)
|
|
{
|
|
*pdwConfidence = dwConfidence;
|
|
}
|
|
|
|
CertFreeCertificateContext(pCertContext);
|
|
|
|
return(pCertWithHighestConfidence);
|
|
}
|
|
|
|
fdwWork = CERT_STORE_SIGNATURE_FLAG;
|
|
}
|
|
}
|
|
|
|
if (!(dwHighestConfidence & CERT_CONFIDENCE_HYGIENE))
|
|
{
|
|
if (pCertContext = _GetExternalIssuerCert(pChildContext,
|
|
dwEncoding,
|
|
&fdwRetError,
|
|
&dwConfidence,
|
|
psftVerifyAsOf))
|
|
{
|
|
if (dwHighestConfidence < dwConfidence)
|
|
{
|
|
CertFreeCertificateContext(pCertWithHighestConfidence);
|
|
|
|
pCertWithHighestConfidence = pCertContext;
|
|
|
|
dwHighestConfidence = dwConfidence;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pdwError)
|
|
{
|
|
*pdwError = fdwRetError;
|
|
}
|
|
|
|
if (pdwConfidence)
|
|
{
|
|
*pdwConfidence = dwHighestConfidence;
|
|
}
|
|
|
|
return(pCertWithHighestConfidence);
|
|
}
|
|
|
|
BOOL WINAPI TrustOpenStores(HCRYPTPROV hProv, OUT DWORD *pchStores,
|
|
HCERTSTORE *pahStores, DWORD dwFlags)
|
|
{
|
|
BOOL fRet;
|
|
DWORD cs = 0;
|
|
HCERTSTORE pas[WVT_STOREID_MAX];
|
|
|
|
fRet = FALSE;
|
|
|
|
if (!(pchStores) ||
|
|
(dwFlags != 0))
|
|
{
|
|
goto ErrorInvalidParam;
|
|
}
|
|
|
|
|
|
//
|
|
// ROOT store - ALWAYS #0 !!!!
|
|
//
|
|
if (!(pas[cs] = StoreProviderGetStore(hProv, WVT_STOREID_ROOT)))
|
|
{
|
|
goto ErrorNoRootStore;
|
|
}
|
|
|
|
cs++;
|
|
|
|
if (pas[cs] = StoreProviderGetStore(hProv, WVT_STOREID_TRUST))
|
|
{
|
|
cs++;
|
|
}
|
|
|
|
if (pas[cs] = StoreProviderGetStore(hProv, WVT_STOREID_CA))
|
|
{
|
|
cs++;
|
|
}
|
|
|
|
if (pas[cs] = StoreProviderGetStore(hProv, WVT_STOREID_MY))
|
|
{
|
|
cs++;
|
|
}
|
|
|
|
if ((pahStores) && (cs > *pchStores))
|
|
{
|
|
*pchStores = cs;
|
|
goto ErrorMoreData;
|
|
}
|
|
|
|
*pchStores = cs;
|
|
|
|
fRet = TRUE;
|
|
|
|
if (!(pahStores))
|
|
{
|
|
goto ErrorMoreData;
|
|
}
|
|
|
|
DWORD i;
|
|
|
|
for (i = 0; i < cs; i++)
|
|
{
|
|
pahStores[i] = pas[i];
|
|
}
|
|
|
|
CommonReturn:
|
|
return(fRet);
|
|
|
|
|
|
ErrorReturn:
|
|
while (cs > 0)
|
|
{
|
|
CertCloseStore(pas[cs - 1], 0);
|
|
cs--;
|
|
}
|
|
|
|
goto CommonReturn;
|
|
|
|
SET_ERROR_VAR_EX(DBG_SS, ErrorMoreData, ERROR_MORE_DATA);
|
|
SET_ERROR_VAR_EX(DBG_SS, ErrorNoRootStore, TRUST_E_SYSTEM_ERROR);
|
|
SET_ERROR_VAR_EX(DBG_SS, ErrorInvalidParam, ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
|
|
BOOL WINAPI TrustIsCertificateSelfSigned(PCCERT_CONTEXT pContext,
|
|
DWORD dwEncoding,
|
|
DWORD dwFlags)
|
|
{
|
|
if (!(pContext) ||
|
|
(dwFlags != 0))
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return(FALSE);
|
|
}
|
|
|
|
if (!(CertCompareCertificateName(dwEncoding,
|
|
&pContext->pCertInfo->Issuer,
|
|
&pContext->pCertInfo->Subject)))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
DWORD dwFlag;
|
|
|
|
dwFlag = CERT_STORE_SIGNATURE_FLAG;
|
|
|
|
if (!(CertVerifySubjectCertificateContext(pContext, pContext, &dwFlag)) ||
|
|
(dwFlag & CERT_STORE_SIGNATURE_FLAG))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
#define sz_CRYPTNET_DLL "cryptnet.dll"
|
|
#define sz_CryptGetObjectUrl "CryptGetObjectUrl"
|
|
#define sz_CryptRetrieveObjectByUrlW "CryptRetrieveObjectByUrlW"
|
|
typedef BOOL (WINAPI *PFN_CRYPT_GET_OBJECT_URL)(
|
|
IN LPCSTR pszUrlOid,
|
|
IN LPVOID pvPara,
|
|
IN DWORD dwFlags,
|
|
OUT OPTIONAL PCRYPT_URL_ARRAY pUrlArray,
|
|
IN OUT DWORD* pcbUrlArray,
|
|
OUT OPTIONAL PCRYPT_URL_INFO pUrlInfo,
|
|
IN OUT OPTIONAL DWORD* pcbUrlInfo,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
);
|
|
|
|
typedef BOOL (WINAPI *PFN_CRYPT_RETRIEVE_OBJECT_BY_URLW)(
|
|
IN LPCWSTR pszUrl,
|
|
IN LPCSTR pszObjectOid,
|
|
IN DWORD dwRetrievalFlags,
|
|
IN DWORD dwTimeout,
|
|
OUT LPVOID* ppvObject,
|
|
IN HCRYPTASYNC hAsyncRetrieve,
|
|
IN OPTIONAL PCRYPT_CREDENTIALS pCredentials,
|
|
IN OPTIONAL LPVOID pvVerify,
|
|
IN OPTIONAL LPVOID pvReserved
|
|
);
|
|
|
|
|
|
PCCERT_CONTEXT _GetExternalIssuerCert(PCCERT_CONTEXT pContext,
|
|
DWORD dwEncoding,
|
|
DWORD *pdwRetError,
|
|
DWORD *pdwConfidence,
|
|
FILETIME *psftVerifyAsOf)
|
|
{
|
|
*pdwConfidence = 0;
|
|
|
|
#if (USE_IEv4CRYPT32)
|
|
|
|
return(NULL);
|
|
|
|
#else
|
|
|
|
|
|
DWORD cbUrlArray;
|
|
CRYPT_URL_ARRAY *pUrlArray;
|
|
PCCERT_CONTEXT pIssuer;
|
|
PCCERT_CONTEXT pCertBestMatch;
|
|
DWORD dwHighestConfidence;
|
|
DWORD dwConfidence;
|
|
DWORD dwStatus;
|
|
DWORD dwError;
|
|
DWORD i;
|
|
|
|
pCertBestMatch = NULL;
|
|
pIssuer = NULL;
|
|
pUrlArray = NULL;
|
|
cbUrlArray = 0;
|
|
dwHighestConfidence = 0;
|
|
|
|
HMODULE hDll = NULL;
|
|
PFN_CRYPT_GET_OBJECT_URL pfnCryptGetObjectUrl;
|
|
PFN_CRYPT_RETRIEVE_OBJECT_BY_URLW pfnCryptRetrieveObjectByUrlW;
|
|
|
|
if (NULL == (hDll = LoadLibraryA(sz_CRYPTNET_DLL)))
|
|
goto LoadCryptNetDllError;
|
|
|
|
if (NULL == (pfnCryptGetObjectUrl =
|
|
(PFN_CRYPT_GET_OBJECT_URL) GetProcAddress(hDll,
|
|
sz_CryptGetObjectUrl)))
|
|
goto CryptGetObjectUrlProcAddressError;
|
|
|
|
if (NULL == (pfnCryptRetrieveObjectByUrlW =
|
|
(PFN_CRYPT_RETRIEVE_OBJECT_BY_URLW) GetProcAddress(hDll,
|
|
sz_CryptRetrieveObjectByUrlW)))
|
|
goto CryptRetrieveObjectByUrlWProcAddressError;
|
|
|
|
|
|
if (!(pfnCryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)pContext, 0, NULL, &cbUrlArray, NULL, NULL, NULL)) ||
|
|
(cbUrlArray < 1))
|
|
{
|
|
goto GetObjectUrlFailed;
|
|
}
|
|
|
|
if (!(pUrlArray = (CRYPT_URL_ARRAY *) new BYTE[cbUrlArray]))
|
|
{
|
|
goto MemoryError;
|
|
}
|
|
|
|
memset(pUrlArray, 0x00, cbUrlArray);
|
|
|
|
if (!(pfnCryptGetObjectUrl(URL_OID_CERTIFICATE_ISSUER, (void *)pContext, 0, pUrlArray, &cbUrlArray, NULL, NULL, NULL)))
|
|
{
|
|
goto GetObjectUrlFailed;
|
|
}
|
|
|
|
for (i = 0; i < pUrlArray->cUrl; i++)
|
|
{
|
|
if (pIssuer)
|
|
{
|
|
CertFreeCertificateContext(pIssuer);
|
|
pIssuer = NULL;
|
|
}
|
|
|
|
if (pfnCryptRetrieveObjectByUrlW(pUrlArray->rgwszUrl[i], CONTEXT_OID_CERTIFICATE, 0, 0, (void **)&pIssuer,
|
|
NULL, NULL, NULL, NULL))
|
|
{
|
|
if (!(CertCompareCertificateName(X509_ASN_ENCODING, &pContext->pCertInfo->Issuer,
|
|
&pIssuer->pCertInfo->Subject)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
dwStatus = CERT_STORE_SIGNATURE_FLAG;
|
|
|
|
if (!(CertVerifySubjectCertificateContext(pContext, pIssuer, &dwStatus)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
dwError = 0;
|
|
_SetConfidenceOnIssuer(dwEncoding, pContext, pIssuer, dwStatus, psftVerifyAsOf,
|
|
&dwConfidence, &dwError);
|
|
|
|
if (dwError != 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (dwConfidence > dwHighestConfidence)
|
|
{
|
|
if (pCertBestMatch)
|
|
{
|
|
CertFreeCertificateContext(pCertBestMatch);
|
|
}
|
|
|
|
dwHighestConfidence = dwConfidence;
|
|
pCertBestMatch = CertDuplicateCertificateContext(pIssuer);
|
|
}
|
|
|
|
if (dwConfidence >= CERT_CONFIDENCE_HIGHEST)
|
|
{
|
|
goto CommonReturn;
|
|
}
|
|
}
|
|
}
|
|
|
|
goto RetrieveObjectFailed;
|
|
|
|
|
|
CommonReturn:
|
|
if (hDll)
|
|
FreeLibrary(hDll);
|
|
|
|
if (pIssuer)
|
|
{
|
|
CertFreeCertificateContext(pIssuer);
|
|
}
|
|
|
|
if (pUrlArray)
|
|
{
|
|
delete pUrlArray;
|
|
}
|
|
|
|
*pdwConfidence = dwHighestConfidence;
|
|
|
|
return(pCertBestMatch);
|
|
|
|
ErrorReturn:
|
|
|
|
if (pCertBestMatch)
|
|
{
|
|
CertFreeCertificateContext(pCertBestMatch);
|
|
pCertBestMatch = NULL;
|
|
}
|
|
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR_EX(DBG_SS, LoadCryptNetDllError)
|
|
TRACE_ERROR_EX(DBG_SS, CryptGetObjectUrlProcAddressError)
|
|
TRACE_ERROR_EX(DBG_SS, CryptRetrieveObjectByUrlWProcAddressError)
|
|
|
|
TRACE_ERROR_EX(DBG_SS, GetObjectUrlFailed);
|
|
TRACE_ERROR_EX(DBG_SS, RetrieveObjectFailed);
|
|
|
|
SET_ERROR_VAR_EX(DBG_SS, MemoryError, ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
#endif // USE_IEv4CRYPT32
|
|
}
|
|
|
|
BOOL WINAPI TrustDecode(DWORD dwModuleId, BYTE **ppbRet, DWORD *pcbRet, DWORD cbHint,
|
|
DWORD dwEncoding, const char *pcszOID, const BYTE *pbEncoded, DWORD cbEncoded,
|
|
DWORD dwDecodeFlags)
|
|
{
|
|
if (!(*ppbRet = new BYTE[cbHint]))
|
|
{
|
|
goto MemoryError;
|
|
}
|
|
|
|
*pcbRet = cbHint;
|
|
|
|
if (!(CryptDecodeObject(dwEncoding, pcszOID, pbEncoded, cbEncoded, dwDecodeFlags,
|
|
*ppbRet, pcbRet)))
|
|
{
|
|
if (GetLastError() != ERROR_MORE_DATA)
|
|
{
|
|
goto DecodeError;
|
|
}
|
|
}
|
|
|
|
if (cbHint < *pcbRet)
|
|
{
|
|
DBG_PRINTF((DBG_SS, "****** TrustDecode(0x%08.8lX): recalling due to bad size: hint: %lu actual: %lu\r\n",
|
|
dwModuleId, cbHint, *pcbRet));
|
|
|
|
DELETE_OBJECT(*ppbRet);
|
|
|
|
return(TrustDecode(dwModuleId, ppbRet, pcbRet, *pcbRet, dwEncoding, pcszOID,
|
|
pbEncoded, cbEncoded, dwDecodeFlags));
|
|
}
|
|
|
|
# if DBG
|
|
if ((cbHint / 3) > *pcbRet)
|
|
{
|
|
DBG_PRINTF((DBG_SS, "TrustDecode(0x%08.8lX): hint too big. hint: %lu actual: %lu\r\n",
|
|
dwModuleId, cbHint, *pcbRet));
|
|
}
|
|
# endif
|
|
|
|
return(TRUE);
|
|
|
|
ErrorReturn:
|
|
DELETE_OBJECT(*ppbRet);
|
|
return(FALSE);
|
|
|
|
TRACE_ERROR_EX(DBG_SS, DecodeError);
|
|
SET_ERROR_VAR_EX(DBG_SS, MemoryError, ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
BOOL WINAPI TrustFreeDecode(DWORD dwModuleId, BYTE **pbAllocated)
|
|
{
|
|
DELETE_OBJECT(*pbAllocated);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
void _SetConfidenceOnIssuer(DWORD dwEncoding, PCCERT_CONTEXT pChildCert, PCCERT_CONTEXT pTestIssuerCert,
|
|
DWORD dwVerificationFlag, FILETIME *psftVerifyAsOf, DWORD *pdwConfidence,
|
|
DWORD *pdwError)
|
|
{
|
|
*pdwConfidence = 0;
|
|
|
|
if (!(dwVerificationFlag & CERT_STORE_SIGNATURE_FLAG))
|
|
{
|
|
*pdwConfidence |= CERT_CONFIDENCE_SIG;
|
|
}
|
|
|
|
if (CertVerifyTimeValidity(psftVerifyAsOf, pTestIssuerCert->pCertInfo) == 0)
|
|
{
|
|
*pdwConfidence |= CERT_CONFIDENCE_TIME;
|
|
}
|
|
|
|
if (CertVerifyValidityNesting(pChildCert->pCertInfo, pTestIssuerCert->pCertInfo))
|
|
{
|
|
*pdwConfidence |= CERT_CONFIDENCE_TIMENEST;
|
|
}
|
|
|
|
if (_CompareAuthKeyId(dwEncoding, pChildCert, pTestIssuerCert))
|
|
{
|
|
*pdwConfidence |= CERT_CONFIDENCE_AUTHIDEXT;
|
|
}
|
|
else if (_CompareAuthKeyId2(dwEncoding, pChildCert, pTestIssuerCert))
|
|
{
|
|
*pdwConfidence |= CERT_CONFIDENCE_AUTHIDEXT;
|
|
}
|
|
|
|
if (_SetCertErrorAndHygiene(pChildCert, pTestIssuerCert, *pdwConfidence, pdwError))
|
|
{
|
|
*pdwConfidence |= CERT_CONFIDENCE_HYGIENE;
|
|
}
|
|
}
|
|
|
|
BOOL _SetCertErrorAndHygiene(PCCERT_CONTEXT pSubjectContext, PCCERT_CONTEXT pIssuerContext,
|
|
DWORD dwCurrentConfidence, DWORD *pdwError)
|
|
{
|
|
*pdwError = ERROR_SUCCESS;
|
|
|
|
if (!(dwCurrentConfidence & CERT_CONFIDENCE_SIG))
|
|
{
|
|
*pdwError = TRUST_E_CERT_SIGNATURE;
|
|
return(FALSE);
|
|
}
|
|
|
|
if ((dwCurrentConfidence & CERT_CONFIDENCE_SIG) &&
|
|
(dwCurrentConfidence & CERT_CONFIDENCE_TIME) &&
|
|
(dwCurrentConfidence & CERT_CONFIDENCE_TIMENEST) &&
|
|
(dwCurrentConfidence & CERT_CONFIDENCE_AUTHIDEXT))
|
|
{
|
|
return(TRUE);
|
|
}
|
|
|
|
if (dwCurrentConfidence & CERT_CONFIDENCE_AUTHIDEXT)
|
|
{
|
|
return(TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
BOOL _CompareAuthKeyId2(DWORD dwEncoding, PCCERT_CONTEXT pChildContext, PCCERT_CONTEXT pParentContext)
|
|
{
|
|
DWORD i;
|
|
PCERT_EXTENSION pExt;
|
|
DWORD cbIdInfo;
|
|
PCERT_AUTHORITY_KEY_ID2_INFO pIdInfo;
|
|
BOOL fRet;
|
|
|
|
|
|
pIdInfo = NULL;
|
|
|
|
if (pChildContext->pCertInfo->cExtension < 1)
|
|
{
|
|
goto NoExtensions;
|
|
}
|
|
|
|
if (!(pExt = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER2, pChildContext->pCertInfo->cExtension,
|
|
pChildContext->pCertInfo->rgExtension)))
|
|
{
|
|
goto NoExtensions;
|
|
}
|
|
|
|
if (!(TrustDecode(WVT_MODID_WINTRUST, (BYTE **)&pIdInfo, &cbIdInfo, 103,
|
|
dwEncoding, X509_AUTHORITY_KEY_ID2, pExt->Value.pbData, pExt->Value.cbData,
|
|
CRYPT_DECODE_NOCOPY_FLAG)))
|
|
{
|
|
goto DecodeFailed;
|
|
}
|
|
|
|
for (i = 0; i < pIdInfo->AuthorityCertIssuer.cAltEntry; i++)
|
|
{
|
|
if (pIdInfo->AuthorityCertIssuer.rgAltEntry[i].dwAltNameChoice ==
|
|
CERT_ALT_NAME_DIRECTORY_NAME)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == pIdInfo->AuthorityCertIssuer.cAltEntry)
|
|
{
|
|
goto NoAltDirectoryName;
|
|
}
|
|
|
|
if (!(CertCompareCertificateName(dwEncoding,
|
|
&pIdInfo->AuthorityCertIssuer.rgAltEntry[i].DirectoryName,
|
|
&pParentContext->pCertInfo->Issuer)))
|
|
{
|
|
goto IncorrectIssuer;
|
|
}
|
|
|
|
//
|
|
// issuer certificate's serial number must match
|
|
//
|
|
if (!(CertCompareIntegerBlob(&pIdInfo->AuthorityCertSerialNumber,
|
|
&pParentContext->pCertInfo->SerialNumber)))
|
|
{
|
|
goto IncorrectIssuer;
|
|
}
|
|
|
|
fRet = TRUE;
|
|
|
|
CommonReturn:
|
|
if (pIdInfo)
|
|
{
|
|
TrustFreeDecode(WVT_MODID_WINTRUST, (BYTE **)&pIdInfo);
|
|
}
|
|
return(fRet);
|
|
|
|
ErrorReturn:
|
|
fRet = FALSE;
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR_EX(DBG_SS, NoExtensions);
|
|
TRACE_ERROR_EX(DBG_SS, DecodeFailed);
|
|
TRACE_ERROR_EX(DBG_SS, IncorrectIssuer);
|
|
TRACE_ERROR_EX(DBG_SS, NoAltDirectoryName);
|
|
}
|
|
|
|
BOOL _CompareAuthKeyId(DWORD dwEncoding, PCCERT_CONTEXT pChildContext, PCCERT_CONTEXT pParentContext)
|
|
{
|
|
PCERT_EXTENSION pExt;
|
|
PCERT_AUTHORITY_KEY_ID_INFO pChildKeyIdInfo;
|
|
DWORD cbKeyIdInfo;
|
|
BOOL fRet;
|
|
|
|
pChildKeyIdInfo = NULL;
|
|
pExt = NULL;
|
|
|
|
if (pChildContext->pCertInfo->cExtension < 1)
|
|
{
|
|
goto NoExtensions;
|
|
}
|
|
|
|
pChildKeyIdInfo = NULL;
|
|
|
|
if (!(pExt = CertFindExtension(szOID_AUTHORITY_KEY_IDENTIFIER,
|
|
pChildContext->pCertInfo->cExtension,
|
|
pChildContext->pCertInfo->rgExtension)))
|
|
{
|
|
goto NoExtensions;
|
|
}
|
|
|
|
if (!(TrustDecode(WVT_MODID_WINTRUST, (BYTE **)&pChildKeyIdInfo, &cbKeyIdInfo, 104,
|
|
dwEncoding, X509_AUTHORITY_KEY_ID, pExt->Value.pbData, pExt->Value.cbData,
|
|
CRYPT_DECODE_NOCOPY_FLAG)))
|
|
{
|
|
goto DecodeFailed;
|
|
}
|
|
|
|
if ((pChildKeyIdInfo->CertIssuer.cbData < 1) ||
|
|
(pChildKeyIdInfo->CertSerialNumber.cbData < 1))
|
|
{
|
|
goto NoKeyId;
|
|
}
|
|
|
|
//
|
|
// issuer certificate's issuer name must match
|
|
//
|
|
if (!(CertCompareCertificateName(dwEncoding, &pChildKeyIdInfo->CertIssuer,
|
|
&pParentContext->pCertInfo->Issuer)))
|
|
{
|
|
goto IncorrectIssuer;
|
|
}
|
|
|
|
//
|
|
// issuer certificate's serial number must match
|
|
//
|
|
if (!(CertCompareIntegerBlob(&pChildKeyIdInfo->CertSerialNumber,
|
|
&pParentContext->pCertInfo->SerialNumber)))
|
|
{
|
|
goto IncorrectIssuer;
|
|
}
|
|
|
|
fRet = TRUE;
|
|
|
|
CommonReturn:
|
|
if (pChildKeyIdInfo)
|
|
{
|
|
TrustFreeDecode(WVT_MODID_WINTRUST, (BYTE **)&pChildKeyIdInfo);
|
|
}
|
|
return(fRet);
|
|
|
|
ErrorReturn:
|
|
fRet = FALSE;
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR_EX(DBG_SS, NoExtensions);
|
|
TRACE_ERROR_EX(DBG_SS, DecodeFailed);
|
|
TRACE_ERROR_EX(DBG_SS, NoKeyId);
|
|
TRACE_ERROR_EX(DBG_SS, IncorrectIssuer);
|
|
}
|
|
|