crypt32(4/6): Implement CertVerifyCertificateChainPolicy for the base policy

Juan Lang juan.lang at gmail.com
Mon Sep 10 18:15:01 CDT 2007


--Juan
-------------- next part --------------
From a04d041aa5c6c2bb6c3eafd915fef32eadf511b4 Mon Sep 17 00:00:00 2001
From: Juan Lang <juan.lang at gmail.com>
Date: Mon, 10 Sep 2007 16:11:49 -0700
Subject: [PATCH] Implement CertVerifyCertificateChainPolicy for the base policy
---
 dlls/crypt32/chain.c       |   86 +++++++++++++++++++++++++++++++++++++++++++-
 dlls/crypt32/tests/chain.c |   42 ++++++++++++++++++---
 2 files changed, 119 insertions(+), 9 deletions(-)

diff --git a/dlls/crypt32/chain.c b/dlls/crypt32/chain.c
index 7b6d7bd..8249596 100644
--- a/dlls/crypt32/chain.c
+++ b/dlls/crypt32/chain.c
@@ -1021,11 +1021,93 @@ void WINAPI CertFreeCertificateChain(PCC
     }
 }
 
+static void find_element_with_error(PCCERT_CHAIN_CONTEXT chain, DWORD error,
+ LONG *iChain, LONG *iElement)
+{
+    DWORD i, j;
+
+    for (i = 0; i < chain->cChain; i++)
+        for (j = 0; j < chain->rgpChain[i]->cElement; j++)
+            if (chain->rgpChain[i]->rgpElement[j]->TrustStatus.dwErrorStatus &
+             error)
+            {
+                *iChain = i;
+                *iElement = j;
+                return;
+            }
+}
+
+static BOOL WINAPI verify_base_policy(LPCSTR szPolicyOID,
+ PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
+ PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
+{
+    pPolicyStatus->lChainIndex = pPolicyStatus->lElementIndex = -1;
+    if (pChainContext->TrustStatus.dwErrorStatus &
+     CERT_TRUST_IS_NOT_SIGNATURE_VALID)
+    {
+        pPolicyStatus->dwError = TRUST_E_CERT_SIGNATURE;
+        find_element_with_error(pChainContext,
+         CERT_TRUST_IS_NOT_SIGNATURE_VALID, &pPolicyStatus->lChainIndex,
+         &pPolicyStatus->lElementIndex);
+    }
+    else if (pChainContext->TrustStatus.dwErrorStatus &
+     CERT_TRUST_IS_UNTRUSTED_ROOT)
+    {
+        pPolicyStatus->dwError = CERT_E_UNTRUSTEDROOT;
+        find_element_with_error(pChainContext,
+         CERT_TRUST_IS_UNTRUSTED_ROOT, &pPolicyStatus->lChainIndex,
+         &pPolicyStatus->lElementIndex);
+    }
+    else if (pChainContext->TrustStatus.dwErrorStatus & CERT_TRUST_IS_CYCLIC)
+    {
+        pPolicyStatus->dwError = CERT_E_CHAINING;
+        find_element_with_error(pChainContext, CERT_TRUST_IS_CYCLIC,
+         &pPolicyStatus->lChainIndex, &pPolicyStatus->lElementIndex);
+        /* For a cyclic chain, which element is a cycle isn't meaningful */
+        pPolicyStatus->lElementIndex = -1;
+    }
+    return TRUE;
+}
+
+typedef BOOL (WINAPI *CertVerifyCertificateChainPolicyFunc)(LPCSTR szPolicyOID,
+ PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
+ PCERT_CHAIN_POLICY_STATUS pPolicyStatus);
+
 BOOL WINAPI CertVerifyCertificateChainPolicy(LPCSTR szPolicyOID,
  PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
  PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
 {
-    FIXME("(%s, %p, %p, %p): stub\n", debugstr_a(szPolicyOID), pChainContext,
+    static HCRYPTOIDFUNCSET set = NULL;
+    BOOL ret = FALSE;
+    CertVerifyCertificateChainPolicyFunc verifyPolicy = NULL;
+    HCRYPTOIDFUNCADDR hFunc = NULL;
+
+    TRACE("(%s, %p, %p, %p)\n", debugstr_a(szPolicyOID), pChainContext,
      pPolicyPara, pPolicyStatus);
-    return FALSE;
+
+    if (!HIWORD(szPolicyOID))
+    {
+        switch (LOWORD(szPolicyOID))
+        {
+        case (int)CERT_CHAIN_POLICY_BASE:
+            verifyPolicy = verify_base_policy;
+            break;
+        default:
+            FIXME("unimplemented for %d\n", LOWORD(szPolicyOID));
+        }
+    }
+    if (!verifyPolicy)
+    {
+        if (!set)
+            set = CryptInitOIDFunctionSet(
+             CRYPT_OID_VERIFY_CERTIFICATE_CHAIN_POLICY_FUNC, 0);
+        CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, szPolicyOID, 0,
+         (void **)&verifyPolicy, hFunc);
+    }
+    if (verifyPolicy)
+        ret = verifyPolicy(szPolicyOID, pChainContext, pPolicyPara,
+         pPolicyStatus);
+    if (hFunc)
+        CryptFreeOIDFunctionAddress(hFunc, 0);
+    return ret;
 }
diff --git a/dlls/crypt32/tests/chain.c b/dlls/crypt32/tests/chain.c
index cbbf0aa..fd8952f 100644
--- a/dlls/crypt32/tests/chain.c
+++ b/dlls/crypt32/tests/chain.c
@@ -1717,6 +1717,39 @@ typedef struct _ChainPolicyCheck
 
 static ChainPolicyCheck basePolicyCheck[] = {
  { { sizeof(chain0) / sizeof(chain0[0]), chain0 },
+   { 0, CERT_E_UNTRUSTEDROOT, 0, 1, NULL }, 0 },
+ { { sizeof(chain1) / sizeof(chain1[0]), chain1 },
+   { 0, TRUST_E_CERT_SIGNATURE, 0, 0, NULL }, 0 },
+ { { sizeof(chain2) / sizeof(chain2[0]), chain2 },
+   { 0, CERT_E_UNTRUSTEDROOT, 0, 1, NULL }, 0 },
+ { { sizeof(chain3) / sizeof(chain3[0]), chain3 },
+   { 0, CERT_E_UNTRUSTEDROOT, 0, 1, NULL }, 0 },
+ { { sizeof(chain4) / sizeof(chain4[0]), chain4 },
+   { 0, CERT_E_UNTRUSTEDROOT, 0, 2, NULL }, 0 },
+ { { sizeof(chain5) / sizeof(chain5[0]), chain5 },
+   { 0, CERT_E_UNTRUSTEDROOT, 0, 1, NULL }, 0 },
+ { { sizeof(chain6) / sizeof(chain6[0]), chain6 },
+   { 0, CERT_E_UNTRUSTEDROOT, 0, 1, NULL }, 0 },
+ { { sizeof(chain7) / sizeof(chain7[0]), chain7 },
+   { 0, CERT_E_UNTRUSTEDROOT, 0, 1, NULL }, 0 },
+ { { sizeof(chain8) / sizeof(chain8[0]), chain8 },
+   { 0, CERT_E_UNTRUSTEDROOT, 0, 2, NULL }, 0 },
+ { { sizeof(chain9) / sizeof(chain9[0]), chain9 },
+   { 0, CERT_E_CHAINING, 0, -1, NULL }, 0 },
+ { { sizeof(chain10) / sizeof(chain10[0]), chain10 },
+   { 0, CERT_E_UNTRUSTEDROOT, 0, 1, NULL }, 0 },
+ { { sizeof(chain11) / sizeof(chain11[0]), chain11 },
+   { 0, CERT_E_UNTRUSTEDROOT, 0, 1, NULL }, 0 },
+ { { sizeof(chain12) / sizeof(chain12[0]), chain12 },
+   { 0, TRUST_E_CERT_SIGNATURE, 0, 1, NULL }, 0 },
+ { { sizeof(selfSignedChain) / sizeof(selfSignedChain[0]), selfSignedChain },
+   { 0, CERT_E_UNTRUSTEDROOT, 0, 0, NULL }, 0 },
+ { { sizeof(iTunesChain) / sizeof(iTunesChain[0]), iTunesChain },
+   { 0, 0, -1, -1, NULL }, 0 },
+};
+
+static ChainPolicyCheck authenticodePolicyCheck[] = {
+ { { sizeof(chain0) / sizeof(chain0[0]), chain0 },
    { 0, CERT_E_UNTRUSTEDROOT, 0, 1, NULL },
    TODO_POLICY },
  { { sizeof(chain1) / sizeof(chain1[0]), chain1 },
@@ -1881,7 +1914,6 @@ static void testVerifyCertChainPolicy(vo
      */
     SetLastError(0xdeadbeef);
     ret = CertVerifyCertificateChainPolicy(NULL, NULL, NULL, &policyStatus);
-    todo_wine
     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
     /* Crashes
@@ -1902,9 +1934,7 @@ static void testVerifyCertChainPolicy(vo
     /* Size of policy status is apparently ignored, as is pChainPolicyPara */
     ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE, chain, NULL,
      &policyStatus);
-    todo_wine
     ok(ret, "CertVerifyCertificateChainPolicy failed: %08x\n", GetLastError());
-    todo_wine
     ok(policyStatus.dwError == CERT_E_UNTRUSTEDROOT,
      "Expected CERT_E_UNTRUSTEDROOT, got %08x\n", policyStatus.dwError);
     ok(policyStatus.lChainIndex == 0 && policyStatus.lElementIndex == 0,
@@ -1912,9 +1942,7 @@ static void testVerifyCertChainPolicy(vo
      policyStatus.lElementIndex);
     ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE, chain,
      &policyPara, &policyStatus);
-    todo_wine
     ok(ret, "CertVerifyCertificateChainPolicy failed: %08x\n", GetLastError());
-    todo_wine
     ok(policyStatus.dwError == CERT_E_UNTRUSTEDROOT,
      "Expected CERT_E_UNTRUSTEDROOT, got %08x\n", policyStatus.dwError);
     ok(policyStatus.lChainIndex == 0 && policyStatus.lElementIndex == 0,
@@ -1930,9 +1958,9 @@ static void testVerifyCertChainPolicy(vo
      * of these chains is.
      */
     for (i = 0; i <
-     sizeof(basePolicyCheck) / sizeof(basePolicyCheck[0]); i++)
+     sizeof(authenticodePolicyCheck) / sizeof(authenticodePolicyCheck[0]); i++)
         checkChainPolicyStatus(CERT_CHAIN_POLICY_AUTHENTICODE,
-         &basePolicyCheck[i], i);
+         &authenticodePolicyCheck[i], i);
     for (i = 0; i <
      sizeof(basicConstraintsPolicyCheck) / sizeof(basicConstraintsPolicyCheck[0]);
      i++)
-- 
1.4.1


More information about the wine-patches mailing list