How to avoid ‘Trust This Publisher’ Dialog

By Madhukar Moogala

From 2016, if modules are signed and the certificate (.cer) file used to sign the modules is not registered in the store, or modules are not located in a trusted location, a window will pop up asking the user to trust the publisher. To avoid this pesky dialog, you can follow any of these steps.

Trust-This-Publisher

1. Adding a Certificate to the Trusted Store During Installation

There is no inherent support in MSI to add a certificate to the certificate store; this must be accomplished using a Custom Action. There are two ways to do this:

  • Method A: Use certutil.exe, a command-line tool from Microsoft.
    certutil.exe -addstore TrustedPublisher mycertfile.cer
  • Method B: Use the Microsoft Crypto API. Sample code for both .NET and C++ is provided below.

.NET Implementation


// Load the certificate file
X509Certificate2 certificate = new X509Certificate2(@"C:\temp\mycertfile.cer");

// Alternatively, to load a PFX file:
// X509Certificate2 certificate = new X509Certificate2(@"C:\temp\mycert.pfx", "pwd123", X509KeyStorageFlags.PersistKeySet);

X509Store store = new X509Store(StoreName.TrustedPublisher, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
store.Add(certificate);
store.Close();

C++ Implementation


#include <windows.h>
#include <wincrypt.h>
#include <tchar.h>
#include <atlstr.h>

#pragma comment(lib, "crypt32.lib")

#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)

typedef struct {
    LPWSTR lpszProgramName;
    LPWSTR lpszPublisherLink;
    LPWSTR lpszMoreInfoLink;
} SPROG_PUBLISHERINFO, *PSPROG_PUBLISHERINFO;

class X509Certificate {
public:
    X509Certificate();
    ~X509Certificate(void);
    bool initialize(LPCTSTR pszFileName);
    bool isCertificateInTrustedPubStore();
    bool installCertificateToTrustedPubStore();

private:
    HCERTSTORE mhStore;
    HCRYPTMSG mhMsg;
    CString msFileName;
    PCMSG_SIGNER_INFO mpSignerInfo;
    SPROG_PUBLISHERINFO mProgPubInfo;
    PCCERT_CONTEXT mpCertContext;
};

X509Certificate::X509Certificate(void)
    : mhStore(NULL), mhMsg(NULL), mpSignerInfo(NULL), mpCertContext(NULL) {
    ZeroMemory(&mProgPubInfo, sizeof(mProgPubInfo));
}

X509Certificate::~X509Certificate(void) {
    if (mProgPubInfo.lpszProgramName != NULL) free(mProgPubInfo.lpszProgramName);
    if (mProgPubInfo.lpszPublisherLink != NULL) free(mProgPubInfo.lpszPublisherLink);
    if (mProgPubInfo.lpszMoreInfoLink != NULL) free(mProgPubInfo.lpszMoreInfoLink);
    if (mpSignerInfo != NULL) free(mpSignerInfo);
    if (mpCertContext != NULL) CertFreeCertificateContext(mpCertContext);
    if (mhStore != NULL) CertCloseStore(mhStore, 0);
    if (mhMsg != NULL) CryptMsgClose(mhMsg);
}

bool X509Certificate::initialize(LPCTSTR pszFileName) {
    if (!PathFileExists(pszFileName)) return false;
    msFileName = pszFileName;

    DWORD dwEncoding, dwContentType, dwFormatType;
    DWORD dwSignerInfo;
    CERT_INFO CertInfo;

    BOOL fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
        pszFileName,
        CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
        CERT_QUERY_FORMAT_FLAG_BINARY,
        0,
        &dwEncoding,
        &dwContentType,
        &dwFormatType,
        &mhStore,
        &mhMsg,
        NULL);

    if (!fResult) return false;

    fResult = CryptMsgGetParam(mhMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &dwSignerInfo);
    if (!fResult) return false;

    mpSignerInfo = (PCMSG_SIGNER_INFO)malloc(dwSignerInfo);
    if (!mpSignerInfo) return false;

    fResult = CryptMsgGetParam(mhMsg, CMSG_SIGNER_INFO_PARAM, 0, (PVOID)mpSignerInfo, &dwSignerInfo);
    if (!fResult) return false;

    CertInfo.Issuer = mpSignerInfo->Issuer;
    CertInfo.SerialNumber = mpSignerInfo->SerialNumber;

    mpCertContext = CertFindCertificateInStore(mhStore,
        ENCODING,
        0,
        CERT_FIND_SUBJECT_CERT,
        (PVOID)&CertInfo,
        NULL);

    return (mpCertContext != NULL);
}

