wintrust(1/10): Test and implement SoftpubLoadMessage (try 2)
Juan Lang
juan.lang at gmail.com
Mon Aug 27 18:34:05 CDT 2007
--Juan
-------------- next part --------------
From 2747cf5b8166db46652a44fa418caa540fbccb3c Mon Sep 17 00:00:00 2001
From: Juan Lang <juanlang at juan.corp.google.com>
Date: Mon, 27 Aug 2007 16:17:52 -0700
Subject: [PATCH] Test and implement SoftpubLoadMessage
---
dlls/wintrust/softpub.c | 264 +++++++++++++++++++++++++++++++++++++++++
dlls/wintrust/tests/softpub.c | 90 ++++++++++++++
dlls/wintrust/wintrust.spec | 2
3 files changed, 355 insertions(+), 1 deletions(-)
diff --git a/dlls/wintrust/softpub.c b/dlls/wintrust/softpub.c
index c5eb503..f78ed9e 100644
--- a/dlls/wintrust/softpub.c
+++ b/dlls/wintrust/softpub.c
@@ -19,6 +19,7 @@ #include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wintrust.h"
+#include "mssip.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
@@ -35,3 +36,266 @@ HRESULT WINAPI SoftpubInitialize(CRYPT_P
TRACE("returning %08x\n", ret);
return ret;
}
+
+/* Assumes data->pWintrustData->pFile exists. Makes sure a file handle is
+ * open for the file.
+ */
+static BOOL SOFTPUB_OpenFile(CRYPT_PROVIDER_DATA *data)
+{
+ BOOL ret = TRUE;
+
+ /* PSDK implies that all values should be initialized to NULL, so callers
+ * typically have hFile as NULL rather than INVALID_HANDLE_VALUE. Check
+ * for both.
+ */
+ if (!data->pWintrustData->pFile->hFile ||
+ data->pWintrustData->pFile->hFile == INVALID_HANDLE_VALUE)
+ {
+ data->pWintrustData->pFile->hFile =
+ CreateFileW(data->pWintrustData->pFile->pcwszFilePath, GENERIC_READ,
+ FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (data->pWintrustData->pFile->hFile != INVALID_HANDLE_VALUE)
+ data->fOpenedFile = TRUE;
+ else
+ ret = FALSE;
+ }
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+/* Assumes data->pWintrustData->pFile exists. Sets data->pPDSip->gSubject to
+ * the file's subject GUID.
+ */
+static BOOL SOFTPUB_GetFileSubject(CRYPT_PROVIDER_DATA *data)
+{
+ BOOL ret;
+
+ if (!data->pWintrustData->pFile->pgKnownSubject)
+ {
+ ret = CryptSIPRetrieveSubjectGuid(
+ data->pWintrustData->pFile->pcwszFilePath,
+ data->pWintrustData->pFile->hFile,
+ &data->pPDSip->gSubject);
+ }
+ else
+ {
+ memcpy(&data->pPDSip->gSubject,
+ data->pWintrustData->pFile->pgKnownSubject, sizeof(GUID));
+ ret = TRUE;
+ }
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+/* Assumes data->pPDSip exists, and its gSubject member set.
+ * Allocates data->pPDSip->pSip and loads it, if possible.
+ */
+static BOOL SOFTPUB_GetSIP(CRYPT_PROVIDER_DATA *data)
+{
+ BOOL ret;
+
+ data->pPDSip->pSip = data->psPfns->pfnAlloc(sizeof(SIP_DISPATCH_INFO));
+ if (data->pPDSip->pSip)
+ ret = CryptSIPLoad(&data->pPDSip->gSubject, 0, data->pPDSip->pSip);
+ else
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ ret = FALSE;
+ }
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+/* Assumes data->pPDSip has been loaded, and data->pPDSip->pSip allocated.
+ * Calls data->pPDSip->pSip->pfGet to construct data->hMsg.
+ */
+static BOOL SOFTPUB_GetMessageFromFile(CRYPT_PROVIDER_DATA *data)
+{
+ BOOL ret;
+ LPBYTE buf = NULL;
+ DWORD size = 0;
+
+ data->pPDSip->psSipSubjectInfo =
+ data->psPfns->pfnAlloc(sizeof(SIP_SUBJECTINFO));
+ if (!data->pPDSip->psSipSubjectInfo)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ data->pPDSip->psSipSubjectInfo->cbSize = sizeof(SIP_SUBJECTINFO);
+ data->pPDSip->psSipSubjectInfo->pgSubjectType = &data->pPDSip->gSubject;
+ data->pPDSip->psSipSubjectInfo->hFile = data->pWintrustData->pFile->hFile;
+ data->pPDSip->psSipSubjectInfo->pwsFileName =
+ data->pWintrustData->pFile->pcwszFilePath;
+ data->pPDSip->psSipSubjectInfo->hProv = data->hProv;
+ ret = data->pPDSip->pSip->pfGet(data->pPDSip->psSipSubjectInfo,
+ &data->dwEncoding, 0, &size, 0);
+ if (!ret)
+ {
+ SetLastError(TRUST_E_NOSIGNATURE);
+ return FALSE;
+ }
+
+ buf = data->psPfns->pfnAlloc(size);
+ if (!buf)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ ret = data->pPDSip->pSip->pfGet(data->pPDSip->psSipSubjectInfo,
+ &data->dwEncoding, 0, &size, buf);
+ if (ret)
+ {
+ data->hMsg = CryptMsgOpenToDecode(data->dwEncoding, 0, 0, data->hProv,
+ NULL, NULL);
+ if (data->hMsg)
+ ret = CryptMsgUpdate(data->hMsg, buf, size, TRUE);
+ }
+
+ data->psPfns->pfnFree(buf);
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL SOFTPUB_CreateStoreFromMessage(CRYPT_PROVIDER_DATA *data)
+{
+ BOOL ret = FALSE;
+ HCERTSTORE store;
+
+ store = CertOpenStore(CERT_STORE_PROV_MSG, data->dwEncoding,
+ data->hProv, CERT_STORE_NO_CRYPT_RELEASE_FLAG, data->hMsg);
+ if (store)
+ {
+ data->pahStores = data->psPfns->pfnAlloc(sizeof(HCERTSTORE));
+ if (data->pahStores)
+ {
+ data->chStores = 1;
+ data->pahStores[0] = CertDuplicateStore(store);
+ CertCloseStore(store, 0);
+ ret = TRUE;
+ }
+ else
+ SetLastError(ERROR_OUTOFMEMORY);
+ }
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static DWORD SOFTPUB_DecodeInnerContent(CRYPT_PROVIDER_DATA *data)
+{
+ BOOL ret;
+ DWORD size;
+ LPBYTE buf = NULL;
+
+ ret = CryptMsgGetParam(data->hMsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL,
+ &size);
+ if (!ret)
+ goto error;
+ buf = data->psPfns->pfnAlloc(size);
+ if (!buf)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ ret = FALSE;
+ goto error;
+ }
+ ret = CryptMsgGetParam(data->hMsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, buf,
+ &size);
+ if (!ret)
+ goto error;
+ if (!strcmp((LPCSTR)buf, SPC_INDIRECT_DATA_OBJID))
+ {
+ data->psPfns->pfnFree(buf);
+ buf = NULL;
+ ret = CryptMsgGetParam(data->hMsg, CMSG_CONTENT_PARAM, 0, NULL, &size);
+ if (!ret)
+ goto error;
+ buf = data->psPfns->pfnAlloc(size);
+ if (!buf)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ ret = FALSE;
+ goto error;
+ }
+ ret = CryptMsgGetParam(data->hMsg, CMSG_CONTENT_PARAM, 0, buf, &size);
+ if (!ret)
+ goto error;
+ ret = CryptDecodeObject(data->dwEncoding,
+ SPC_INDIRECT_DATA_CONTENT_STRUCT, buf, size, 0, NULL, &size);
+ if (!ret)
+ goto error;
+ data->pPDSip->psIndirectData = data->psPfns->pfnAlloc(size);
+ if (!data->pPDSip->psIndirectData)
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ ret = FALSE;
+ goto error;
+ }
+ ret = CryptDecodeObject(data->dwEncoding,
+ SPC_INDIRECT_DATA_CONTENT_STRUCT, buf, size, 0,
+ data->pPDSip->psIndirectData, &size);
+ }
+ else
+ {
+ FIXME("unimplemented for OID %s\n", (LPCSTR)buf);
+ SetLastError(TRUST_E_SUBJECT_FORM_UNKNOWN);
+ ret = FALSE;
+ }
+
+error:
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+HRESULT WINAPI SoftpubLoadMessage(CRYPT_PROVIDER_DATA *data)
+{
+ BOOL ret;
+
+ TRACE("(%p)\n", data);
+
+ if (!data->padwTrustStepErrors)
+ return S_FALSE;
+
+ switch (data->pWintrustData->dwUnionChoice)
+ {
+ case WTD_CHOICE_CERT:
+ /* Do nothing!? See the tests */
+ ret = TRUE;
+ break;
+ case WTD_CHOICE_FILE:
+ if (!data->pWintrustData->pFile)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ ret = FALSE;
+ goto error;
+ }
+ ret = SOFTPUB_OpenFile(data);
+ if (!ret)
+ goto error;
+ ret = SOFTPUB_GetFileSubject(data);
+ if (!ret)
+ goto error;
+ ret = SOFTPUB_GetSIP(data);
+ if (!ret)
+ goto error;
+ ret = SOFTPUB_GetMessageFromFile(data);
+ if (!ret)
+ goto error;
+ ret = SOFTPUB_CreateStoreFromMessage(data);
+ if (!ret)
+ goto error;
+ ret = SOFTPUB_DecodeInnerContent(data);
+ break;
+ default:
+ FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ ret = FALSE;
+ }
+
+error:
+ if (!ret)
+ data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] =
+ GetLastError();
+ return ret ? S_OK : S_FALSE;
+}
diff --git a/dlls/wintrust/tests/softpub.c b/dlls/wintrust/tests/softpub.c
index 3186379..a6e2025 100644
--- a/dlls/wintrust/tests/softpub.c
+++ b/dlls/wintrust/tests/softpub.c
@@ -115,6 +115,95 @@ static void testInitialize(SAFE_PROVIDER
}
}
+static const BYTE v1CertWithPubKey[] = {
+0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
+0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
+0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
+0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
+0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
+0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
+0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
+0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
+0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
+0x01,0x01 };
+
+static void testObjTrust(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
+{
+ HRESULT ret;
+ CRYPT_PROVIDER_DATA data = { 0 };
+ WINTRUST_DATA wintrust_data = { 0 };
+ WINTRUST_CERT_INFO certInfo = { sizeof(WINTRUST_CERT_INFO), 0 };
+ WINTRUST_FILE_INFO fileInfo = { sizeof(WINTRUST_FILE_INFO), 0 };
+
+ if (!funcs->pfnObjectTrust)
+ {
+ skip("missing pfnObjectTrust\n");
+ return;
+ }
+
+ /* Crashes
+ ret = funcs->pfnObjectTrust(NULL);
+ */
+ data.pWintrustData = &wintrust_data;
+ data.padwTrustStepErrors =
+ funcs->pfnAlloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
+ if (data.padwTrustStepErrors)
+ {
+ static const WCHAR notepad[] = { '\\','n','o','t','e','p','a','d','.',
+ 'e','x','e',0 };
+ WCHAR notepadPath[MAX_PATH];
+ PROVDATA_SIP provDataSIP = { 0 };
+ static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
+ 0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
+
+ ret = funcs->pfnObjectTrust(&data);
+ ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
+ ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
+ ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n",
+ data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
+ wintrust_data.pCert = &certInfo;
+ wintrust_data.dwUnionChoice = WTD_CHOICE_CERT;
+ ret = funcs->pfnObjectTrust(&data);
+ ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
+ certInfo.psCertContext = (PCERT_CONTEXT)CertCreateCertificateContext(
+ X509_ASN_ENCODING, v1CertWithPubKey, sizeof(v1CertWithPubKey));
+ ret = funcs->pfnObjectTrust(&data);
+ ok(ret == S_OK, "Expected S_OK, got %08x\n", ret);
+ CertFreeCertificateContext(certInfo.psCertContext);
+ certInfo.psCertContext = NULL;
+ wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
+ wintrust_data.pFile = NULL;
+ ret = funcs->pfnObjectTrust(&data);
+ ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
+ ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
+ ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %08x\n",
+ data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
+ wintrust_data.pFile = &fileInfo;
+ /* Crashes
+ ret = funcs->pfnObjectTrust(&data);
+ */
+ GetWindowsDirectoryW(notepadPath, MAX_PATH);
+ lstrcatW(notepadPath, notepad);
+ fileInfo.pcwszFilePath = notepadPath;
+ /* pfnObjectTrust now crashes unless both pPDSip and psPfns are set */
+ data.pPDSip = &provDataSIP;
+ data.psPfns = (CRYPT_PROVIDER_FUNCTIONS *)funcs;
+ ret = funcs->pfnObjectTrust(&data);
+ ok(ret == S_FALSE, "Expected S_FALSE, got %08x\n", ret);
+ ok(data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] ==
+ TRUST_E_NOSIGNATURE, "Expected TRUST_E_NOSIGNATURE, got %08x\n",
+ data.padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
+ ok(!memcmp(&provDataSIP.gSubject, &unknown, sizeof(unknown)),
+ "Unexpected subject GUID\n");
+ ok(provDataSIP.pSip != NULL, "Expected a SIP\n");
+ ok(provDataSIP.psSipSubjectInfo != NULL, "Expected a subject info\n");
+ funcs->pfnFree(data.padwTrustStepErrors);
+ }
+}
+
START_TEST(softpub)
{
static GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
@@ -128,5 +217,6 @@ START_TEST(softpub)
else
{
testInitialize(&funcs, &generic_verify_v2);
+ testObjTrust(&funcs, &generic_verify_v2);
}
}
diff --git a/dlls/wintrust/wintrust.spec b/dlls/wintrust/wintrust.spec
index 71f104c..fe9df8a 100644
--- a/dlls/wintrust/wintrust.spec
+++ b/dlls/wintrust/wintrust.spec
@@ -66,7 +66,7 @@
@ stub SoftpubFreeDefUsageCallData
@ stdcall SoftpubInitialize(ptr)
@ stub SoftpubLoadDefUsageCallData
-@ stub SoftpubLoadMessage
+@ stdcall SoftpubLoadMessage(ptr)
@ stub SoftpubLoadSignature
@ stub TrustDecode
@ stub TrustFindIssuerCertificate
--
1.4.1
More information about the wine-patches
mailing list