VBoxCertUtil.cpp revision 52f056572badad93a580b8871f411abceb85baf0
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * VBoxCertUtil - VBox Certificate Utility - Windows Only.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Copyright (C) 2012 Oracle Corporation
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * available from http://www.virtualbox.org. This file is free software;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * you can redistribute it and/or modify it under the terms of the GNU
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * General Public License (GPL) as published by the Free Software
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/*******************************************************************************
956a0e3c076406b83d635174a201fd8761ee5133vboxsync* Header Files *
956a0e3c076406b83d635174a201fd8761ee5133vboxsync*******************************************************************************/
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/*******************************************************************************
956a0e3c076406b83d635174a201fd8761ee5133vboxsync* Global Variables *
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync*******************************************************************************/
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/** The verbosity level. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define MY_CASE(a_uConst) case a_uConst: return #a_uConst;
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync RTStrPrintf(s_szErr, sizeof(s_szErr), "%#x (%d)", dwErr, dwErr);
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync#if 0 /* hacking */
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsyncstatic RTEXITCODE addToStore(const char *pszFilename, PCRTUTF16 pwszStore)
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync * Open the source.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync int rc = RTFileReadAll(pszFilename, &pvFile, &cbFile);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTFileReadAll failed on '%s': %Rrc", pszFilename, rc);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync PCCERT_CONTEXT pCertCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Open the destination.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync HCERTSTORE hDstStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /*CERT_SYSTEM_STORE_LOCAL_MACHINE*/ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync 0 /* dwFlags (reserved) */,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgInfo("Successfully added '%s' to the '%ls' store (ctx type %u)", pszFilename, pwszStore, dwContextType);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertAddSerializedElementToStore returned %s", errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (CertAddCertificateContextToStore(hDstStore, pCertCtx, CERT_STORE_ADD_NEW, NULL))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgInfo("Successfully added '%s' to the '%ls' store", pszFilename, pwszStore);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertOpenStore returned %s", errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertCreateCertificateContext returned %s", errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync HCERTSTORE hSrcStore = PFXImportCertStore(&Blob, L"", )
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#endif /* hacking */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Reads a certificate from a file, returning a context or a the handle to a
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * temporary memory store.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @returns true on success, false on failure (error message written).
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pszCertFile The name of the file containing the
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * certificates.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param ppOutCtx Where to return the certificate context.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param phSrcStore Where to return the handle to the temporary
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * memory store.
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic bool readCertFile(const char *pszCertFile, PCCERT_CONTEXT *ppOutCtx, HCERTSTORE *phSrcStore)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync bool fRc = false;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync int rc = RTFileReadAll(pszCertFile, &pvFile, &cbFile);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync *ppOutCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** @todo figure out if it's some other format... */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertCreateCertificateContext returned %s parsing the content of '%s'",
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("RTFileReadAll failed on '%s': %Rrc", pszCertFile, rc);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Opens a certificate store.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @returns true on success, false on failure (error message written).
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param dwDst The destination, like
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync * CERT_SYSTEM_STORE_LOCAL_MACHINE or
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * CERT_SYSTEM_STORE_CURRENT_USER.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pszStoreNm The store name.
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic HCERTSTORE openCertStore(DWORD dwDst, const char *pszStoreNm)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgInfo("Opening store %#x:'%s'", dwDst, pszStoreNm);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertOpenStore failed opening %#x:'%s': %s",
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Removes a certificate, given by file, from a store
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @returns true on success, false on failure (error message written).
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param dwDst The destination, like
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * CERT_SYSTEM_STORE_LOCAL_MACHINE or
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * CERT_SYSTEM_STORE_CURRENT_USER.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pszStoreNm The store name.
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync * @param pszCertFile The file containing the certificate to add.
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic bool removeCertFromStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Read the certificate file first.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return false;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (!CertGetNameStringW(pSrcCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Open the destination store.
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync bool fRc = false;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync unsigned cDeleted = 0;
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync while ((pCurCtx = CertEnumCertificatesInStore(hDstStore, pCurCtx)) != NULL)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pCurCtx->pCertInfo, pSrcCtx->pCertInfo))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync PCCERT_CONTEXT pDeleteCtx = CertDuplicateCertificateContext(pCurCtx);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync RTMsgError("CertDeleteFromStore('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertDuplicateCertificateContext('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgInfo("Found no matching certificates to remove.");
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("Path not implemented at line %d\n", __LINE__);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Adds a certificate to a store.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @returns true on success, false on failure (error message written).
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync * @param dwDst The destination, like
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * CERT_SYSTEM_STORE_LOCAL_MACHINE or
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * CERT_SYSTEM_STORE_CURRENT_USER.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pszStoreNm The store name.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param pszCertFile The file containing the certificate to add.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * @param dwDisposition The disposition towards existing certificates when
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * adding it. CERT_STORE_ADD_NEW is a safe one.
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic bool addCertToStore(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile, DWORD dwDisposition)
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync * Read the certificate file first.
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync return false;
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync * Open the destination store.
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync bool fRc = false;
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync RTMsgInfo("Adding '%s' to %#x:'%s'... (disp %d)", pszCertFile, dwDst, pszStoreNm, dwDisposition);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (CertAddCertificateContextToStore(hDstStore, pSrcCtx, dwDisposition, NULL))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync RTMsgError("Path not implemented at line %d\n", __LINE__);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync * Worker for cmdDisplayAll.
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsyncstatic BOOL WINAPI displaySystemStoreCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo,
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync RTPrintf(" pvSystemStore=%p dwFlags=%#x pStoreInfo=%p pvReserved=%p\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync const CERT_SYSTEM_STORE_RELOCATE_PARA *pRelPara = (const CERT_SYSTEM_STORE_RELOCATE_PARA *)pvSystemStore;
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync RTPrintf(" %#010x '%ls' hKeyBase=%p\n", dwFlags, pwszStoreNm, pRelPara->hKeyBase);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Open the store and list the certificates within.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync DWORD dwDst = (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync HCERTSTORE hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync while ((pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) != NULL)
if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL /*pvTypePara*/,
RTMsgError("CertOpenStore failed opening %#x:'%ls': %s\n", dwDst, pwszStoreNm, errorToString(GetLastError()));
return TRUE;
static BOOL WINAPI displaySystemStoreLocation(LPCWSTR pwszStoreLocation, DWORD dwFlags, void *pvReserved, void *pvArg)
return TRUE;
return RTMsgErrorExit(RTEXITCODE_SYNTAX, "CertEnumSystemStoreLocation failed: %s\n", errorToString(GetLastError()));
return RTEXITCODE_SUCCESS;
int rc;
switch (rc)
return RTEXITCODE_SUCCESS;
if (pszRootCert)
case VINF_GETOPT_NOT_OPTION:
if (pszTrustedCert)
if (!pszTrustedCert)
if ( pszRootCert
return RTEXITCODE_FAILURE;
if (!removeCertFromStoreByFile(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", pszTrustedCert))
return RTEXITCODE_FAILURE;
if (g_cVerbosityLevel > 0)
if (pszRootCert)
RTMsgInfo("Successfully removed '%s' as root and '%s' as trusted publisher", pszRootCert, pszTrustedCert);
return RTEXITCODE_SUCCESS;
int rc;
switch (rc)
return RTEXITCODE_SUCCESS;
if (pszRootCert)
case VINF_GETOPT_NOT_OPTION:
if (pszTrustedCert)
if (!pszTrustedCert)
if ( pszRootCert
return RTEXITCODE_FAILURE;
if (!addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", pszTrustedCert, CERT_STORE_ADD_NEW))
return RTEXITCODE_FAILURE;
if (g_cVerbosityLevel > 0)
if (pszRootCert)
RTMsgInfo("Successfully added '%s' as root and '%s' as trusted publisher", pszRootCert, pszTrustedCert);
return RTEXITCODE_SUCCESS;
} VCUACTION;
switch (rc)
if (g_cVerbosityLevel > 0)
return RTEXITCODE_SUCCESS;
return RTEXITCODE_SUCCESS;
case VCUACTION_DISPLAY_ALL:
return RTEXITCODE_SYNTAX;