Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a signing catalog file member tag?

Tags:

c++

winapi

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.

like image 325
Billy ONeal Avatar asked Oct 30 '12 17:10

Billy ONeal


2 Answers

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.)

like image 159
Simon Mourier Avatar answered Sep 24 '22 21:09

Simon Mourier


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.

like image 25
Sergey K. Avatar answered Sep 23 '22 21:09

Sergey K.