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