Juan Lang : crypt32: Don' t assume intermediate certificates are allowed to be CAs.

Alexandre Julliard julliard at winehq.org
Thu Feb 12 11:14:43 CST 2009


Module: wine
Branch: master
Commit: 913affe4efa990a9e3e40b5a5b168d5da7667f66
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=913affe4efa990a9e3e40b5a5b168d5da7667f66

Author: Juan Lang <juan.lang at gmail.com>
Date:   Wed Feb 11 10:07:33 2009 -0800

crypt32: Don't assume intermediate certificates are allowed to be CAs.

---

 dlls/crypt32/chain.c       |   21 ++++++++++++++++-----
 dlls/crypt32/tests/chain.c |    6 ++----
 2 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c
index 64aba77..30b1422 100644
--- a/dlls/crypt32/chain.c
+++ b/dlls/crypt32/chain.c
@@ -412,8 +412,12 @@ static BOOL CRYPT_DecodeBasicConstraints(PCCERT_CONTEXT cert,
 }
 
 /* Checks element's basic constraints to see if it can act as a CA, with
- * remainingCAs CAs left in this chain.  Updates chainConstraints with the
- * element's constraints, if:
+ * remainingCAs CAs left in this chain.  A root certificate is assumed to be
+ * allowed to be a CA whether or not the basic constraints extension is present,
+ * whereas an intermediate CA cert is not.  This matches the expected usage in
+ * RFC 3280:  a conforming intermediate CA MUST contain the basic constraints
+ * extension.  It also appears to match Microsoft's implementation.
+ * Updates chainConstraints with the element's constraints, if:
  * 1. chainConstraints doesn't have a path length constraint, or
  * 2. element's path length constraint is smaller than chainConstraints's
  * Sets *pathLengthConstraintViolated to TRUE if a path length violation
@@ -423,13 +427,13 @@ static BOOL CRYPT_DecodeBasicConstraints(PCCERT_CONTEXT cert,
  */
 static BOOL CRYPT_CheckBasicConstraintsForCA(PCCERT_CONTEXT cert,
  CERT_BASIC_CONSTRAINTS2_INFO *chainConstraints, DWORD remainingCAs,
- BOOL *pathLengthConstraintViolated)
+ BOOL isRoot, BOOL *pathLengthConstraintViolated)
 {
     BOOL validBasicConstraints;
     CERT_BASIC_CONSTRAINTS2_INFO constraints;
 
     if ((validBasicConstraints = CRYPT_DecodeBasicConstraints(cert,
-     &constraints, TRUE)))
+     &constraints, isRoot)))
     {
         if (!constraints.fCA)
         {
@@ -825,6 +829,13 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
              CERT_TRUST_IS_NOT_TIME_VALID;
         if (i != 0)
         {
+            BOOL isRoot;
+
+            if (i == chain->cElement - 1)
+                isRoot = CRYPT_IsCertificateSelfSigned(
+                 chain->rgpElement[i]->pCertContext);
+            else
+                isRoot = FALSE;
             /* Check the signature of the cert this issued */
             if (!CryptVerifyCertificateSignatureEx(0, X509_ASN_ENCODING,
              CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT,
@@ -841,7 +852,7 @@ static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
                  CERT_TRUST_INVALID_BASIC_CONSTRAINTS;
             else if (!CRYPT_CheckBasicConstraintsForCA(
              chain->rgpElement[i]->pCertContext, &constraints, i - 1,
-             &pathLengthConstraintViolated))
+             isRoot, &pathLengthConstraintViolated))
                 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
                  CERT_TRUST_INVALID_BASIC_CONSTRAINTS;
             else if (constraints.fPathLenConstraint &&
diff --git a/dlls/crypt32/tests/chain.c b/dlls/crypt32/tests/chain.c
index 0b5263b..6197841 100644
--- a/dlls/crypt32/tests/chain.c
+++ b/dlls/crypt32/tests/chain.c
@@ -1566,8 +1566,7 @@ static ChainCheck chainCheck[] = {
        CERT_TRUST_HAS_PREFERRED_ISSUER },
      { CERT_TRUST_INVALID_BASIC_CONSTRAINTS | CERT_TRUST_IS_UNTRUSTED_ROOT |
        CERT_TRUST_IS_NOT_TIME_VALID, 0 },
-     1, simpleStatus8 },
-   TODO_ERROR },
+     1, simpleStatus8 }, 0 },
  /* Earlier versions of Windows incorrectly don't set
   * CERT_TRUST_INVALID_BASIC_CONSTRAINTS on this chain.
   */
@@ -1795,8 +1794,7 @@ static const ChainPolicyCheck basicConstraintsPolicyCheck[] = {
  { { sizeof(chain7) / sizeof(chain7[0]), chain7 },
    { 0, 0, -1, -1, NULL }, 0 },
  { { sizeof(chain8) / sizeof(chain8[0]), chain8 },
-   { 0, TRUST_E_BASIC_CONSTRAINTS, 0, 1, NULL },
-   TODO_ERROR | TODO_CHAINS | TODO_ELEMENTS },
+   { 0, TRUST_E_BASIC_CONSTRAINTS, 0, 1, NULL }, 0 },
  { { sizeof(chain9) / sizeof(chain9[0]), chain9 },
    { 0, TRUST_E_BASIC_CONSTRAINTS, 0, 1, NULL }, 0 },
  { { sizeof(chain10) / sizeof(chain10[0]), chain10 },




More information about the wine-cvs mailing list