VirtualBox

Ignore:
Timestamp:
Jan 11, 2012 1:57:34 PM (13 years ago)
Author:
vboxsync
Message:

VBoxCertUtil.cpp: More useful code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/tools/VBoxCertUtil.cpp

    r39733 r39746  
    77#include <Wincrypt.h>
    88
     9#include <iprt/buildconfig.h>
    910#include <iprt/err.h>
    1011#include <iprt/file.h>
     12#include <iprt/getopt.h>
    1113#include <iprt/initterm.h>
    1214#include <iprt/message.h>
    1315#include <iprt/stream.h>
    1416#include <iprt/string.h>
     17#include <iprt/time.h>
     18
     19
     20/*******************************************************************************
     21*   Global Variables                                                           *
     22*******************************************************************************/
     23/** The verbosity level. */
     24static unsigned  g_cVerbosityLevel = 1;
     25
    1526
    1627static const char *errorToString(DWORD dwErr)
     
    7384        default:
    7485        {
     86            PCRTCOMERRMSG pWinComMsg = RTErrCOMGet(dwErr);
     87            if (pWinComMsg)
     88                return pWinComMsg->pszDefine;
     89
    7590            static char s_szErr[32];
    76             RTStrPrintf(s_szErr, sizeof(s_szErr), "#x (%d)", dwErr, dwErr);
     91            RTStrPrintf(s_szErr, sizeof(s_szErr), "%#x (%d)", dwErr, dwErr);
    7792            return s_szErr;
    7893        }
     
    8095}
    8196
     97#if 0 /* hacking */
    8298static RTEXITCODE addToStore(const char *pszFilename, PCRTUTF16 pwszStore)
    8399{
     
    137153        }
    138154        else
    139             RTMsgError("CertOpenStoreW returned %s", errorToString(GetLastError()));
     155            RTMsgError("CertOpenStore returned %s", errorToString(GetLastError()));
    140156        CertFreeCertificateContext(pCertCtx);
    141157    }
     
    154170#endif
    155171}
     172#endif /* hacking */
     173
     174
     175/**
     176 * Reads a certificate from a file, returning a context or a the handle to a
     177 * temporary memory store.
     178 *
     179 * @returns true on success, false on failure (error message written).
     180 * @param   pszCertFile         The name of the file containing the
     181 *                              certificates.
     182 * @param   ppOutCtx            Where to return the certificate context.
     183 * @param   phSrcStore          Where to return the handle to the temporary
     184 *                              memory store.
     185 */
     186static bool readCertFile(const char *pszCertFile, PCCERT_CONTEXT *ppOutCtx, HCERTSTORE *phSrcStore)
     187{
     188    *ppOutCtx   = NULL;
     189    *phSrcStore = NULL;
     190
     191    bool    fRc = false;
     192    void   *pvFile;
     193    size_t  cbFile;
     194    int rc = RTFileReadAll(pszCertFile, &pvFile, &cbFile);
     195    if (RT_SUCCESS(rc))
     196    {
     197        *ppOutCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
     198                                                 (PBYTE)pvFile, (DWORD)cbFile);
     199        if (*ppOutCtx)
     200            rc = true;
     201        else
     202        {
     203            /** @todo figure out if it's some other format... */
     204            RTMsgError("CertCreateCertificateContext returned %s parsing the content of '%s'",
     205                       errorToString(GetLastError()), pszCertFile);
     206        }
     207    }
     208    else
     209        RTMsgError("RTFileReadAll failed on '%s': %Rrc", pszCertFile, rc);
     210    RTFileReadAllFree(pvFile, cbFile);
     211    return fRc;
     212}
     213
     214
     215/**
     216 * Opens a certificate store.
     217 *
     218 * @returns true on success, false on failure (error message written).
     219 * @param   dwDst           The destination, like
     220 *                          CERT_SYSTEM_STORE_LOCAL_MACHINE or
     221 *                          ERT_SYSTEM_STORE_CURRENT_USER.
     222 * @param   pszStoreNm      The store name.
     223 */
     224static HCERTSTORE openCertStore(DWORD dwDst, const char *pszStoreNm)
     225{
     226    HCERTSTORE hStore = NULL;
     227    PRTUTF16   pwszStoreNm;
     228    int rc = RTStrToUtf16(pszStoreNm, &pwszStoreNm);
     229    if (RT_SUCCESS(rc))
     230    {
     231        if (g_cVerbosityLevel > 1)
     232            RTMsgInfo("Opening store %#x:'%s'", dwDst, pszStoreNm);
     233
     234        hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
     235                               PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
     236                               NULL /* hCryptProv = default */,
     237                               dwDst | CERT_STORE_OPEN_EXISTING_FLAG,
     238                               pwszStoreNm);
     239        if (hStore == NULL)
     240            RTMsgError("CertOpenStore failed opening %#x:'%s': %s",
     241                       dwDst, pszStoreNm, errorToString(GetLastError()));
     242
     243        RTUtf16Free(pwszStoreNm);
     244    }
     245    return hStore;
     246}
     247
     248
     249/**
     250 * Adds a certificate to a store.
     251 *
     252 * @returns true on success, false on failure (error message written).
     253 * @param   dwDst           The destination, like
     254 *                          CERT_SYSTEM_STORE_LOCAL_MACHINE or
     255 *                          ERT_SYSTEM_STORE_CURRENT_USER.
     256 * @param   pszStoreNm      The store name.
     257 * @param   pszCertFile     The file containing the certificate to add.
     258 * @param   dwDisposition   The disposition towards existing certificates when
     259 *                          adding it.  CERT_STORE_ADD_NEW is a safe one.
     260 */
     261static bool addCertToStore(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile, DWORD dwDisposition)
     262{
     263    /*
     264     * Read the certificate file first.
     265     */
     266    PCCERT_CONTEXT  pSrcCtx   = NULL;
     267    HCERTSTORE      hSrcStore = NULL;
     268    if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
     269        return false;
     270
     271    /*
     272     * Open the destination store.
     273     */
     274    bool fRc = false;
     275    HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
     276    if (hDstStore)
     277    {
     278        if (pSrcCtx)
     279        {
     280            if (g_cVerbosityLevel > 1)
     281                RTMsgInfo("Adding '%s' to %#x:'%s'... (disp %d)", pszCertFile, dwDst, pszStoreNm, dwDisposition);
     282
     283            if (CertAddCertificateContextToStore(hDstStore, pSrcCtx, dwDisposition, NULL))
     284                fRc = true;
     285            else
     286                RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
     287        }
     288        else
     289        {
     290            RTMsgError("Path not implemented at line %d\n",  __LINE__);
     291        }
     292
     293        CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
     294    }
     295    if (pSrcCtx)
     296        CertFreeCertificateContext(pSrcCtx);
     297    if (hSrcStore)
     298        CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
     299    return fRc;
     300}
     301
     302/**
     303 * Worker for cmdDisplayAll.
     304 */
     305static BOOL WINAPI displaySystemStoreCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo,
     306                                              void *pvReserved, void *pvArg)
     307{
     308    if (g_cVerbosityLevel > 1)
     309        RTPrintf("    pvSystemStore=%p dwFlags=%#x pStoreInfo=%p pvReserved=%p\n", pvSystemStore, dwFlags, pStoreInfo, pvReserved);
     310    LPCWSTR pwszStoreNm = NULL;
     311    if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
     312    {
     313        const CERT_SYSTEM_STORE_RELOCATE_PARA *pRelPara = (const CERT_SYSTEM_STORE_RELOCATE_PARA *)pvSystemStore;
     314        pwszStoreNm = pRelPara->pwszSystemStore;
     315        RTPrintf("    %#010x '%ls' hKeyBase=%p\n", dwFlags, pwszStoreNm, pRelPara->hKeyBase);
     316    }
     317    else
     318    {
     319        pwszStoreNm = (LPCWSTR)pvSystemStore;
     320        RTPrintf("    %#010x '%ls'\n", dwFlags, pwszStoreNm);
     321    }
     322
     323    /*
     324     * Open the store and list the certificates within.
     325     */
     326    DWORD      dwDst  = (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK);
     327    HCERTSTORE hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
     328                                      PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
     329                                      NULL /* hCryptProv = default */,
     330                                      dwDst | CERT_STORE_OPEN_EXISTING_FLAG,
     331                                      pwszStoreNm);
     332    if (hStore)
     333    {
     334        PCCERT_CONTEXT pCertCtx = NULL;
     335        while ((pCertCtx = CertEnumCertificatesInStore(hStore, pCertCtx)) != NULL)
     336        {
     337            if (g_cVerbosityLevel > 1)
     338                RTPrintf("        pCertCtx=%p dwCertEncodingType=%#x cbCertEncoded=%#x pCertInfo=%p\n",
     339                         pCertCtx, pCertCtx->dwCertEncodingType, pCertCtx->cbCertEncoded, pCertCtx->pCertInfo);
     340            WCHAR wszName[1024];
     341            if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/,
     342                                   wszName, sizeof(wszName)))
     343            {
     344                RTPrintf("        '%ls'\n", wszName);
     345                if (pCertCtx->pCertInfo)
     346                {
     347                    RTTIMESPEC TmpTS;
     348                    char  szNotBefore[80];
     349                    RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotBefore),
     350                                       szNotBefore, sizeof(szNotBefore));
     351                    char  szNotAfter[80];
     352                    RTTimeSpecToString(RTTimeSpecSetNtFileTime(&TmpTS, &pCertCtx->pCertInfo->NotAfter),
     353                                       szNotAfter, sizeof(szNotAfter));
     354
     355                    RTPrintf("            NotBefore='%s'\n", szNotBefore);
     356                    RTPrintf("            NotAfter ='%s'\n", szNotAfter);
     357                    if (pCertCtx->pCertInfo->Issuer.cbData)
     358                    {
     359                        if (CertGetNameStringW(pCertCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL /*pvTypePara*/,
     360                                               wszName, sizeof(wszName)))
     361                            RTPrintf("            Issuer='%ls'\n", wszName);
     362                        else
     363                            RTMsgError("CertGetNameStringW(Issuer) failed: %s\n", errorToString(GetLastError()));
     364                    }
     365                }
     366            }
     367            else
     368                RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError()));
     369
     370        }
     371
     372        CertCloseStore(hStore, CERT_CLOSE_STORE_CHECK_FLAG);
     373    }
     374    else
     375        RTMsgError("CertOpenStore failed opening %#x:'%ls': %s\n", dwDst, pwszStoreNm, errorToString(GetLastError()));
     376
     377    return TRUE;
     378}
     379
     380/**
     381 * Worker for cmdDisplayAll.
     382 */
     383static BOOL WINAPI displaySystemStoreLocation(LPCWSTR pwszStoreLocation, DWORD dwFlags, void *pvReserved, void *pvArg)
     384{
     385    NOREF(pvReserved); NOREF(pvArg);
     386    RTPrintf("System store location: %#010x '%ls'\n", dwFlags, pwszStoreLocation);
     387    if (!CertEnumSystemStore(dwFlags, NULL, NULL /*pvArg*/, displaySystemStoreCallback))
     388        RTMsgError("CertEnumSystemStore failed on %#x:'%ls': %s\n",
     389                   dwFlags, pwszStoreLocation, errorToString(GetLastError()));
     390
     391    return TRUE;
     392}
     393
     394/**
     395 * Handler for the 'display-all' command.
     396 */
     397static RTEXITCODE cmdDisplayAll(int argc, char **argv)
     398{
     399    if (argc != 1)
     400        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "the display-all command takes no arguments\n");
     401
     402    if (!CertEnumSystemStoreLocation(0, NULL /*pvArg*/, displaySystemStoreLocation))
     403        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "CertEnumSystemStoreLocation failed: %s\n", errorToString(GetLastError()));
     404
     405    return RTEXITCODE_SUCCESS;
     406}
     407
     408/**
     409 * Handler for the 'add-trusted-publisher' command.
     410 */
     411static RTEXITCODE cmdAddTrustedPublisher(int argc, char **argv)
     412{
     413    /*
     414     * Parse arguments.
     415     */
     416    static const RTGETOPTDEF s_aOptions[] =
     417    {
     418        { "--root",     'r',    RTGETOPT_REQ_STRING },
     419    };
     420
     421    const char *pszRootCert    = NULL;
     422    const char *pszTrustedCert = NULL;
     423
     424    int             rc;
     425    RTGETOPTUNION   ValueUnion;
     426    RTGETOPTSTATE   GetState;
     427    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
     428    while ((rc = RTGetOpt(&GetState, &ValueUnion)))
     429    {
     430        switch (rc)
     431        {
     432            case 'h':
     433                RTPrintf("Usage: VBoxCertUtil add-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
     434                break;
     435
     436            case 'V':
     437                RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
     438                return RTEXITCODE_SUCCESS;
     439
     440            case 'r':
     441                if (pszRootCert)
     442                    return RTMsgErrorExit(RTEXITCODE_SUCCESS,
     443                                          "You've already specified '%s' as root certificate.",
     444                                          pszRootCert);
     445                pszRootCert = ValueUnion.psz;
     446                break;
     447
     448            case VINF_GETOPT_NOT_OPTION:
     449                if (pszTrustedCert)
     450                    return RTMsgErrorExit(RTEXITCODE_SUCCESS,
     451                                          "You've already specified '%s' as trusted certificate.",
     452                                          pszRootCert);
     453                pszTrustedCert = ValueUnion.psz;
     454                break;
     455
     456            default:
     457                return RTGetOptPrintError(rc, &ValueUnion);
     458        }
     459    }
     460    if (!pszTrustedCert)
     461        return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No trusted certificate specified.");
     462
     463    /*
     464     * Do the job.
     465     */
     466    if (   pszRootCert
     467        && !addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", pszRootCert, CERT_STORE_ADD_NEW))
     468        return RTEXITCODE_FAILURE;
     469    if (!addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", pszTrustedCert, CERT_STORE_ADD_NEW))
     470        return RTEXITCODE_FAILURE;
     471
     472    if (g_cVerbosityLevel > 0)
     473    {
     474        if (pszRootCert)
     475            RTMsgInfo("Successfully added '%s' as root and '%s' as trusted publisher", pszRootCert, pszTrustedCert);
     476        else
     477            RTMsgInfo("Successfully added '%s' as trusted publisher", pszTrustedCert);
     478    }
     479    return RTEXITCODE_SUCCESS;
     480}
    156481
    157482
     
    162487        return RTMsgInitFailure(rc);
    163488
    164 
    165     RTEXITCODE rcExit;
    166 
    167     rcExit = addToStore("my", L"my");
    168 
    169     return rcExit;
    170 }
     489    /*
     490     * Parse arguments up to the command and pass it on to the command handlers.
     491     */
     492    typedef enum
     493    {
     494        VCUACTION_ADD_TRUSTED_PUBLISHER = 1000,
     495        VCUACTION_DISPLAY_ALL,
     496        VCUACTION_END
     497    } VCUACTION;
     498
     499    static const RTGETOPTDEF s_aOptions[] =
     500    {
     501        { "--verbose",              'v',                                RTGETOPT_REQ_NOTHING },
     502        { "--quiet",                'q',                                RTGETOPT_REQ_NOTHING },
     503        { "add-trusted-publisher",  VCUACTION_ADD_TRUSTED_PUBLISHER,    RTGETOPT_REQ_NOTHING },
     504        { "display-all",            VCUACTION_DISPLAY_ALL,              RTGETOPT_REQ_NOTHING },
     505    };
     506
     507    RTGETOPTUNION   ValueUnion;
     508    RTGETOPTSTATE   GetState;
     509    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
     510    while ((rc = RTGetOpt(&GetState, &ValueUnion)))
     511    {
     512        switch (rc)
     513        {
     514            case 'v':
     515                g_cVerbosityLevel++;
     516                break;
     517
     518            case 'q':
     519                if (g_cVerbosityLevel > 0)
     520                    g_cVerbosityLevel--;
     521                break;
     522
     523            case 'h':
     524                RTPrintf("Usage: TODO\n");
     525                break;
     526
     527            case 'V':
     528                RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
     529                return RTEXITCODE_SUCCESS;
     530
     531            case VCUACTION_ADD_TRUSTED_PUBLISHER:
     532                return cmdAddTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
     533
     534            case VCUACTION_DISPLAY_ALL:
     535                return cmdDisplayAll(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
     536
     537            default:
     538                return RTGetOptPrintError(rc, &ValueUnion);
     539        }
     540    }
     541
     542    RTMsgError("Missing command...\n");
     543    return RTEXITCODE_SYNTAX;
     544}
     545
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette