mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 02:18:45 +00:00
crypt32: Halt chain creation when a cycle is detected.
This commit is contained in:
parent
51a9d208ee
commit
b8b787a810
|
@ -212,6 +212,45 @@ static inline BOOL CRYPT_IsCertificateSelfSigned(PCCERT_CONTEXT cert)
|
||||||
&cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
|
&cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CRYPT_FreeChainElement(PCERT_CHAIN_ELEMENT element)
|
||||||
|
{
|
||||||
|
CertFreeCertificateContext(element->pCertContext);
|
||||||
|
CryptMemFree(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CRYPT_CheckSimpleChainForCycles(PCERT_SIMPLE_CHAIN chain)
|
||||||
|
{
|
||||||
|
DWORD i, j, cyclicCertIndex = 0;
|
||||||
|
|
||||||
|
/* O(n^2) - I don't think there's a faster way */
|
||||||
|
for (i = 0; !cyclicCertIndex && i < chain->cElement; i++)
|
||||||
|
for (j = i + 1; !cyclicCertIndex && j < chain->cElement; j++)
|
||||||
|
if (CertCompareCertificate(X509_ASN_ENCODING,
|
||||||
|
chain->rgpElement[i]->pCertContext->pCertInfo,
|
||||||
|
chain->rgpElement[j]->pCertContext->pCertInfo))
|
||||||
|
cyclicCertIndex = j;
|
||||||
|
if (cyclicCertIndex)
|
||||||
|
{
|
||||||
|
chain->rgpElement[cyclicCertIndex]->TrustStatus.dwErrorStatus
|
||||||
|
|= CERT_TRUST_IS_CYCLIC;
|
||||||
|
/* Release remaining certs */
|
||||||
|
for (i = cyclicCertIndex + 1; i < chain->cElement; i++)
|
||||||
|
CRYPT_FreeChainElement(chain->rgpElement[i]);
|
||||||
|
/* Truncate chain */
|
||||||
|
chain->cElement = cyclicCertIndex + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checks whether the chain is cyclic by examining the last element's status */
|
||||||
|
static inline BOOL CRYPT_IsSimpleChainCyclic(PCERT_SIMPLE_CHAIN chain)
|
||||||
|
{
|
||||||
|
if (chain->cElement)
|
||||||
|
return chain->rgpElement[chain->cElement - 1]->TrustStatus.dwErrorStatus
|
||||||
|
& CERT_TRUST_IS_CYCLIC;
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Gets cert's issuer from store, and returns the validity flags associated
|
/* Gets cert's issuer from store, and returns the validity flags associated
|
||||||
* with it. Returns NULL if no issuer whose public key matches cert's
|
* with it. Returns NULL if no issuer whose public key matches cert's
|
||||||
* signature could be found.
|
* signature could be found.
|
||||||
|
@ -233,8 +272,8 @@ static PCCERT_CONTEXT CRYPT_GetIssuerFromStore(HCERTSTORE store,
|
||||||
return issuer;
|
return issuer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL CRYPT_AddCertToSimpleChain(PCERT_SIMPLE_CHAIN chain,
|
static BOOL CRYPT_AddCertToSimpleChain(PCertificateChainEngine engine,
|
||||||
PCCERT_CONTEXT cert, DWORD dwFlags)
|
PCERT_SIMPLE_CHAIN chain, PCCERT_CONTEXT cert, DWORD dwFlags)
|
||||||
{
|
{
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
PCERT_CHAIN_ELEMENT element = CryptMemAlloc(sizeof(CERT_CHAIN_ELEMENT));
|
PCERT_CHAIN_ELEMENT element = CryptMemAlloc(sizeof(CERT_CHAIN_ELEMENT));
|
||||||
|
@ -273,13 +312,15 @@ static BOOL CRYPT_AddCertToSimpleChain(PCERT_SIMPLE_CHAIN chain,
|
||||||
prevElement->TrustStatus.dwErrorStatus |=
|
prevElement->TrustStatus.dwErrorStatus |=
|
||||||
CERT_TRUST_IS_NOT_TIME_NESTED;
|
CERT_TRUST_IS_NOT_TIME_NESTED;
|
||||||
}
|
}
|
||||||
/* FIXME: check valid usages, name constraints, and for cycles */
|
/* FIXME: check valid usages and name constraints */
|
||||||
/* FIXME: initialize the rest of element */
|
/* FIXME: initialize the rest of element */
|
||||||
|
chain->rgpElement[chain->cElement++] = element;
|
||||||
|
if (chain->cElement % engine->CycleDetectionModulus)
|
||||||
|
CRYPT_CheckSimpleChainForCycles(chain);
|
||||||
chain->TrustStatus.dwErrorStatus |=
|
chain->TrustStatus.dwErrorStatus |=
|
||||||
element->TrustStatus.dwErrorStatus;
|
element->TrustStatus.dwErrorStatus;
|
||||||
chain->TrustStatus.dwInfoStatus |=
|
chain->TrustStatus.dwInfoStatus |=
|
||||||
element->TrustStatus.dwInfoStatus;
|
element->TrustStatus.dwInfoStatus;
|
||||||
chain->rgpElement[chain->cElement++] = element;
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -288,12 +329,6 @@ static BOOL CRYPT_AddCertToSimpleChain(PCERT_SIMPLE_CHAIN chain,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CRYPT_FreeChainElement(PCERT_CHAIN_ELEMENT element)
|
|
||||||
{
|
|
||||||
CertFreeCertificateContext(element->pCertContext);
|
|
||||||
CryptMemFree(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void CRYPT_FreeSimpleChain(PCERT_SIMPLE_CHAIN chain)
|
static void CRYPT_FreeSimpleChain(PCERT_SIMPLE_CHAIN chain)
|
||||||
{
|
{
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
@ -327,8 +362,9 @@ static BOOL CRYPT_BuildSimpleChain(HCERTCHAINENGINE hChainEngine,
|
||||||
{
|
{
|
||||||
memset(chain, 0, sizeof(CERT_SIMPLE_CHAIN));
|
memset(chain, 0, sizeof(CERT_SIMPLE_CHAIN));
|
||||||
chain->cbSize = sizeof(CERT_SIMPLE_CHAIN);
|
chain->cbSize = sizeof(CERT_SIMPLE_CHAIN);
|
||||||
ret = CRYPT_AddCertToSimpleChain(chain, cert, 0);
|
ret = CRYPT_AddCertToSimpleChain(engine, chain, cert, 0);
|
||||||
while (ret && !CRYPT_IsCertificateSelfSigned(cert))
|
while (ret && !CRYPT_IsSimpleChainCyclic(chain) &&
|
||||||
|
!CRYPT_IsCertificateSelfSigned(cert))
|
||||||
{
|
{
|
||||||
DWORD flags;
|
DWORD flags;
|
||||||
PCCERT_CONTEXT issuer = CRYPT_GetIssuerFromStore(world, cert,
|
PCCERT_CONTEXT issuer = CRYPT_GetIssuerFromStore(world, cert,
|
||||||
|
@ -336,7 +372,7 @@ static BOOL CRYPT_BuildSimpleChain(HCERTCHAINENGINE hChainEngine,
|
||||||
|
|
||||||
if (issuer)
|
if (issuer)
|
||||||
{
|
{
|
||||||
ret = CRYPT_AddCertToSimpleChain(chain, issuer, flags);
|
ret = CRYPT_AddCertToSimpleChain(engine, chain, issuer, flags);
|
||||||
cert = issuer;
|
cert = issuer;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -1529,14 +1529,13 @@ static ChainCheck chainCheck[] = {
|
||||||
CERT_TRUST_IS_NOT_TIME_VALID, 0 },
|
CERT_TRUST_IS_NOT_TIME_VALID, 0 },
|
||||||
1, simpleStatus8 },
|
1, simpleStatus8 },
|
||||||
TODO_ERROR | TODO_INFO },
|
TODO_ERROR | TODO_INFO },
|
||||||
/* This (cyclic) chain never completes in Wine, so don't test it yet
|
/* This (cyclic) chain fails in Wine */
|
||||||
{ { sizeof(chain9) / sizeof(chain9[0]), chain9 },
|
{ { sizeof(chain9) / sizeof(chain9[0]), chain9 },
|
||||||
{ { 0, CERT_TRUST_HAS_PREFERRED_ISSUER },
|
{ { 0, CERT_TRUST_HAS_PREFERRED_ISSUER },
|
||||||
{ CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT |
|
{ CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT |
|
||||||
CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_CYCLIC, 0 },
|
CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_CYCLIC, 0 },
|
||||||
1, simpleStatus9 },
|
1, simpleStatus9 },
|
||||||
TODO_ERROR | TODO_INFO },
|
TODO_CHAIN | TODO_ERROR | TODO_INFO },
|
||||||
*/
|
|
||||||
{ { sizeof(chain10) / sizeof(chain10[0]), chain10 },
|
{ { sizeof(chain10) / sizeof(chain10[0]), chain10 },
|
||||||
{ { 0, CERT_TRUST_HAS_PREFERRED_ISSUER },
|
{ { 0, CERT_TRUST_HAS_PREFERRED_ISSUER },
|
||||||
{ CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus10 },
|
{ CERT_TRUST_IS_UNTRUSTED_ROOT, 0 }, 1, simpleStatus10 },
|
||||||
|
|
Loading…
Reference in a new issue