wintrust: Test and implement SoftpubLoadMessage.

This commit is contained in:
Juan Lang 2007-08-27 16:17:52 -07:00 committed by Alexandre Julliard
parent 01b083c575
commit 5a3fb3b566
3 changed files with 355 additions and 1 deletions

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -66,7 +66,7 @@
@ stub SoftpubFreeDefUsageCallData
@ stdcall SoftpubInitialize(ptr)
@ stub SoftpubLoadDefUsageCallData
@ stub SoftpubLoadMessage
@ stdcall SoftpubLoadMessage(ptr)
@ stub SoftpubLoadSignature
@ stub TrustDecode
@ stub TrustFindIssuerCertificate