VBoxCertUtil.cpp revision 52f056572badad93a580b8871f411abceb85baf0
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/* $Id$ */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/** @file
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * VBoxCertUtil - VBox Certificate Utility - Windows Only.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/*
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Copyright (C) 2012 Oracle Corporation
956a0e3c076406b83d635174a201fd8761ee5133vboxsync *
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
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/*******************************************************************************
956a0e3c076406b83d635174a201fd8761ee5133vboxsync* Header Files *
956a0e3c076406b83d635174a201fd8761ee5133vboxsync*******************************************************************************/
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#include <Windows.h>
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#include <Wincrypt.h>
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#include <iprt/buildconfig.h>
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#include <iprt/err.h>
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync#include <iprt/file.h>
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync#include <iprt/getopt.h>
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync#include <iprt/initterm.h>
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync#include <iprt/message.h>
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#include <iprt/stream.h>
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#include <iprt/string.h>
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#include <iprt/time.h>
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/*******************************************************************************
956a0e3c076406b83d635174a201fd8761ee5133vboxsync* Global Variables *
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync*******************************************************************************/
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/** The verbosity level. */
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic unsigned g_cVerbosityLevel = 1;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic const char *errorToString(DWORD dwErr)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync{
956a0e3c076406b83d635174a201fd8761ee5133vboxsync switch (dwErr)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#define MY_CASE(a_uConst) case a_uConst: return #a_uConst;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_MSG_ERROR);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_UNKNOWN_ALGO);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_OID_FORMAT);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_INVALID_MSG_TYPE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_UNEXPECTED_ENCODING);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_AUTH_ATTR_MISSING);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_HASH_VALUE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_INVALID_INDEX);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_ALREADY_DECRYPTED);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NOT_DECRYPTED);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_RECIPIENT_NOT_FOUND);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_CONTROL_TYPE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_ISSUER_SERIALNUMBER);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_SIGNER_NOT_FOUND);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_ATTRIBUTES_MISSING);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_STREAM_MSG_NOT_READY);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_STREAM_INSUFFICIENT_DATA);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_I_NEW_PROTECTION_REQUIRED);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_BAD_LEN);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_BAD_ENCODE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_FILE_ERROR);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NOT_FOUND);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_EXISTS);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NO_PROVIDER);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_SELF_SIGNED);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_DELETED_PREV);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NO_MATCH);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_UNEXPECTED_MSG_TYPE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NO_KEY_PROPERTY);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NO_DECRYPT_CERT);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_BAD_MSG);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NO_SIGNER);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_PENDING_CLOSE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_REVOKED);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NO_REVOCATION_DLL);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NO_REVOCATION_CHECK);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_REVOCATION_OFFLINE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NOT_IN_REVOCATION_DATABASE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_INVALID_NUMERIC_STRING);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_INVALID_PRINTABLE_STRING);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_INVALID_IA5_STRING);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_INVALID_X500_STRING);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NOT_CHAR_STRING);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync MY_CASE(CRYPT_E_FILERESIZED);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync MY_CASE(CRYPT_E_SECURITY_SETTINGS);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync MY_CASE(CRYPT_E_NO_VERIFY_USAGE_DLL);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync MY_CASE(CRYPT_E_NO_VERIFY_USAGE_CHECK);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_VERIFY_USAGE_OFFLINE);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NOT_IN_CTL);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_NO_TRUSTED_SIGNER);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_MISSING_PUBKEY_PARA);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync MY_CASE(CRYPT_E_OSS_ERROR);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync default:
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync PCRTCOMERRMSG pWinComMsg = RTErrCOMGet(dwErr);
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync if (pWinComMsg)
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync return pWinComMsg->pszDefine;
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync static char s_szErr[32];
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync RTStrPrintf(s_szErr, sizeof(s_szErr), "%#x (%d)", dwErr, dwErr);
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync return s_szErr;
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync }
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync }
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync}
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsync#if 0 /* hacking */
a15d881e9ec9bffe9b27ae4174efb8d4dc4a0e17vboxsyncstatic RTEXITCODE addToStore(const char *pszFilename, PCRTUTF16 pwszStore)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync{
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /*
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync * Open the source.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync void *pvFile;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync size_t cbFile;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync int rc = RTFileReadAll(pszFilename, &pvFile, &cbFile);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (RT_FAILURE(rc))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTFileReadAll failed on '%s': %Rrc", pszFilename, rc);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTEXITCODE rcExit = RTEXITCODE_FAILURE;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync PCCERT_CONTEXT pCertCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync (PBYTE)pvFile,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync (DWORD)cbFile);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (pCertCtx)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /*
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Open the destination.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync HCERTSTORE hDstStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync NULL /* hCryptProv = default */,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /*CERT_SYSTEM_STORE_LOCAL_MACHINE*/ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync pwszStore);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (hDstStore != NULL)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#if 0
956a0e3c076406b83d635174a201fd8761ee5133vboxsync DWORD dwContextType;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (CertAddSerializedElementToStore(hDstStore,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync pCertCtx->pbCertEncoded,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync pCertCtx->cbCertEncoded,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CERT_STORE_ADD_NEW,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync 0 /* dwFlags (reserved) */,
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync CERT_STORE_ALL_CONTEXT_FLAG,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync &dwContextType,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync NULL))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgInfo("Successfully added '%s' to the '%ls' store (ctx type %u)", pszFilename, pwszStore, dwContextType);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync rcExit = RTEXITCODE_SUCCESS;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertAddSerializedElementToStore returned %s", errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (CertAddCertificateContextToStore(hDstStore, pCertCtx, CERT_STORE_ADD_NEW, NULL))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgInfo("Successfully added '%s' to the '%ls' store", pszFilename, pwszStore);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync rcExit = RTEXITCODE_SUCCESS;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#endif
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertOpenStore returned %s", errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CertFreeCertificateContext(pCertCtx);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertCreateCertificateContext returned %s", errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTFileReadAllFree(pvFile, cbFile);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return rcExit;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#if 0
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CRYPT_DATA_BLOB Blob;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync Blob.cbData = (DWORD)cbData;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync Blob.pbData = (PBYTE)pvData;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync HCERTSTORE hSrcStore = PFXImportCertStore(&Blob, L"", )
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#endif
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync}
956a0e3c076406b83d635174a201fd8761ee5133vboxsync#endif /* hacking */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/**
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Reads a certificate from a file, returning a context or a the handle to a
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * temporary memory store.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync *
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.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync */
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic bool readCertFile(const char *pszCertFile, PCCERT_CONTEXT *ppOutCtx, HCERTSTORE *phSrcStore)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync{
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync *ppOutCtx = NULL;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync *phSrcStore = NULL;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync bool fRc = false;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync void *pvFile;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync size_t cbFile;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync int rc = RTFileReadAll(pszCertFile, &pvFile, &cbFile);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (RT_SUCCESS(rc))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync *ppOutCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync (PBYTE)pvFile, (DWORD)cbFile);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (*ppOutCtx)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync fRc = true;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /** @todo figure out if it's some other format... */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertCreateCertificateContext returned %s parsing the content of '%s'",
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync errorToString(GetLastError()), pszCertFile);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("RTFileReadAll failed on '%s': %Rrc", pszCertFile, rc);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTFileReadAllFree(pvFile, cbFile);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return fRc;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync}
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/**
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Opens a certificate store.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync *
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.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync */
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic HCERTSTORE openCertStore(DWORD dwDst, const char *pszStoreNm)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync{
956a0e3c076406b83d635174a201fd8761ee5133vboxsync HCERTSTORE hStore = NULL;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync PRTUTF16 pwszStoreNm;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync int rc = RTStrToUtf16(pszStoreNm, &pwszStoreNm);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (RT_SUCCESS(rc))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (g_cVerbosityLevel > 1)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgInfo("Opening store %#x:'%s'", dwDst, pszStoreNm);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync NULL /* hCryptProv = default */,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync dwDst | CERT_STORE_OPEN_EXISTING_FLAG,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync pwszStoreNm);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (hStore == NULL)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertOpenStore failed opening %#x:'%s': %s",
956a0e3c076406b83d635174a201fd8761ee5133vboxsync dwDst, pszStoreNm, errorToString(GetLastError()));
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTUtf16Free(pwszStoreNm);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return hStore;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync}
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/**
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Removes a certificate, given by file, from a store
956a0e3c076406b83d635174a201fd8761ee5133vboxsync *
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.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync */
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic bool removeCertFromStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync{
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /*
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Read the certificate file first.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync PCCERT_CONTEXT pSrcCtx = NULL;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync HCERTSTORE hSrcStore = NULL;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return false;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync WCHAR wszName[1024];
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (!CertGetNameStringW(pSrcCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync wszName, sizeof(wszName)))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync wszName[0] = '\0';
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /*
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Open the destination store.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync */
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync bool fRc = false;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (hDstStore)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (pSrcCtx)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync fRc = true;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync unsigned cDeleted = 0;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync PCCERT_CONTEXT pCurCtx = NULL;
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync while ((pCurCtx = CertEnumCertificatesInStore(hDstStore, pCurCtx)) != NULL)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pCurCtx->pCertInfo, pSrcCtx->pCertInfo))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (g_cVerbosityLevel > 1)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgInfo("Removing '%ls'...", wszName);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync PCCERT_CONTEXT pDeleteCtx = CertDuplicateCertificateContext(pCurCtx);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (pDeleteCtx)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (CertDeleteCertificateFromStore(pDeleteCtx))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync cDeleted++;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync else
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync RTMsgError("CertDeleteFromStore('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertDuplicateCertificateContext('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync if (!cDeleted)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgInfo("Found no matching certificates to remove.");
4e47bb772df0d04d1ded3e06354de547d52e2d06vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("Path not implemented at line %d\n", __LINE__);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (pSrcCtx)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CertFreeCertificateContext(pSrcCtx);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (hSrcStore)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return fRc;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync}
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/**
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Adds a certificate to a store.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync *
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.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync */
956a0e3c076406b83d635174a201fd8761ee5133vboxsyncstatic bool addCertToStore(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile, DWORD dwDisposition)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync{
956a0e3c076406b83d635174a201fd8761ee5133vboxsync /*
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync * Read the certificate file first.
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync */
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync PCCERT_CONTEXT pSrcCtx = NULL;
8a63f697e3c0c9afe0dc326c3db61fd4217fa895vboxsync HCERTSTORE hSrcStore = NULL;
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync return false;
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync /*
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync * Open the destination store.
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync */
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync bool fRc = false;
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync if (hDstStore)
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync {
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync if (pSrcCtx)
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync {
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync if (g_cVerbosityLevel > 1)
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync RTMsgInfo("Adding '%s' to %#x:'%s'... (disp %d)", pszCertFile, dwDst, pszStoreNm, dwDisposition);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (CertAddCertificateContextToStore(hDstStore, pSrcCtx, dwDisposition, NULL))
956a0e3c076406b83d635174a201fd8761ee5133vboxsync fRc = true;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync RTMsgError("Path not implemented at line %d\n", __LINE__);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync if (pSrcCtx)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync CertFreeCertificateContext(pSrcCtx);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (hSrcStore)
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync return fRc;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync}
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
956a0e3c076406b83d635174a201fd8761ee5133vboxsync/**
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync * Worker for cmdDisplayAll.
956a0e3c076406b83d635174a201fd8761ee5133vboxsync */
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsyncstatic BOOL WINAPI displaySystemStoreCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync void *pvReserved, void *pvArg)
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync{
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (g_cVerbosityLevel > 1)
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync RTPrintf(" pvSystemStore=%p dwFlags=%#x pStoreInfo=%p pvReserved=%p\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync LPCWSTR pwszStoreNm = NULL;
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync const CERT_SYSTEM_STORE_RELOCATE_PARA *pRelPara = (const CERT_SYSTEM_STORE_RELOCATE_PARA *)pvSystemStore;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync pwszStoreNm = pRelPara->pwszSystemStore;
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync RTPrintf(" %#010x '%ls' hKeyBase=%p\n", dwFlags, pwszStoreNm, pRelPara->hKeyBase);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync }
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync else
956a0e3c076406b83d635174a201fd8761ee5133vboxsync {
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync pwszStoreNm = (LPCWSTR)pvSystemStore;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync RTPrintf(" %#010x '%ls'\n", dwFlags, pwszStoreNm);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync }
956a0e3c076406b83d635174a201fd8761ee5133vboxsync
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync /*
956a0e3c076406b83d635174a201fd8761ee5133vboxsync * Open the store and list the certificates within.
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync */
956a0e3c076406b83d635174a201fd8761ee5133vboxsync DWORD dwDst = (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK);
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync HCERTSTORE hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
2a0a20dee7f474c26cc8f6f9d7aa12c345c2b73bvboxsync NULL /* hCryptProv = default */,
956a0e3c076406b83d635174a201fd8761ee5133vboxsync dwDst | CERT_STORE_OPEN_EXISTING_FLAG,
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync pwszStoreNm);
956a0e3c076406b83d635174a201fd8761ee5133vboxsync if (hStore)
68fb2428898c55a7172e6a75a0a8d7ce259919bdvboxsync {
956a0e3c076406b83d635174a201fd8761ee5133vboxsync PCCERT_CONTEXT pCertCtx = NULL;
956a0e3c076406b83d635174a201fd8761ee5133vboxsync while ((pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) != NULL)
{
if (g_cVerbosityLevel > 1)
RTPrintf(" pCertCtx=%p dwCertEncodingType=%#x cbCertEncoded=%#x pCertInfo=%p\n",
pCertCtx, pCertCtx->dwCertEncodingType, pCertCtx->cbCertEncoded, pCertCtx->pCertInfo);
WCHAR wszName[1024];
if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/,
wszName, sizeof(wszName)))
{
RTPrintf(" '%ls'\n", wszName);
if (pCertCtx->pCertInfo)
{
RTTIMESPEC TmpTS;
char szNotBefore[80];
RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotBefore),
szNotBefore, sizeof(szNotBefore));
char szNotAfter[80];
RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotAfter),
szNotAfter, sizeof(szNotAfter));
RTPrintf(" NotBefore='%s'\n", szNotBefore);
RTPrintf(" NotAfter ='%s'\n", szNotAfter);
if (pCertCtx->pCertInfo->Issuer.cbData)
{
if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL /*pvTypePara*/,
wszName, sizeof(wszName)))
RTPrintf(" Issuer='%ls'\n", wszName);
else
RTMsgError("CertGetNameStringW(Issuer) failed: %s\n", errorToString(GetLastError()));
}
}
}
else
RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError()));
}
CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
}
else
RTMsgError("CertOpenStore failed opening %#x:'%ls': %s\n", dwDst, pwszStoreNm, errorToString(GetLastError()));
return TRUE;
}
/**
* Worker for cmdDisplayAll.
*/
static BOOL WINAPI displaySystemStoreLocation(LPCWSTR pwszStoreLocation, DWORD dwFlags, void *pvReserved, void *pvArg)
{
NOREF(pvReserved); NOREF(pvArg);
RTPrintf("System store location: %#010x '%ls'\n", dwFlags, pwszStoreLocation);
if (!CertEnumSystemStore(dwFlags, NULL, NULL /*pvArg*/, displaySystemStoreCallback))
RTMsgError("CertEnumSystemStore failed on %#x:'%ls': %s\n",
dwFlags, pwszStoreLocation, errorToString(GetLastError()));
return TRUE;
}
/**
* Handler for the 'display-all' command.
*/
static RTEXITCODE cmdDisplayAll(int argc, char **argv)
{
if (argc != 1)
return RTMsgErrorExit(RTEXITCODE_SYNTAX, "the display-all command takes no arguments\n");
if (!CertEnumSystemStoreLocation(0, NULL /*pvArg*/, displaySystemStoreLocation))
return RTMsgErrorExit(RTEXITCODE_SYNTAX, "CertEnumSystemStoreLocation failed: %s\n", errorToString(GetLastError()));
return RTEXITCODE_SUCCESS;
}
/**
* Handler for the 'remove-trusted-publisher' command.
*/
static RTEXITCODE cmdRemoveTrustedPublisher(int argc, char **argv)
{
/*
* Parse arguments.
*/
static const RTGETOPTDEF s_aOptions[] =
{
{ "--root", 'r', RTGETOPT_REQ_STRING },
};
const char *pszRootCert = NULL;
const char *pszTrustedCert = NULL;
int rc;
RTGETOPTUNION ValueUnion;
RTGETOPTSTATE GetState;
RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
while ((rc = RTGetOpt(&GetState, &ValueUnion)))
{
switch (rc)
{
case 'h':
RTPrintf("Usage: VBoxCertUtil remove-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
break;
case 'V':
RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
return RTEXITCODE_SUCCESS;
case 'r':
if (pszRootCert)
return RTMsgErrorExit(RTEXITCODE_SUCCESS,
"You've already specified '%s' as root certificate.",
pszRootCert);
pszRootCert = ValueUnion.psz;
break;
case VINF_GETOPT_NOT_OPTION:
if (pszTrustedCert)
return RTMsgErrorExit(RTEXITCODE_SUCCESS,
"You've already specified '%s' as trusted certificate.",
pszRootCert);
pszTrustedCert = ValueUnion.psz;
break;
default:
return RTGetOptPrintError(rc, &ValueUnion);
}
}
if (!pszTrustedCert)
return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No trusted certificate specified.");
/*
* Do the job.
*/
if ( pszRootCert
&& !removeCertFromStoreByFile(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", 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);
else
RTMsgInfo("Successfully removed '%s' as trusted publisher", pszTrustedCert);
}
return RTEXITCODE_SUCCESS;
}
/**
* Handler for the 'add-trusted-publisher' command.
*/
static RTEXITCODE cmdAddTrustedPublisher(int argc, char **argv)
{
/*
* Parse arguments.
*/
static const RTGETOPTDEF s_aOptions[] =
{
{ "--root", 'r', RTGETOPT_REQ_STRING },
};
const char *pszRootCert = NULL;
const char *pszTrustedCert = NULL;
int rc;
RTGETOPTUNION ValueUnion;
RTGETOPTSTATE GetState;
RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
while ((rc = RTGetOpt(&GetState, &ValueUnion)))
{
switch (rc)
{
case 'h':
RTPrintf("Usage: VBoxCertUtil add-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
break;
case 'V':
RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
return RTEXITCODE_SUCCESS;
case 'r':
if (pszRootCert)
return RTMsgErrorExit(RTEXITCODE_SUCCESS,
"You've already specified '%s' as root certificate.",
pszRootCert);
pszRootCert = ValueUnion.psz;
break;
case VINF_GETOPT_NOT_OPTION:
if (pszTrustedCert)
return RTMsgErrorExit(RTEXITCODE_SUCCESS,
"You've already specified '%s' as trusted certificate.",
pszTrustedCert);
pszTrustedCert = ValueUnion.psz;
break;
default:
return RTGetOptPrintError(rc, &ValueUnion);
}
}
if (!pszTrustedCert)
return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No trusted certificate specified.");
/*
* Do the job.
*/
/** @todo The root-cert part needs to be made more flexible. */
if ( pszRootCert
&& !addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", pszRootCert, CERT_STORE_ADD_NEW))
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);
else
RTMsgInfo("Successfully added '%s' as trusted publisher", pszTrustedCert);
}
return RTEXITCODE_SUCCESS;
}
/**
* Displays the usage info.
* @param argv0 Program name.
*/
static void showUsage(const char *argv0)
{
RTPrintf("Usage: %Rbn [-v[v]] <command>\n"
" or %Rbn <-V|--version>\n"
" or %Rbn <-h|--help>\n"
"\n"
"Available commands:\n"
" add-trusted-publisher, remove-trusted-publisher,\n"
" display-all\n"
, argv0, argv0, argv0);
}
int main(int argc, char **argv)
{
int rc = RTR3InitExe(argc, &argv, 0);
if (RT_FAILURE(rc))
return RTMsgInitFailure(rc);
/*
* Parse arguments up to the command and pass it on to the command handlers.
*/
typedef enum
{
VCUACTION_ADD_TRUSTED_PUBLISHER = 1000,
VCUACTION_REMOVE_TRUSTED_PUBLISHER,
VCUACTION_DISPLAY_ALL,
VCUACTION_END
} VCUACTION;
static const RTGETOPTDEF s_aOptions[] =
{
{ "--verbose", 'v', RTGETOPT_REQ_NOTHING },
{ "--quiet", 'q', RTGETOPT_REQ_NOTHING },
{ "add-trusted-publisher", VCUACTION_ADD_TRUSTED_PUBLISHER, RTGETOPT_REQ_NOTHING },
{ "remove-trusted-publisher", VCUACTION_REMOVE_TRUSTED_PUBLISHER, RTGETOPT_REQ_NOTHING },
{ "display-all", VCUACTION_DISPLAY_ALL, RTGETOPT_REQ_NOTHING },
};
RTGETOPTUNION ValueUnion;
RTGETOPTSTATE GetState;
RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
while ((rc = RTGetOpt(&GetState, &ValueUnion)))
{
switch (rc)
{
case 'v':
g_cVerbosityLevel++;
break;
case 'q':
if (g_cVerbosityLevel > 0)
g_cVerbosityLevel--;
break;
case 'h':
showUsage(argv[0]);
return RTEXITCODE_SUCCESS;
case 'V':
RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
return RTEXITCODE_SUCCESS;
case VCUACTION_ADD_TRUSTED_PUBLISHER:
return cmdAddTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
case VCUACTION_REMOVE_TRUSTED_PUBLISHER:
return cmdRemoveTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
case VCUACTION_DISPLAY_ALL:
return cmdDisplayAll(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
default:
return RTGetOptPrintError(rc, &ValueUnion);
}
}
RTMsgError("Missing command...");
showUsage(argv[0]);
return RTEXITCODE_SYNTAX;
}