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:
parent
8714c11247
commit
dd7a45be7c
|
@ -2594,84 +2594,84 @@ static void CRYPT_VerifyChainRevocation(PCERT_CHAIN_CONTEXT chain,
|
||||||
cContext = 0;
|
cContext = 0;
|
||||||
if (cContext)
|
if (cContext)
|
||||||
{
|
{
|
||||||
PCCERT_CONTEXT *contexts =
|
DWORD i, j, iContext, revocationFlags;
|
||||||
CryptMemAlloc(cContext * sizeof(PCCERT_CONTEXT));
|
CERT_REVOCATION_PARA revocationPara = { sizeof(revocationPara), 0 };
|
||||||
|
CERT_REVOCATION_STATUS revocationStatus =
|
||||||
|
{ sizeof(revocationStatus), 0 };
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
if (contexts)
|
revocationFlags = CERT_VERIFY_REV_CHAIN_FLAG;
|
||||||
|
if (chainFlags & CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY)
|
||||||
|
revocationFlags |= CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION;
|
||||||
|
if (chainFlags & CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT)
|
||||||
|
revocationFlags |= CERT_VERIFY_REV_ACCUMULATIVE_TIMEOUT_FLAG;
|
||||||
|
revocationPara.pftTimeToUse = pTime;
|
||||||
|
if (hAdditionalStore)
|
||||||
{
|
{
|
||||||
DWORD i, j, iContext, revocationFlags;
|
revocationPara.cCertStore = 1;
|
||||||
CERT_REVOCATION_PARA revocationPara = { sizeof(revocationPara), 0 };
|
revocationPara.rgCertStore = &hAdditionalStore;
|
||||||
CERT_REVOCATION_STATUS revocationStatus =
|
revocationPara.hCrlStore = hAdditionalStore;
|
||||||
{ sizeof(revocationStatus), 0 };
|
}
|
||||||
BOOL ret;
|
if (pChainPara->cbSize == sizeof(CERT_CHAIN_PARA))
|
||||||
|
{
|
||||||
|
revocationPara.dwUrlRetrievalTimeout =
|
||||||
|
pChainPara->dwUrlRetrievalTimeout;
|
||||||
|
revocationPara.fCheckFreshnessTime =
|
||||||
|
pChainPara->fCheckRevocationFreshnessTime;
|
||||||
|
revocationPara.dwFreshnessTime =
|
||||||
|
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;
|
||||||
|
|
||||||
for (i = 0, iContext = 0; iContext < cContext && i < chain->cChain;
|
if (j < chain->rgpChain[i]->cElement - 1)
|
||||||
i++)
|
revocationPara.pIssuerCert =
|
||||||
{
|
chain->rgpChain[i]->rgpElement[j + 1]->pCertContext;
|
||||||
for (j = 0; iContext < cContext &&
|
else
|
||||||
j < chain->rgpChain[i]->cElement; j++)
|
revocationPara.pIssuerCert = NULL;
|
||||||
contexts[iContext++] =
|
ret = CertVerifyRevocation(X509_ASN_ENCODING,
|
||||||
chain->rgpChain[i]->rgpElement[j]->pCertContext;
|
CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certToCheck,
|
||||||
}
|
revocationFlags, &revocationPara, &revocationStatus);
|
||||||
revocationFlags = CERT_VERIFY_REV_CHAIN_FLAG;
|
if (!ret)
|
||||||
if (chainFlags & CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY)
|
{
|
||||||
revocationFlags |= CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION;
|
PCERT_CHAIN_ELEMENT element = CRYPT_FindIthElementInChain(
|
||||||
if (chainFlags & CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT)
|
chain, iContext);
|
||||||
revocationFlags |= CERT_VERIFY_REV_ACCUMULATIVE_TIMEOUT_FLAG;
|
DWORD error;
|
||||||
revocationPara.pftTimeToUse = pTime;
|
|
||||||
if (hAdditionalStore)
|
|
||||||
{
|
|
||||||
revocationPara.cCertStore = 1;
|
|
||||||
revocationPara.rgCertStore = &hAdditionalStore;
|
|
||||||
revocationPara.hCrlStore = hAdditionalStore;
|
|
||||||
}
|
|
||||||
if (pChainPara->cbSize == sizeof(CERT_CHAIN_PARA))
|
|
||||||
{
|
|
||||||
revocationPara.dwUrlRetrievalTimeout =
|
|
||||||
pChainPara->dwUrlRetrievalTimeout;
|
|
||||||
revocationPara.fCheckFreshnessTime =
|
|
||||||
pChainPara->fCheckRevocationFreshnessTime;
|
|
||||||
revocationPara.dwFreshnessTime =
|
|
||||||
pChainPara->dwRevocationFreshnessTime;
|
|
||||||
}
|
|
||||||
ret = CertVerifyRevocation(X509_ASN_ENCODING,
|
|
||||||
CERT_CONTEXT_REVOCATION_TYPE, cContext, (void **)contexts,
|
|
||||||
revocationFlags, &revocationPara, &revocationStatus);
|
|
||||||
if (!ret)
|
|
||||||
{
|
|
||||||
PCERT_CHAIN_ELEMENT element =
|
|
||||||
CRYPT_FindIthElementInChain(chain, revocationStatus.dwIndex);
|
|
||||||
DWORD error;
|
|
||||||
|
|
||||||
switch (revocationStatus.dwError)
|
switch (revocationStatus.dwError)
|
||||||
{
|
{
|
||||||
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;
|
||||||
break;
|
break;
|
||||||
case CRYPT_E_REVOCATION_OFFLINE:
|
case CRYPT_E_REVOCATION_OFFLINE:
|
||||||
error = CERT_TRUST_IS_OFFLINE_REVOCATION;
|
error = CERT_TRUST_IS_OFFLINE_REVOCATION;
|
||||||
break;
|
break;
|
||||||
case CRYPT_E_REVOKED:
|
case CRYPT_E_REVOKED:
|
||||||
error = CERT_TRUST_IS_REVOKED;
|
error = CERT_TRUST_IS_REVOKED;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARN("unmapped error %08x\n", revocationStatus.dwError);
|
WARN("unmapped error %08x\n", revocationStatus.dwError);
|
||||||
error = 0;
|
error = 0;
|
||||||
|
}
|
||||||
|
if (element)
|
||||||
|
{
|
||||||
|
/* FIXME: set element's pRevocationInfo member */
|
||||||
|
element->TrustStatus.dwErrorStatus |= error;
|
||||||
|
}
|
||||||
|
chain->TrustStatus.dwErrorStatus |= error;
|
||||||
}
|
}
|
||||||
if (element)
|
|
||||||
{
|
|
||||||
/* FIXME: set element's pRevocationInfo member */
|
|
||||||
element->TrustStatus.dwErrorStatus |= error;
|
|
||||||
}
|
|
||||||
chain->TrustStatus.dwErrorStatus |= error;
|
|
||||||
}
|
}
|
||||||
CryptMemFree(contexts);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue