crypt32: Check revocation status of chain element-by-element.

Due to a quirk in CertVerifyRevocation (see its tests), checking an
entire chain doesn't appear to be supported, even though the API would
appear to support doing so.  Checking element by element allows
revocation to be checked for the entire chain.
This commit is contained in:
Juan Lang 2009-12-02 12:48:59 -08:00 committed by Alexandre Julliard
parent 8714c11247
commit dd7a45be7c
1 changed files with 72 additions and 72 deletions

View File

@ -2593,11 +2593,6 @@ static void CRYPT_VerifyChainRevocation(PCERT_CHAIN_CONTEXT chain,
else else
cContext = 0; cContext = 0;
if (cContext) if (cContext)
{
PCCERT_CONTEXT *contexts =
CryptMemAlloc(cContext * sizeof(PCCERT_CONTEXT));
if (contexts)
{ {
DWORD i, j, iContext, revocationFlags; DWORD i, j, iContext, revocationFlags;
CERT_REVOCATION_PARA revocationPara = { sizeof(revocationPara), 0 }; CERT_REVOCATION_PARA revocationPara = { sizeof(revocationPara), 0 };
@ -2605,14 +2600,6 @@ static void CRYPT_VerifyChainRevocation(PCERT_CHAIN_CONTEXT chain,
{ sizeof(revocationStatus), 0 }; { sizeof(revocationStatus), 0 };
BOOL ret; BOOL ret;
for (i = 0, iContext = 0; iContext < cContext && i < chain->cChain;
i++)
{
for (j = 0; iContext < cContext &&
j < chain->rgpChain[i]->cElement; j++)
contexts[iContext++] =
chain->rgpChain[i]->rgpElement[j]->pCertContext;
}
revocationFlags = CERT_VERIFY_REV_CHAIN_FLAG; revocationFlags = CERT_VERIFY_REV_CHAIN_FLAG;
if (chainFlags & CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY) if (chainFlags & CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY)
revocationFlags |= CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION; revocationFlags |= CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION;
@ -2634,13 +2621,26 @@ static void CRYPT_VerifyChainRevocation(PCERT_CHAIN_CONTEXT chain,
revocationPara.dwFreshnessTime = revocationPara.dwFreshnessTime =
pChainPara->dwRevocationFreshnessTime; pChainPara->dwRevocationFreshnessTime;
} }
for (i = 0, iContext = 0; iContext < cContext && i < chain->cChain; i++)
{
for (j = 0; iContext < cContext &&
j < chain->rgpChain[i]->cElement; j++, iContext++)
{
PCCERT_CONTEXT certToCheck =
chain->rgpChain[i]->rgpElement[j]->pCertContext;
if (j < chain->rgpChain[i]->cElement - 1)
revocationPara.pIssuerCert =
chain->rgpChain[i]->rgpElement[j + 1]->pCertContext;
else
revocationPara.pIssuerCert = NULL;
ret = CertVerifyRevocation(X509_ASN_ENCODING, ret = CertVerifyRevocation(X509_ASN_ENCODING,
CERT_CONTEXT_REVOCATION_TYPE, cContext, (void **)contexts, CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certToCheck,
revocationFlags, &revocationPara, &revocationStatus); revocationFlags, &revocationPara, &revocationStatus);
if (!ret) if (!ret)
{ {
PCERT_CHAIN_ELEMENT element = PCERT_CHAIN_ELEMENT element = CRYPT_FindIthElementInChain(
CRYPT_FindIthElementInChain(chain, revocationStatus.dwIndex); chain, iContext);
DWORD error; DWORD error;
switch (revocationStatus.dwError) switch (revocationStatus.dwError)
@ -2648,8 +2648,8 @@ static void CRYPT_VerifyChainRevocation(PCERT_CHAIN_CONTEXT chain,
case CRYPT_E_NO_REVOCATION_CHECK: case CRYPT_E_NO_REVOCATION_CHECK:
case CRYPT_E_NO_REVOCATION_DLL: case CRYPT_E_NO_REVOCATION_DLL:
case CRYPT_E_NOT_IN_REVOCATION_DATABASE: case CRYPT_E_NOT_IN_REVOCATION_DATABASE:
/* If the revocation status is unknown, it's assumed to be /* If the revocation status is unknown, it's assumed
* offline too. * to be offline too.
*/ */
error = CERT_TRUST_REVOCATION_STATUS_UNKNOWN | error = CERT_TRUST_REVOCATION_STATUS_UNKNOWN |
CERT_TRUST_IS_OFFLINE_REVOCATION; CERT_TRUST_IS_OFFLINE_REVOCATION;
@ -2671,7 +2671,7 @@ static void CRYPT_VerifyChainRevocation(PCERT_CHAIN_CONTEXT chain,
} }
chain->TrustStatus.dwErrorStatus |= error; chain->TrustStatus.dwErrorStatus |= error;
} }
CryptMemFree(contexts); }
} }
} }
} }