bool X509Certificate::isCertificateInTrustedPubStore() {
    if (mpCertContext == NULL) return false;

    HCERTSTORE hCertStore = NULL;
    PCCERT_CONTEXT pFoundCertContext = NULL;
    bool bFound = false;

    hCertStore = CertOpenStore(
        CERT_STORE_PROV_SYSTEM,
        0,
        0,
        CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_CURRENT_USER,
        _T("TrustedPublisher"));

    if (hCertStore != NULL) {
        pFoundCertContext = CertFindCertificateInStore(hCertStore, ENCODING, 0, CERT_FIND_EXISTING, mpCertContext, NULL);
        if (pFoundCertContext != NULL) {
            bFound = true;
            CertFreeCertificateContext(pFoundCertContext);
        }
        CertCloseStore(hCertStore, 0);
    }
    return bFound;
}

bool X509Certificate::installCertificateToTrustedPubStore() {
    if (mpCertContext == NULL) return false;

    bool bRet = false;
    HCERTSTORE hCertStore = CertOpenStore(
        CERT_STORE_PROV_SYSTEM,
        0,
        0,
        CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE,
        _T("TrustedPublisher"));

    if (hCertStore != NULL) {
        if (CertAddCertificateContextToStore(hCertStore, mpCertContext, CERT_STORE_ADD_NEWER, NULL)) {
            bRet = true;
        } else if (GetLastError() == CRYPT_E_EXISTS) {
            bRet = true;
        }
        CertCloseStore(hCertStore, 0);
    }
    return bRet;
}

2. Check the Box

Manually check the checkbox in the security dialog that says: “Always trust applications from XXXXX.”

3. Use a Trusted Location

Install your modules in the following directories, which are trusted by default:

  • C:\Program Files\Autodesk\ApplicationPlugins
  • C:\Program Files (x86)\Autodesk\ApplicationPlugins

Comments

8 responses to “How to avoid ‘Trust This Publisher’ Dialog”

  1. Senthilkumar C K Avatar
    Senthilkumar C K

    Hi Madhukar,
    Thanks for the valuable info.
    Is there any way to avoid the pop-up for first time itself?
    Thanks,
    Senthilkumar C K

  2. Yes, you need to install certificate to store during installation of your plugin, this can be achieved by custom action when your prepare your MSI.

  3. If you are an ADN partner, Exchange store will help you.

  4. Hi Madhukar, I want to use AcSignTool command line tool to sign my lisp files but there doesn’t seem to be any documentation available to understand the tool behavior especially how I can supply a certificate to the AcSignTool to sign my files, can you please throw some light.

  5. LarsR Avatar
    LarsR

    Hi Madhukar,
    I have added a call to certutil in our installer to register our code signing certificate (.cer file). This works fine, but produces a command window flashing by at install time. To avoid this I am trying to implement the C++ code as custom action. I am having trouble with it – the CryptQueryObject() fails since the .cer file isnt in PKCS7, and not binary either (it’s BASE64).
    Changing the parameters to the function to CERT_QUERY_CONTENT_FLAG_ALL and CERT_QUERY_FORMAT_FLAG_ALL makes the call pass, but mhMsg is NULL so the rest fails.
    Do you have any advice on how to get this to work?

  6. LarsR Avatar
    LarsR

    I found the solution. The file passed to the C++ implementation should be a file signed with the certificate to install, i.e. an EXE or DLL file. Then the code works.
    Br,
    Lars

  7. Does this really work? It doesn’t for me.
    3. Trusted Location
    Install the modules in C:\Program Files\Autodesk\ApplicationPlugins or C:\Program Files (x86)\Autodesk\ApplicationPlugins

  8. Hi Harry,
    Can you please elaborate your question ? checkIf the C:\Program Files\Autodesk\ApplicationPlugins or C:\Program Files (x86)\Autodesk\ApplicationPlugins are in trusted location in your AutoCAD profile ?
    May be more generic one’s are
    %APPDATA%\Autodesk\ApplicationPlugins
    %ALLUSERSPROFILE%\Autodesk\ApplicationPlugins
    %ProgramFiles%\Autodesk\ApplicationPlugins
    %ProgramFiles(x86)%\Autodesk\ApplicationPlugins (In 64-bit OS)

Leave a Reply to Madhukar MoogalaCancel reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading