Module: wine Branch: master Commit: fc8545b43a2929a9bc337a2f3acca2cc7441354c URL: http://source.winehq.org/git/wine.git/?a=commit;h=fc8545b43a2929a9bc337a2f3a...
Author: Juan Lang juan.lang@gmail.com Date: Tue Aug 5 11:06:17 2008 -0700
crypt32: Implement CryptMsgGetAndVerifySigner.
---
dlls/crypt32/msg.c | 112 ++++++++++++++++++++++++++++++++++++++++++++- dlls/crypt32/tests/msg.c | 16 ------- 2 files changed, 109 insertions(+), 19 deletions(-)
diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c index 1ad6a96..ff4e0f4 100644 --- a/dlls/crypt32/msg.c +++ b/dlls/crypt32/msg.c @@ -2446,12 +2446,118 @@ BOOL WINAPI CryptMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags, return msg->control(hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara); }
+static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg, + DWORD dwSignerIndex) +{ + CERT_INFO *certInfo = NULL; + DWORD size; + + if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL, + &size)) + { + certInfo = CryptMemAlloc(size); + if (certInfo) + { + if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, + dwSignerIndex, certInfo, &size)) + { + CryptMemFree(certInfo); + certInfo = NULL; + } + } + } + return certInfo; +} + BOOL WINAPI CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg, DWORD cSignerStore, HCERTSTORE *rghSignerStore, DWORD dwFlags, PCCERT_CONTEXT *ppSigner, DWORD *pdwSignerIndex) { - FIXME("(%p, %d, %p, %08x, %p, %p): stub\n", hCryptMsg, cSignerStore, + HCERTSTORE store; + DWORD i, signerIndex; + PCCERT_CONTEXT signerCert = NULL; + BOOL ret = FALSE; + + TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg, cSignerStore, rghSignerStore, dwFlags, ppSigner, pdwSignerIndex); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + + /* Clear output parameters */ + if (ppSigner) + *ppSigner = NULL; + if (pdwSignerIndex && !(dwFlags & CMSG_USE_SIGNER_INDEX_FLAG)) + *pdwSignerIndex = 0; + + /* Create store to search for signer certificates */ + store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + if (!(dwFlags & CMSG_TRUSTED_SIGNER_FLAG)) + { + HCERTSTORE msgStore = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0, + hCryptMsg); + + CertAddStoreToCollection(store, msgStore, 0, 0); + CertCloseStore(msgStore, 0); + } + for (i = 0; i < cSignerStore; i++) + CertAddStoreToCollection(store, rghSignerStore[i], 0, 0); + + /* Find signer cert */ + if (dwFlags & CMSG_USE_SIGNER_INDEX_FLAG) + { + CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg, + *pdwSignerIndex); + + if (signer) + { + signerIndex = *pdwSignerIndex; + signerCert = CertFindCertificateInStore(store, X509_ASN_ENCODING, + 0, CERT_FIND_SUBJECT_CERT, signer, NULL); + CryptMemFree(signer); + } + } + else + { + DWORD count, size = sizeof(count); + + if (CryptMsgGetParam(hCryptMsg, CMSG_SIGNER_COUNT_PARAM, 0, &count, + &size)) + { + for (i = 0; !signerCert && i < count; i++) + { + CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg, + i); + + if (signer) + { + signerCert = CertFindCertificateInStore(store, + X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, signer, + NULL); + if (signerCert) + signerIndex = i; + CryptMemFree(signer); + } + } + } + if (!signerCert) + SetLastError(CRYPT_E_NO_TRUSTED_SIGNER); + } + if (signerCert) + { + if (!(dwFlags & CMSG_SIGNER_ONLY_FLAG)) + ret = CryptMsgControl(hCryptMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE, + signerCert->pCertInfo); + else + ret = TRUE; + if (ret) + { + if (ppSigner) + *ppSigner = CertDuplicateCertificateContext(signerCert); + if (pdwSignerIndex) + *pdwSignerIndex = signerIndex; + } + CertFreeCertificateContext(signerCert); + } + + CertCloseStore(store, 0); + return ret; } diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c index 53652c6..0f7dcb6 100644 --- a/dlls/crypt32/tests/msg.c +++ b/dlls/crypt32/tests/msg.c @@ -2580,26 +2580,21 @@ static void test_msg_get_and_verify_signer(void) /* An empty message has no signer */ SetLastError(0xdeadbeef); ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL); - todo_wine ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); /* The signer is cleared on error */ signer = (PCCERT_CONTEXT)0xdeadbeef; SetLastError(0xdeadbeef); ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, &signer, NULL); - todo_wine ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); - todo_wine ok(!signer, "expected signer to be NULL\n"); /* The signer index is also cleared on error */ signerIndex = 0xdeadbeef; SetLastError(0xdeadbeef); ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, &signerIndex); - todo_wine ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); - todo_wine ok(!signerIndex, "expected 0, got %d\n", signerIndex); /* An unsigned message (msgData isn't a signed message at all) * likewise has no signer. @@ -2607,7 +2602,6 @@ static void test_msg_get_and_verify_signer(void) CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE); SetLastError(0xdeadbeef); ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL); - todo_wine ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); CryptMsgClose(msg); @@ -2617,7 +2611,6 @@ static void test_msg_get_and_verify_signer(void) CryptMsgUpdate(msg, signedEmptyContent, sizeof(signedEmptyContent), TRUE); SetLastError(0xdeadbeef); ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL); - todo_wine ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); CryptMsgClose(msg); @@ -2627,21 +2620,16 @@ static void test_msg_get_and_verify_signer(void) CryptMsgUpdate(msg, signedWithCertWithValidPubKeyContent, sizeof(signedWithCertWithValidPubKeyContent), TRUE); ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL); - todo_wine ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError()); /* the signer index can be retrieved, .. */ signerIndex = 0xdeadbeef; ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, &signerIndex); - todo_wine ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError()); - todo_wine ok(signerIndex == 0, "expected 0, got %d\n", signerIndex); /* as can the signer cert. */ signer = (PCCERT_CONTEXT)0xdeadbeef; ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, &signer, NULL); - todo_wine ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError()); - todo_wine ok(signer != NULL && signer != (PCCERT_CONTEXT)0xdeadbeef, "expected a valid signer\n"); if (signer && signer != (PCCERT_CONTEXT)0xdeadbeef) @@ -2652,7 +2640,6 @@ static void test_msg_get_and_verify_signer(void) SetLastError(0xdeadbeef); ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, CMSG_USE_SIGNER_INDEX_FLAG, NULL, &signerIndex); - todo_wine ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX, "expected CRYPT_E_INVALID_INDEX, got 0x%08x\n", GetLastError()); /* Specifying CMSG_TRUSTED_SIGNER_FLAG and no cert stores causes the @@ -2661,7 +2648,6 @@ static void test_msg_get_and_verify_signer(void) SetLastError(0xdeadbeef); ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, CMSG_TRUSTED_SIGNER_FLAG, NULL, NULL); - todo_wine ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); /* Specifying CMSG_TRUSTED_SIGNER_FLAG and an empty cert store also causes @@ -2672,7 +2658,6 @@ static void test_msg_get_and_verify_signer(void) SetLastError(0xdeadbeef); ret = CryptMsgGetAndVerifySigner(msg, 1, &store, CMSG_TRUSTED_SIGNER_FLAG, NULL, NULL); - todo_wine ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER, "expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError()); ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, @@ -2686,7 +2671,6 @@ static void test_msg_get_and_verify_signer(void) SetLastError(0xdeadbeef); ret = CryptMsgGetAndVerifySigner(msg, 1, &store, CMSG_TRUSTED_SIGNER_FLAG, NULL, NULL); - todo_wine ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError()); CertCloseStore(store, 0); CryptMsgClose(msg);