VBoxStubCertUtil.cpp revision 3a5ff19579e4b3e58a9cdea06fdab1fa6cc961d2
78a072e1b56619e3230735ae073668311232ec94vboxsync/* $Id: VBoxStubCertUtil.cpp 81975 2012-11-09 13:28:58Z bird $ */
78a072e1b56619e3230735ae073668311232ec94vboxsync/** @file
78a072e1b56619e3230735ae073668311232ec94vboxsync * VBoxStub - VirtualBox's Windows installer stub (certificate manipulations).
78a072e1b56619e3230735ae073668311232ec94vboxsync *
78a072e1b56619e3230735ae073668311232ec94vboxsync * NOTE: The content of this file is partly
78a072e1b56619e3230735ae073668311232ec94vboxsync * grabbed from src/VBox/Additions/WINNT/tools/VBoxCertUtil.cpp
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/*
78a072e1b56619e3230735ae073668311232ec94vboxsync * Copyright (C) 2012 Oracle Corporation
78a072e1b56619e3230735ae073668311232ec94vboxsync *
78a072e1b56619e3230735ae073668311232ec94vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
78a072e1b56619e3230735ae073668311232ec94vboxsync * available from http://www.virtualbox.org. This file is free software;
78a072e1b56619e3230735ae073668311232ec94vboxsync * you can redistribute it and/or modify it under the terms of the GNU
78a072e1b56619e3230735ae073668311232ec94vboxsync * General Public License (GPL) as published by the Free Software
78a072e1b56619e3230735ae073668311232ec94vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
78a072e1b56619e3230735ae073668311232ec94vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
78a072e1b56619e3230735ae073668311232ec94vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/*******************************************************************************
78a072e1b56619e3230735ae073668311232ec94vboxsync* Header Files *
78a072e1b56619e3230735ae073668311232ec94vboxsync*******************************************************************************/
78a072e1b56619e3230735ae073668311232ec94vboxsync#include <Windows.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync#include <Wincrypt.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync#include <iprt/string.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync#include <iprt/message.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync#include <iprt/err.h>
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/**
78a072e1b56619e3230735ae073668311232ec94vboxsync * Reads a certificate from a (const char []) buffer, returning a context
78a072e1b56619e3230735ae073668311232ec94vboxsync * or a the handle to a temporary memory store.
78a072e1b56619e3230735ae073668311232ec94vboxsync *
78a072e1b56619e3230735ae073668311232ec94vboxsync * @returns true on success, false on failure (error message written).
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param kpCertBuf The pointer to the buffer containing the
78a072e1b56619e3230735ae073668311232ec94vboxsync * certificates.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param cbCertBuf Size of @param kpCertBuf in bytes.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param ppOutCtx Where to return the handle to the temporary
78a072e1b56619e3230735ae073668311232ec94vboxsync * memory store.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsyncstatic bool readCertBuf(const unsigned char kpCertBuf[], DWORD cbCertBuf, PCCERT_CONTEXT *ppOutCtx)
78a072e1b56619e3230735ae073668311232ec94vboxsync{
78a072e1b56619e3230735ae073668311232ec94vboxsync *ppOutCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
78a072e1b56619e3230735ae073668311232ec94vboxsync (PBYTE)kpCertBuf, cbCertBuf);
78a072e1b56619e3230735ae073668311232ec94vboxsync if (*ppOutCtx)
78a072e1b56619e3230735ae073668311232ec94vboxsync return true;
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync return false;
78a072e1b56619e3230735ae073668311232ec94vboxsync}
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync/**
78a072e1b56619e3230735ae073668311232ec94vboxsync * Opens a certificate store.
78a072e1b56619e3230735ae073668311232ec94vboxsync *
08c4185261c17943cff6cc94522579696eeeb478vboxsync * @returns true on success, false on failure (error message written).
08c4185261c17943cff6cc94522579696eeeb478vboxsync * @param dwDst The destination, like
08c4185261c17943cff6cc94522579696eeeb478vboxsync * CERT_SYSTEM_STORE_LOCAL_MACHINE or
08c4185261c17943cff6cc94522579696eeeb478vboxsync * CERT_SYSTEM_STORE_CURRENT_USER.
08c4185261c17943cff6cc94522579696eeeb478vboxsync * @param pszStoreNm The store name.
08c4185261c17943cff6cc94522579696eeeb478vboxsync */
08c4185261c17943cff6cc94522579696eeeb478vboxsyncstatic HCERTSTORE openCertStore(DWORD dwDst, const char *pszStoreNm)
08c4185261c17943cff6cc94522579696eeeb478vboxsync{
08c4185261c17943cff6cc94522579696eeeb478vboxsync HCERTSTORE hStore = NULL;
08c4185261c17943cff6cc94522579696eeeb478vboxsync PRTUTF16 pwszStoreNm;
08c4185261c17943cff6cc94522579696eeeb478vboxsync int rc = RTStrToUtf16(pszStoreNm, &pwszStoreNm);
08c4185261c17943cff6cc94522579696eeeb478vboxsync if (RT_SUCCESS(rc))
08c4185261c17943cff6cc94522579696eeeb478vboxsync {
08c4185261c17943cff6cc94522579696eeeb478vboxsync /*
08c4185261c17943cff6cc94522579696eeeb478vboxsync * Make sure CERT_STORE_OPEN_EXISTING_FLAG is not set. This causes Windows XP
08c4185261c17943cff6cc94522579696eeeb478vboxsync * to return ACCESS_DENIED when installing TrustedPublisher certificates via
08c4185261c17943cff6cc94522579696eeeb478vboxsync * CertAddCertificateContextToStore() if the TrustedPublisher store never has
08c4185261c17943cff6cc94522579696eeeb478vboxsync * been used (through certmgr.exe and friends) yet.
08c4185261c17943cff6cc94522579696eeeb478vboxsync *
08c4185261c17943cff6cc94522579696eeeb478vboxsync * According to MSDN, if neither CERT_STORE_OPEN_EXISTING_FLAG nor
08c4185261c17943cff6cc94522579696eeeb478vboxsync * CERT_STORE_CREATE_NEW_FLAG is set, the store will be either opened or
08c4185261c17943cff6cc94522579696eeeb478vboxsync * created accordingly.
08c4185261c17943cff6cc94522579696eeeb478vboxsync */
78a072e1b56619e3230735ae073668311232ec94vboxsync dwDst &= ~CERT_STORE_OPEN_EXISTING_FLAG;
08c4185261c17943cff6cc94522579696eeeb478vboxsync
08c4185261c17943cff6cc94522579696eeeb478vboxsync hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
08c4185261c17943cff6cc94522579696eeeb478vboxsync PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
08c4185261c17943cff6cc94522579696eeeb478vboxsync NULL /* hCryptProv = default */,
08c4185261c17943cff6cc94522579696eeeb478vboxsync dwDst,
08c4185261c17943cff6cc94522579696eeeb478vboxsync pwszStoreNm);
08c4185261c17943cff6cc94522579696eeeb478vboxsync
08c4185261c17943cff6cc94522579696eeeb478vboxsync RTUtf16Free(pwszStoreNm);
08c4185261c17943cff6cc94522579696eeeb478vboxsync }
08c4185261c17943cff6cc94522579696eeeb478vboxsync return hStore;
08c4185261c17943cff6cc94522579696eeeb478vboxsync}
08c4185261c17943cff6cc94522579696eeeb478vboxsync
08c4185261c17943cff6cc94522579696eeeb478vboxsync/**
08c4185261c17943cff6cc94522579696eeeb478vboxsync * Adds a certificate to a store.
08c4185261c17943cff6cc94522579696eeeb478vboxsync *
08c4185261c17943cff6cc94522579696eeeb478vboxsync * @returns true on success, false on failure (error message written).
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param dwDst The destination, like
08c4185261c17943cff6cc94522579696eeeb478vboxsync * CERT_SYSTEM_STORE_LOCAL_MACHINE or
08c4185261c17943cff6cc94522579696eeeb478vboxsync * CERT_SYSTEM_STORE_CURRENT_USER.
78a072e1b56619e3230735ae073668311232ec94vboxsync * @param pszStoreNm The store name.
08c4185261c17943cff6cc94522579696eeeb478vboxsync * @param kpCertBuf Buffer that contains a certificate
08c4185261c17943cff6cc94522579696eeeb478vboxsync * @param cbCertBuf Size of @param kpCertBuf in bytes
08c4185261c17943cff6cc94522579696eeeb478vboxsync */
08c4185261c17943cff6cc94522579696eeeb478vboxsyncbool addCertToStore(DWORD dwDst, const char *pszStoreNm, const unsigned char kpCertBuf[], DWORD cbCertBuf)
78a072e1b56619e3230735ae073668311232ec94vboxsync{
08c4185261c17943cff6cc94522579696eeeb478vboxsync /*
08c4185261c17943cff6cc94522579696eeeb478vboxsync * Get certificate from buffer.
78a072e1b56619e3230735ae073668311232ec94vboxsync */
08c4185261c17943cff6cc94522579696eeeb478vboxsync PCCERT_CONTEXT pSrcCtx = NULL;
08c4185261c17943cff6cc94522579696eeeb478vboxsync bool fRc = false;
78a072e1b56619e3230735ae073668311232ec94vboxsync
08c4185261c17943cff6cc94522579696eeeb478vboxsync if (!readCertBuf(kpCertBuf, cbCertBuf, &pSrcCtx))
08c4185261c17943cff6cc94522579696eeeb478vboxsync {
08c4185261c17943cff6cc94522579696eeeb478vboxsync RTMsgError("Unable to get certificate context: %d", GetLastError());
08c4185261c17943cff6cc94522579696eeeb478vboxsync return fRc;
08c4185261c17943cff6cc94522579696eeeb478vboxsync }
08c4185261c17943cff6cc94522579696eeeb478vboxsync
08c4185261c17943cff6cc94522579696eeeb478vboxsync /*
08c4185261c17943cff6cc94522579696eeeb478vboxsync * Open the certificates store.
08c4185261c17943cff6cc94522579696eeeb478vboxsync */
08c4185261c17943cff6cc94522579696eeeb478vboxsync HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
08c4185261c17943cff6cc94522579696eeeb478vboxsync if (hDstStore)
78a072e1b56619e3230735ae073668311232ec94vboxsync {
08c4185261c17943cff6cc94522579696eeeb478vboxsync /*
08c4185261c17943cff6cc94522579696eeeb478vboxsync * Finally, add certificate to store
08c4185261c17943cff6cc94522579696eeeb478vboxsync */
08c4185261c17943cff6cc94522579696eeeb478vboxsync if (CertAddCertificateContextToStore(hDstStore, pSrcCtx, CERT_STORE_ADD_REPLACE_EXISTING, NULL))
08c4185261c17943cff6cc94522579696eeeb478vboxsync fRc = true;
08c4185261c17943cff6cc94522579696eeeb478vboxsync else
08c4185261c17943cff6cc94522579696eeeb478vboxsync RTMsgError("Unable to install certificate: %d", GetLastError());
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
78a072e1b56619e3230735ae073668311232ec94vboxsync }
78a072e1b56619e3230735ae073668311232ec94vboxsync else
78a072e1b56619e3230735ae073668311232ec94vboxsync RTMsgError("Unable to open certificates store: %d", GetLastError());
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync /* Release resources */
78a072e1b56619e3230735ae073668311232ec94vboxsync CertFreeCertificateContext(pSrcCtx);
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync return fRc;
78a072e1b56619e3230735ae073668311232ec94vboxsync}
78a072e1b56619e3230735ae073668311232ec94vboxsync