wintrust: Test and implement SoftpubLoadMessage.
This commit is contained in:
parent
01b083c575
commit
5a3fb3b566
|
@ -19,6 +19,7 @@
|
|||
#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_PROVIDER_DATA *data)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -115,6 +115,95 @@ static void testInitialize(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID)
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
@ stub SoftpubFreeDefUsageCallData
|
||||
@ stdcall SoftpubInitialize(ptr)
|
||||
@ stub SoftpubLoadDefUsageCallData
|
||||
@ stub SoftpubLoadMessage
|
||||
@ stdcall SoftpubLoadMessage(ptr)
|
||||
@ stub SoftpubLoadSignature
|
||||
@ stub TrustDecode
|
||||
@ stub TrustFindIssuerCertificate
|
||||
|
|
Loading…
Reference in New Issue