VirtualBox

Ignore:
Timestamp:
Sep 10, 2022 3:46:13 AM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
153568
Message:

Add/Nt/CertUtil: Added a root-exist command for checking if a certificate is found in the root store. Also added separate commands for adding and removing root certificates and did some general structure improvements. bugref:10261

File:
1 edited

Legend:

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

    r96407 r96685  
    4040#include <iprt/message.h>
    4141#include <iprt/path.h>
     42#include <iprt/process.h>
    4243#include <iprt/stream.h>
    4344#include <iprt/string.h>
    4445#include <iprt/time.h>
    4546#include <iprt/utf16.h>
     47
     48
     49/*********************************************************************************************************************************
     50*   Defined Constants And Macros                                                                                                 *
     51*********************************************************************************************************************************/
     52#define VCU_COMMON_OPTION_DEFINITIONS() \
     53        { "--verbose",                  'v',                                RTGETOPT_REQ_NOTHING }, \
     54        { "--quiet",                    'q',                                RTGETOPT_REQ_NOTHING }
     55
     56#define VCU_COMMON_OPTION_HANDLING() \
     57            case 'v': \
     58                g_cVerbosityLevel++; \
     59                break; \
     60            \
     61            case 'q': \
     62                if (g_cVerbosityLevel > 0) \
     63                    g_cVerbosityLevel--; \
     64                break; \
     65            \
     66            case 'V': \
     67                return displayVersion()
     68
    4669
    4770
     
    120143}
    121144
     145
     146/**
     147 * Deals with -V and --version.
     148 */
     149static RTEXITCODE displayVersion(void)
     150{
     151    RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
     152    return RTEXITCODE_SUCCESS;
     153}
     154
     155
    122156#if 0 /* hacking */
    123157static RTEXITCODE addToStore(const char *pszFilename, PCRTUTF16 pwszStore)
     
    283317}
    284318
     319
     320/**
     321 * Worker for 'root-exists', searching by exact relative distinguished name.
     322 */
     323static RTEXITCODE checkIfCertExistsInStoreByRdn(DWORD dwStore, const char *pszStoreNm, const char *pszStoreDesc,
     324                                                const char *pszName, RTEXITCODE rcExit, uint32_t *pcFound)
     325{
     326    /*
     327     * Convert the name into something that can be searched for.
     328     */
     329    PRTUTF16 pwszName = NULL;
     330    int rc = RTStrToUtf16(pszName, &pwszName);
     331    if (RT_FAILURE(rc))
     332        return RTMsgErrorExitFailure("RTStrToUtf16 failed: %Rrc", rc);
     333
     334
     335    BYTE            abNameBuf[16384]; /* this should be more than sufficient... */
     336    CERT_NAME_BLOB  NameBlob = { sizeof(abNameBuf), abNameBuf };
     337    PCRTUTF16       pwszErr  = NULL;
     338    if (CertStrToNameW(X509_ASN_ENCODING, pwszName, CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG, NULL /*pvReserved*/,
     339                       NameBlob.pbData, &NameBlob.cbData, &pwszErr))
     340    {
     341        /*
     342         * Now perform the search.
     343         */
     344        HCERTSTORE hDstStore = openCertStore(dwStore, pszStoreNm);
     345        if (hDstStore)
     346        {
     347            uint32_t        cFound  = 0;
     348            uint32_t        idxCur  = 0;
     349            PCCERT_CONTEXT  pCurCtx = NULL;
     350            while ((pCurCtx = CertEnumCertificatesInStore(hDstStore, pCurCtx)) != NULL)
     351            {
     352                if (pCurCtx->pCertInfo)
     353                {
     354                    if (g_cVerbosityLevel > 1)
     355                    {
     356                        WCHAR wszCurName[1024];
     357                        if (CertNameToStrW(X509_ASN_ENCODING, &pCurCtx->pCertInfo->Subject,
     358                                           CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
     359                                           wszCurName, sizeof(wszCurName)))
     360                            RTMsgInfo("Considering #%u: '%ls' ...", idxCur, wszCurName);
     361                        else
     362                            RTMsgInfo("Considering #%u: CertNameToStrW -> %u ...", idxCur, GetLastError());
     363                    }
     364
     365                    if (CertCompareCertificateName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &pCurCtx->pCertInfo->Subject, &NameBlob))
     366                    {
     367                        if (g_cVerbosityLevel > 0)
     368                            RTMsgInfo("Found '%ls' in the %s store...", pwszName, pszStoreDesc);
     369                        cFound++;
     370                    }
     371                }
     372                idxCur++;
     373            }
     374
     375            *pcFound += cFound;
     376            if (!cFound && g_cVerbosityLevel > 0)
     377                RTMsgInfo("Certificate with subject '%ls' was _NOT_ found in the %s store.", pwszName, pszStoreDesc);
     378
     379            CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
     380        }
     381        else
     382            rcExit = RTEXITCODE_FAILURE;
     383    }
     384    else
     385        rcExit = RTMsgErrorExitFailure("CertStrToNameW failed at position %zu: %s\n"
     386                                       " '%ls'\n"
     387                                       "  %*s",
     388                                       pwszErr - pwszName, errorToString(GetLastError()), pwszName, pwszErr - pwszName, "^");
     389    RTUtf16Free(pwszName);
     390    return rcExit;
     391}
     392
     393
    285394/**
    286395 * Removes a certificate, given by file, from a store
    287396 *
    288  * @returns true on success, false on failure (error message written).
     397 * @returns Command exit code.
    289398 * @param   dwDst           The destination, like
    290399 *                          CERT_SYSTEM_STORE_LOCAL_MACHINE or
    291400 *                          CERT_SYSTEM_STORE_CURRENT_USER.
    292401 * @param   pszStoreNm      The store name.
     402 * @param   pszStoreDesc    The store descriptor (all lower case).
    293403 * @param   pszCertFile     The file containing the certificate to add.
    294  */
    295 static bool removeCertFromStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile)
    296 {
    297     /*
    298      * Read the certificate file first.
     404 * @param   rcExit          Incoming exit status.
     405 */
     406static RTEXITCODE removeCertFromStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszStoreDesc,
     407                                            const char *pszCertFile, RTEXITCODE rcExit)
     408{
     409    /*
     410     * Read the certificate file first and get the certificate name from it.
    299411     */
    300412    PCCERT_CONTEXT  pSrcCtx   = NULL;
    301413    HCERTSTORE      hSrcStore = NULL;
    302414    if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
    303         return false;
     415        return RTEXITCODE_FAILURE;
    304416
    305417    WCHAR wszName[1024];
     
    314426     * Open the destination store.
    315427     */
    316     bool fRc = false;
    317428    HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
    318429    if (hDstStore)
     
    320431        if (pSrcCtx)
    321432        {
    322             fRc = true;
    323433            unsigned        cDeleted = 0;
    324434            PCCERT_CONTEXT  pCurCtx  = NULL;
     
    333443                    {
    334444                        if (CertDeleteCertificateFromStore(pDeleteCtx))
     445                        {
    335446                            cDeleted++;
     447                            if (g_cVerbosityLevel > 0)
     448                                RTMsgInfo("Successfully removed '%s' ('%ls') from the %s store", pszCertFile, wszName, pszStoreDesc);
     449                        }
    336450                        else
    337                             RTMsgError("CertDeleteFromStore('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
     451                            rcExit = RTMsgErrorExitFailure("CertDeleteFromStore('%ls') failed: %s\n",
     452                                                           wszName, errorToString(GetLastError()));
    338453                    }
    339454                    else
    340                         RTMsgError("CertDuplicateCertificateContext('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
     455                        rcExit = RTMsgErrorExitFailure("CertDuplicateCertificateContext('%ls') failed: %s\n",
     456                                                       wszName, errorToString(GetLastError()));
    341457                }
    342458            }
     
    346462        }
    347463        else
    348         {
    349             RTMsgError("Path not implemented at line %d\n",  __LINE__);
    350         }
     464            rcExit = RTMsgErrorExitFailure("Code path not implemented at line %d\n",  __LINE__);
     465
    351466
    352467        CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
    353468    }
     469    else
     470        rcExit = RTEXITCODE_FAILURE;
    354471    if (pSrcCtx)
    355472        CertFreeCertificateContext(pSrcCtx);
    356473    if (hSrcStore)
    357474        CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
    358     return fRc;
    359 }
     475    return rcExit;
     476}
     477
    360478
    361479/**
     
    371489 *                          adding it.  CERT_STORE_ADD_NEW is a safe one.
    372490 */
    373 static bool addCertToStore(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile, DWORD dwDisposition)
     491static bool addCertToStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile, DWORD dwDisposition)
    374492{
    375493    /*
     
    399517        }
    400518        else
    401             RTMsgError("Path not implemented at line %d\n",  __LINE__);
     519            RTMsgError("Code path not implemented at line %d\n",  __LINE__);
    402520
    403521        CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
     
    409527    return fRc;
    410528}
     529
     530
     531/**
     532 * Handle adding one or more certificates to a store.
     533 */
     534static RTEXITCODE addCertToStoreByFilePattern(DWORD dwDst, const char *pszStoreNm, const char *pszStoreDesc,
     535                                              const char *pszFilePattern, RTEXITCODE rcExit, uint32_t *pcImports)
     536{
     537    PCRTPATHGLOBENTRY pResultHead;
     538    int rc = RTPathGlob(pszFilePattern, RTPATHGLOB_F_NO_DIRS, &pResultHead, NULL);
     539    if (RT_SUCCESS(rc))
     540    {
     541        for (PCRTPATHGLOBENTRY pCur = pResultHead; pCur; pCur = pCur->pNext)
     542        {
     543            if (addCertToStoreByFile(dwDst, pszStoreNm, pCur->szPath, CERT_STORE_ADD_NEW))
     544                RTMsgInfo("Successfully added '%s' as %s", pCur->szPath, pszStoreDesc);
     545            else
     546                rcExit = RTEXITCODE_FAILURE;
     547            *pcImports += 1;
     548        }
     549        RTPathGlobFree(pResultHead);
     550    }
     551    else
     552    {
     553        rcExit = RTMsgErrorExit(RTEXITCODE_SUCCESS, "glob failed on '%s': %Rrc", pszFilePattern, rc);
     554        *pcImports += 1;
     555    }
     556    return rcExit;
     557}
     558
    411559
    412560/**
     
    489637}
    490638
     639
    491640/**
    492641 * Worker for cmdDisplayAll.
     
    504653}
    505654
     655
    506656/**
    507657 * Handler for the 'display-all' command.
     
    509659static RTEXITCODE cmdDisplayAll(int argc, char **argv)
    510660{
    511     RT_NOREF(argv);
    512     if (argc != 1)
    513         return RTMsgErrorExit(RTEXITCODE_SYNTAX, "the display-all command takes no arguments\n");
    514 
    515     if (!CertEnumSystemStoreLocation(0, NULL /*pvArg*/, displaySystemStoreLocation))
    516         return RTMsgErrorExit(RTEXITCODE_SYNTAX, "CertEnumSystemStoreLocation failed: %s\n", errorToString(GetLastError()));
    517 
    518     return RTEXITCODE_SUCCESS;
    519 }
    520 
    521 /**
    522  * Handler for the 'remove-trusted-publisher' command.
    523  */
    524 static RTEXITCODE cmdRemoveTrustedPublisher(int argc, char **argv)
    525 {
    526661    /*
    527662     * Parse arguments.
     
    529664    static const RTGETOPTDEF s_aOptions[] =
    530665    {
    531         { "--root",     'r',    RTGETOPT_REQ_STRING },
     666        VCU_COMMON_OPTION_DEFINITIONS(),
    532667    };
    533 
    534     const char *pszRootCert    = NULL;
    535     const char *pszTrustedCert = NULL;
    536668
    537669    int             rc;
     
    543675        switch (rc)
    544676        {
     677            VCU_COMMON_OPTION_HANDLING();
     678
     679            case 'h':
     680                RTPrintf("Usage: VBoxCertUtil display-all [-v|--verbose] [-q|--quiet]\n");
     681                return RTEXITCODE_SUCCESS;
     682
     683            default:
     684                return RTGetOptPrintError(rc, &ValueUnion);
     685        }
     686    }
     687
     688    /*
     689     * Do the enumerating.
     690     */
     691    if (!CertEnumSystemStoreLocation(0, NULL /*pvArg*/, displaySystemStoreLocation))
     692        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "CertEnumSystemStoreLocation failed: %s\n", errorToString(GetLastError()));
     693    return RTEXITCODE_SUCCESS;
     694}
     695
     696
     697/**
     698 * Handler for the 'root-exists' command.
     699 */
     700static RTEXITCODE cmdRootExists(int argc, char **argv)
     701{
     702    /*
     703     * Parse arguments.
     704     */
     705    static const RTGETOPTDEF s_aOptions[] =
     706    {
     707        VCU_COMMON_OPTION_DEFINITIONS(),
     708    };
     709
     710    RTEXITCODE      rcExit    = RTEXITCODE_SUCCESS;
     711    uint32_t        cFound    = 0;
     712    uint32_t        cSearched = 0;
     713
     714    int             rc;
     715    RTGETOPTUNION   ValueUnion;
     716    RTGETOPTSTATE   GetState;
     717    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
     718    while ((rc = RTGetOpt(&GetState, &ValueUnion)))
     719    {
     720        switch (rc)
     721        {
     722            VCU_COMMON_OPTION_HANDLING();
     723
     724            case 'h':
     725                RTPrintf("Usage: VBoxCertUtil root-exists <full-subject-name> [alternative-subject-name [...]]\n"
     726                         "\n"
     727                         "Exit code: 10 if not found, 0 if found.\n"
     728                         "\n"
     729                         "The names are on the form 'C=US; O=Company; OU=some unit; CN=a cert name'\n"
     730                         "where semi-colon is the X.500 attribute separator and spaces surrounding it\n"
     731                         "the type (CN, OU, ) and '=' are generally ignored.\n"
     732                         "\n"
     733                         "At verbosity level 2, the full subject name of each certificate in the store\n"
     734                         "will be listed as the search progresses.  These can be used as search input.\n"
     735                         );
     736                return RTEXITCODE_SUCCESS;
     737
     738            case VINF_GETOPT_NOT_OPTION:
     739                rcExit = checkIfCertExistsInStoreByRdn(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", "root",
     740                                                       ValueUnion.psz, rcExit, &cFound);
     741                cSearched++;
     742                break;
     743
     744            default:
     745                return RTGetOptPrintError(rc, &ValueUnion);
     746        }
     747    }
     748
     749    if (!cSearched)
     750        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "No certificate name specified.");
     751    return cFound ? RTEXITCODE_SUCCESS : rcExit == RTEXITCODE_SUCCESS ? (RTEXITCODE)10 : rcExit;
     752}
     753
     754
     755
     756/**
     757 * Handler for the 'remove-root' command.
     758 */
     759static RTEXITCODE cmdRemoveRoot(int argc, char **argv)
     760{
     761    /*
     762     * Parse arguments.
     763     */
     764    static const RTGETOPTDEF s_aOptions[] =
     765    {
     766        VCU_COMMON_OPTION_DEFINITIONS(),
     767    };
     768
     769    RTEXITCODE      rcExit = RTEXITCODE_SUCCESS;
     770    uint32_t        cRemoved = 0;
     771
     772    int             rc;
     773    RTGETOPTUNION   ValueUnion;
     774    RTGETOPTSTATE   GetState;
     775    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
     776    while ((rc = RTGetOpt(&GetState, &ValueUnion)))
     777    {
     778        switch (rc)
     779        {
     780            VCU_COMMON_OPTION_HANDLING();
     781
     782            case 'h':
     783                RTPrintf("Usage: VBoxCertUtil remove-root <root-cert-file>\n");
     784                return RTEXITCODE_SUCCESS;
     785
     786            case VINF_GETOPT_NOT_OPTION:
     787                rcExit = removeCertFromStoreByFile(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", "root", ValueUnion.psz, rcExit);
     788                cRemoved++;
     789                break;
     790
     791            default:
     792                return RTGetOptPrintError(rc, &ValueUnion);
     793        }
     794    }
     795    if (!cRemoved)
     796        return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No certificate specified.");
     797    return rcExit;
     798}
     799
     800
     801/**
     802 * Handler for the 'remove-trusted-publisher' command.
     803 */
     804static RTEXITCODE cmdRemoveTrustedPublisher(int argc, char **argv)
     805{
     806    /*
     807     * Parse arguments.
     808     */
     809    static const RTGETOPTDEF s_aOptions[] =
     810    {
     811        { "--root",     'r',    RTGETOPT_REQ_STRING },
     812        VCU_COMMON_OPTION_DEFINITIONS(),
     813    };
     814
     815    RTEXITCODE      rcExit = RTEXITCODE_SUCCESS;
     816    uint32_t        cRemoved = 0;
     817
     818    int             rc;
     819    RTGETOPTUNION   ValueUnion;
     820    RTGETOPTSTATE   GetState;
     821    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
     822    while ((rc = RTGetOpt(&GetState, &ValueUnion)))
     823    {
     824        switch (rc)
     825        {
     826            VCU_COMMON_OPTION_HANDLING();
     827
    545828            case 'h':
    546829                RTPrintf("Usage: VBoxCertUtil remove-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
     830                return RTEXITCODE_SUCCESS;
     831
     832            case 'r':
     833                rcExit = removeCertFromStoreByFile(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", "root", ValueUnion.psz, rcExit);
     834                cRemoved++;
    547835                break;
    548836
    549             case 'V':
    550                 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
    551                 return RTEXITCODE_SUCCESS;
    552 
    553             case 'r':
    554                 if (pszRootCert)
    555                     return RTMsgErrorExit(RTEXITCODE_SUCCESS,
    556                                           "You've already specified '%s' as root certificate.",
    557                                           pszRootCert);
    558                 pszRootCert = ValueUnion.psz;
    559                 break;
    560 
    561837            case VINF_GETOPT_NOT_OPTION:
    562                 if (pszTrustedCert)
    563                     return RTMsgErrorExit(RTEXITCODE_SUCCESS,
    564                                           "You've already specified '%s' as trusted certificate.",
    565                                           pszRootCert);
    566                 pszTrustedCert = ValueUnion.psz;
     838                rcExit = removeCertFromStoreByFile(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", "trusted publisher",
     839                                                   ValueUnion.psz, rcExit);
     840                cRemoved++;
    567841                break;
    568842
     
    571845        }
    572846    }
    573     if (!pszTrustedCert)
    574         return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No trusted certificate specified.");
    575 
    576     /*
    577      * Do the job.
    578      */
    579     if (   pszRootCert
    580         && !removeCertFromStoreByFile(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", pszRootCert))
    581         return RTEXITCODE_FAILURE;
    582     if (!removeCertFromStoreByFile(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", pszTrustedCert))
    583         return RTEXITCODE_FAILURE;
    584 
    585     if (g_cVerbosityLevel > 0)
    586     {
    587         if (pszRootCert)
    588             RTMsgInfo("Successfully removed '%s' as root and '%s' as trusted publisher", pszRootCert, pszTrustedCert);
    589         else
    590             RTMsgInfo("Successfully removed '%s' as trusted publisher", pszTrustedCert);
    591     }
    592     return RTEXITCODE_SUCCESS;
    593 }
    594 
    595 
    596 /**
    597  * Handler for the 'add-trusted-publisher' command.
    598  */
    599 static RTEXITCODE cmdAddTrustedPublisher(int argc, char **argv)
     847    if (!cRemoved)
     848        return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No certificate specified.");
     849    return rcExit;
     850}
     851
     852
     853/**
     854 * Handler for the 'add-root' command.
     855 */
     856static RTEXITCODE cmdAddRoot(int argc, char **argv)
    600857{
    601858    /*
     
    604861    static const RTGETOPTDEF s_aOptions[] =
    605862    {
    606         { "--root",     'r',    RTGETOPT_REQ_STRING },
     863        VCU_COMMON_OPTION_DEFINITIONS(),
    607864    };
    608865
     
    617874        switch (rc)
    618875        {
     876            VCU_COMMON_OPTION_HANDLING();
     877
    619878            case 'h':
    620                 RTPrintf("Usage: VBoxCertUtil add-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
     879                RTPrintf("Usage: VBoxCertUtil add-root <root-cert>\n");
     880                return RTEXITCODE_SUCCESS;
     881
     882            case VINF_GETOPT_NOT_OPTION:
     883                rcExit = addCertToStoreByFilePattern(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", "root",
     884                                                     ValueUnion.psz, rcExit, &cImports);
    621885                break;
    622 
    623             case 'V':
    624                 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
    625                 return RTEXITCODE_SUCCESS;
    626 
    627             case 'r':
    628             case VINF_GETOPT_NOT_OPTION:
    629             {
    630                 const char * const  pszStoreNm   = rc == 'r' ? "Root" : "TrustedPublisher";
    631                 const char * const  pszStoreDesc = rc == 'r' ? "root" : "trusted publisher";
    632                 PCRTPATHGLOBENTRY   pResultHead;
    633                 rc = RTPathGlob(ValueUnion.psz, RTPATHGLOB_F_NO_DIRS, &pResultHead, NULL);
    634                 if (RT_SUCCESS(rc))
    635                 {
    636                     for (PCRTPATHGLOBENTRY pCur = pResultHead; pCur; pCur = pCur->pNext)
    637                     {
    638                         if (addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, pszStoreNm, pCur->szPath, CERT_STORE_ADD_NEW))
    639                             RTMsgInfo("Successfully added '%s' as %s", pCur->szPath, pszStoreDesc);
    640                         else
    641                             rcExit = RTEXITCODE_FAILURE;
    642                         cImports++;
    643                     }
    644                     RTPathGlobFree(pResultHead);
    645                 }
    646                 else
    647                 {
    648                     rcExit = RTMsgErrorExit(RTEXITCODE_SUCCESS, "glob failed on '%s': %Rrc", ValueUnion.psz, rc);
    649                     cImports++;
    650                 }
    651                 break;
    652             }
    653886
    654887            default:
     
    663896
    664897/**
     898 * Handler for the 'add-trusted-publisher' command.
     899 */
     900static RTEXITCODE cmdAddTrustedPublisher(int argc, char **argv)
     901{
     902    /*
     903     * Parse arguments and execute imports as we move along.
     904     */
     905    static const RTGETOPTDEF s_aOptions[] =
     906    {
     907        { "--root",     'r',    RTGETOPT_REQ_STRING },
     908        VCU_COMMON_OPTION_DEFINITIONS(),
     909    };
     910
     911    RTEXITCODE          rcExit = RTEXITCODE_SUCCESS;
     912    unsigned            cImports = 0;
     913    RTGETOPTUNION       ValueUnion;
     914    RTGETOPTSTATE       GetState;
     915    int rc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
     916    AssertRC(rc);
     917    while ((rc = RTGetOpt(&GetState, &ValueUnion)))
     918    {
     919        switch (rc)
     920        {
     921            VCU_COMMON_OPTION_HANDLING();
     922
     923            case 'h':
     924                RTPrintf("Usage: VBoxCertUtil add-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
     925                return RTEXITCODE_SUCCESS;
     926
     927            case 'r':
     928                rcExit = addCertToStoreByFilePattern(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", "root",
     929                                                     ValueUnion.psz, rcExit, &cImports);
     930                break;
     931
     932            case VINF_GETOPT_NOT_OPTION:
     933                rcExit = addCertToStoreByFilePattern(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", "trusted publisher",
     934                                                     ValueUnion.psz, rcExit, &cImports);
     935                break;
     936
     937            default:
     938                return RTGetOptPrintError(rc, &ValueUnion);
     939        }
     940    }
     941    if (cImports == 0)
     942        return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No trusted or root certificates specified.");
     943    return rcExit;
     944}
     945
     946
     947/**
    665948 * Displays the usage info.
    666  * @param   argv0               Program name.
    667  */
    668 static void showUsage(const char *argv0)
    669 {
    670     RTPrintf("Usage: %Rbn [-v[v]] <command>\n"
     949 */
     950static void showUsage(void)
     951{
     952    const char * const pszShortNm = RTProcShortName();
     953    RTPrintf("Usage: %Rbn [-v[v]|--verbose] [-q[q]|--quiet] <command>\n"
    671954             "   or  %Rbn <-V|--version>\n"
    672955             "   or  %Rbn <-h|--help>\n"
    673956             "\n"
    674957             "Available commands:\n"
    675              "    add-trusted-publisher, remove-trusted-publisher,\n"
     958             "    add-trusted-publisher\n"
     959             "    add-root\n"
     960             "    remove-trusted-publisher\n"
     961             "    remove-root\n"
    676962             "    display-all\n"
    677              , argv0, argv0, argv0);
     963             , pszShortNm, pszShortNm, pszShortNm);
    678964}
    679965
     
    691977    {
    692978        VCUACTION_ADD_TRUSTED_PUBLISHER = 1000,
     979        VCUACTION_ADD_ROOT,
    693980        VCUACTION_REMOVE_TRUSTED_PUBLISHER,
     981        VCUACTION_REMOVE_ROOT,
     982        VCUACTION_ROOT_EXISTS,
    694983        VCUACTION_DISPLAY_ALL,
    695984        VCUACTION_END
     
    698987    static const RTGETOPTDEF s_aOptions[] =
    699988    {
    700         { "--verbose",                  'v',                                RTGETOPT_REQ_NOTHING },
    701         { "--quiet",                    'q',                                RTGETOPT_REQ_NOTHING },
    702989        { "add-trusted-publisher",      VCUACTION_ADD_TRUSTED_PUBLISHER,    RTGETOPT_REQ_NOTHING },
     990        { "add-root",                   VCUACTION_ADD_ROOT,                 RTGETOPT_REQ_NOTHING },
    703991        { "remove-trusted-publisher",   VCUACTION_REMOVE_TRUSTED_PUBLISHER, RTGETOPT_REQ_NOTHING },
     992        { "remove-root",                VCUACTION_REMOVE_ROOT,              RTGETOPT_REQ_NOTHING },
     993        { "root-exists",                VCUACTION_ROOT_EXISTS,              RTGETOPT_REQ_NOTHING },
    704994        { "display-all",                VCUACTION_DISPLAY_ALL,              RTGETOPT_REQ_NOTHING },
     995        VCU_COMMON_OPTION_DEFINITIONS(),
    705996    };
    706997
     
    7121003        switch (rc)
    7131004        {
    714             case 'v':
    715                 g_cVerbosityLevel++;
    716                 break;
    717 
    718             case 'q':
    719                 if (g_cVerbosityLevel > 0)
    720                     g_cVerbosityLevel--;
    721                 break;
    722 
    723             case 'h':
    724                 showUsage(argv[0]);
    725                 return RTEXITCODE_SUCCESS;
    726 
    727             case 'V':
    728                 RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
    729                 return RTEXITCODE_SUCCESS;
    730 
    7311005            case VCUACTION_ADD_TRUSTED_PUBLISHER:
    7321006                return cmdAddTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
    7331007
     1008            case VCUACTION_ADD_ROOT:
     1009                return cmdAddRoot(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
     1010
    7341011            case VCUACTION_REMOVE_TRUSTED_PUBLISHER:
    7351012                return cmdRemoveTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
    7361013
     1014            case VCUACTION_REMOVE_ROOT:
     1015                return cmdRemoveRoot(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
     1016
     1017            case VCUACTION_ROOT_EXISTS:
     1018                return cmdRootExists(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
     1019
    7371020            case VCUACTION_DISPLAY_ALL:
    7381021                return cmdDisplayAll(argc - GetState.iNext + 1, argv + GetState.iNext - 1);
    7391022
     1023            case 'h':
     1024                showUsage();
     1025                return RTEXITCODE_SUCCESS;
     1026
     1027            VCU_COMMON_OPTION_HANDLING();
     1028
    7401029            default:
    7411030                return RTGetOptPrintError(rc, &ValueUnion);
     
    7441033
    7451034    RTMsgError("Missing command...");
    746     showUsage(argv[0]);
     1035    showUsage();
    7471036    return RTEXITCODE_SYNTAX;
    7481037}
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