wintrust(4/5): Test and implement SoftpubLoadMessage (with patch)
Juan Lang
juan.lang at gmail.com
Mon Aug 27 11:39:25 CDT 2007
--Juan
-------------- next part --------------
From ca8875d25f54fb4a89f53e132bfb8cf6a9db9fda Mon Sep 17 00:00:00 2001
From: Juan Lang <juan.lang at gmail.com>
Date: Fri, 24 Aug 2007 15:14:48 -0700
Subject: [PATCH] Test and implement SoftpubLoadMessage
---
dlls/wintrust/softpub.c | 257 +++++++++++++++++++++++++++++++++++++++++
dlls/wintrust/tests/softpub.c | 90 ++++++++++++++
dlls/wintrust/wintrust.spec | 2
3 files changed, 348 insertions(+), 1 deletions(-)
diff --git a/dlls/wintrust/softpub.c b/dlls/wintrust/softpub.c
index c5eb503..9d08d19 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,259 @@ 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 DWORD SOFTPUB_OpenFile(CRYPT_PROVIDER_DATA *data)
+{
+ DWORD err = ERROR_SUCCESS;
+
+ /* 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
+ err = GetLastError();
+ }
+ return err;
+}
+
+/* Assumes data->pWintrustData->pFile exists. Sets data->pPDSip->gSubject to
+ * the file's subject GUID.
+ */
+static DWORD SOFTPUB_GetFileSubject(CRYPT_PROVIDER_DATA *data)
+{
+ DWORD err = ERROR_SUCCESS;
+
+ if (!data->pWintrustData->pFile->pgKnownSubject)
+ {
+ BOOL ret = CryptSIPRetrieveSubjectGuid(
+ data->pWintrustData->pFile->pcwszFilePath,
+ data->pWintrustData->pFile->hFile,
+ &data->pPDSip->gSubject);
+
+ if (!ret)
+ err = GetLastError();
+ }
+ else
+ memcpy(&data->pPDSip->gSubject,
+ data->pWintrustData->pFile->pgKnownSubject, sizeof(GUID));
+ return err;
+}
+
+/* Assumes data->pPDSip exists, and its gSubject member set.
+ * Allocates data->pPDSip->pSip and loads it, if possible.
+ */
+static DWORD SOFTPUB_GetSIP(CRYPT_PROVIDER_DATA *data)
+{
+ DWORD err = ERROR_SUCCESS;
+
+ data->pPDSip->pSip = data->psPfns->pfnAlloc(sizeof(SIP_DISPATCH_INFO));
+ if (data->pPDSip->pSip)
+ {
+ if (!CryptSIPLoad(&data->pPDSip->gSubject, 0, data->pPDSip->pSip))
+ err = GetLastError();
+ }
+ else
+ err = ERROR_OUTOFMEMORY;
+ return err;
+}
+
+/* Assumes data->pPDSip has been loaded, and data->pPDSip->pSip allocated.
+ * Calls data->pPDSip->pSip->pfGet to construct data->hMsg.
+ */
+static DWORD SOFTPUB_GetMessageFromFile(CRYPT_PROVIDER_DATA *data)
+{
+ BOOL ret;
+ DWORD err = ERROR_SUCCESS;
+ LPBYTE buf = NULL;
+ DWORD size = 0;
+
+ data->pPDSip->psSipSubjectInfo =
+ data->psPfns->pfnAlloc(sizeof(SIP_SUBJECTINFO));
+ if (!data->pPDSip->psSipSubjectInfo)
+ return ERROR_OUTOFMEMORY;
+
+ 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)
+ {
+ /* FIXME: this passes the tests, but perhaps this should be
+ * set by pfGet instead?
+ */
+ return TRUST_E_NOSIGNATURE;
+ }
+
+ buf = data->psPfns->pfnAlloc(size);
+ if (!buf)
+ return ERROR_OUTOFMEMORY;
+
+ 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);
+ }
+
+ if (!ret || !data->hMsg)
+ err = GetLastError();
+ data->psPfns->pfnFree(buf);
+ return err;
+}
+
+static DWORD SOFTPUB_CreateStoreFromMessage(CRYPT_PROVIDER_DATA *data)
+{
+ DWORD err = ERROR_SUCCESS;
+ 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);
+ }
+ else
+ err = ERROR_OUTOFMEMORY;
+ }
+ else
+ err = GetLastError();
+ return err;
+}
+
+static DWORD SOFTPUB_DecodeInnerContent(CRYPT_PROVIDER_DATA *data)
+{
+ DWORD err = ERROR_SUCCESS;
+ BOOL ret;
+ DWORD size;
+ LPBYTE buf = NULL;
+
+ ret = CryptMsgGetParam(data->hMsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, NULL,
+ &size);
+ if (!ret)
+ {
+ err = GetLastError();
+ goto error;
+ }
+ buf = data->psPfns->pfnAlloc(size);
+ if (!buf)
+ {
+ err = ERROR_OUTOFMEMORY;
+ goto error;
+ }
+ ret = CryptMsgGetParam(data->hMsg, CMSG_INNER_CONTENT_TYPE_PARAM, 0, buf,
+ &size);
+ 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)
+ {
+ err = GetLastError();
+ goto error;
+ }
+ buf = data->psPfns->pfnAlloc(size);
+ ret = CryptMsgGetParam(data->hMsg, CMSG_CONTENT_PARAM, 0, buf, &size);
+ if (!ret)
+ {
+ err = GetLastError();
+ goto error;
+ }
+ ret = CryptDecodeObject(data->dwEncoding,
+ SPC_INDIRECT_DATA_CONTENT_STRUCT, buf, size, 0, NULL, &size);
+ if (!ret)
+ {
+ err = GetLastError();
+ goto error;
+ }
+ data->pPDSip->psIndirectData = data->psPfns->pfnAlloc(size);
+ if (!data->pPDSip->psIndirectData)
+ {
+ err = ERROR_OUTOFMEMORY;
+ goto error;
+ }
+ ret = CryptDecodeObject(data->dwEncoding,
+ SPC_INDIRECT_DATA_CONTENT_STRUCT, buf, size, 0,
+ data->pPDSip->psIndirectData, &size);
+ if (!ret)
+ err = GetLastError();
+ }
+ else
+ {
+ FIXME("unimplemented for OID %s\n", (LPCSTR)buf);
+ err = TRUST_E_SUBJECT_FORM_UNKNOWN;
+ }
+
+error:
+ return err;
+}
+
+HRESULT WINAPI SoftpubLoadMessage(CRYPT_PROVIDER_DATA *data)
+{
+ DWORD err = ERROR_SUCCESS;
+
+ TRACE("(%p)\n", data);
+
+ if (!data->padwTrustStepErrors)
+ return S_FALSE;
+
+ switch (data->pWintrustData->dwUnionChoice)
+ {
+ case WTD_CHOICE_CERT:
+ /* Do nothing!? See the tests */
+ break;
+ case WTD_CHOICE_FILE:
+ if (!data->pWintrustData->pFile)
+ {
+ err = ERROR_INVALID_PARAMETER;
+ goto error;
+ }
+ err = SOFTPUB_OpenFile(data);
+ if (err)
+ goto error;
+ err = SOFTPUB_GetFileSubject(data);
+ if (err)
+ goto error;
+ err = SOFTPUB_GetSIP(data);
+ if (err)
+ goto error;
+ err = SOFTPUB_GetMessageFromFile(data);
+ if (err)
+ goto error;
+ err = SOFTPUB_CreateStoreFromMessage(data);
+ if (err)
+ goto error;
+ err = SOFTPUB_DecodeInnerContent(data);
+ break;
+ default:
+ FIXME("unimplemented for %d\n", data->pWintrustData->dwUnionChoice);
+ err = ERROR_INVALID_PARAMETER;
+ }
+
+error:
+ data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV] = err;
+ return err ? S_FALSE : S_OK;
+}
diff --git a/dlls/wintrust/tests/softpub.c b/dlls/wintrust/tests/softpub.c
index a474324..085673f 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