VirtualBox

Changeset 64848 in vbox


Ignore:
Timestamp:
Dec 13, 2016 1:57:59 PM (8 years ago)
Author:
vboxsync
Message:

RTSignTool: adding show-exe command (incomplete code)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/tools/RTSignTool.cpp

    r64731 r64848  
    4141#include <iprt/stream.h>
    4242#include <iprt/string.h>
     43#include <iprt/crypto/digest.h>
    4344#include <iprt/crypto/x509.h>
    4445#include <iprt/crypto/pkcs7.h>
    4546#include <iprt/crypto/store.h>
     47#include <iprt/crypto/spc.h>
    4648#ifdef VBOX
    4749# include <VBox/sup.h> /* Certificates */
     
    5860    RTSIGNTOOLHELP_FULL
    5961} RTSIGNTOOLHELP;
     62
     63
     64typedef struct SHOWEXEPKCS7
     65{
     66    uint8_t const              *pbBuf;
     67    size_t                      cbBuf;
     68    const char                 *pszFilename;
     69    unsigned                    cVerbosity;
     70    RTLDRMOD                    hLdrMod;
     71    /** The outer content info wrapper. */
     72    RTCRPKCS7CONTENTINFO        ContentInfo;
     73    /** Pointer to the decoded SignedData inside the ContentInfo member. */
     74    PRTCRPKCS7SIGNEDDATA        pSignedData;
     75    /** Pointer to the indirect data content. */
     76    PRTCRSPCINDIRECTDATACONTENT pIndData;
     77
     78    char                        szPrefix[256];
     79    char                        szTmp[4096];
     80} SHOWEXEPKCS7;
     81typedef SHOWEXEPKCS7 *PSHOWEXEPKCS7;
    6082
    6183
     
    6688static RTEXITCODE HelpHelp(PRTSTREAM pStrm, RTSIGNTOOLHELP enmLevel);
    6789static RTEXITCODE HandleVersion(int cArgs, char **papszArgs);
     90#ifndef IPRT_IN_BUILD_TOOL
     91static int HandleShowExeWorkerPkcs7Display(PSHOWEXEPKCS7 pThis, PRTCRPKCS7SIGNEDDATA pSignedData, size_t offPrefix);
     92#endif
    6893
    6994
     
    265290} VERIFYEXESTATE;
    266291
    267 #ifdef VBOX
     292# ifdef VBOX
    268293/** Certificate store load set.
    269294 * Declared outside HandleVerifyExe because of braindead gcc visibility crap. */
     
    274299    unsigned        cTAs;
    275300};
    276 #endif
     301# endif
    277302
    278303/**
     
    619644
    620645#endif /* !IPRT_IN_BUILD_TOOL */
     646////
     647#ifndef IPRT_IN_BUILD_TOOL
     648
     649/*
     650 * The 'show-exe' command.
     651 */
     652static RTEXITCODE HelpShowExe(PRTSTREAM pStrm, RTSIGNTOOLHELP enmLevel)
     653{
     654    RT_NOREF_PV(enmLevel);
     655    RTStrmPrintf(pStrm,
     656                 "show-exe [--verbose|-v] [--quiet|-q] <exe1> [exe2 [..]]\n");
     657    return RTEXITCODE_SUCCESS;
     658}
     659
     660
     661static int HandleShowExeWorkerPkcs7Decode(PSHOWEXEPKCS7 pThis)
     662{
     663    RTERRINFOSTATIC     ErrInfo;
     664    RTASN1CURSORPRIMARY PrimaryCursor;
     665    RTAsn1CursorInitPrimary(&PrimaryCursor, pThis->pbBuf, pThis->cbBuf, RTErrInfoInitStatic(&ErrInfo),
     666                            &g_RTAsn1DefaultAllocator, 0, "WinCert");
     667
     668    int rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &pThis->ContentInfo, "CI");
     669    if (RT_SUCCESS(rc))
     670    {
     671        if (RTCrPkcs7ContentInfo_IsSignedData(&pThis->ContentInfo))
     672        {
     673            pThis->pSignedData = pThis->ContentInfo.u.pSignedData;
     674
     675            /*
     676             * Decode the authenticode bits.
     677             */
     678            if (!strcmp(pThis->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID))
     679            {
     680                pThis->pIndData = pThis->pSignedData->ContentInfo.u.pIndirectDataContent;
     681                Assert(pThis->pIndData);
     682
     683                /*
     684                 * Check that things add up.
     685                 */
     686                rc = RTCrPkcs7SignedData_CheckSanity(pThis->pSignedData,
     687                                                     RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE
     688                                                     | RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH
     689                                                     | RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT,
     690                                                     RTErrInfoInitStatic(&ErrInfo), "SD");
     691                if (RT_FAILURE(rc))
     692                    RTMsgError("PKCS#7 sanity check failed for '%s': %Rrc - %s\n", pThis->pszFilename, rc, ErrInfo.szMsg);
     693                if (RT_SUCCESS(rc))
     694                {
     695                    rc = RTCrSpcIndirectDataContent_CheckSanityEx(pThis->pIndData,
     696                                                                  pThis->pSignedData,
     697                                                                  RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH,
     698                                                                  RTErrInfoInitStatic(&ErrInfo));
     699                    if (RT_FAILURE(rc))
     700                        RTMsgError("SPC indirect data content sanity check failed for '%s': %Rrc - %s\n",
     701                                   pThis->pszFilename, rc, ErrInfo.szMsg);
     702                }
     703            }
     704            else
     705                RTMsgError("Unexpected the signed content in '%s': %s (expected %s)", pThis->pszFilename,
     706                           pThis->pSignedData->ContentInfo.ContentType.szObjId, RTCRSPCINDIRECTDATACONTENT_OID);
     707        }
     708        else
     709            RTMsgError("PKCS#7 content is inside '%s' is not 'signedData': %s\n",
     710                       pThis->pszFilename, pThis->ContentInfo.ContentType.szObjId);
     711    }
     712    else
     713        RTMsgError("RTCrPkcs7ContentInfo_DecodeAsn1 failed on '%s': %Rrc - %s\n", pThis->pszFilename, rc, ErrInfo.szMsg);
     714    return rc;
     715}
     716
     717
     718static int HandleShowExeWorkerPkcs7DisplayAttrib(PSHOWEXEPKCS7 pThis, size_t offPrefix, PCRTCRPKCS7ATTRIBUTE pAttr)
     719{
     720    const char *pszType;
     721    int rc = RTAsn1QueryObjIdName(&pAttr->Type, pThis->szTmp, sizeof(pThis->szTmp));
     722    if (RT_SUCCESS(rc))
     723        RTPrintf("%s%s (%s)\n", pThis->szPrefix, pThis->szTmp, pAttr->Type.szObjId);
     724    else
     725        RTPrintf("%s%s\n", pThis->szPrefix, pAttr->Type.szObjId);
     726
     727    rc = VINF_SUCCESS;
     728    switch (pAttr->enmType)
     729    {
     730        case RTCRPKCS7ATTRIBUTETYPE_UNKNOWN:
     731            if (pAttr->uValues.pCores->cItems <= 1)
     732                RTPrintf("%s %u bytes\n", pThis->szPrefix,pAttr->uValues.pCores->SetCore.Asn1Core.cb);
     733            else
     734                RTPrintf("%s %u bytes divided by %u items\n", pThis->szPrefix, pAttr->uValues.pCores->SetCore.Asn1Core.cb, pAttr->uValues.pCores->cItems);
     735            for (unsigned i = 0; i < pAttr->uValues.pCores->cItems; i++)
     736            {
     737
     738            }
     739            break;
     740
     741        /** Object IDs, use pObjIds. */
     742        case RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS:
     743        /** Octet strings, use pOctetStrings. */
     744        case RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS:
     745        /** Counter signatures (PKCS \#9), use pCounterSignatures. */
     746        case RTCRPKCS7ATTRIBUTETYPE_COUNTER_SIGNATURES:
     747        /** Signing time (PKCS \#9), use pSigningTime. */
     748        case RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME:
     749        /** Microsoft timestamp info (RFC-3161) signed data, use pContentInfo. */
     750        case RTCRPKCS7ATTRIBUTETYPE_MS_TIMESTAMP:
     751        case RTCRPKCS7ATTRIBUTETYPE_MS_NESTED_SIGNATURE:
     752            if (pAttr->uValues.pContentInfos->cItems > 1)
     753                RTPrintf("%s%u nested signatures, %u bytes in total\n", pThis->szPrefix,
     754                         pAttr->uValues.pContentInfos->cItems, pAttr->uValues.pContentInfos->SetCore.Asn1Core.cb);
     755            for (unsigned i = 0; i < pAttr->uValues.pContentInfos->cItems; i++)
     756            {
     757                size_t offPrefix2 = offPrefix;
     758                if (pAttr->uValues.pContentInfos->cItems > 1)
     759                    offPrefix2 += RTStrPrintf(&pThis->szPrefix[offPrefix], sizeof(pThis->szPrefix) - offPrefix, "NestedSig[%u]: ", i);
     760                else
     761                    offPrefix2 += RTStrPrintf(&pThis->szPrefix[offPrefix], sizeof(pThis->szPrefix) - offPrefix, "  ");
     762                //    offPrefix2 += RTStrPrintf(&pThis->szPrefix[offPrefix], sizeof(pThis->szPrefix) - offPrefix, "NestedSig: ", i);
     763                PCRTCRPKCS7CONTENTINFO pContentInfo = &pAttr->uValues.pContentInfos->paItems[i];
     764                int rc2;
     765                if (RTCrPkcs7ContentInfo_IsSignedData(&pThis->ContentInfo))
     766                    rc2 = HandleShowExeWorkerPkcs7Display(pThis, pContentInfo->u.pSignedData, offPrefix2);
     767                else
     768                    rc2 = RTMsgErrorRc(VERR_ASN1_UNEXPECTED_OBJ_ID, "%sPKCS#7 content in nested signature is not 'signedData': %s",
     769                                       pThis->szPrefix, pContentInfo->ContentType.szObjId);
     770                if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
     771                    rc = rc2;
     772            }
     773            break;
     774
     775        case RTCRPKCS7ATTRIBUTETYPE_INVALID:
     776            RTPrintf("%sINVALID!\n", pThis->szPrefix);
     777            break;
     778        case RTCRPKCS7ATTRIBUTETYPE_NOT_PRESENT:
     779            RTPrintf("%sNOT PRESENT!\n", pThis->szPrefix);
     780            break;
     781        default:
     782            RTPrintf("%senmType=%d!\n", pThis->szPrefix, pAttr->enmType);
     783            break;
     784    }
     785    //if (RTAsn1ObjId_CompareWithString(&pAttr->Type, ))
     786    //{
     787    //}
     788    return rc;
     789}
     790
     791
     792static int HandleShowExeWorkerPkcs7Display(PSHOWEXEPKCS7 pThis, PRTCRPKCS7SIGNEDDATA pSignedData, size_t offPrefix)
     793{
     794    pThis->szPrefix[offPrefix] = '\0';
     795
     796    /* Display list of signing algorithms. */
     797    RTPrintf("%sDigestAlgorithms: ", pThis->szPrefix);
     798    for (unsigned i = 0; i < pSignedData->DigestAlgorithms.cItems; i++)
     799    {
     800        PCRTCRX509ALGORITHMIDENTIFIER pAlgoId = &pSignedData->DigestAlgorithms.paItems[i];
     801        const char *pszDigestType = RTCrDigestTypeToName(RTCrX509AlgorithmIdentifier_QueryDigestType(pAlgoId));
     802        if (!pszDigestType)
     803            pszDigestType = pAlgoId->Algorithm.szObjId;
     804        RTPrintf(i == 0 ? "%s" : ", %s", pszDigestType);
     805    }
     806    RTPrintf("\n");
     807
     808    /* Display certificates (Certificates). */
     809
     810    /* Show signatures (SignerInfos). */
     811    unsigned const cSigInfos = pSignedData->SignerInfos.cItems;
     812    for (unsigned i = 0; i < cSigInfos; i++)
     813    {
     814        PRTCRPKCS7SIGNERINFO pSigInfo = &pSignedData->SignerInfos.paItems[i];
     815        size_t offPrefix2 = offPrefix;
     816        if (cSigInfos != 1)
     817            offPrefix2 += RTStrPrintf(&pThis->szPrefix[offPrefix], sizeof(pThis->szPrefix) - offPrefix, "SignerInfo[%u]: ", i);
     818
     819        int rc = RTAsn1Integer_ToString(&pSigInfo->IssuerAndSerialNumber.SerialNumber,
     820                                        pThis->szTmp, sizeof(pThis->szTmp), 0 /*fFlags*/, NULL);
     821        if (RT_FAILURE(rc))
     822            RTStrPrintf(pThis->szTmp, sizeof(pThis->szTmp), "%Rrc", rc);
     823        RTPrintf("%s                  Serial No: %s\n", pThis->szPrefix, pThis->szTmp);
     824
     825        rc = RTCrX509Name_FormatAsString(&pSigInfo->IssuerAndSerialNumber.Name, pThis->szTmp, sizeof(pThis->szTmp), NULL);
     826        if (RT_FAILURE(rc))
     827            RTStrPrintf(pThis->szTmp, sizeof(pThis->szTmp), "%Rrc", rc);
     828        RTPrintf("%s                     Issuer: %s\n", pThis->szPrefix, pThis->szTmp);
     829
     830        const char *pszType = RTCrDigestTypeToName(RTCrX509AlgorithmIdentifier_QueryDigestType(&pSigInfo->DigestAlgorithm));
     831        if (!pszType)
     832            pszType = pSigInfo->DigestAlgorithm.Algorithm.szObjId;
     833        RTPrintf("%s           Digest Algorithm: %s\n", pThis->szPrefix, pszType);
     834
     835        rc = RTAsn1QueryObjIdName(&pSigInfo->DigestEncryptionAlgorithm.Algorithm, pThis->szTmp, sizeof(pThis->szTmp));
     836        if (RT_SUCCESS(rc))
     837            pszType = pThis->szTmp;
     838        else
     839            pszType = pSigInfo->DigestAlgorithm.Algorithm.szObjId;
     840        RTPrintf("%sDigest Encryption Algorithm: %s\n", pThis->szPrefix, pszType);
     841
     842        if (pSigInfo->AuthenticatedAttributes.cItems == 0)
     843            RTPrintf("%s   Authenticated Attributes: none\n", pThis->szPrefix);
     844        else
     845        {
     846            RTPrintf("%s   Authenticated Attributes: %u item%s\n", pThis->szPrefix,
     847                     pSigInfo->AuthenticatedAttributes.cItems, pSigInfo->AuthenticatedAttributes.cItems > 1 ? "s" : "");
     848            for (unsigned j = 0; j < pSigInfo->AuthenticatedAttributes.cItems; j++)
     849            {
     850                PRTCRPKCS7ATTRIBUTE pAttr = &pSigInfo->AuthenticatedAttributes.paItems[j];
     851                size_t offPrefix3 = offPrefix2 + RTStrPrintf(&pThis->szPrefix[offPrefix2], sizeof(pThis->szPrefix) - offPrefix2,
     852                                                             "     AuthAttrib[%u]: ", j);
     853                HandleShowExeWorkerPkcs7DisplayAttrib(pThis, offPrefix3, pAttr);
     854            }
     855            pThis->szPrefix[offPrefix2] = '\0';
     856        }
     857
     858        if (pSigInfo->UnauthenticatedAttributes.cItems == 0)
     859            RTPrintf("%s Unauthenticated Attributes: none\n", pThis->szPrefix);
     860        else
     861        {
     862            RTPrintf("%s Unauthenticated Attributes: %u item%s\n", pThis->szPrefix,
     863                     pSigInfo->UnauthenticatedAttributes.cItems, pSigInfo->UnauthenticatedAttributes.cItems > 1 ? "s" : "");
     864            for (unsigned j = 0; j < pSigInfo->UnauthenticatedAttributes.cItems; j++)
     865            {
     866                PRTCRPKCS7ATTRIBUTE pAttr = &pSigInfo->UnauthenticatedAttributes.paItems[j];
     867                size_t offPrefix3 = offPrefix2 + RTStrPrintf(&pThis->szPrefix[offPrefix2], sizeof(pThis->szPrefix) - offPrefix2,
     868                                                             "   UnauthAttrib[%u]: ", j);
     869                HandleShowExeWorkerPkcs7DisplayAttrib(pThis, offPrefix3, pAttr);
     870            }
     871            pThis->szPrefix[offPrefix2] = '\0';
     872        }
     873
     874#if 0
     875        /** Authenticated attributes, optional [0].
     876         * @todo Check how other producers formats this. The microsoft one does not
     877         *       have explicit tags, but combines it with the SET OF. */
     878        RTCRPKCS7ATTRIBUTES                 AuthenticatedAttributes;
     879
     880        /** The encrypted digest. */
     881        RTASN1OCTETSTRING                   EncryptedDigest;
     882        /** Unauthenticated attributes, optional [1].
     883         * @todo Check how other producers formats this. The microsoft one does not
     884         *       have explicit tags, but combines it with the SET OF. */
     885        RTCRPKCS7ATTRIBUTES                 UnauthenticatedAttributes;
     886#endif
     887    }
     888    pThis->szPrefix[offPrefix] = '\0';
     889
     890    return VINF_SUCCESS;
     891}
     892
     893
     894/**
     895 * Shows the signing info for one executable.
     896 *
     897 * @returns RTEXITCODE_SUCCESS on success, RTEXITCODE_FAILURE on failure.
     898 * @param   pszFilename         The path to the executable.
     899 * @param   cVerbosity          The verbosity level.
     900 * @param   enmLdrArch          Sub image selector.
     901 */
     902static RTEXITCODE HandleShowExeWorker(const char *pszFilename, unsigned cVerbosity, RTLDRARCH enmLdrArch)
     903{
     904    /*
     905     * Open the image and check if it's signed.
     906     */
     907    RTLDRMOD hLdrMod;
     908    int rc = RTLdrOpen(pszFilename, RTLDR_O_FOR_VALIDATION, enmLdrArch, &hLdrMod);
     909    if (RT_FAILURE(rc))
     910        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening executable image '%s': %Rrc", pszFilename, rc);
     911
     912    bool fIsSigned = false;
     913    rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_IS_SIGNED, &fIsSigned, sizeof(fIsSigned));
     914    if (RT_SUCCESS(rc) && fIsSigned)
     915    {
     916        /*
     917         * Query the PKCS#7 data (assuming M$ style signing) and hand it to a worker.
     918         */
     919        size_t cbActual = 0;
     920        size_t cbBuf = _64K;
     921        void  *pvBuf = RTMemAllocZ(cbBuf);
     922        if (pvBuf)
     923        {
     924            rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, NULL /*pvBits*/, pvBuf, cbBuf, &cbActual);
     925            if (rc == VERR_BUFFER_OVERFLOW)
     926            {
     927                RTMemFree(pvBuf);
     928                cbBuf = cbActual;
     929                pvBuf = RTMemAllocZ(cbActual);
     930                if (pvBuf)
     931                    rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, NULL /*pvBits*/, pvBuf, cbBuf, &cbActual);
     932                else
     933                    rc = VERR_NO_MEMORY;
     934            }
     935        }
     936        else
     937            rc = VERR_NO_MEMORY;
     938        if (RT_SUCCESS(rc))
     939        {
     940            SHOWEXEPKCS7 This;
     941            RT_ZERO(This);
     942            This.pbBuf       = (uint8_t const *)pvBuf;
     943            This.cbBuf       = cbActual;
     944            This.cVerbosity  = cVerbosity;
     945            This.pszFilename = pszFilename;
     946            This.hLdrMod     = hLdrMod;
     947            rc = HandleShowExeWorkerPkcs7Decode(&This);
     948            if (RT_SUCCESS(rc))
     949                rc = HandleShowExeWorkerPkcs7Display(&This, This.pSignedData, 0);
     950            RTCrPkcs7ContentInfo_Delete(&This.ContentInfo);
     951        }
     952        else
     953            RTMsgError("RTLdrQueryPropEx/RTLDRPROP_PKCS7_SIGNED_DATA failed on '%s': %Rrc\n", pszFilename, rc);
     954        RTMemFree(pvBuf);
     955    }
     956    else if (RT_SUCCESS(rc))
     957        RTMsgInfo("'%s': not signed\n", pszFilename);
     958    else
     959        RTMsgError("RTLdrQueryProp/RTLDRPROP_IS_SIGNED failed on '%s': %Rrc\n", pszFilename, rc);
     960
     961    int rc2 = RTLdrClose(hLdrMod);
     962    if (RT_FAILURE(rc2))
     963        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTLdrClose failed: %Rrc\n", rc2);
     964    if (RT_FAILURE(rc))
     965        return rc != VERR_LDRVI_NOT_SIGNED ? RTEXITCODE_FAILURE : RTEXITCODE_SKIPPED;
     966
     967    return RTEXITCODE_SUCCESS;
     968}
     969
     970static RTEXITCODE HandleShowExe(int cArgs, char **papszArgs)
     971{
     972    /* Note! This code does not try to clean up the crypto stores on failure.
     973             This is intentional as the code is only expected to be used in a
     974             one-command-per-process environment where we do exit() upon
     975             returning from this function. */
     976
     977    /*
     978     * Parse arguments.
     979     */
     980    static const RTGETOPTDEF s_aOptions[] =
     981    {
     982        { "--verbose",      'v', RTGETOPT_REQ_NOTHING },
     983        { "--quiet",        'q', RTGETOPT_REQ_NOTHING },
     984    };
     985
     986    unsigned  cVerbose   = 0;
     987    RTLDRARCH enmLdrArch = RTLDRARCH_WHATEVER;
     988
     989    RTGETOPTSTATE GetState;
     990    int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
     991    AssertRCReturn(rc, RTEXITCODE_FAILURE);
     992    RTGETOPTUNION ValueUnion;
     993    int ch;
     994    while ((ch = RTGetOpt(&GetState, &ValueUnion)) && ch != VINF_GETOPT_NOT_OPTION)
     995    {
     996        switch (ch)
     997        {
     998            case 'v': cVerbose++; break;
     999            case 'q': cVerbose = 0; break;
     1000            case 'V': return HandleVersion(cArgs, papszArgs);
     1001            case 'h': return HelpShowExe(g_pStdOut, RTSIGNTOOLHELP_FULL);
     1002            default:  return RTGetOptPrintError(ch, &ValueUnion);
     1003        }
     1004    }
     1005    if (ch != VINF_GETOPT_NOT_OPTION)
     1006        return RTMsgErrorExit(RTEXITCODE_FAILURE, "No executable given.");
     1007
     1008    /*
     1009     * Do it.
     1010     */
     1011    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     1012    do
     1013    {
     1014        RTEXITCODE rcExitThis = HandleShowExeWorker(ValueUnion.psz, cVerbose, enmLdrArch);
     1015        if (rcExitThis != RTEXITCODE_SUCCESS && rcExit == RTEXITCODE_SUCCESS)
     1016            rcExit = rcExitThis;
     1017    } while ((ch = RTGetOpt(&GetState, &ValueUnion)) == VINF_GETOPT_NOT_OPTION);
     1018    if (ch != 0)
     1019        return RTGetOptPrintError(ch, &ValueUnion);
     1020
     1021    return rcExit;
     1022}
     1023
     1024#endif /* !IPRT_IN_BUILD_TOOL */
     1025////
    6211026
    6221027/*
     
    8821287#ifndef IPRT_IN_BUILD_TOOL
    8831288    { "verify-exe",                     HandleVerifyExe,                    HelpVerifyExe },
     1289    { "show-exe",                       HandleShowExe,                      HelpShowExe },
    8841290#endif
    8851291    { "make-tainfo",                    HandleMakeTaInfo,                   HelpMakeTaInfo },
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