I'm filling out the WINTRUST_CATALOG_INFO structure. I've calculated the hash for a file and found the catalog file to use.
There's one member I don't know how to fill out though:
pcwszMemberTag
Tag of a member file to be verified.
Most of the example code for this I've seen around on the internet seems to turn the file hash into a hex-encoded version of itself, and pass that as the member tag. I'm not sure why that would be though.
Tags exist because file names are not reliable. pcwszMemberTag
corresponds to what has been set as pwszReferenceTag
when the member was added to the catalog (using the CryptCATPutMemberInfo function for example).
To be really compliant with how the API is supposed to work, I think you're supposed to get the member information first, before you can fully setup WINTRUST_CATALOG_INFO. To determine member information, you must use the CryptCATEnumerateMember function (there is also a CryptCATGetMemberInfo function but you can't use it - chicken and egg issue - you don't have the tag) and determine what member you are interested in by any way you want (using other CRYPTCATMEMBER structure fields)
Using an hexadecimal representation of the hash of a file for the reference tag is common usage (MakeCat probably does it so it looks like the standard), but I don't think it's mandatory at all - the Java stuff in the other answer is not using this convention (see also this link: RE: CryptCATGetMemberInfo samples with a Microsoft guy answer.)
It contains a text reference to the file name. This code may help to understand the workflow:
HRESULT Cwvt::VerifyTrust(HANDLE hFile, HWND hWnd, PJAVA_TRUST *ppJavaTrust,
LPCWSTR szStatusText,
IInternetHostSecurityManager *pHostSecurityManager,
LPSTR szFilePath, LPSTR szCatalogFile,
CDownload *pdl)
{
LPWSTR wzFileName = NULL;
LPWSTR wzFilePath = NULL;
LPWSTR wzCatalogFile = NULL;
GUID guidJava = JAVA_POLICY_PROVIDER_DOWNLOAD;
GUID guidCor = COR_POLICY_PROVIDER_DOWNLOAD;
GUID guidAuthenticode = WINTRUST_ACTION_GENERIC_VERIFY_V2;
GUID *pguidActionIDJava = &guidJava;
GUID *pguidActionIDCor = &guidCor;
WINTRUST_DATA wintrustData;
WINTRUST_DATA wtdAuthenticode;
WINTRUST_FILE_INFO fileData;
JAVA_POLICY_PROVIDER javaPolicyData;
WCHAR wpath [MAX_PATH];
PJAVA_TRUST pbJavaTrust = NULL;
IServiceProvider *pServProv = NULL;
LPCATALOGFILEINFO pcfi = NULL;
HRESULT hr = S_OK;
ZEROSTRUCT(wintrustData);
ZEROSTRUCT(fileData);
ZEROSTRUCT(javaPolicyData);
javaPolicyData.cbSize = sizeof(JAVA_POLICY_PROVIDER);
javaPolicyData.VMBased = FALSE;
javaPolicyData.fNoBadUI = FALSE;
javaPolicyData.pwszZone = szStatusText;
javaPolicyData.pZoneManager = (LPVOID)pHostSecurityManager;
fileData.cbStruct = sizeof(WINTRUST_FILE_INFO);
fileData.pcwszFilePath = szStatusText;
fileData.hFile = hFile;
wintrustData.cbStruct = sizeof(WINTRUST_DATA);
wintrustData.pPolicyCallbackData = &javaPolicyData;
if ( (hWnd == INVALID_HANDLE_VALUE) || IsUIRestricted())
wintrustData.dwUIChoice = WTD_UI_NONE;
else
wintrustData.dwUIChoice = WTD_UI_ALL;
wintrustData.dwUnionChoice = WTD_CHOICE_FILE;
wintrustData.pFile = &fileData;
if (szCatalogFile) {
::Ansi2Unicode(szCatalogFile, &wzCatalogFile);
::Ansi2Unicode(szFilePath, &wzFilePath);
wzFileName = PathFindFileNameW(szStatusText);
if (!m_bHaveWTData) {
memset(&m_wtCatalogInfo, 0x0, sizeof(m_wtCatalogInfo));
m_wtCatalogInfo.cbStruct = sizeof(WINTRUST_CATALOG_INFO);
m_bHaveWTData = TRUE;
}
m_wtCatalogInfo.pcwszCatalogFilePath = wzCatalogFile;
m_wtCatalogInfo.pcwszMemberTag = wzFileName;
m_wtCatalogInfo.pcwszMemberFilePath = wzFilePath;
wtdAuthenticode = wintrustData;
wtdAuthenticode.pCatalog = &m_wtCatalogInfo;
wtdAuthenticode.dwUnionChoice = WTD_CHOICE_CATALOG;
wtdAuthenticode.dwStateAction = WTD_STATEACTION_VERIFY;
wtdAuthenticode.dwUIChoice = WTD_UI_NONE;
hr = WinVerifyTrust(hWnd, &guidAuthenticode, &wtdAuthenticode);
if (FAILED(hr)) {
hr = WinVerifyTrust(hWnd, pguidActionIDCor, &wintrustData);
if (hr == TRUST_E_PROVIDER_UNKNOWN)
hr = WinVerifyTrust(hWnd, pguidActionIDJava, &wintrustData);
}
else {
// Clone Java permissions
pbJavaTrust = pdl->GetCodeDownload()->GetJavaTrust();
if (!pbJavaTrust) {
hr = pdl->GetBSC()->QueryInterface(IID_IServiceProvider, (void **)&pServProv);
if (SUCCEEDED(hr)) {
hr = pServProv->QueryService(IID_ICatalogFileInfo, IID_ICatalogFileInfo, (void **)&pcfi);
if (SUCCEEDED(hr)) {
pcfi->GetJavaTrust((void **)&pbJavaTrust);
}
}
SAFERELEASE(pServProv);
SAFERELEASE(pcfi);
pdl->SetMainCABJavaTrustPermissions(pbJavaTrust);
}
}
}
else {
hr = WinVerifyTrust(hWnd, pguidActionIDCor, &wintrustData);
if (hr == TRUST_E_PROVIDER_UNKNOWN)
hr = WinVerifyTrust(hWnd, pguidActionIDJava, &wintrustData);
if (SUCCEEDED(hr)) {
pdl->SetMainCABJavaTrustPermissions(javaPolicyData.pbJavaTrust);
}
}
SAFEDELETE(wzCatalogFile);
SAFEDELETE(wzFilePath);
// BUGBUG: this works around a wvt bug that returns 0x57 (success) when
// you hit No to an usigned control
if (SUCCEEDED(hr) && hr != S_OK) {
hr = TRUST_E_FAIL;
}
if (FAILED(hr)) {
// display original hr intact to help debugging
// CodeDownloadDebugOut(DEB_CODEDL, TRUE, ID_CDLDBG_VERIFYTRUST_FAILED, hr);
} else {
*ppJavaTrust = javaPolicyData.pbJavaTrust;
}
if (hr == TRUST_E_SUBJECT_NOT_TRUSTED && wintrustData.dwUIChoice == WTD_UI_NONE) {
// if we didn't ask for the UI to be out up there has been no UI
// work around WVT bvug that it returns us this special error code
// without putting up UI.
hr = TRUST_E_FAIL; // this will put up mshtml ui after the fact
// that security settings prevented us
}
if (FAILED(hr) && (hr != TRUST_E_SUBJECT_NOT_TRUSTED)) {
// trust system has failed without UI
// map error to this generic error that will falg our client to put
// up additional info that this is a trust system error if reqd.
hr = TRUST_E_FAIL;
}
if (hr == TRUST_E_SUBJECT_NOT_TRUSTED) {
pdl->GetCodeDownload()->SetUserDeclined();
}
return hr;
}
HRESULT GetActivePolicy(IInternetHostSecurityManager* pZoneManager,
LPCWSTR pwszZone,
DWORD dwUrlAction,
DWORD& dwPolicy)
{
HRESULT hr = TRUST_E_FAIL;
HRESULT hr2 = TRUST_E_FAIL;
DWORD cbPolicy = sizeof(DWORD);
// Policy are ordered such that high numbers are the most conservative
// and the lower numbers are less conservative
DWORD dwDocumentPolicy = URLPOLICY_ALLOW;
DWORD dwUrlPolicy = URLPOLICY_ALLOW;
// We are going for the most conservative so lets set the
// value to the least conservative
dwPolicy = URLPOLICY_ALLOW;
IInternetSecurityManager* iSM = NULL;
// Ask the document base for its policy
if(pZoneManager) { // Given a IInternetHostSecurityManager
hr = pZoneManager->ProcessUrlAction(dwUrlAction,
(PBYTE) &dwDocumentPolicy,
cbPolicy,
NULL,
0,
PUAF_NOUI,
0);
}
// Get the policy for the URL
if(pwszZone) { // Create an IInternetSecurityManager
hr2 = CoInternetCreateSecurityManager(NULL,
&iSM,
0);
if(hr2 == S_OK) { // We got the manager so get the policy info
hr2 = iSM->ProcessUrlAction(pwszZone,
dwUrlAction,
(PBYTE) &dwUrlPolicy,
cbPolicy,
NULL,
0,
PUAF_NOUI,
0);
iSM->Release();
}
else
iSM = NULL;
}
// if they both failed and we have zones then set it to deny and return an error
if(FAILED(hr) && FAILED(hr2)) {
// If we failed because there are on zones then lets QUERY
// BUGBUG: we should actually try to get the IE30 security policy here.
if(iSM == NULL && pZoneManager == NULL) {
dwPolicy = URLPOLICY_QUERY;
hr = S_OK;
}
else {
dwPolicy = URLPOLICY_DISALLOW;
hr = TRUST_E_FAIL;
}
}
else {
if(SUCCEEDED(hr))
dwPolicy = dwDocumentPolicy;
if(SUCCEEDED(hr2))
dwPolicy = dwPolicy > dwUrlPolicy ? dwPolicy : dwUrlPolicy;
if (dwPolicy == URLPOLICY_DISALLOW)
hr = TRUST_E_FAIL;
else
hr = S_OK;
}
return hr;
}
Some additional comments can be found in MSDN. Using the hexadecimal representation of the hash of a file for the reference tag is common usage but is not mandatory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With