mirror of
https://github.com/reactos/wine.git
synced 2024-12-05 02:07:16 +00:00
1087 lines
32 KiB
C
1087 lines
32 KiB
C
/*
|
|
* Copyright 2001 Rein Klazes
|
|
* Copyright 2007 Juan Lang
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdarg.h>
|
|
|
|
#define NONAMELESSUNION
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "winerror.h"
|
|
#include "winreg.h"
|
|
#include "guiddef.h"
|
|
#include "wintrust.h"
|
|
#include "softpub.h"
|
|
#include "mscat.h"
|
|
#include "objbase.h"
|
|
#include "winuser.h"
|
|
#include "cryptdlg.h"
|
|
#include "cryptuiapi.h"
|
|
#include "wintrust_priv.h"
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(wintrust);
|
|
|
|
|
|
/* Utility functions */
|
|
void * WINAPI WINTRUST_Alloc(DWORD cb)
|
|
{
|
|
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
|
|
}
|
|
|
|
static void* WINTRUST_ReAlloc(void *ptr, DWORD cb) __WINE_ALLOC_SIZE(2);
|
|
static void* WINTRUST_ReAlloc(void *ptr, DWORD cb)
|
|
{
|
|
return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, cb);
|
|
}
|
|
|
|
void WINAPI WINTRUST_Free(void *p)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, p);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* DllMain (WINTRUST.@)
|
|
*/
|
|
BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
|
|
{
|
|
switch(reason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
DisableThreadLibraryCalls( inst );
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* TrustIsCertificateSelfSigned (WINTRUST.@)
|
|
*/
|
|
BOOL WINAPI TrustIsCertificateSelfSigned( PCCERT_CONTEXT cert )
|
|
{
|
|
BOOL ret;
|
|
|
|
TRACE("%p\n", cert);
|
|
ret = CertCompareCertificateName(cert->dwCertEncodingType,
|
|
&cert->pCertInfo->Subject, &cert->pCertInfo->Issuer);
|
|
return ret;
|
|
}
|
|
|
|
typedef HRESULT (WINAPI *wintrust_step_func)(CRYPT_PROVIDER_DATA *data);
|
|
|
|
struct wintrust_step
|
|
{
|
|
wintrust_step_func func;
|
|
DWORD error_index;
|
|
};
|
|
|
|
static DWORD WINTRUST_ExecuteSteps(const struct wintrust_step *steps,
|
|
DWORD numSteps, CRYPT_PROVIDER_DATA *provData)
|
|
{
|
|
DWORD i, err = ERROR_SUCCESS;
|
|
|
|
for (i = 0; !err && i < numSteps; i++)
|
|
{
|
|
err = steps[i].func(provData);
|
|
if (err)
|
|
err = provData->padwTrustStepErrors[steps[i].error_index];
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static CRYPT_PROVIDER_DATA *WINTRUST_AllocateProviderData(void)
|
|
{
|
|
CRYPT_PROVIDER_DATA *provData;
|
|
|
|
provData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_DATA));
|
|
if (!provData)
|
|
goto oom;
|
|
provData->cbStruct = sizeof(CRYPT_PROVIDER_DATA);
|
|
|
|
provData->padwTrustStepErrors =
|
|
WINTRUST_Alloc(TRUSTERROR_MAX_STEPS * sizeof(DWORD));
|
|
if (!provData->padwTrustStepErrors)
|
|
goto oom;
|
|
provData->cdwTrustStepErrors = TRUSTERROR_MAX_STEPS;
|
|
|
|
provData->u.pPDSip = WINTRUST_Alloc(sizeof(PROVDATA_SIP));
|
|
if (!provData->u.pPDSip)
|
|
goto oom;
|
|
provData->u.pPDSip->cbStruct = sizeof(PROVDATA_SIP);
|
|
|
|
provData->psPfns = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_FUNCTIONS));
|
|
if (!provData->psPfns)
|
|
goto oom;
|
|
provData->psPfns->cbStruct = sizeof(CRYPT_PROVIDER_FUNCTIONS);
|
|
return provData;
|
|
|
|
oom:
|
|
if (provData)
|
|
{
|
|
WINTRUST_Free(provData->padwTrustStepErrors);
|
|
WINTRUST_Free(provData->u.pPDSip);
|
|
WINTRUST_Free(provData->psPfns);
|
|
WINTRUST_Free(provData);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* Adds trust steps for each function in psPfns. Assumes steps has at least
|
|
* 5 entries. Returns the number of steps added.
|
|
*/
|
|
static DWORD WINTRUST_AddTrustStepsFromFunctions(struct wintrust_step *steps,
|
|
const CRYPT_PROVIDER_FUNCTIONS *psPfns)
|
|
{
|
|
DWORD numSteps = 0;
|
|
|
|
if (psPfns->pfnInitialize)
|
|
{
|
|
steps[numSteps].func = psPfns->pfnInitialize;
|
|
steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_WVTINIT;
|
|
}
|
|
if (psPfns->pfnObjectTrust)
|
|
{
|
|
steps[numSteps].func = psPfns->pfnObjectTrust;
|
|
steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_OBJPROV;
|
|
}
|
|
if (psPfns->pfnSignatureTrust)
|
|
{
|
|
steps[numSteps].func = psPfns->pfnSignatureTrust;
|
|
steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_SIGPROV;
|
|
}
|
|
if (psPfns->pfnCertificateTrust)
|
|
{
|
|
steps[numSteps].func = psPfns->pfnCertificateTrust;
|
|
steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_CERTPROV;
|
|
}
|
|
if (psPfns->pfnFinalPolicy)
|
|
{
|
|
steps[numSteps].func = psPfns->pfnFinalPolicy;
|
|
steps[numSteps++].error_index = TRUSTERROR_STEP_FINAL_POLICYPROV;
|
|
}
|
|
return numSteps;
|
|
}
|
|
|
|
static LONG WINTRUST_DefaultVerify(HWND hwnd, GUID *actionID,
|
|
WINTRUST_DATA *data)
|
|
{
|
|
DWORD err = ERROR_SUCCESS, numSteps = 0;
|
|
CRYPT_PROVIDER_DATA *provData;
|
|
BOOL ret;
|
|
struct wintrust_step verifySteps[5];
|
|
|
|
TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
|
|
|
|
provData = WINTRUST_AllocateProviderData();
|
|
if (!provData)
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
|
|
if (!ret)
|
|
{
|
|
err = GetLastError();
|
|
goto error;
|
|
}
|
|
|
|
data->hWVTStateData = provData;
|
|
provData->pWintrustData = data;
|
|
if (hwnd == INVALID_HANDLE_VALUE)
|
|
provData->hWndParent = GetDesktopWindow();
|
|
else
|
|
provData->hWndParent = hwnd;
|
|
provData->pgActionID = actionID;
|
|
WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
|
|
|
|
numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
|
|
provData->psPfns);
|
|
err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
|
|
goto done;
|
|
|
|
error:
|
|
if (provData)
|
|
{
|
|
WINTRUST_Free(provData->padwTrustStepErrors);
|
|
WINTRUST_Free(provData->u.pPDSip);
|
|
WINTRUST_Free(provData->psPfns);
|
|
WINTRUST_Free(provData);
|
|
}
|
|
done:
|
|
TRACE("returning %08x\n", err);
|
|
return err;
|
|
}
|
|
|
|
static LONG WINTRUST_DefaultClose(HWND hwnd, GUID *actionID,
|
|
WINTRUST_DATA *data)
|
|
{
|
|
DWORD err = ERROR_SUCCESS;
|
|
CRYPT_PROVIDER_DATA *provData = data->hWVTStateData;
|
|
|
|
TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
|
|
|
|
if (provData)
|
|
{
|
|
if (provData->psPfns->pfnCleanupPolicy)
|
|
err = provData->psPfns->pfnCleanupPolicy(provData);
|
|
|
|
WINTRUST_Free(provData->padwTrustStepErrors);
|
|
WINTRUST_Free(provData->u.pPDSip);
|
|
WINTRUST_Free(provData->psPfns);
|
|
WINTRUST_Free(provData);
|
|
data->hWVTStateData = NULL;
|
|
}
|
|
TRACE("returning %08x\n", err);
|
|
return err;
|
|
}
|
|
|
|
static LONG WINTRUST_DefaultVerifyAndClose(HWND hwnd, GUID *actionID,
|
|
WINTRUST_DATA *data)
|
|
{
|
|
LONG err;
|
|
|
|
TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
|
|
|
|
err = WINTRUST_DefaultVerify(hwnd, actionID, data);
|
|
WINTRUST_DefaultClose(hwnd, actionID, data);
|
|
TRACE("returning %08x\n", err);
|
|
return err;
|
|
}
|
|
|
|
static LONG WINTRUST_PublishedSoftware(HWND hwnd, GUID *actionID,
|
|
WINTRUST_DATA *data)
|
|
{
|
|
WINTRUST_DATA wintrust_data = { sizeof(wintrust_data), 0 };
|
|
/* Undocumented: the published software action is passed a path,
|
|
* and pSIPClientData points to a WIN_TRUST_SUBJECT_FILE.
|
|
*/
|
|
LPWIN_TRUST_SUBJECT_FILE subjectFile = data->pSIPClientData;
|
|
WINTRUST_FILE_INFO fileInfo = { sizeof(fileInfo), 0 };
|
|
|
|
TRACE("subjectFile->hFile: %p\n", subjectFile->hFile);
|
|
TRACE("subjectFile->lpPath: %s\n", debugstr_w(subjectFile->lpPath));
|
|
fileInfo.pcwszFilePath = subjectFile->lpPath;
|
|
fileInfo.hFile = subjectFile->hFile;
|
|
wintrust_data.u.pFile = &fileInfo;
|
|
wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
|
|
wintrust_data.dwUIChoice = WTD_UI_NONE;
|
|
|
|
return WINTRUST_DefaultVerifyAndClose(hwnd, actionID, &wintrust_data);
|
|
}
|
|
|
|
/* Sadly, the function to load the cert for the CERT_CERTIFICATE_ACTION_VERIFY
|
|
* action is not stored in the registry and is located in wintrust, not in
|
|
* cryptdlg along with the rest of the implementation (verified by running the
|
|
* action with a native wintrust.dll.)
|
|
*/
|
|
static HRESULT WINAPI WINTRUST_CertVerifyObjTrust(CRYPT_PROVIDER_DATA *data)
|
|
{
|
|
BOOL ret;
|
|
|
|
TRACE("(%p)\n", data);
|
|
|
|
if (!data->padwTrustStepErrors)
|
|
return S_FALSE;
|
|
|
|
switch (data->pWintrustData->dwUnionChoice)
|
|
{
|
|
case WTD_CHOICE_BLOB:
|
|
if (data->pWintrustData->u.pBlob &&
|
|
data->pWintrustData->u.pBlob->cbStruct == sizeof(WINTRUST_BLOB_INFO) &&
|
|
data->pWintrustData->u.pBlob->cbMemObject ==
|
|
sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
|
|
data->pWintrustData->u.pBlob->pbMemObject)
|
|
{
|
|
CERT_VERIFY_CERTIFICATE_TRUST *pCert =
|
|
(CERT_VERIFY_CERTIFICATE_TRUST *)
|
|
data->pWintrustData->u.pBlob->pbMemObject;
|
|
|
|
if (pCert->cbSize == sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
|
|
pCert->pccert)
|
|
{
|
|
CRYPT_PROVIDER_SGNR signer = { sizeof(signer), { 0 } };
|
|
DWORD i;
|
|
SYSTEMTIME sysTime;
|
|
|
|
/* Add a signer with nothing but the time to verify, so we can
|
|
* add a cert to it
|
|
*/
|
|
GetSystemTime(&sysTime);
|
|
SystemTimeToFileTime(&sysTime, &signer.sftVerifyAsOf);
|
|
ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
|
|
if (!ret)
|
|
goto error;
|
|
ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
|
|
pCert->pccert);
|
|
if (!ret)
|
|
goto error;
|
|
for (i = 0; ret && i < pCert->cRootStores; i++)
|
|
ret = data->psPfns->pfnAddStore2Chain(data,
|
|
pCert->rghstoreRoots[i]);
|
|
for (i = 0; ret && i < pCert->cStores; i++)
|
|
ret = data->psPfns->pfnAddStore2Chain(data,
|
|
pCert->rghstoreCAs[i]);
|
|
for (i = 0; ret && i < pCert->cTrustStores; i++)
|
|
ret = data->psPfns->pfnAddStore2Chain(data,
|
|
pCert->rghstoreTrust[i]);
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
ret = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
ret = FALSE;
|
|
}
|
|
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();
|
|
TRACE("returning %d (%08x)\n", ret ? S_OK : S_FALSE,
|
|
data->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_OBJPROV]);
|
|
return ret ? S_OK : S_FALSE;
|
|
}
|
|
|
|
static LONG WINTRUST_CertVerify(HWND hwnd, GUID *actionID,
|
|
WINTRUST_DATA *data)
|
|
{
|
|
DWORD err = ERROR_SUCCESS, numSteps = 0;
|
|
CRYPT_PROVIDER_DATA *provData;
|
|
BOOL ret;
|
|
struct wintrust_step verifySteps[5];
|
|
|
|
TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
|
|
|
|
provData = WINTRUST_AllocateProviderData();
|
|
if (!provData)
|
|
return ERROR_OUTOFMEMORY;
|
|
|
|
ret = WintrustLoadFunctionPointers(actionID, provData->psPfns);
|
|
if (!ret)
|
|
{
|
|
err = GetLastError();
|
|
goto error;
|
|
}
|
|
if (!provData->psPfns->pfnObjectTrust)
|
|
provData->psPfns->pfnObjectTrust = WINTRUST_CertVerifyObjTrust;
|
|
/* Not sure why, but native skips the policy check */
|
|
provData->psPfns->pfnCertCheckPolicy = NULL;
|
|
|
|
data->hWVTStateData = provData;
|
|
provData->pWintrustData = data;
|
|
if (hwnd == INVALID_HANDLE_VALUE)
|
|
provData->hWndParent = GetDesktopWindow();
|
|
else
|
|
provData->hWndParent = hwnd;
|
|
provData->pgActionID = actionID;
|
|
WintrustGetRegPolicyFlags(&provData->dwRegPolicySettings);
|
|
|
|
numSteps = WINTRUST_AddTrustStepsFromFunctions(verifySteps,
|
|
provData->psPfns);
|
|
err = WINTRUST_ExecuteSteps(verifySteps, numSteps, provData);
|
|
goto done;
|
|
|
|
error:
|
|
if (provData)
|
|
{
|
|
WINTRUST_Free(provData->padwTrustStepErrors);
|
|
WINTRUST_Free(provData->u.pPDSip);
|
|
WINTRUST_Free(provData->psPfns);
|
|
WINTRUST_Free(provData);
|
|
}
|
|
done:
|
|
TRACE("returning %08x\n", err);
|
|
return err;
|
|
}
|
|
|
|
static LONG WINTRUST_CertVerifyAndClose(HWND hwnd, GUID *actionID,
|
|
WINTRUST_DATA *data)
|
|
{
|
|
LONG err;
|
|
|
|
TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(actionID), data);
|
|
|
|
err = WINTRUST_CertVerify(hwnd, actionID, data);
|
|
WINTRUST_DefaultClose(hwnd, actionID, data);
|
|
TRACE("returning %08x\n", err);
|
|
return err;
|
|
}
|
|
|
|
static LONG WINTRUST_CertActionVerify(HWND hwnd, GUID *actionID,
|
|
WINTRUST_DATA *data)
|
|
{
|
|
DWORD stateAction;
|
|
LONG err = ERROR_SUCCESS;
|
|
|
|
if (WVT_ISINSTRUCT(WINTRUST_DATA, data->cbStruct, dwStateAction))
|
|
stateAction = data->dwStateAction;
|
|
else
|
|
{
|
|
TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
|
|
stateAction = WTD_STATEACTION_IGNORE;
|
|
}
|
|
switch (stateAction)
|
|
{
|
|
case WTD_STATEACTION_IGNORE:
|
|
err = WINTRUST_CertVerifyAndClose(hwnd, actionID, data);
|
|
break;
|
|
case WTD_STATEACTION_VERIFY:
|
|
err = WINTRUST_CertVerify(hwnd, actionID, data);
|
|
break;
|
|
case WTD_STATEACTION_CLOSE:
|
|
err = WINTRUST_DefaultClose(hwnd, actionID, data);
|
|
break;
|
|
default:
|
|
FIXME("unimplemented for %d\n", data->dwStateAction);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
static void dump_file_info(WINTRUST_FILE_INFO *pFile)
|
|
{
|
|
TRACE("%p\n", pFile);
|
|
if (pFile)
|
|
{
|
|
TRACE("cbStruct: %d\n", pFile->cbStruct);
|
|
TRACE("pcwszFilePath: %s\n", debugstr_w(pFile->pcwszFilePath));
|
|
TRACE("hFile: %p\n", pFile->hFile);
|
|
TRACE("pgKnownSubject: %s\n", debugstr_guid(pFile->pgKnownSubject));
|
|
}
|
|
}
|
|
|
|
static void dump_catalog_info(WINTRUST_CATALOG_INFO *catalog)
|
|
{
|
|
TRACE("%p\n", catalog);
|
|
if (catalog)
|
|
{
|
|
TRACE("cbStruct: %d\n", catalog->cbStruct);
|
|
TRACE("dwCatalogVersion: %d\n", catalog->dwCatalogVersion);
|
|
TRACE("pcwszCatalogFilePath: %s\n",
|
|
debugstr_w(catalog->pcwszCatalogFilePath));
|
|
TRACE("pcwszMemberTag: %s\n", debugstr_w(catalog->pcwszMemberTag));
|
|
TRACE("pcwszMemberFilePath: %s\n",
|
|
debugstr_w(catalog->pcwszMemberFilePath));
|
|
TRACE("hMemberFile: %p\n", catalog->hMemberFile);
|
|
TRACE("pbCalculatedFileHash: %p\n", catalog->pbCalculatedFileHash);
|
|
TRACE("cbCalculatedFileHash: %d\n", catalog->cbCalculatedFileHash);
|
|
TRACE("pcCatalogContext: %p\n", catalog->pcCatalogContext);
|
|
}
|
|
}
|
|
|
|
static void dump_blob_info(WINTRUST_BLOB_INFO *blob)
|
|
{
|
|
TRACE("%p\n", blob);
|
|
if (blob)
|
|
{
|
|
TRACE("cbStruct: %d\n", blob->cbStruct);
|
|
TRACE("gSubject: %s\n", debugstr_guid(&blob->gSubject));
|
|
TRACE("pcwszDisplayName: %s\n", debugstr_w(blob->pcwszDisplayName));
|
|
TRACE("cbMemObject: %d\n", blob->cbMemObject);
|
|
TRACE("pbMemObject: %p\n", blob->pbMemObject);
|
|
TRACE("cbMemSignedMsg: %d\n", blob->cbMemSignedMsg);
|
|
TRACE("pbMemSignedMsg: %p\n", blob->pbMemSignedMsg);
|
|
}
|
|
}
|
|
|
|
static void dump_sgnr_info(WINTRUST_SGNR_INFO *sgnr)
|
|
{
|
|
TRACE("%p\n", sgnr);
|
|
if (sgnr)
|
|
{
|
|
TRACE("cbStruct: %d\n", sgnr->cbStruct);
|
|
TRACE("pcwszDisplayName: %s\n", debugstr_w(sgnr->pcwszDisplayName));
|
|
TRACE("psSignerInfo: %p\n", sgnr->psSignerInfo);
|
|
TRACE("chStores: %d\n", sgnr->chStores);
|
|
}
|
|
}
|
|
|
|
static void dump_cert_info(WINTRUST_CERT_INFO *cert)
|
|
{
|
|
TRACE("%p\n", cert);
|
|
if (cert)
|
|
{
|
|
TRACE("cbStruct: %d\n", cert->cbStruct);
|
|
TRACE("pcwszDisplayName: %s\n", debugstr_w(cert->pcwszDisplayName));
|
|
TRACE("psCertContext: %p\n", cert->psCertContext);
|
|
TRACE("chStores: %d\n", cert->chStores);
|
|
TRACE("dwFlags: %08x\n", cert->dwFlags);
|
|
TRACE("psftVerifyAsOf: %p\n", cert->psftVerifyAsOf);
|
|
}
|
|
}
|
|
|
|
static void dump_wintrust_data(WINTRUST_DATA *data)
|
|
{
|
|
TRACE("%p\n", data);
|
|
if (data)
|
|
{
|
|
TRACE("cbStruct: %d\n", data->cbStruct);
|
|
TRACE("pPolicyCallbackData: %p\n", data->pPolicyCallbackData);
|
|
TRACE("pSIPClientData: %p\n", data->pSIPClientData);
|
|
TRACE("dwUIChoice: %d\n", data->dwUIChoice);
|
|
TRACE("fdwRevocationChecks: %08x\n", data->fdwRevocationChecks);
|
|
TRACE("dwUnionChoice: %d\n", data->dwUnionChoice);
|
|
switch (data->dwUnionChoice)
|
|
{
|
|
case WTD_CHOICE_FILE:
|
|
dump_file_info(data->u.pFile);
|
|
break;
|
|
case WTD_CHOICE_CATALOG:
|
|
dump_catalog_info(data->u.pCatalog);
|
|
break;
|
|
case WTD_CHOICE_BLOB:
|
|
dump_blob_info(data->u.pBlob);
|
|
break;
|
|
case WTD_CHOICE_SIGNER:
|
|
dump_sgnr_info(data->u.pSgnr);
|
|
break;
|
|
case WTD_CHOICE_CERT:
|
|
dump_cert_info(data->u.pCert);
|
|
break;
|
|
}
|
|
TRACE("dwStateAction: %d\n", data->dwStateAction);
|
|
TRACE("hWVTStateData: %p\n", data->hWVTStateData);
|
|
TRACE("pwszURLReference: %s\n", debugstr_w(data->pwszURLReference));
|
|
TRACE("dwProvFlags: %08x\n", data->dwProvFlags);
|
|
TRACE("dwUIContext: %d\n", data->dwUIContext);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* WinVerifyTrust (WINTRUST.@)
|
|
*
|
|
* Verifies an object by calling the specified trust provider.
|
|
*
|
|
* PARAMS
|
|
* hwnd [I] Handle to a caller window.
|
|
* ActionID [I] Pointer to a GUID that identifies the action to perform.
|
|
* ActionData [I] Information used by the trust provider to verify the object.
|
|
*
|
|
* RETURNS
|
|
* Success: Zero.
|
|
* Failure: A TRUST_E_* error code.
|
|
*
|
|
* NOTES
|
|
* Trust providers can be found at:
|
|
* HKLM\SOFTWARE\Microsoft\Cryptography\Providers\Trust\
|
|
*/
|
|
LONG WINAPI WinVerifyTrust( HWND hwnd, GUID *ActionID, LPVOID ActionData )
|
|
{
|
|
static const GUID unknown = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,
|
|
0x00,0xC0,0x4F,0xC2,0x95,0xEE } };
|
|
static const GUID published_software = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
|
|
static const GUID generic_verify_v2 = WINTRUST_ACTION_GENERIC_VERIFY_V2;
|
|
static const GUID generic_cert_verify = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
|
|
static const GUID generic_chain_verify = WINTRUST_ACTION_GENERIC_CHAIN_VERIFY;
|
|
static const GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY;
|
|
LONG err = ERROR_SUCCESS;
|
|
WINTRUST_DATA *actionData = ActionData;
|
|
|
|
TRACE("(%p, %s, %p)\n", hwnd, debugstr_guid(ActionID), ActionData);
|
|
dump_wintrust_data(ActionData);
|
|
|
|
/* Support for known old-style callers: */
|
|
if (IsEqualGUID(ActionID, &published_software))
|
|
err = WINTRUST_PublishedSoftware(hwnd, ActionID, ActionData);
|
|
else if (IsEqualGUID(ActionID, &cert_action_verify))
|
|
err = WINTRUST_CertActionVerify(hwnd, ActionID, ActionData);
|
|
else
|
|
{
|
|
DWORD stateAction;
|
|
|
|
/* Check known actions to warn of possible problems */
|
|
if (!IsEqualGUID(ActionID, &unknown) &&
|
|
!IsEqualGUID(ActionID, &generic_verify_v2) &&
|
|
!IsEqualGUID(ActionID, &generic_cert_verify) &&
|
|
!IsEqualGUID(ActionID, &generic_chain_verify))
|
|
WARN("unknown action %s, default behavior may not be right\n",
|
|
debugstr_guid(ActionID));
|
|
if (WVT_ISINSTRUCT(WINTRUST_DATA, actionData->cbStruct, dwStateAction))
|
|
stateAction = actionData->dwStateAction;
|
|
else
|
|
{
|
|
TRACE("no dwStateAction, assuming WTD_STATEACTION_IGNORE\n");
|
|
stateAction = WTD_STATEACTION_IGNORE;
|
|
}
|
|
switch (stateAction)
|
|
{
|
|
case WTD_STATEACTION_IGNORE:
|
|
err = WINTRUST_DefaultVerifyAndClose(hwnd, ActionID, ActionData);
|
|
break;
|
|
case WTD_STATEACTION_VERIFY:
|
|
err = WINTRUST_DefaultVerify(hwnd, ActionID, ActionData);
|
|
break;
|
|
case WTD_STATEACTION_CLOSE:
|
|
err = WINTRUST_DefaultClose(hwnd, ActionID, ActionData);
|
|
break;
|
|
default:
|
|
FIXME("unimplemented for %d\n", actionData->dwStateAction);
|
|
}
|
|
}
|
|
|
|
TRACE("returning %08x\n", err);
|
|
return err;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* WinVerifyTrustEx (WINTRUST.@)
|
|
*/
|
|
HRESULT WINAPI WinVerifyTrustEx( HWND hwnd, GUID *ActionID,
|
|
WINTRUST_DATA* ActionData )
|
|
{
|
|
return WinVerifyTrust(hwnd, ActionID, ActionData);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* WTHelperGetProvSignerFromChain (WINTRUST.@)
|
|
*/
|
|
CRYPT_PROVIDER_SGNR * WINAPI WTHelperGetProvSignerFromChain(
|
|
CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner,
|
|
DWORD idxCounterSigner)
|
|
{
|
|
CRYPT_PROVIDER_SGNR *sgnr;
|
|
|
|
TRACE("(%p %d %d %d)\n", pProvData, idxSigner, fCounterSigner,
|
|
idxCounterSigner);
|
|
|
|
if (idxSigner >= pProvData->csSigners || !pProvData->pasSigners)
|
|
return NULL;
|
|
sgnr = &pProvData->pasSigners[idxSigner];
|
|
if (fCounterSigner)
|
|
{
|
|
if (idxCounterSigner >= sgnr->csCounterSigners ||
|
|
!sgnr->pasCounterSigners)
|
|
return NULL;
|
|
sgnr = &sgnr->pasCounterSigners[idxCounterSigner];
|
|
}
|
|
TRACE("returning %p\n", sgnr);
|
|
return sgnr;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* WTHelperGetProvCertFromChain (WINTRUST.@)
|
|
*/
|
|
CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
|
|
CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert)
|
|
{
|
|
CRYPT_PROVIDER_CERT *cert;
|
|
|
|
TRACE("(%p %d)\n", pSgnr, idxCert);
|
|
|
|
if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
|
|
return NULL;
|
|
cert = &pSgnr->pasCertChain[idxCert];
|
|
TRACE("returning %p\n", cert);
|
|
return cert;
|
|
}
|
|
|
|
CRYPT_PROVIDER_PRIVDATA *WINAPI WTHelperGetProvPrivateDataFromChain(
|
|
CRYPT_PROVIDER_DATA* pProvData,
|
|
GUID* pgProviderID)
|
|
{
|
|
CRYPT_PROVIDER_PRIVDATA *privdata = NULL;
|
|
DWORD i;
|
|
|
|
TRACE("(%p, %s)\n", pProvData, debugstr_guid(pgProviderID));
|
|
|
|
for (i = 0; i < pProvData->csProvPrivData; i++)
|
|
if (IsEqualGUID(pgProviderID, &pProvData->pasProvPrivData[i].gProviderID))
|
|
{
|
|
privdata = &pProvData->pasProvPrivData[i];
|
|
break;
|
|
}
|
|
|
|
return privdata;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* WTHelperProvDataFromStateData (WINTRUST.@)
|
|
*/
|
|
CRYPT_PROVIDER_DATA * WINAPI WTHelperProvDataFromStateData(HANDLE hStateData)
|
|
{
|
|
TRACE("%p\n", hStateData);
|
|
return hStateData;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* WTHelperGetFileName(WINTRUST.@)
|
|
*/
|
|
LPCWSTR WINAPI WTHelperGetFileName(WINTRUST_DATA *data)
|
|
{
|
|
TRACE("%p\n",data);
|
|
if (data->dwUnionChoice == WTD_CHOICE_FILE)
|
|
return data->u.pFile->pcwszFilePath;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* WTHelperGetFileHandle(WINTRUST.@)
|
|
*/
|
|
HANDLE WINAPI WTHelperGetFileHandle(WINTRUST_DATA *data)
|
|
{
|
|
TRACE("%p\n",data);
|
|
if (data->dwUnionChoice == WTD_CHOICE_FILE)
|
|
return data->u.pFile->hFile;
|
|
else
|
|
return INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
static BOOL WINAPI WINTRUST_enumUsages(PCCRYPT_OID_INFO pInfo, void *pvArg)
|
|
{
|
|
PCCRYPT_OID_INFO **usages = pvArg;
|
|
DWORD cUsages;
|
|
BOOL ret;
|
|
|
|
if (!*usages)
|
|
{
|
|
cUsages = 0;
|
|
*usages = WINTRUST_Alloc(2 * sizeof(PCCRYPT_OID_INFO));
|
|
}
|
|
else
|
|
{
|
|
PCCRYPT_OID_INFO *ptr;
|
|
|
|
/* Count the existing usages.
|
|
* FIXME: make sure the new usage doesn't duplicate any in the list?
|
|
*/
|
|
for (cUsages = 0, ptr = *usages; *ptr; ptr++, cUsages++)
|
|
;
|
|
*usages = WINTRUST_ReAlloc(*usages,
|
|
(cUsages + 2) * sizeof(PCCRYPT_OID_INFO));
|
|
}
|
|
if (*usages)
|
|
{
|
|
(*usages)[cUsages] = pInfo;
|
|
(*usages)[cUsages + 1] = NULL;
|
|
ret = TRUE;
|
|
}
|
|
else
|
|
{
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
ret = FALSE;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* WTHelperGetKnownUsages(WINTRUST.@)
|
|
*
|
|
* Enumerates the known enhanced key usages as an array of PCCRYPT_OID_INFOs.
|
|
*
|
|
* PARAMS
|
|
* action [In] 1 => allocate and return known usages, 2 => free previously
|
|
* allocated usages.
|
|
* usages [In/Out] If action == 1, *usages is set to an array of
|
|
* PCCRYPT_OID_INFO *. The array is terminated with a NULL
|
|
* pointer.
|
|
* If action == 2, *usages is freed.
|
|
*
|
|
* RETURNS
|
|
* TRUE on success, FALSE on failure.
|
|
*/
|
|
BOOL WINAPI WTHelperGetKnownUsages(DWORD action, PCCRYPT_OID_INFO **usages)
|
|
{
|
|
BOOL ret;
|
|
|
|
TRACE("(%d, %p)\n", action, usages);
|
|
|
|
if (!usages)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
if (action == 1)
|
|
{
|
|
*usages = NULL;
|
|
ret = CryptEnumOIDInfo(CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, usages,
|
|
WINTRUST_enumUsages);
|
|
}
|
|
else if (action == 2)
|
|
{
|
|
WINTRUST_Free(*usages);
|
|
*usages = NULL;
|
|
ret = TRUE;
|
|
}
|
|
else
|
|
{
|
|
WARN("unknown action %d\n", action);
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
ret = FALSE;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static const WCHAR Software_Publishing[] = {
|
|
'S','o','f','t','w','a','r','e','\\',
|
|
'M','i','c','r','o','s','o','f','t','\\',
|
|
'W','i','n','d','o','w','s','\\',
|
|
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
|
|
'W','i','n','t','r','u','s','t','\\',
|
|
'T','r','u','s','t',' ','P','r','o','v','i','d','e','r','s','\\',
|
|
'S','o','f','t','w','a','r','e',' ',
|
|
'P','u','b','l','i','s','h','i','n','g',0 };
|
|
static const WCHAR State[] = { 'S','t','a','t','e',0 };
|
|
|
|
/***********************************************************************
|
|
* WintrustGetRegPolicyFlags (WINTRUST.@)
|
|
*/
|
|
void WINAPI WintrustGetRegPolicyFlags( DWORD* pdwPolicyFlags )
|
|
{
|
|
HKEY key;
|
|
LONG r;
|
|
|
|
TRACE("%p\n", pdwPolicyFlags);
|
|
|
|
*pdwPolicyFlags = 0;
|
|
r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0, NULL, 0,
|
|
KEY_READ, NULL, &key, NULL);
|
|
if (!r)
|
|
{
|
|
DWORD size = sizeof(DWORD);
|
|
|
|
r = RegQueryValueExW(key, State, NULL, NULL, (LPBYTE)pdwPolicyFlags,
|
|
&size);
|
|
RegCloseKey(key);
|
|
if (r)
|
|
{
|
|
/* Failed to query, create and return default value */
|
|
*pdwPolicyFlags = WTPF_IGNOREREVOCATIONONTS |
|
|
WTPF_OFFLINEOKNBU_COM |
|
|
WTPF_OFFLINEOKNBU_IND |
|
|
WTPF_OFFLINEOK_COM |
|
|
WTPF_OFFLINEOK_IND;
|
|
WintrustSetRegPolicyFlags(*pdwPolicyFlags);
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* WintrustSetRegPolicyFlags (WINTRUST.@)
|
|
*/
|
|
BOOL WINAPI WintrustSetRegPolicyFlags( DWORD dwPolicyFlags)
|
|
{
|
|
HKEY key;
|
|
LONG r;
|
|
|
|
TRACE("%x\n", dwPolicyFlags);
|
|
|
|
r = RegCreateKeyExW(HKEY_CURRENT_USER, Software_Publishing, 0,
|
|
NULL, 0, KEY_WRITE, NULL, &key, NULL);
|
|
if (!r)
|
|
{
|
|
r = RegSetValueExW(key, State, 0, REG_DWORD, (LPBYTE)&dwPolicyFlags,
|
|
sizeof(DWORD));
|
|
RegCloseKey(key);
|
|
}
|
|
if (r) SetLastError(r);
|
|
return r == ERROR_SUCCESS;
|
|
}
|
|
|
|
/* Utility functions */
|
|
|
|
BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store)
|
|
{
|
|
BOOL ret = FALSE;
|
|
|
|
TRACE("(%p, %p)\n", data, store);
|
|
|
|
if (data->chStores)
|
|
data->pahStores = WINTRUST_ReAlloc(data->pahStores,
|
|
(data->chStores + 1) * sizeof(HCERTSTORE));
|
|
else
|
|
{
|
|
data->pahStores = WINTRUST_Alloc(sizeof(HCERTSTORE));
|
|
data->chStores = 0;
|
|
}
|
|
if (data->pahStores)
|
|
{
|
|
data->pahStores[data->chStores++] = CertDuplicateStore(store);
|
|
ret = TRUE;
|
|
}
|
|
else
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return ret;
|
|
}
|
|
|
|
BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data,
|
|
BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr)
|
|
{
|
|
BOOL ret = FALSE;
|
|
|
|
TRACE("(%p, %d, %d, %p)\n", data, fCounterSigner, idxSigner, sgnr);
|
|
|
|
if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR))
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
if (fCounterSigner)
|
|
{
|
|
FIXME("unimplemented for counter signers\n");
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
if (data->csSigners)
|
|
data->pasSigners = WINTRUST_ReAlloc(data->pasSigners,
|
|
(data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR));
|
|
else
|
|
{
|
|
data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
|
|
data->csSigners = 0;
|
|
}
|
|
if (data->pasSigners)
|
|
{
|
|
if (idxSigner < data->csSigners)
|
|
memmove(&data->pasSigners[idxSigner],
|
|
&data->pasSigners[idxSigner + 1],
|
|
(data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR));
|
|
ret = TRUE;
|
|
if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR))
|
|
{
|
|
/* The PSDK says psSigner should be allocated using pfnAlloc, but
|
|
* it doesn't say anything about ownership. Since callers are
|
|
* internal, assume ownership is passed, and just store the
|
|
* pointer.
|
|
*/
|
|
memcpy(&data->pasSigners[idxSigner], sgnr,
|
|
sizeof(CRYPT_PROVIDER_SGNR));
|
|
}
|
|
else
|
|
memset(&data->pasSigners[idxSigner], 0,
|
|
sizeof(CRYPT_PROVIDER_SGNR));
|
|
data->csSigners++;
|
|
}
|
|
else
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return ret;
|
|
}
|
|
|
|
BOOL WINAPI WINTRUST_AddCert(CRYPT_PROVIDER_DATA *data, DWORD idxSigner,
|
|
BOOL fCounterSigner, DWORD idxCounterSigner, PCCERT_CONTEXT pCert2Add)
|
|
{
|
|
BOOL ret = FALSE;
|
|
|
|
TRACE("(%p, %d, %d, %d, %p)\n", data, idxSigner, fCounterSigner,
|
|
idxSigner, pCert2Add);
|
|
|
|
if (fCounterSigner)
|
|
{
|
|
FIXME("unimplemented for counter signers\n");
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
if (data->pasSigners[idxSigner].csCertChain)
|
|
data->pasSigners[idxSigner].pasCertChain =
|
|
WINTRUST_ReAlloc(data->pasSigners[idxSigner].pasCertChain,
|
|
(data->pasSigners[idxSigner].csCertChain + 1) *
|
|
sizeof(CRYPT_PROVIDER_CERT));
|
|
else
|
|
{
|
|
data->pasSigners[idxSigner].pasCertChain =
|
|
WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_CERT));
|
|
data->pasSigners[idxSigner].csCertChain = 0;
|
|
}
|
|
if (data->pasSigners[idxSigner].pasCertChain)
|
|
{
|
|
CRYPT_PROVIDER_CERT *cert = &data->pasSigners[idxSigner].pasCertChain[
|
|
data->pasSigners[idxSigner].csCertChain];
|
|
|
|
cert->cbStruct = sizeof(CRYPT_PROVIDER_CERT);
|
|
cert->pCert = CertDuplicateCertificateContext(pCert2Add);
|
|
data->pasSigners[idxSigner].csCertChain++;
|
|
ret = TRUE;
|
|
}
|
|
else
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return ret;
|
|
}
|
|
|
|
BOOL WINAPI WINTRUST_AddPrivData(CRYPT_PROVIDER_DATA *data,
|
|
CRYPT_PROVIDER_PRIVDATA *pPrivData2Add)
|
|
{
|
|
BOOL ret = FALSE;
|
|
|
|
TRACE("(%p, %p)\n", data, pPrivData2Add);
|
|
|
|
if (pPrivData2Add->cbStruct > sizeof(CRYPT_PROVIDER_PRIVDATA))
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
WARN("invalid struct size\n");
|
|
return FALSE;
|
|
}
|
|
if (data->csProvPrivData)
|
|
data->pasProvPrivData = WINTRUST_ReAlloc(data->pasProvPrivData,
|
|
(data->csProvPrivData + 1) * sizeof(CRYPT_PROVIDER_SGNR));
|
|
else
|
|
{
|
|
data->pasProvPrivData = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR));
|
|
data->csProvPrivData = 0;
|
|
}
|
|
if (data->pasProvPrivData)
|
|
{
|
|
DWORD i;
|
|
|
|
for (i = 0; i < data->csProvPrivData; i++)
|
|
if (IsEqualGUID(&pPrivData2Add->gProviderID, &data->pasProvPrivData[i]))
|
|
break;
|
|
|
|
data->pasProvPrivData[i] = *pPrivData2Add;
|
|
if (i == data->csProvPrivData)
|
|
data->csProvPrivData++;
|
|
}
|
|
else
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return ret;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* OpenPersonalTrustDBDialog (WINTRUST.@)
|
|
*
|
|
* Opens the certificate manager dialog, showing only the stores that
|
|
* contain trusted software publishers.
|
|
*
|
|
* PARAMS
|
|
* hwnd [I] handle of parent window
|
|
*
|
|
* RETURNS
|
|
* TRUE if the dialog could be opened, FALSE if not.
|
|
*/
|
|
BOOL WINAPI OpenPersonalTrustDBDialog(HWND hwnd)
|
|
{
|
|
CRYPTUI_CERT_MGR_STRUCT uiCertMgr;
|
|
|
|
uiCertMgr.dwSize = sizeof(uiCertMgr);
|
|
uiCertMgr.hwndParent = hwnd;
|
|
uiCertMgr.dwFlags = CRYPTUI_CERT_MGR_PUBLISHER_TAB;
|
|
uiCertMgr.pwszTitle = NULL;
|
|
uiCertMgr.pszInitUsageOID = NULL;
|
|
return CryptUIDlgCertMgr(&uiCertMgr);
|
|
}
|