Module: wine
Branch: master
Commit: d94e4d315a573db454eb4ec3761242ff8b3c24e2
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d94e4d315a573db454eb4ec37…
Author: Juan Lang <juan.lang(a)gmail.com>
Date: Thu Nov 5 13:12:07 2009 -0800
crypt32: Permit lack of key usage extension on root certificates.
This reverts 60770fb011b0a60d7862e7fe9c7a6d24d68ac0ad, although it
updates the comments to give a reason. Thanks to Matt Van Gundy for
pointing it out to me.
---
dlls/crypt32/chain.c | 29 ++++++++++++++++++++---------
1 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c
index c4ecfa4..c9ca356 100644
--- a/dlls/crypt32/chain.c
+++ b/dlls/crypt32/chain.c
@@ -1083,7 +1083,7 @@ static void dump_element(PCCERT_CONTEXT cert)
}
static BOOL CRYPT_KeyUsageValid(PCertificateChainEngine engine,
- PCCERT_CONTEXT cert, BOOL isCA, DWORD index)
+ PCCERT_CONTEXT cert, BOOL isRoot, BOOL isCA, DWORD index)
{
PCERT_EXTENSION ext;
BOOL ret;
@@ -1132,20 +1132,24 @@ static BOOL CRYPT_KeyUsageValid(PCertificateChainEngine engine,
* perhaps this is prudent. On the other hand, MS also accepts V3
* certs without key usage extensions. We are more restrictive:
* we accept locally installed V1 or V2 certs as CA certs.
+ * We also accept a lack of key usage extension on root certs,
+ * which is implied in RFC 5280, section 6.1: the trust anchor's
+ * only requirement is that it was used to issue the next
+ * certificate in the chain.
*/
- ret = FALSE;
- if (cert->pCertInfo->dwVersion == CERT_V1 ||
+ if (isRoot)
+ ret = TRUE;
+ else if (cert->pCertInfo->dwVersion == CERT_V1 ||
cert->pCertInfo->dwVersion == CERT_V2)
{
PCCERT_CONTEXT localCert = CRYPT_FindCertInStore(
engine->hWorld, cert);
- if (localCert)
- {
- CertFreeCertificateContext(localCert);
- ret = TRUE;
- }
+ ret = localCert != NULL;
+ CertFreeCertificateContext(localCert);
}
+ else
+ ret = FALSE;
if (!ret)
WARN_(chain)("no key usage extension on a CA cert\n");
}
@@ -1273,8 +1277,15 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
chain->cElement, debugstr_w(filetime_to_str(time)));
for (i = chain->cElement - 1; i >= 0; i--)
{
+ BOOL isRoot;
+
if (TRACE_ON(chain))
dump_element(chain->rgpElement[i]->pCertContext);
+ if (i == chain->cElement - 1)
+ isRoot = CRYPT_IsCertificateSelfSigned(
+ chain->rgpElement[i]->pCertContext);
+ else
+ isRoot = FALSE;
if (CertVerifyTimeValidity(time,
chain->rgpElement[i]->pCertContext->pCertInfo) != 0)
chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
@@ -1316,7 +1327,7 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
CERT_TRUST_INVALID_BASIC_CONSTRAINTS;
}
if (!CRYPT_KeyUsageValid(engine, chain->rgpElement[i]->pCertContext,
- constraints.fCA, i))
+ isRoot, constraints.fCA, i))
chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
if (i != 0)