2009-01-23 13:06:33 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2008 Maarten Lankhorst
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define NONAMELESSUNION
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
2019-10-26 21:53:42 +00:00
|
|
|
#ifdef __REACTOS__
|
|
|
|
#include <wchar.h>
|
|
|
|
#endif
|
2009-01-23 13:06:33 +00:00
|
|
|
|
2018-03-09 12:01:37 +00:00
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "winnls.h"
|
|
|
|
#include "winreg.h"
|
|
|
|
#include "wincrypt.h"
|
|
|
|
#include "wintrust.h"
|
|
|
|
#include "winuser.h"
|
|
|
|
#include "objbase.h"
|
|
|
|
#include "cryptdlg.h"
|
|
|
|
#include "cryptuiapi.h"
|
2009-01-23 13:06:33 +00:00
|
|
|
#include "cryptres.h"
|
2018-03-09 12:01:37 +00:00
|
|
|
#include "wine/debug.h"
|
2009-01-23 13:06:33 +00:00
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(cryptdlg);
|
|
|
|
|
|
|
|
static HINSTANCE hInstance;
|
|
|
|
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|
|
|
{
|
|
|
|
TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
|
|
|
|
|
|
|
|
switch (fdwReason)
|
|
|
|
{
|
|
|
|
case DLL_WINE_PREATTACH:
|
|
|
|
return FALSE; /* prefer native version */
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
DisableThreadLibraryCalls(hinstDLL);
|
|
|
|
hInstance = hinstDLL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetFriendlyNameOfCertA (CRYPTDLG.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI GetFriendlyNameOfCertA(PCCERT_CONTEXT pccert, LPSTR pchBuffer,
|
|
|
|
DWORD cchBuffer)
|
|
|
|
{
|
|
|
|
return CertGetNameStringA(pccert, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
|
|
|
|
pchBuffer, cchBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetFriendlyNameOfCertW (CRYPTDLG.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert, LPWSTR pchBuffer,
|
|
|
|
DWORD cchBuffer)
|
|
|
|
{
|
|
|
|
return CertGetNameStringW(pccert, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0, NULL,
|
|
|
|
pchBuffer, cchBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CertTrustInit (CRYPTDLG.@)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI CertTrustInit(CRYPT_PROVIDER_DATA *pProvData)
|
|
|
|
{
|
|
|
|
HRESULT ret = S_FALSE;
|
|
|
|
|
|
|
|
TRACE("(%p)\n", pProvData);
|
|
|
|
|
|
|
|
if (pProvData->padwTrustStepErrors &&
|
|
|
|
!pProvData->padwTrustStepErrors[TRUSTERROR_STEP_FINAL_WVTINIT])
|
|
|
|
ret = S_OK;
|
|
|
|
TRACE("returning %08x\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CertTrustCertPolicy (CRYPTDLG.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI CertTrustCertPolicy(CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSignerChain, DWORD idxCounterSigner)
|
|
|
|
{
|
|
|
|
FIXME("(%p, %d, %s, %d)\n", pProvData, idxSigner, fCounterSignerChain ? "TRUE" : "FALSE", idxCounterSigner);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CertTrustCleanup (CRYPTDLG.@)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI CertTrustCleanup(CRYPT_PROVIDER_DATA *pProvData)
|
|
|
|
{
|
|
|
|
FIXME("(%p)\n", pProvData);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL CRYPTDLG_CheckOnlineCRL(void)
|
|
|
|
{
|
|
|
|
static const WCHAR policyFlagsKey[] = { 'S','o','f','t','w','a','r','e',
|
|
|
|
'\\','M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g',
|
|
|
|
'r','a','p','h','y','\\','{','7','8','0','1','e','b','d','0','-','c','f',
|
|
|
|
'4','b','-','1','1','d','0','-','8','5','1','f','-','0','0','6','0','9',
|
|
|
|
'7','9','3','8','7','e','a','}',0 };
|
|
|
|
static const WCHAR policyFlags[] = { 'P','o','l','i','c','y','F','l','a',
|
|
|
|
'g','s',0 };
|
|
|
|
HKEY key;
|
|
|
|
BOOL ret = FALSE;
|
|
|
|
|
|
|
|
if (!RegOpenKeyExW(HKEY_LOCAL_MACHINE, policyFlagsKey, 0, KEY_READ, &key))
|
|
|
|
{
|
|
|
|
DWORD type, flags, size = sizeof(flags);
|
|
|
|
|
|
|
|
if (!RegQueryValueExW(key, policyFlags, NULL, &type, (BYTE *)&flags,
|
|
|
|
&size) && type == REG_DWORD)
|
|
|
|
{
|
|
|
|
/* The flag values aren't defined in any header I'm aware of, but
|
|
|
|
* this value is well documented on the net.
|
|
|
|
*/
|
|
|
|
if (flags & 0x00010000)
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
RegCloseKey(key);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns TRUE if pCert is not in the Disallowed system store, or FALSE if it
|
|
|
|
* is.
|
|
|
|
*/
|
|
|
|
static BOOL CRYPTDLG_IsCertAllowed(PCCERT_CONTEXT pCert)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
BYTE hash[20];
|
|
|
|
DWORD size = sizeof(hash);
|
|
|
|
|
|
|
|
if ((ret = CertGetCertificateContextProperty(pCert,
|
|
|
|
CERT_SIGNATURE_HASH_PROP_ID, hash, &size)))
|
|
|
|
{
|
|
|
|
static const WCHAR disallowedW[] =
|
|
|
|
{ 'D','i','s','a','l','l','o','w','e','d',0 };
|
|
|
|
HCERTSTORE disallowed = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
|
|
|
|
X509_ASN_ENCODING, 0, CERT_SYSTEM_STORE_CURRENT_USER, disallowedW);
|
|
|
|
|
|
|
|
if (disallowed)
|
|
|
|
{
|
|
|
|
PCCERT_CONTEXT found = CertFindCertificateInStore(disallowed,
|
|
|
|
X509_ASN_ENCODING, 0, CERT_FIND_SIGNATURE_HASH, hash, NULL);
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
{
|
|
|
|
ret = FALSE;
|
|
|
|
CertFreeCertificateContext(found);
|
|
|
|
}
|
|
|
|
CertCloseStore(disallowed, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD CRYPTDLG_TrustStatusToConfidence(DWORD errorStatus)
|
|
|
|
{
|
|
|
|
DWORD confidence = 0;
|
|
|
|
|
|
|
|
confidence = 0;
|
|
|
|
if (!(errorStatus & CERT_TRUST_IS_NOT_SIGNATURE_VALID))
|
|
|
|
confidence |= CERT_CONFIDENCE_SIG;
|
|
|
|
if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_VALID))
|
|
|
|
confidence |= CERT_CONFIDENCE_TIME;
|
|
|
|
if (!(errorStatus & CERT_TRUST_IS_NOT_TIME_NESTED))
|
|
|
|
confidence |= CERT_CONFIDENCE_TIMENEST;
|
|
|
|
return confidence;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL CRYPTDLG_CopyChain(CRYPT_PROVIDER_DATA *data,
|
|
|
|
PCCERT_CHAIN_CONTEXT chain)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
CRYPT_PROVIDER_SGNR signer;
|
|
|
|
PCERT_SIMPLE_CHAIN simpleChain = chain->rgpChain[0];
|
|
|
|
DWORD i;
|
|
|
|
|
|
|
|
memset(&signer, 0, sizeof(signer));
|
|
|
|
signer.cbStruct = sizeof(signer);
|
|
|
|
ret = data->psPfns->pfnAddSgnr2Chain(data, FALSE, 0, &signer);
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
CRYPT_PROVIDER_SGNR *sgnr = WTHelperGetProvSignerFromChain(data, 0,
|
|
|
|
FALSE, 0);
|
|
|
|
|
|
|
|
if (sgnr)
|
|
|
|
{
|
|
|
|
sgnr->dwError = simpleChain->TrustStatus.dwErrorStatus;
|
|
|
|
sgnr->pChainContext = CertDuplicateCertificateChain(chain);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = FALSE;
|
|
|
|
for (i = 0; ret && i < simpleChain->cElement; i++)
|
|
|
|
{
|
|
|
|
ret = data->psPfns->pfnAddCert2Chain(data, 0, FALSE, 0,
|
|
|
|
simpleChain->rgpElement[i]->pCertContext);
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
CRYPT_PROVIDER_CERT *cert;
|
|
|
|
|
|
|
|
if ((cert = WTHelperGetProvCertFromChain(sgnr, i)))
|
|
|
|
{
|
|
|
|
CERT_CHAIN_ELEMENT *element = simpleChain->rgpElement[i];
|
|
|
|
|
|
|
|
cert->dwConfidence = CRYPTDLG_TrustStatusToConfidence(
|
|
|
|
element->TrustStatus.dwErrorStatus);
|
|
|
|
cert->dwError = element->TrustStatus.dwErrorStatus;
|
|
|
|
cert->pChainElement = element;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static CERT_VERIFY_CERTIFICATE_TRUST *CRYPTDLG_GetVerifyData(
|
|
|
|
CRYPT_PROVIDER_DATA *data)
|
|
|
|
{
|
|
|
|
CERT_VERIFY_CERTIFICATE_TRUST *pCert = NULL;
|
|
|
|
|
|
|
|
/* This should always be true, but just in case the calling function is
|
|
|
|
* called directly:
|
|
|
|
*/
|
|
|
|
if (data->pWintrustData->dwUnionChoice == WTD_CHOICE_BLOB &&
|
|
|
|
data->pWintrustData->u.pBlob && data->pWintrustData->u.pBlob->cbMemObject ==
|
|
|
|
sizeof(CERT_VERIFY_CERTIFICATE_TRUST) &&
|
|
|
|
data->pWintrustData->u.pBlob->pbMemObject)
|
|
|
|
pCert = (CERT_VERIFY_CERTIFICATE_TRUST *)
|
|
|
|
data->pWintrustData->u.pBlob->pbMemObject;
|
|
|
|
return pCert;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HCERTCHAINENGINE CRYPTDLG_MakeEngine(CERT_VERIFY_CERTIFICATE_TRUST *cert)
|
|
|
|
{
|
|
|
|
HCERTCHAINENGINE engine = NULL;
|
|
|
|
HCERTSTORE root = NULL, trust = NULL;
|
|
|
|
DWORD i;
|
|
|
|
|
|
|
|
if (cert->cRootStores)
|
|
|
|
{
|
|
|
|
root = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
|
|
|
|
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
|
|
|
if (root)
|
|
|
|
{
|
|
|
|
for (i = 0; i < cert->cRootStores; i++)
|
|
|
|
CertAddStoreToCollection(root, cert->rghstoreRoots[i], 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cert->cTrustStores)
|
|
|
|
{
|
|
|
|
trust = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
|
|
|
|
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
2013-04-08 16:31:05 +00:00
|
|
|
if (trust)
|
2009-01-23 13:06:33 +00:00
|
|
|
{
|
|
|
|
for (i = 0; i < cert->cTrustStores; i++)
|
|
|
|
CertAddStoreToCollection(trust, cert->rghstoreTrust[i], 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cert->cRootStores || cert->cStores || cert->cTrustStores)
|
|
|
|
{
|
|
|
|
CERT_CHAIN_ENGINE_CONFIG config;
|
|
|
|
|
|
|
|
memset(&config, 0, sizeof(config));
|
|
|
|
config.cbSize = sizeof(config);
|
|
|
|
config.hRestrictedRoot = root;
|
|
|
|
config.hRestrictedTrust = trust;
|
|
|
|
config.cAdditionalStore = cert->cStores;
|
|
|
|
config.rghAdditionalStore = cert->rghstoreCAs;
|
|
|
|
config.hRestrictedRoot = root;
|
|
|
|
CertCreateCertificateChainEngine(&config, &engine);
|
|
|
|
CertCloseStore(root, 0);
|
|
|
|
CertCloseStore(trust, 0);
|
|
|
|
}
|
|
|
|
return engine;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CertTrustFinalPolicy (CRYPTDLG.@)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI CertTrustFinalPolicy(CRYPT_PROVIDER_DATA *data)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
DWORD err = S_OK;
|
|
|
|
CERT_VERIFY_CERTIFICATE_TRUST *pCert = CRYPTDLG_GetVerifyData(data);
|
|
|
|
|
|
|
|
TRACE("(%p)\n", data);
|
|
|
|
|
|
|
|
if (data->pWintrustData->dwUIChoice != WTD_UI_NONE)
|
|
|
|
FIXME("unimplemented for UI choice %d\n",
|
|
|
|
data->pWintrustData->dwUIChoice);
|
|
|
|
if (pCert)
|
|
|
|
{
|
|
|
|
DWORD flags = 0;
|
|
|
|
CERT_CHAIN_PARA chainPara;
|
|
|
|
HCERTCHAINENGINE engine;
|
|
|
|
|
|
|
|
memset(&chainPara, 0, sizeof(chainPara));
|
|
|
|
chainPara.cbSize = sizeof(chainPara);
|
|
|
|
if (CRYPTDLG_CheckOnlineCRL())
|
|
|
|
flags |= CERT_CHAIN_REVOCATION_CHECK_END_CERT;
|
|
|
|
engine = CRYPTDLG_MakeEngine(pCert);
|
|
|
|
GetSystemTimeAsFileTime(&data->sftSystemTime);
|
|
|
|
ret = CRYPTDLG_IsCertAllowed(pCert->pccert);
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
PCCERT_CHAIN_CONTEXT chain;
|
|
|
|
|
|
|
|
ret = CertGetCertificateChain(engine, pCert->pccert,
|
|
|
|
&data->sftSystemTime, NULL, &chainPara, flags, NULL, &chain);
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
if (chain->cChain != 1)
|
|
|
|
{
|
|
|
|
FIXME("unimplemented for more than 1 simple chain\n");
|
|
|
|
err = TRUST_E_SUBJECT_FORM_UNKNOWN;
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
else if ((ret = CRYPTDLG_CopyChain(data, chain)))
|
|
|
|
{
|
|
|
|
if (CertVerifyTimeValidity(&data->sftSystemTime,
|
|
|
|
pCert->pccert->pCertInfo))
|
|
|
|
{
|
|
|
|
ret = FALSE;
|
|
|
|
err = CERT_E_EXPIRED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
err = TRUST_E_SYSTEM_ERROR;
|
|
|
|
CertFreeCertificateChain(chain);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
err = TRUST_E_SUBJECT_NOT_TRUSTED;
|
|
|
|
}
|
|
|
|
CertFreeCertificateChainEngine(engine);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = FALSE;
|
|
|
|
err = TRUST_E_NOSIGNATURE;
|
|
|
|
}
|
|
|
|
/* Oddly, native doesn't set the error in the trust step error location,
|
|
|
|
* probably because this action is more advisory than anything else.
|
|
|
|
* Instead it stores it as the final error, but the function "succeeds" in
|
|
|
|
* any case.
|
|
|
|
*/
|
|
|
|
if (!ret)
|
|
|
|
data->dwFinalError = err;
|
|
|
|
TRACE("returning %d (%08x)\n", S_OK, data->dwFinalError);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CertViewPropertiesA (CRYPTDLG.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI CertViewPropertiesA(CERT_VIEWPROPERTIES_STRUCT_A *info)
|
|
|
|
{
|
|
|
|
CERT_VIEWPROPERTIES_STRUCT_W infoW;
|
|
|
|
LPWSTR title = NULL;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
TRACE("(%p)\n", info);
|
|
|
|
|
|
|
|
memcpy(&infoW, info, sizeof(infoW));
|
|
|
|
if (info->szTitle)
|
|
|
|
{
|
|
|
|
int len = MultiByteToWideChar(CP_ACP, 0, info->szTitle, -1, NULL, 0);
|
|
|
|
|
|
|
|
title = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
if (title)
|
|
|
|
{
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, info->szTitle, -1, title, len);
|
|
|
|
infoW.szTitle = title;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = FALSE;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret = CertViewPropertiesW(&infoW);
|
|
|
|
HeapFree(GetProcessHeap(), 0, title);
|
|
|
|
error:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CertViewPropertiesW (CRYPTDLG.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI CertViewPropertiesW(CERT_VIEWPROPERTIES_STRUCT_W *info)
|
|
|
|
{
|
|
|
|
static GUID cert_action_verify = CERT_CERTIFICATE_ACTION_VERIFY;
|
|
|
|
CERT_VERIFY_CERTIFICATE_TRUST trust;
|
|
|
|
WINTRUST_BLOB_INFO blob;
|
|
|
|
WINTRUST_DATA wtd;
|
|
|
|
LONG err;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
TRACE("(%p)\n", info);
|
|
|
|
|
|
|
|
memset(&trust, 0, sizeof(trust));
|
|
|
|
trust.cbSize = sizeof(trust);
|
|
|
|
trust.pccert = info->pCertContext;
|
|
|
|
trust.cRootStores = info->cRootStores;
|
|
|
|
trust.rghstoreRoots = info->rghstoreRoots;
|
|
|
|
trust.cStores = info->cStores;
|
|
|
|
trust.rghstoreCAs = info->rghstoreCAs;
|
|
|
|
trust.cTrustStores = info->cTrustStores;
|
|
|
|
trust.rghstoreTrust = info->rghstoreTrust;
|
|
|
|
memset(&blob, 0, sizeof(blob));
|
|
|
|
blob.cbStruct = sizeof(blob);
|
|
|
|
blob.cbMemObject = sizeof(trust);
|
|
|
|
blob.pbMemObject = (BYTE *)&trust;
|
|
|
|
memset(&wtd, 0, sizeof(wtd));
|
|
|
|
wtd.cbStruct = sizeof(wtd);
|
|
|
|
wtd.dwUIChoice = WTD_UI_NONE;
|
|
|
|
wtd.dwUnionChoice = WTD_CHOICE_BLOB;
|
|
|
|
wtd.u.pBlob = &blob;
|
|
|
|
wtd.dwStateAction = WTD_STATEACTION_VERIFY;
|
|
|
|
err = WinVerifyTrust(NULL, &cert_action_verify, &wtd);
|
|
|
|
if (err == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
CRYPTUI_VIEWCERTIFICATE_STRUCTW uiInfo;
|
|
|
|
BOOL propsChanged = FALSE;
|
|
|
|
|
|
|
|
memset(&uiInfo, 0, sizeof(uiInfo));
|
|
|
|
uiInfo.dwSize = sizeof(uiInfo);
|
|
|
|
uiInfo.hwndParent = info->hwndParent;
|
|
|
|
uiInfo.dwFlags =
|
|
|
|
CRYPTUI_DISABLE_ADDTOSTORE | CRYPTUI_ENABLE_EDITPROPERTIES;
|
|
|
|
uiInfo.szTitle = info->szTitle;
|
|
|
|
uiInfo.pCertContext = info->pCertContext;
|
|
|
|
uiInfo.cPurposes = info->cArrayPurposes;
|
|
|
|
uiInfo.rgszPurposes = (LPCSTR *)info->arrayPurposes;
|
|
|
|
uiInfo.u.hWVTStateData = wtd.hWVTStateData;
|
|
|
|
uiInfo.fpCryptProviderDataTrustedUsage = TRUE;
|
|
|
|
uiInfo.cPropSheetPages = info->cArrayPropSheetPages;
|
|
|
|
uiInfo.rgPropSheetPages = info->arrayPropSheetPages;
|
|
|
|
uiInfo.nStartPage = info->nStartPage;
|
|
|
|
ret = CryptUIDlgViewCertificateW(&uiInfo, &propsChanged);
|
|
|
|
wtd.dwStateAction = WTD_STATEACTION_CLOSE;
|
|
|
|
WinVerifyTrust(NULL, &cert_action_verify, &wtd);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = FALSE;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL CRYPT_FormatHexString(const BYTE *pbEncoded, DWORD cbEncoded,
|
|
|
|
WCHAR *str, DWORD *pcchStr)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
DWORD charsNeeded;
|
|
|
|
|
|
|
|
if (cbEncoded)
|
|
|
|
charsNeeded = (cbEncoded * 3);
|
|
|
|
else
|
|
|
|
charsNeeded = 1;
|
|
|
|
if (!str)
|
|
|
|
{
|
|
|
|
*pcchStr = charsNeeded;
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
else if (*pcchStr < charsNeeded)
|
|
|
|
{
|
|
|
|
*pcchStr = charsNeeded;
|
|
|
|
SetLastError(ERROR_MORE_DATA);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
static const WCHAR fmt[] = { '%','0','2','x',' ',0 };
|
|
|
|
static const WCHAR endFmt[] = { '%','0','2','x',0 };
|
|
|
|
DWORD i;
|
|
|
|
LPWSTR ptr = str;
|
|
|
|
|
|
|
|
*pcchStr = charsNeeded;
|
|
|
|
if (cbEncoded)
|
|
|
|
{
|
|
|
|
for (i = 0; i < cbEncoded; i++)
|
|
|
|
{
|
|
|
|
if (i < cbEncoded - 1)
|
2019-10-26 21:53:42 +00:00
|
|
|
ptr += swprintf(ptr, fmt, pbEncoded[i]);
|
2009-01-23 13:06:33 +00:00
|
|
|
else
|
2019-10-26 21:53:42 +00:00
|
|
|
ptr += swprintf(ptr, endFmt, pbEncoded[i]);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*ptr = 0;
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 };
|
|
|
|
static const WCHAR colonCrlf[] = { ':','\r','\n',0 };
|
|
|
|
static const WCHAR colonSpace[] = { ':',' ',0 };
|
|
|
|
static const WCHAR crlf[] = { '\r','\n',0 };
|
|
|
|
static const WCHAR commaSep[] = { ',',' ',0 };
|
|
|
|
|
|
|
|
static BOOL CRYPT_FormatCPS(DWORD dwCertEncodingType,
|
|
|
|
DWORD dwFormatStrType, const BYTE *pbEncoded, DWORD cbEncoded,
|
|
|
|
WCHAR *str, DWORD *pcchStr)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
DWORD size, charsNeeded = 1;
|
|
|
|
CERT_NAME_VALUE *cpsValue;
|
|
|
|
|
|
|
|
if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING,
|
|
|
|
pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &cpsValue, &size)))
|
|
|
|
{
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
LPCWSTR sep;
|
2010-03-03 20:42:01 +00:00
|
|
|
DWORD sepLen;
|
2009-01-23 13:06:33 +00:00
|
|
|
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
sep = crlf;
|
|
|
|
else
|
|
|
|
sep = commaSep;
|
2010-03-03 20:42:01 +00:00
|
|
|
|
2019-10-26 21:53:42 +00:00
|
|
|
sepLen = lstrlenW(sep);
|
2009-01-23 13:06:33 +00:00
|
|
|
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
charsNeeded += 3 * lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
charsNeeded += cpsValue->Value.cbData / sizeof(WCHAR);
|
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, (LPWSTR)cpsValue->Value.pbData);
|
2009-01-23 13:06:33 +00:00
|
|
|
str += cpsValue->Value.cbData / sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
charsNeeded += sepLen;
|
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, sep);
|
2009-01-23 13:06:33 +00:00
|
|
|
str += sepLen;
|
|
|
|
}
|
|
|
|
LocalFree(cpsValue);
|
|
|
|
if (!str)
|
|
|
|
*pcchStr = charsNeeded;
|
|
|
|
else if (*pcchStr < charsNeeded)
|
|
|
|
{
|
|
|
|
*pcchStr = charsNeeded;
|
|
|
|
SetLastError(ERROR_MORE_DATA);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*pcchStr = charsNeeded;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static BOOL CRYPT_FormatUserNotice(DWORD dwCertEncodingType,
|
|
|
|
DWORD dwFormatStrType, const BYTE *pbEncoded, DWORD cbEncoded,
|
|
|
|
WCHAR *str, DWORD *pcchStr)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
DWORD size, charsNeeded = 1;
|
|
|
|
CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
|
|
|
|
|
|
|
|
if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
|
|
|
|
X509_PKIX_POLICY_QUALIFIER_USERNOTICE, pbEncoded, cbEncoded,
|
|
|
|
CRYPT_DECODE_ALLOC_FLAG, NULL, ¬ice, &size)))
|
|
|
|
{
|
|
|
|
static const WCHAR numFmt[] = { '%','d',0 };
|
|
|
|
CERT_POLICY_QUALIFIER_NOTICE_REFERENCE *pNoticeRef =
|
|
|
|
notice->pNoticeReference;
|
|
|
|
LPCWSTR headingSep, sep;
|
|
|
|
DWORD headingSepLen, sepLen;
|
|
|
|
LPWSTR noticeRef, organization, noticeNum, noticeText;
|
|
|
|
DWORD noticeRefLen, organizationLen, noticeNumLen, noticeTextLen;
|
|
|
|
WCHAR noticeNumStr[11];
|
|
|
|
|
|
|
|
noticeRefLen = LoadStringW(hInstance, IDS_NOTICE_REF,
|
|
|
|
(LPWSTR)¬iceRef, 0);
|
|
|
|
organizationLen = LoadStringW(hInstance, IDS_ORGANIZATION,
|
|
|
|
(LPWSTR)&organization, 0);
|
|
|
|
noticeNumLen = LoadStringW(hInstance, IDS_NOTICE_NUM,
|
|
|
|
(LPWSTR)¬iceNum, 0);
|
|
|
|
noticeTextLen = LoadStringW(hInstance, IDS_NOTICE_TEXT,
|
|
|
|
(LPWSTR)¬iceText, 0);
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
{
|
|
|
|
headingSep = colonCrlf;
|
|
|
|
sep = crlf;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
headingSep = colonSpace;
|
|
|
|
sep = commaSep;
|
|
|
|
}
|
2019-10-26 21:53:42 +00:00
|
|
|
sepLen = lstrlenW(sep);
|
|
|
|
headingSepLen = lstrlenW(headingSep);
|
2009-01-23 13:06:33 +00:00
|
|
|
|
|
|
|
if (pNoticeRef)
|
|
|
|
{
|
|
|
|
DWORD k;
|
|
|
|
LPCSTR src;
|
|
|
|
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
charsNeeded += 3 * lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
charsNeeded += noticeRefLen;
|
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
|
|
|
memcpy(str, noticeRef, noticeRefLen * sizeof(WCHAR));
|
|
|
|
str += noticeRefLen;
|
|
|
|
}
|
|
|
|
charsNeeded += headingSepLen;
|
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, headingSep);
|
2009-01-23 13:06:33 +00:00
|
|
|
str += headingSepLen;
|
|
|
|
}
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
charsNeeded += 4 * lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
charsNeeded += organizationLen;
|
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
|
|
|
memcpy(str, organization, organizationLen * sizeof(WCHAR));
|
|
|
|
str += organizationLen;
|
|
|
|
}
|
|
|
|
charsNeeded += strlen(pNoticeRef->pszOrganization);
|
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
for (src = pNoticeRef->pszOrganization; src && *src;
|
|
|
|
src++, str++)
|
|
|
|
*str = *src;
|
|
|
|
charsNeeded += sepLen;
|
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, sep);
|
2009-01-23 13:06:33 +00:00
|
|
|
str += sepLen;
|
|
|
|
}
|
|
|
|
for (k = 0; k < pNoticeRef->cNoticeNumbers; k++)
|
|
|
|
{
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
charsNeeded += 4 * lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
charsNeeded += noticeNumLen;
|
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
|
|
|
memcpy(str, noticeNum, noticeNumLen * sizeof(WCHAR));
|
|
|
|
str += noticeNumLen;
|
|
|
|
}
|
2019-10-26 21:53:42 +00:00
|
|
|
swprintf(noticeNumStr, numFmt, k + 1);
|
|
|
|
charsNeeded += lstrlenW(noticeNumStr);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, noticeNumStr);
|
|
|
|
str += lstrlenW(noticeNumStr);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
charsNeeded += sepLen;
|
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, sep);
|
2009-01-23 13:06:33 +00:00
|
|
|
str += sepLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (notice->pszDisplayText)
|
|
|
|
{
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
charsNeeded += 3 * lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
charsNeeded += noticeTextLen;
|
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
|
|
|
memcpy(str, noticeText, noticeTextLen * sizeof(WCHAR));
|
|
|
|
str += noticeTextLen;
|
|
|
|
}
|
2019-10-26 21:53:42 +00:00
|
|
|
charsNeeded += lstrlenW(notice->pszDisplayText);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, notice->pszDisplayText);
|
|
|
|
str += lstrlenW(notice->pszDisplayText);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
charsNeeded += sepLen;
|
|
|
|
if (str && *pcchStr >= charsNeeded)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, sep);
|
2009-01-23 13:06:33 +00:00
|
|
|
str += sepLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LocalFree(notice);
|
|
|
|
if (!str)
|
|
|
|
*pcchStr = charsNeeded;
|
|
|
|
else if (*pcchStr < charsNeeded)
|
|
|
|
{
|
|
|
|
*pcchStr = charsNeeded;
|
|
|
|
SetLastError(ERROR_MORE_DATA);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*pcchStr = charsNeeded;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* FormatVerisignExtension (CRYPTDLG.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI FormatVerisignExtension(DWORD dwCertEncodingType,
|
|
|
|
DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
|
|
|
|
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
|
|
|
|
DWORD *pcbFormat)
|
|
|
|
{
|
|
|
|
CERT_POLICIES_INFO *policies;
|
|
|
|
DWORD size;
|
|
|
|
BOOL ret = FALSE;
|
|
|
|
|
|
|
|
if (!cbEncoded)
|
|
|
|
{
|
|
|
|
SetLastError(E_INVALIDARG);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_POLICIES,
|
|
|
|
pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &policies, &size)))
|
|
|
|
{
|
|
|
|
static const WCHAR numFmt[] = { '%','d',0 };
|
|
|
|
DWORD charsNeeded = 1; /* space for NULL terminator */
|
|
|
|
LPCWSTR headingSep, sep;
|
|
|
|
DWORD headingSepLen, sepLen;
|
|
|
|
WCHAR policyNum[11], policyQualifierNum[11];
|
|
|
|
LPWSTR certPolicy, policyId, policyQualifierInfo, policyQualifierId;
|
|
|
|
LPWSTR cps, userNotice, qualifier;
|
|
|
|
DWORD certPolicyLen, policyIdLen, policyQualifierInfoLen;
|
|
|
|
DWORD policyQualifierIdLen, cpsLen, userNoticeLen, qualifierLen;
|
|
|
|
DWORD i;
|
|
|
|
LPWSTR str = pbFormat;
|
|
|
|
|
|
|
|
certPolicyLen = LoadStringW(hInstance, IDS_CERT_POLICY,
|
|
|
|
(LPWSTR)&certPolicy, 0);
|
|
|
|
policyIdLen = LoadStringW(hInstance, IDS_POLICY_ID, (LPWSTR)&policyId,
|
|
|
|
0);
|
|
|
|
policyQualifierInfoLen = LoadStringW(hInstance,
|
|
|
|
IDS_POLICY_QUALIFIER_INFO, (LPWSTR)&policyQualifierInfo, 0);
|
|
|
|
policyQualifierIdLen = LoadStringW(hInstance, IDS_POLICY_QUALIFIER_ID,
|
|
|
|
(LPWSTR)&policyQualifierId, 0);
|
|
|
|
cpsLen = LoadStringW(hInstance, IDS_CPS, (LPWSTR)&cps, 0);
|
|
|
|
userNoticeLen = LoadStringW(hInstance, IDS_USER_NOTICE,
|
|
|
|
(LPWSTR)&userNotice, 0);
|
|
|
|
qualifierLen = LoadStringW(hInstance, IDS_QUALIFIER,
|
|
|
|
(LPWSTR)&qualifier, 0);
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
{
|
|
|
|
headingSep = colonCrlf;
|
|
|
|
sep = crlf;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
headingSep = colonSpace;
|
|
|
|
sep = commaSep;
|
|
|
|
}
|
2019-10-26 21:53:42 +00:00
|
|
|
sepLen = lstrlenW(sep);
|
|
|
|
headingSepLen = lstrlenW(headingSep);
|
2009-01-23 13:06:33 +00:00
|
|
|
|
|
|
|
for (i = 0; ret && i < policies->cPolicyInfo; i++)
|
|
|
|
{
|
|
|
|
CERT_POLICY_INFO *policy = &policies->rgPolicyInfo[i];
|
|
|
|
DWORD j;
|
|
|
|
LPCSTR src;
|
|
|
|
|
|
|
|
charsNeeded += 1; /* '['*/
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
*str++ = '[';
|
2019-10-26 21:53:42 +00:00
|
|
|
swprintf(policyNum, numFmt, i + 1);
|
|
|
|
charsNeeded += lstrlenW(policyNum);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, policyNum);
|
|
|
|
str += lstrlenW(policyNum);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
charsNeeded += 1; /* ']'*/
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
*str++ = ']';
|
|
|
|
charsNeeded += certPolicyLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
memcpy(str, certPolicy, certPolicyLen * sizeof(WCHAR));
|
|
|
|
str += certPolicyLen;
|
|
|
|
}
|
|
|
|
charsNeeded += headingSepLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, headingSep);
|
2009-01-23 13:06:33 +00:00
|
|
|
str += headingSepLen;
|
|
|
|
}
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
charsNeeded += lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
charsNeeded += policyIdLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
memcpy(str, policyId, policyIdLen * sizeof(WCHAR));
|
|
|
|
str += policyIdLen;
|
|
|
|
}
|
|
|
|
charsNeeded += strlen(policy->pszPolicyIdentifier);
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
for (src = policy->pszPolicyIdentifier; src && *src;
|
|
|
|
src++, str++)
|
|
|
|
*str = *src;
|
|
|
|
}
|
|
|
|
charsNeeded += sepLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, sep);
|
2009-01-23 13:06:33 +00:00
|
|
|
str += sepLen;
|
|
|
|
}
|
|
|
|
for (j = 0; j < policy->cPolicyQualifier; j++)
|
|
|
|
{
|
|
|
|
CERT_POLICY_QUALIFIER_INFO *qualifierInfo =
|
|
|
|
&policy->rgPolicyQualifier[j];
|
|
|
|
DWORD sizeRemaining;
|
|
|
|
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
charsNeeded += lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
charsNeeded += 1; /* '['*/
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
*str++ = '[';
|
2019-10-26 21:53:42 +00:00
|
|
|
charsNeeded += lstrlenW(policyNum);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, policyNum);
|
|
|
|
str += lstrlenW(policyNum);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
charsNeeded += 1; /* ','*/
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
*str++ = ',';
|
2019-10-26 21:53:42 +00:00
|
|
|
swprintf(policyQualifierNum, numFmt, j + 1);
|
|
|
|
charsNeeded += lstrlenW(policyQualifierNum);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, policyQualifierNum);
|
|
|
|
str += lstrlenW(policyQualifierNum);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
charsNeeded += 1; /* ']'*/
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
*str++ = ']';
|
|
|
|
charsNeeded += policyQualifierInfoLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
memcpy(str, policyQualifierInfo,
|
|
|
|
policyQualifierInfoLen * sizeof(WCHAR));
|
|
|
|
str += policyQualifierInfoLen;
|
|
|
|
}
|
|
|
|
charsNeeded += headingSepLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, headingSep);
|
2009-01-23 13:06:33 +00:00
|
|
|
str += headingSepLen;
|
|
|
|
}
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
charsNeeded += 2 * lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
charsNeeded += policyQualifierIdLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
memcpy(str, policyQualifierId,
|
|
|
|
policyQualifierIdLen * sizeof(WCHAR));
|
|
|
|
str += policyQualifierIdLen;
|
|
|
|
}
|
|
|
|
if (!strcmp(qualifierInfo->pszPolicyQualifierId,
|
|
|
|
szOID_PKIX_POLICY_QUALIFIER_CPS))
|
|
|
|
{
|
|
|
|
charsNeeded += cpsLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
memcpy(str, cps, cpsLen * sizeof(WCHAR));
|
|
|
|
str += cpsLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!strcmp(qualifierInfo->pszPolicyQualifierId,
|
|
|
|
szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
|
|
|
|
{
|
|
|
|
charsNeeded += userNoticeLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
memcpy(str, userNotice, userNoticeLen * sizeof(WCHAR));
|
|
|
|
str += userNoticeLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
charsNeeded += strlen(qualifierInfo->pszPolicyQualifierId);
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
for (src = qualifierInfo->pszPolicyQualifierId;
|
|
|
|
src && *src; src++, str++)
|
|
|
|
*str = *src;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
charsNeeded += sepLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, sep);
|
2009-01-23 13:06:33 +00:00
|
|
|
str += sepLen;
|
|
|
|
}
|
|
|
|
if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
charsNeeded += 2 * lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
|
|
|
lstrcpyW(str, indent);
|
|
|
|
str += lstrlenW(indent);
|
2009-01-23 13:06:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
charsNeeded += qualifierLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
memcpy(str, qualifier, qualifierLen * sizeof(WCHAR));
|
|
|
|
str += qualifierLen;
|
|
|
|
}
|
|
|
|
charsNeeded += headingSepLen;
|
|
|
|
if (str && *pcbFormat >= charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
2019-10-26 21:53:42 +00:00
|
|
|
lstrcpyW(str, headingSep);
|
2009-01-23 13:06:33 +00:00
|
|
|
str += headingSepLen;
|
|
|
|
}
|
|
|
|
/* This if block is deliberately redundant with the same if
|
|
|
|
* block above, in order to keep the code more readable (the
|
|
|
|
* code flow follows the order in which the strings are output.)
|
|
|
|
*/
|
|
|
|
if (!strcmp(qualifierInfo->pszPolicyQualifierId,
|
|
|
|
szOID_PKIX_POLICY_QUALIFIER_CPS))
|
|
|
|
{
|
|
|
|
if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
/* Insufficient space, determine how much is needed. */
|
|
|
|
ret = CRYPT_FormatCPS(dwCertEncodingType,
|
|
|
|
dwFormatStrType, qualifierInfo->Qualifier.pbData,
|
|
|
|
qualifierInfo->Qualifier.cbData, NULL, &size);
|
|
|
|
if (ret)
|
|
|
|
charsNeeded += size - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sizeRemaining = *pcbFormat / sizeof(WCHAR);
|
|
|
|
sizeRemaining -= str - (LPWSTR)pbFormat;
|
|
|
|
ret = CRYPT_FormatCPS(dwCertEncodingType,
|
|
|
|
dwFormatStrType, qualifierInfo->Qualifier.pbData,
|
|
|
|
qualifierInfo->Qualifier.cbData, str, &sizeRemaining);
|
|
|
|
if (ret || GetLastError() == ERROR_MORE_DATA)
|
|
|
|
{
|
|
|
|
charsNeeded += sizeRemaining - 1;
|
|
|
|
str += sizeRemaining - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!strcmp(qualifierInfo->pszPolicyQualifierId,
|
|
|
|
szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
|
|
|
|
{
|
|
|
|
if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
/* Insufficient space, determine how much is needed. */
|
|
|
|
ret = CRYPT_FormatUserNotice(dwCertEncodingType,
|
|
|
|
dwFormatStrType, qualifierInfo->Qualifier.pbData,
|
|
|
|
qualifierInfo->Qualifier.cbData, NULL, &size);
|
|
|
|
if (ret)
|
|
|
|
charsNeeded += size - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sizeRemaining = *pcbFormat / sizeof(WCHAR);
|
|
|
|
sizeRemaining -= str - (LPWSTR)pbFormat;
|
|
|
|
ret = CRYPT_FormatUserNotice(dwCertEncodingType,
|
|
|
|
dwFormatStrType, qualifierInfo->Qualifier.pbData,
|
|
|
|
qualifierInfo->Qualifier.cbData, str, &sizeRemaining);
|
|
|
|
if (ret || GetLastError() == ERROR_MORE_DATA)
|
|
|
|
{
|
|
|
|
charsNeeded += sizeRemaining - 1;
|
|
|
|
str += sizeRemaining - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!str || *pcbFormat < charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
/* Insufficient space, determine how much is needed. */
|
|
|
|
ret = CRYPT_FormatHexString(
|
|
|
|
qualifierInfo->Qualifier.pbData,
|
|
|
|
qualifierInfo->Qualifier.cbData, NULL, &size);
|
|
|
|
if (ret)
|
|
|
|
charsNeeded += size - 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sizeRemaining = *pcbFormat / sizeof(WCHAR);
|
|
|
|
sizeRemaining -= str - (LPWSTR)pbFormat;
|
|
|
|
ret = CRYPT_FormatHexString(
|
|
|
|
qualifierInfo->Qualifier.pbData,
|
|
|
|
qualifierInfo->Qualifier.cbData, str, &sizeRemaining);
|
|
|
|
if (ret || GetLastError() == ERROR_MORE_DATA)
|
|
|
|
{
|
|
|
|
charsNeeded += sizeRemaining - 1;
|
|
|
|
str += sizeRemaining - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LocalFree(policies);
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
if (!pbFormat)
|
|
|
|
*pcbFormat = charsNeeded * sizeof(WCHAR);
|
|
|
|
else if (*pcbFormat < charsNeeded * sizeof(WCHAR))
|
|
|
|
{
|
|
|
|
*pcbFormat = charsNeeded * sizeof(WCHAR);
|
|
|
|
SetLastError(ERROR_MORE_DATA);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*pcbFormat = charsNeeded * sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define szOID_MICROSOFT_Encryption_Key_Preference "1.3.6.1.4.1.311.16.4"
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* DllRegisterServer (CRYPTDLG.@)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI DllRegisterServer(void)
|
|
|
|
{
|
|
|
|
static WCHAR cryptdlg[] = { 'c','r','y','p','t','d','l','g','.',
|
|
|
|
'd','l','l',0 };
|
|
|
|
static WCHAR wintrust[] = { 'w','i','n','t','r','u','s','t','.',
|
|
|
|
'd','l','l',0 };
|
|
|
|
static WCHAR certTrustInit[] = { 'C','e','r','t','T','r','u','s','t',
|
|
|
|
'I','n','i','t',0 };
|
|
|
|
static WCHAR wintrustCertificateTrust[] = { 'W','i','n','t','r','u','s','t',
|
|
|
|
'C','e','r','t','i','f','i','c','a','t','e','T','r','u','s','t',0 };
|
|
|
|
static WCHAR certTrustCertPolicy[] = { 'C','e','r','t','T','r','u','s','t',
|
|
|
|
'C','e','r','t','P','o','l','i','c','y',0 };
|
|
|
|
static WCHAR certTrustFinalPolicy[] = { 'C','e','r','t','T','r','u','s','t',
|
|
|
|
'F','i','n','a','l','P','o','l','i','c','y',0 };
|
|
|
|
static WCHAR certTrustCleanup[] = { 'C','e','r','t','T','r','u','s','t',
|
|
|
|
'C','l','e','a','n','u','p',0 };
|
|
|
|
static const WCHAR cryptDlg[] = { 'c','r','y','p','t','d','l','g','.',
|
|
|
|
'd','l','l',0 };
|
|
|
|
CRYPT_REGISTER_ACTIONID reg;
|
|
|
|
GUID guid = CERT_CERTIFICATE_ACTION_VERIFY;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
|
|
memset(®, 0, sizeof(reg));
|
|
|
|
reg.cbStruct = sizeof(reg);
|
|
|
|
reg.sInitProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
|
|
reg.sInitProvider.pwszDLLName = cryptdlg;
|
|
|
|
reg.sInitProvider.pwszFunctionName = certTrustInit;
|
|
|
|
reg.sCertificateProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
|
|
reg.sCertificateProvider.pwszDLLName = wintrust;
|
|
|
|
reg.sCertificateProvider.pwszFunctionName = wintrustCertificateTrust;
|
|
|
|
reg.sCertificatePolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
|
|
reg.sCertificatePolicyProvider.pwszDLLName = cryptdlg;
|
|
|
|
reg.sCertificatePolicyProvider.pwszFunctionName = certTrustCertPolicy;
|
|
|
|
reg.sFinalPolicyProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
|
|
reg.sFinalPolicyProvider.pwszDLLName = cryptdlg;
|
|
|
|
reg.sFinalPolicyProvider.pwszFunctionName = certTrustFinalPolicy;
|
|
|
|
reg.sCleanupProvider.cbStruct = sizeof(CRYPT_TRUST_REG_ENTRY);
|
|
|
|
reg.sCleanupProvider.pwszDLLName = cryptdlg;
|
|
|
|
reg.sCleanupProvider.pwszFunctionName = certTrustCleanup;
|
|
|
|
if (!WintrustAddActionID(&guid, WT_ADD_ACTION_ID_RET_RESULT_FLAG, ®))
|
|
|
|
hr = GetLastError();
|
|
|
|
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
|
|
|
|
"1.3.6.1.4.1.311.16.1.1", cryptDlg, "EncodeAttrSequence");
|
|
|
|
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
|
|
|
|
szOID_MICROSOFT_Encryption_Key_Preference, cryptDlg, "EncodeRecipientID");
|
|
|
|
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
|
|
|
|
"1.3.6.1.4.1.311.16.1.1", cryptDlg, "DecodeAttrSequence");
|
|
|
|
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
|
|
|
|
szOID_MICROSOFT_Encryption_Key_Preference, cryptDlg, "DecodeRecipientID");
|
|
|
|
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
|
|
|
|
szOID_PKIX_KP_EMAIL_PROTECTION, cryptDlg, "FormatPKIXEmailProtection");
|
|
|
|
CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
|
|
|
|
szOID_CERT_POLICIES, cryptDlg, "FormatVerisignExtension");
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* DllUnregisterServer (CRYPTDLG.@)
|
|
|
|
*/
|
|
|
|
HRESULT WINAPI DllUnregisterServer(void)
|
|
|
|
{
|
|
|
|
GUID guid = CERT_CERTIFICATE_ACTION_VERIFY;
|
|
|
|
|
|
|
|
WintrustRemoveActionID(&guid);
|
|
|
|
CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
|
|
|
|
"1.3.6.1.4.1.311.16.1.1");
|
|
|
|
CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC,
|
|
|
|
szOID_MICROSOFT_Encryption_Key_Preference);
|
|
|
|
CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
|
|
|
|
"1.3.6.1.4.1.311.16.1.1");
|
|
|
|
CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC,
|
|
|
|
szOID_MICROSOFT_Encryption_Key_Preference);
|
|
|
|
CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
|
|
|
|
szOID_PKIX_KP_EMAIL_PROTECTION);
|
|
|
|
CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC,
|
|
|
|
szOID_CERT_POLICIES);
|
|
|
|
return S_OK;
|
|
|
|
}
|