Module: wine Branch: master Commit: b56f0c5b687043bd8c8d09d1773bd606800b35a0 URL: http://source.winehq.org/git/wine.git/?a=commit;h=b56f0c5b687043bd8c8d09d177...
Author: Juan Lang juan.lang@gmail.com Date: Mon Sep 10 16:11:49 2007 -0700
crypt32: 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(PCCERT_CHAIN_CONTEXT pChainContext) } }
+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(void) */ 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(void) /* 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(void) 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(void) * 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++)