VirtualBox

Changeset 57577 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 28, 2015 6:57:36 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
102405
Message:

IPRT,QtGui: Redid the certificate download code in the GUI and reduced the number of unnecessary wrapper methods. Removed RTHttpCertDigest, adding RTHttpFreeResponse and RTHttpFreeResponseText. Also added RTCrPemParseContent.

Location:
trunk/src/VBox
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/net/UINetworkReply.cpp

    r57573 r57577  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - UINetworkReply stuff implementation.
     3 * VBox Qt GUI - UINetworkReply, i.e. HTTP/HTTPS for update pings++.
    44 */
    55
    66/*
    7  * Copyright (C) 2012-2013 Oracle Corporation
     7 * Copyright (C) 2012-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3737#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
    3838
     39#include <iprt/crypto/pem.h>
    3940#include <iprt/crypto/store.h>
    4041#include <iprt/err.h>
     
    4445#include <iprt/zip.h>
    4546
    46 /* Our network-reply thread: */
     47
     48/**
     49 * Our network-reply thread
     50 */
    4751class UINetworkReplyPrivateThread : public QThread
    4852{
     
    7377        /** The certificate subject name. */
    7478        const char *pszSubject;
    75         /** @todo add zip path and direct URLs. */
    7679        /** The size of the DER (ASN.1) encoded certificate. */
    7780        uint16_t    cbEncoded;
     
    8689        /** The SHA-512 fingerprint (of the encoded data).   */
    8790        uint8_t     abSha512[RTSHA512_HASH_SIZE];
     91        /** Filename in the zip file we download (PEM). */
     92        const char *pszZipFile;
     93        /** List of direct URLs to PEM formatted files.. */
     94        const char *apszUrls[4];
    8895    } CERTINFO;
    8996
     
    103110     * @{ */
    104111    static QString fullCertificateFileName();
    105     static int abort(RTHTTP pHttp);
    106     static int applyProxyRules(RTHTTP pHttp, const QString &strHostName, int iPort);
    107     static int applyRawHeaders(RTHTTP pHttp, const QList<QByteArray> &headers, const QNetworkRequest &request);
    108     static int performGetRequestForText(RTHTTP pHttp, const QNetworkRequest &request, QByteArray &reply);
    109     static int performGetRequestForBinary(RTHTTP pHttp, const QNetworkRequest &request, QByteArray &reply);
     112    static int applyProxyRules(RTHTTP hHttp, const QString &strHostName, int iPort);
     113    static int applyRawHeaders(RTHTTP hHttp, const QList<QByteArray> &headers, const QNetworkRequest &request);
     114    static uint64_t certAllFoundMask(void);
     115    static uint64_t certEntryFoundMask(uint32_t iCert);
    110116    static bool checkCertificatesInFile(const char *pszCaCertFile);
    111117    static bool checkCertificatesInStore(RTCRSTORE hStore, unsigned *pcCertificates = NULL);
    112     static int decompressCertificate(const QByteArray &package, QByteArray &certificate, const QString &strName);
    113     static int downloadCertificates(RTHTTP pHttp, const QString &strFullCertificateFileName);
    114     static int downloadCertificatePca3G5(RTHTTP pHttp, QByteArray &certificate);
    115     static int downloadCertificatePca3(RTHTTP pHttp, QByteArray &certificate);
     118    static int downloadCertificates(RTHTTP hHttp, const char *pszCaCertFile);
     119    static int convertVerifyAndAddPemCertificateToStore(RTCRSTORE hStore, void const *pvResponse,
     120                                                        size_t cbResponse, const CERTINFO *pCertInfo);
    116121    static int retrieveCertificatesFromSystem(const char *pszCaCertFile);
    117     static int verifyCertificatePca3G5(RTHTTP pHttp, QByteArray const &certificate);
    118     static int verifyCertificatePca3(RTHTTP pHttp, QByteArray const &certificate);
    119     static int verifyCertificate(RTHTTP pHttp, QByteArray const &certificate, CERTINFO const *pCertInfo);
    120     static int saveDownloadedCertificates(const QString &strFullCertificateFileName, const QByteArray &certificatePca3G5, const QByteArray &certificatePca3);
    121     static int saveCertificate(QFile &file, const QByteArray &certificate);
    122122    /** @} */
    123123
     
    128128    QNetworkRequest m_request;
    129129    int m_iError;
    130     RTHTTP m_pHttp;
     130    /** IPRT HTTP client instance handle. */
     131    RTHTTP m_hHttp;
    131132    QByteArray m_reply;
    132133
     
    162163            0x77, 0xa5, 0x40, 0x22, 0x18, 0x12, 0xcb, 0x3d,
    163164            0x0a, 0x67, 0x83, 0x87, 0xc5, 0x45, 0xc4, 0x99
    164         }
     165        },
     166        /*.pszZipFile     =*/
     167        "VeriSign Root Certificates/Generation 1 (G1) PCAs/Class 3 Public Primary Certification Authority.pem",
     168        /*.apszUrls[3]    =*/
     169        {
     170            "http://www.symantec.com/content/en/us/enterprise/verisign/roots/Class-3-Public-Primary-Certification-Authority.pem",
     171            "http://www.verisign.com/repository/roots/root-certificates/PCA-3.pem", /* dead */
     172            NULL,
     173            "http://updates.virtualbox.org/cacerts-symantec-PCA-3-pem-has-gone-missing-again" /* attention getter */
     174        },
    165175    },
    166176    /*[1] =*/   /* The original version with the MD2 signature. */
     
    185195            0xce, 0xef, 0xb2, 0x71, 0x8e, 0x91, 0x60, 0xa2,
    186196            0xc8, 0x0c, 0x5a, 0xe7, 0x8b, 0x33, 0xf2, 0xaa
    187         }
     197        },
     198        /*.pszZipFile     =*/ NULL,
     199        /*.apszUrls[3]    =*/ { NULL, NULL, NULL },
    188200    },
    189201    /*[2] =*/
     
    209221            0x44, 0xeb, 0x2c, 0x74, 0x25, 0x9e, 0x5d, 0xfb,
    210222            0xd2, 0x6b, 0xa8, 0x9a, 0xf0, 0xb3, 0x6a, 0x01
    211         }
     223        },
     224        /*.pszZipFile     =*/
     225        "VeriSign Root Certificates/Generation 5 (G5) PCA/VeriSign Class 3 Public Primary Certification Authority - G5.pem",
     226        /*.apszUrls[3]    =*/
     227        {
     228            "http://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem",
     229            "http://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class-3-Public-Primary-Certification-Authority-G5.pem", /* (in case they correct above typo) */
     230            "http://www.verisign.com/repository/roots/root-certificates/PCA-3G5.pem", /* dead */
     231            "http://updates.virtualbox.org/cacerts-symantec-PCA-3G5-pem-has-gone-missing-again" /* attention getter */
     232        },
    212233    },
    213234};
     
    221242    : m_request(request)
    222243    , m_iError(VINF_SUCCESS)
    223     , m_pHttp(0)
     244    , m_hHttp(NIL_RTHTTP)
    224245{
    225246}
     
    228249{
    229250    /* Call for abort: */
    230     abort(m_pHttp);
     251    if (m_hHttp != NIL_RTHTTP)
     252        RTHttpAbort(m_hHttp);
    231253}
    232254
     
    242264
    243265    /* Apply proxy rules: */
    244     return applyProxyRules(m_pHttp,
     266    return applyProxyRules(m_hHttp,
    245267                           proxyManager.proxyHost(),
    246268                           proxyManager.proxyPort().toUInt());
     
    264286    int rc;
    265287    if (checkCertificatesInFile(pszCaCertFile))
    266         rc = RTHttpSetCAFile(m_pHttp, pszCaCertFile);
     288        rc = RTHttpSetCAFile(m_hHttp, pszCaCertFile);
    267289    else
    268290    {
     
    274296        rc = retrieveCertificatesFromSystem(pszCaCertFile);
    275297        if (RT_FAILURE(rc))
    276             rc = downloadCertificates(m_pHttp, strFullCertificateFileName);
     298            rc = downloadCertificates(m_hHttp, pszCaCertFile);
    277299
    278300        if (RT_SUCCESS(rc))
    279             rc = RTHttpSetCAFile(m_pHttp, pszCaCertFile);
     301            rc = RTHttpSetCAFile(m_hHttp, pszCaCertFile);
    280302    }
    281303
     
    294316
    295317    /* Apply raw headers: */
    296     return applyRawHeaders(m_pHttp, headers, m_request);
     318    return applyRawHeaders(m_hHttp, headers, m_request);
    297319}
    298320
     
    302324    m_strContext = tr("During network request");
    303325
    304     /* Perform GET request: */
    305     return performGetRequestForText(m_pHttp, m_request, m_reply);
     326    /* Paranoia: */
     327    m_reply.clear();
     328
     329    /* Perform blocking HTTP GET request: */
     330    char *pszResponse;
     331    /** @todo r=bird: Use RTHttpGetBinary? */
     332    int rc = RTHttpGetText(m_hHttp, m_request.url().toString().toUtf8().constData(), &pszResponse);
     333    if (RT_SUCCESS(rc))
     334    {
     335        m_reply = QByteArray(pszResponse);
     336        RTHttpFreeResponseText(pszResponse);
     337    }
     338
     339    return rc;
    306340}
    307341
     
    309343{
    310344    /* Init: */
    311     RTR3InitExeNoArguments(RTR3INIT_FLAGS_SUPLIB);
     345    RTR3InitExeNoArguments(RTR3INIT_FLAGS_SUPLIB); /** @todo r=bird: WTF? */
    312346
    313347    /* Create HTTP object: */
    314348    if (RT_SUCCESS(m_iError))
    315         m_iError = RTHttpCreate(&m_pHttp);
     349        m_iError = RTHttpCreate(&m_hHttp);
    316350
    317351    /* Apply proxy-rules: */
     
    331365        m_iError = performMainRequest();
    332366
    333     /* Destroy HTTP object: */
    334     if (m_pHttp)
    335     {
    336         RTHttpDestroy(m_pHttp);
    337         m_pHttp = 0;
     367    /* Destroy HTTP client instance: */
     368    RTHTTP hHttp = m_hHttp;
     369    if (hHttp != NIL_RTHTTP)
     370    {
     371        /** @todo r=bird: There is a race here between this and abort()! */
     372        m_hHttp = NIL_RTHTTP;
     373        RTHttpDestroy(hHttp);
    338374    }
    339375}
     
    347383
    348384/* static */
    349 int UINetworkReplyPrivateThread::abort(RTHTTP pHttp)
     385int UINetworkReplyPrivateThread::applyProxyRules(RTHTTP hHttp, const QString &strHostName, int iPort)
    350386{
    351387    /* Make sure HTTP is created: */
    352     if (!pHttp)
    353         return VERR_INVALID_POINTER;
    354 
    355     /* Call for HTTP abort: */
    356     return RTHttpAbort(pHttp);
    357 }
    358 
    359 /* static */
    360 int UINetworkReplyPrivateThread::applyProxyRules(RTHTTP pHttp, const QString &strHostName, int iPort)
    361 {
    362     /* Make sure HTTP is created: */
    363     if (!pHttp)
    364         return VERR_INVALID_POINTER;
     388    if (hHttp == NIL_RTHTTP)
     389        return VERR_INVALID_HANDLE;
    365390
    366391    /* Apply HTTP proxy: */
    367     return RTHttpSetProxy(pHttp,
     392    return RTHttpSetProxy(hHttp,
    368393                          strHostName.toAscii().constData(),
    369394                          iPort,
     
    372397
    373398/* static */
    374 int UINetworkReplyPrivateThread::applyRawHeaders(RTHTTP pHttp, const QList<QByteArray> &headers, const QNetworkRequest &request)
     399int UINetworkReplyPrivateThread::applyRawHeaders(RTHTTP hHttp, const QList<QByteArray> &headers, const QNetworkRequest &request)
    375400{
    376401    /* Make sure HTTP is created: */
    377     if (!pHttp)
    378         return VERR_INVALID_POINTER;
     402    if (hHttp == NIL_RTHTTP)
     403        return VERR_INVALID_HANDLE;
    379404
    380405    /* We should format them first: */
     
    391416
    392417    /* Apply HTTP headers: */
    393     return RTHttpSetHeaders(pHttp, formattedHeaderPointers.size(), ppFormattedHeaders);
    394 }
    395 
    396 /* static */
    397 int UINetworkReplyPrivateThread::performGetRequestForText(RTHTTP pHttp, const QNetworkRequest &request, QByteArray &reply)
    398 {
    399     /* Make sure HTTP is created: */
    400     if (!pHttp)
    401         return VERR_INVALID_POINTER;
    402 
    403     /* Perform blocking HTTP GET request: */
    404     char *pszBuffer = 0;
    405     int rc = RTHttpGetText(pHttp,
    406                            request.url().toString().toAscii().constData(),
    407                            &pszBuffer);
    408     reply = QByteArray(pszBuffer);
    409     RTMemFree(pszBuffer);
    410     return rc;
    411 }
    412 
    413 /* static */
    414 int UINetworkReplyPrivateThread::performGetRequestForBinary(RTHTTP pHttp, const QNetworkRequest &request, QByteArray &reply)
    415 {
    416     /* Make sure HTTP is created: */
    417     if (!pHttp)
    418         return VERR_INVALID_POINTER;
    419 
    420     /* Perform blocking HTTP GET request: */
    421     void *pBuffer = 0;
    422     size_t size = 0;
    423     int rc = RTHttpGetBinary(pHttp,
    424                              request.url().toString().toAscii().constData(),
    425                              &pBuffer, &size);
    426     reply = QByteArray((const char*)pBuffer, (int)size);
    427     RTMemFree(pBuffer);
    428     return rc;
     418    return RTHttpSetHeaders(hHttp, formattedHeaderPointers.size(), ppFormattedHeaders);
    429419}
    430420
     
    436426 * @param   pszCaCertFile   The path to the certificate file.
    437427 */
    438 /* static */ bool
     428/*static*/ bool
    439429UINetworkReplyPrivateThread::checkCertificatesInFile(const char *pszCaCertFile)
    440430{
     
    483473
    484474    return fFoundCerts;
     475}
     476
     477/**
     478 * Calculates the 64-bit all-certs found mask.
     479 *
     480 * @returns 64-bit mask.
     481 */
     482/*static*/ uint64_t
     483UINetworkReplyPrivateThread::certAllFoundMask()
     484{
     485    AssertCompile(RT_ELEMENTS(s_aCerts) < 64);
     486    return RT_BIT_64(RT_ELEMENTS(s_aCerts)) - UINT64_C(1);
     487}
     488
     489/**
     490 * Calculates the 64-bit 'found' mask for a certificate entry.
     491 *
     492 * @returns 64-bit mask.
     493 * @param   iCert               The certificate entry.
     494 */
     495/*static*/ uint64_t
     496UINetworkReplyPrivateThread::certEntryFoundMask(uint32_t iCert)
     497{
     498    Assert(iCert < RT_ELEMENTS(s_aCerts));
     499    uint64_t fMask = RT_BIT_64(iCert);
     500
     501    /*
     502     * Tedium: Also mark certificates that this is an alternative to, we only need
     503     *         the public key once.
     504     */
     505    uint16_t iAlt = s_aCerts[iCert].iAlternativeTo;
     506    if (iAlt != UINT16_MAX)
     507    {
     508        unsigned cMax = 10;
     509        do
     510        {
     511            Assert(iAlt < RT_ELEMENTS(s_aCerts));
     512            Assert(cMax > 1);
     513            Assert(strcmp(s_aCerts[iAlt].pszSubject, s_aCerts[iCert].pszSubject) == 0);
     514            fMask |= RT_BIT_64(iAlt);
     515            iAlt = s_aCerts[iAlt].iAlternativeTo;
     516        } while (iAlt != iCert && cMax-- > 0);
     517    }
     518
     519    return fMask;
    485520}
    486521
     
    528563                            if (RTSha512Check(pCertCtx->pabEncoded, pCertCtx->cbEncoded, s_aCerts[i].abSha512))
    529564                            {
    530                                 fFoundCerts |= RT_BIT_64(i);
    531 
    532                                 /*
    533                                  * Tedium: Also mark certificates that this is an alternative to, we only need
    534                                  *         the public key once.
    535                                  */
    536                                 uint16_t iAlt = s_aCerts[i].iAlternativeTo;
    537                                 if (iAlt != UINT16_MAX)
    538                                 {
    539                                     unsigned cMax = 10;
    540                                     do
    541                                     {
    542                                         Assert(iAlt < RT_ELEMENTS(s_aCerts));
    543                                         Assert(cMax > 1);
    544                                         Assert(strcmp(s_aCerts[iAlt].pszSubject, s_aCerts[i].pszSubject) == 0);
    545                                         fFoundCerts |= RT_BIT_64(iAlt);
    546                                         iAlt = s_aCerts[iAlt].iAlternativeTo;
    547                                     } while (iAlt != i && cMax-- > 0);
    548                                 }
     565                                fFoundCerts |= certEntryFoundMask(i);
    549566                                break;
    550567                            }
     
    565582         * Did we locate all of them?
    566583         */
    567         AssertCompile(RT_ELEMENTS(s_aCerts) < 64);
    568         if (fFoundCerts == RT_BIT_64(RT_ELEMENTS(s_aCerts)) - UINT64_C(1))
     584        if (fFoundCerts == certAllFoundMask())
    569585            return true;
    570586    }
     
    573589}
    574590
    575 /* static */
    576 int UINetworkReplyPrivateThread::decompressCertificate(const QByteArray &package, QByteArray &certificate, const QString &strName)
    577 {
    578     /* Decompress certificate: */
    579     void *pDecompressedBuffer;
    580     size_t cDecompressedSize;
    581     int rc = RTZipPkzipMemDecompress(&pDecompressedBuffer, &cDecompressedSize, package, package.size(), strName.toLatin1().constData());
     591/*static*/ int
     592UINetworkReplyPrivateThread::downloadCertificates(RTHTTP hHttp, const char *pszCaCertFile)
     593{
     594    /*
     595     * Prepare temporary certificate store.
     596     */
     597    RTCRSTORE hStore;
     598    int rc = RTCrStoreCreateInMem(&hStore, RT_ELEMENTS(s_aCerts));
     599    AssertRCReturn(rc, rc);
     600
     601    /*
     602     * Accounts for certificates we've downloaded, verified and added to the store.
     603     */
     604    uint64_t fFoundCerts = 0;
     605    AssertCompile(RT_ELEMENTS(s_aCerts) < 64);
     606
     607    /*
     608     * Try get the roots.zip from symantec (or virtualbox.org) first.
     609     */
     610    static const char * const a_apszRootsZipUrls[] =
     611    {
     612        "http://www.symantec.com/content/en/us/enterprise/verisign/roots/roots.zip",
     613        "http://updates.virtualbox.org/cacerts-symantec-roots-zip-has-gone-missing-again" /* Just to try grab our attention. */
     614    };
     615    for (uint32_t iUrl = 0; iUrl < RT_ELEMENTS(a_apszRootsZipUrls); iUrl++)
     616    {
     617        void   *pvRootsZip;
     618        size_t  cbRootsZip;
     619        rc = RTHttpGetBinary(hHttp, a_apszRootsZipUrls[iUrl], &pvRootsZip, &cbRootsZip);
     620        if (RT_SUCCESS(rc))
     621        {
     622            for (uint32_t i = 0; i < RT_ELEMENTS(s_aCerts); i++)
     623                if (s_aCerts[i].pszZipFile)
     624                {
     625                    void  *pvFile;
     626                    size_t cbFile;
     627                    rc = RTZipPkzipMemDecompress(&pvFile, &cbFile, pvRootsZip, cbRootsZip, s_aCerts[i].pszZipFile);
     628                    if (RT_SUCCESS(rc))
     629                    {
     630                        rc = convertVerifyAndAddPemCertificateToStore(hStore, pvFile, cbFile, &s_aCerts[i]);
     631                        RTMemFree(pvFile);
     632                        if (RT_SUCCESS(rc))
     633                            fFoundCerts |= certEntryFoundMask(i);
     634                    }
     635                }
     636            RTHttpFreeResponse(pvRootsZip);
     637            if (fFoundCerts == certAllFoundMask())
     638                break;
     639        }
     640    }
     641
     642    /*
     643     * Fallback: Try download certificates separately.
     644     */
     645    if (fFoundCerts != certAllFoundMask())
     646        for (uint32_t i = 0; i < RT_ELEMENTS(s_aCerts); i++)
     647            if (!(fFoundCerts & RT_BIT_64(i)))
     648                for (uint32_t iUrl = 0; iUrl < RT_ELEMENTS(s_aCerts[i].apszUrls); i++)
     649                    if (s_aCerts[i].apszUrls[iUrl])
     650                    {
     651                        void  *pvResponse;
     652                        size_t cbResponse;
     653                        rc = RTHttpGetBinary(hHttp, s_aCerts[i].apszUrls[iUrl], &pvResponse, &cbResponse);
     654                        if (RT_SUCCESS(rc))
     655                        {
     656                            rc = convertVerifyAndAddPemCertificateToStore(hStore, pvResponse, cbResponse, &s_aCerts[i]);
     657                            RTHttpFreeResponse(pvResponse);
     658                            if (RT_SUCCESS(rc))
     659                            {
     660                                fFoundCerts |= certEntryFoundMask(i);
     661                                break;
     662                            }
     663                        }
     664                    }
     665
     666    /*
     667     * See if we've got the certificates we want, save it we do.
     668     */
     669    if (fFoundCerts == certAllFoundMask())
     670        rc = RTCrStoreCertExportAsPem(hStore, 0 /*fFlags*/, pszCaCertFile);
     671    else if (RT_SUCCESS(rc))
     672        rc = VERR_NOT_FOUND;
     673
     674    RTCrStoreRelease(hStore);
     675    return rc;
     676}
     677
     678/**
     679 * Converts a PEM certificate, verifies it against @a pCertInfo and adds it to
     680 * the given store.
     681 *
     682 * @returns IPRT status code.
     683 * @param   hStore              The store to add it to.
     684 * @param   pvResponse          The raw PEM certificate file bytes.
     685 * @param   cbResponse          The number of bytes.
     686 * @param   pCertInfo           The certificate info (we use hashes and encoded
     687 *                              size).
     688 */
     689/*static*/ int
     690UINetworkReplyPrivateThread::convertVerifyAndAddPemCertificateToStore(RTCRSTORE hStore,
     691                                                                      void const *pvResponse, size_t cbResponse,
     692                                                                      const CERTINFO *pCertInfo)
     693{
     694    /*
     695     * Convert the PEM certificate to its binary form so we can hash it.
     696     */
     697    static RTCRPEMMARKERWORD const s_aWords_Certificate[]  = { { RT_STR_TUPLE("CERTIFICATE") } };
     698    static RTCRPEMMARKER     const s_aCertificateMarkers[] = { { s_aWords_Certificate, RT_ELEMENTS(s_aWords_Certificate) }, };
     699    RTERRINFOSTATIC StaticErrInfo;
     700    PCRTCRPEMSECTION pSectionHead;
     701    int rc = RTCrPemParseContent(pvResponse, cbResponse, 0 /*fFlags*/,
     702                                 &s_aCertificateMarkers[0], RT_ELEMENTS(s_aCertificateMarkers),
     703                                 &pSectionHead, RTErrInfoInitStatic(&StaticErrInfo));
     704    if (RTErrInfoIsSet(&StaticErrInfo.Core))
     705        LogRel(("RTCrPemParseContent: %s\n", StaticErrInfo.Core.pszMsg));
    582706    if (RT_SUCCESS(rc))
    583707    {
    584         /* Copy certificate: */
    585         certificate = QByteArray((const char*)pDecompressedBuffer, (int)cDecompressedSize);
    586         /* Free decompressed buffer: */
    587         RTMemFree(pDecompressedBuffer);
    588     }
    589     /* Return result: */
    590     return rc;
    591 }
    592 
    593 /* static */
    594 int UINetworkReplyPrivateThread::downloadCertificates(RTHTTP pHttp, const QString &strFullCertificateFileName)
    595 {
    596     /* Prepare certificates: */
    597     QByteArray certificatePca3G5;
    598     QByteArray certificatePca3;
    599 
    600     /* Receive certificate package: */
    601     QByteArray package;
    602     const QNetworkRequest address(QUrl("http://www.symantec.com/content/en/us/enterprise/verisign/roots/roots.zip"));
    603     int rc = performGetRequestForBinary(pHttp, address, package);
    604     /* UnZIP PCA-3G5 certificate: */
    605     if (RT_SUCCESS(rc))
    606     {
    607         rc = decompressCertificate(package, certificatePca3G5,
    608                                    "VeriSign Root Certificates/Generation 5 (G5) PCA/VeriSign Class 3 Public Primary Certification Authority - G5.pem");
    609         /* Verify PCA-3G5 certificate: */
    610         if (RT_SUCCESS(rc))
    611             rc = verifyCertificatePca3G5(pHttp, certificatePca3G5);
    612     }
    613     /* UnZIP PCA-3 certificate: */
    614     if (RT_SUCCESS(rc))
    615     {
    616         rc = decompressCertificate(package, certificatePca3,
    617                                    "VeriSign Root Certificates/Generation 1 (G1) PCAs/Class 3 Public Primary Certification Authority.pem");
    618         /* Verify PCA-3 certificate: */
    619         if (RT_SUCCESS(rc))
    620             rc = verifyCertificatePca3(pHttp, certificatePca3);
    621     }
    622 
    623     /* Fallback.. download certificates separately: */
    624     if (RT_FAILURE(rc))
    625     {
    626         /* Reset result: */
    627         rc = VINF_SUCCESS;
    628         /* Download PCA-3G5 certificate: */
    629         if (RT_SUCCESS(rc))
    630             rc = downloadCertificatePca3G5(pHttp, certificatePca3G5);
    631         /* Download PCA-3 certificate: */
    632         if (RT_SUCCESS(rc))
    633             rc = downloadCertificatePca3(pHttp, certificatePca3);
    634     }
    635 
    636     /* Save certificates: */
    637     if (RT_SUCCESS(rc))
    638         rc = saveDownloadedCertificates(strFullCertificateFileName, certificatePca3G5, certificatePca3);
    639 
    640     /* Return result-code: */
    641     return rc;
    642 }
    643 
    644 /* static */
    645 int UINetworkReplyPrivateThread::downloadCertificatePca3G5(RTHTTP pHttp, QByteArray &certificate)
    646 {
    647     /* Receive certificate: */
    648     const QNetworkRequest address(QUrl("http://www.verisign.com/repository/roots/root-certificates/PCA-3G5.pem"));
    649     int rc = performGetRequestForText(pHttp, address, certificate);
    650 
    651     /* Verify certificate: */
    652     if (RT_SUCCESS(rc))
    653         rc = verifyCertificatePca3G5(pHttp, certificate);
    654 
    655     /* Return result-code: */
    656     return rc;
    657 }
    658 
    659 /* static */
    660 int UINetworkReplyPrivateThread::downloadCertificatePca3(RTHTTP pHttp, QByteArray &certificate)
    661 {
    662     /* Receive certificate: */
    663     const QNetworkRequest address(QUrl("http://www.verisign.com/repository/roots/root-certificates/PCA-3.pem"));
    664     int rc = performGetRequestForText(pHttp, address, certificate);
    665 
    666     /* Verify certificate: */
    667     if (RT_SUCCESS(rc))
    668         rc = verifyCertificatePca3(pHttp, certificate);
    669 
    670     /* Return result-code: */
     708        /*
     709         * Look at what we got back and hash it.
     710         */
     711        rc = VERR_NOT_FOUND;
     712        for (PCRTCRPEMSECTION pCur = pSectionHead; pCur; pCur = pCur->pNext)
     713            if (pCur->cbData == pCertInfo->cbEncoded)
     714            {
     715                if (   RTSha1Check(pCur->pbData, pCur->cbData, pCertInfo->abSha1)
     716                    && RTSha512Check(pCur->pbData, pCur->cbData, pCertInfo->abSha512))
     717                {
     718                    /*
     719                     * Matching, add it to the store.
     720                     */
     721                    rc = RTCrStoreCertAddEncoded(hStore,
     722                                                 RTCRCERTCTX_F_ENC_X509_DER | RTCRCERTCTX_F_ADD_IF_NOT_FOUND,
     723                                                 pCur->pbData, pCur->cbData,
     724                                                 RTErrInfoInitStatic(&StaticErrInfo));
     725                    if (RTErrInfoIsSet(&StaticErrInfo.Core))
     726                        LogRel(("RTCrStoreCertAddEncoded: %s\n", StaticErrInfo.Core.pszMsg));
     727                    else if (RT_FAILURE(rc))
     728                        LogRel(("RTCrStoreCertAddEncoded: %Rrc\n", rc));
     729                    if (RT_SUCCESS(rc))
     730                        break;
     731                }
     732                else
     733                    LogRel(("convertVerifyAndAddPemCertificateToStore: hash mismatch (cbData=%#zx)\n", pCur->cbData));
     734            }
     735            else
     736                LogRel(("convertVerifyAndAddPemCertificateToStore: cbData=%#zx expected %#zx\n",
     737                        pCur->cbData, pCertInfo->cbEncoded));
     738
     739        RTCrPemFreeSections(pSectionHead);
     740    }
    671741    return rc;
    672742}
     
    679749 * @param   pszCaCertFile           Where to store the certificates.
    680750 */
    681 int UINetworkReplyPrivateThread::retrieveCertificatesFromSystem(const char *pszCaCertFile)
     751/*static*/ int
     752UINetworkReplyPrivateThread::retrieveCertificatesFromSystem(const char *pszCaCertFile)
    682753{
    683754    /*
     
    711782
    712783    /*
    713      * See if we've got the certificates we want.
     784     * See if we've got the certificates we want, save it we do.
    714785     */
    715786    if (checkCertificatesInStore(hUserStore))
     
    722793
    723794
    724 /* static */
    725 int UINetworkReplyPrivateThread::verifyCertificatePca3G5(RTHTTP pHttp, QByteArray const &certificate)
    726 {
    727     const CERTINFO *pCertInfo = &s_aCerts[2];
    728     Assert(pCertInfo->cbEncoded == 0x4d7);
    729     return verifyCertificate(pHttp, certificate, pCertInfo);
    730 }
    731 
    732 /* static */
    733 int UINetworkReplyPrivateThread::verifyCertificatePca3(RTHTTP pHttp, QByteArray const &certificate)
    734 {
    735     const CERTINFO *pCertInfo = &s_aCerts[0];
    736     Assert(pCertInfo->cbEncoded == 0x240);
    737     Assert(pCertInfo->abSha1[0] == 0xa1);
    738     return verifyCertificate(pHttp, certificate, pCertInfo);
    739 }
    740 
    741 /* static */
    742 int UINetworkReplyPrivateThread::verifyCertificate(RTHTTP pHttp, QByteArray const &certificate, CERTINFO const *pCertInfo)
    743 {
    744     /* Make sure HTTP is created: */
    745     if (!pHttp)
    746         return VERR_INVALID_POINTER;
    747 
    748     /*
    749      * Convert the PEM formatted certificate into bytes and create
    750      * SHA-1 and SHA-512 digest for them.
    751      */
    752     uint8_t *pabSha1;
    753     size_t   cbSha1;
    754     uint8_t *pabSha512;
    755     size_t   cbSha512;
    756     int rc = RTHttpCertDigest(pHttp, (char *)certificate.constData(), certificate.size(),
    757                               &pabSha1, &cbSha1, &pabSha512, &cbSha512); /* Insane interface! (cbSha1, cbSha512, non-const data) Will be replaced eventually... */
    758     if (RT_SUCCESS(rc))
    759     {
    760         Assert(cbSha1   == RTSHA1_DIGEST_LEN);
    761         Assert(cbSha512 == RTSHA512_DIGEST_LEN);
    762 
    763         /* Verify digest: */
    764         if (memcmp(pCertInfo->abSha1, pabSha1, RTSHA1_DIGEST_LEN))
    765             rc = VERR_HTTP_CACERT_WRONG_FORMAT;
    766         if (memcmp(pCertInfo->abSha512, pabSha512, RTSHA512_DIGEST_LEN))
    767             rc = VERR_HTTP_CACERT_WRONG_FORMAT;
    768 
    769         /* Cleanup digest: */
    770         RTMemFree(pabSha1);
    771         RTMemFree(pabSha512);
    772     }
    773 
    774     /* Return result-code: */
    775     return rc;
    776 }
    777 
    778 /* static */ int
    779 UINetworkReplyPrivateThread::saveDownloadedCertificates(const QString &strFullCertificateFileName,
    780                                                         const QByteArray &certificatePca3G5,
    781                                                         const QByteArray &certificatePca3)
    782 {
    783     /* Open certificates file: */
    784     QFile file(strFullCertificateFileName);
    785     bool fFileOpened = file.open(QIODevice::WriteOnly);
    786     int rc = fFileOpened ? VINF_SUCCESS : VERR_OPEN_FAILED;
    787 
    788     /* Save certificates: */
    789     if (RT_SUCCESS(rc))
    790         rc = saveCertificate(file, certificatePca3G5);
    791     if (RT_SUCCESS(rc))
    792         rc = saveCertificate(file, certificatePca3);
    793 
    794     /* Close certificates file: */
    795     if (fFileOpened)
    796         file.close();
    797 
    798     /* Return result-code: */
    799     return rc;
    800 }
    801 
    802 /* static */
    803 int UINetworkReplyPrivateThread::saveCertificate(QFile &file, const QByteArray &certificate)
    804 {
    805     /* Save certificate: */
    806     int rc = VINF_SUCCESS;
    807     if (RT_SUCCESS(rc))
    808         rc = file.write(certificate) != -1 ? VINF_SUCCESS : VERR_WRITE_ERROR;
    809 
    810     /* Add 'new-line' character: */
    811     if (RT_SUCCESS(rc))
    812 #ifdef Q_WS_WIN
    813         rc = file.write("\r\n") != -1 ? VINF_SUCCESS : VERR_WRITE_ERROR;
    814 #else /* Q_WS_WIN */
    815         rc = file.write("\n") != -1 ? VINF_SUCCESS : VERR_WRITE_ERROR;
    816 #endif /* !Q_WS_WIN */
    817 
    818     /* Return result-code: */
    819     return rc;
    820 }
    821 
    822 
    823 /* Our network-reply object: */
     795
     796/**
     797 * Our network-reply (HTTP) object.
     798 */
    824799class UINetworkReplyPrivate : public QObject
    825800{
  • trunk/src/VBox/Runtime/common/crypto/pemfile.cpp

    r57572 r57577  
    264264 * @param   cbFile              The number of bytes.
    265265 */
    266 static bool rtCrPemIsBinaryFile(uint8_t *pbFile, size_t cbFile)
     266static bool rtCrPemIsBinaryBlob(uint8_t const *pbFile, size_t cbFile)
    267267{
    268268    /*
     
    334334
    335335
    336 RTDECL(int) RTCrPemReadFile(const char *pszFilename, uint32_t fFlags, PCRTCRPEMMARKER paMarkers, size_t cMarkers,
    337                             PCRTCRPEMSECTION *ppSectionHead, PRTERRINFO pErrInfo)
    338 {
    339     AssertReturn(!(fFlags & ~RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR), VERR_INVALID_FLAGS);
    340 
    341     size_t      cbContent;
    342     uint8_t    *pbContent;
    343     int rc = RTFileReadAllEx(pszFilename, 0, 64U*_1M, RTFILE_RDALL_O_DENY_WRITE, (void **)&pbContent, &cbContent);
    344     if (RT_SUCCESS(rc))
    345     {
    346         PRTCRPEMSECTION pSection = (PRTCRPEMSECTION)RTMemAllocZ(sizeof(*pSection));
    347         if (pSection)
    348         {
    349             /*
    350              * Try locate the first section.
    351              */
    352             size_t          offBegin, offEnd, offResume;
    353             PCRTCRPEMMARKER pMatch;
    354             if (   !rtCrPemIsBinaryFile(pbContent, cbContent)
    355                 && rtCrPemFindMarkerSection(pbContent, cbContent, 0 /*offStart*/, paMarkers, cMarkers,
    356                                             &pMatch, &offBegin, &offEnd, &offResume) )
     336RTDECL(int) RTCrPemParseContent(void const *pvContent, size_t cbContent, uint32_t fFlags,
     337                                PCRTCRPEMMARKER paMarkers, size_t cMarkers,
     338                                PCRTCRPEMSECTION *ppSectionHead, PRTERRINFO pErrInfo)
     339{
     340    /*
     341     * Input validation.
     342     */
     343    AssertPtr(ppSectionHead);
     344    *ppSectionHead = NULL;
     345    AssertReturn(cbContent, VINF_EOF);
     346    AssertPtr(pvContent);
     347    AssertPtr(paMarkers);
     348
     349    /*
     350     * Pre-allocate a section.
     351     */
     352    int rc = VINF_SUCCESS;
     353    PRTCRPEMSECTION pSection = (PRTCRPEMSECTION)RTMemAllocZ(sizeof(*pSection));
     354    if (pSection)
     355    {
     356        /*
     357         * Try locate the first section.
     358         */
     359        uint8_t const  *pbContent = (uint8_t const *)pvContent;
     360        size_t          offBegin, offEnd, offResume;
     361        PCRTCRPEMMARKER pMatch;
     362        if (   !rtCrPemIsBinaryBlob(pbContent, cbContent)
     363            && rtCrPemFindMarkerSection(pbContent, cbContent, 0 /*offStart*/, paMarkers, cMarkers,
     364                                        &pMatch, &offBegin, &offEnd, &offResume) )
     365        {
     366            PCRTCRPEMSECTION *ppNext = ppSectionHead;
     367            for (;;)
    357368            {
    358                 PCRTCRPEMSECTION *ppNext = ppSectionHead;
    359                 for (;;)
     369                //pSection->pNext       = NULL;
     370                pSection->pMarker       = pMatch;
     371                //pSection->pbData      = NULL;
     372                //pSection->cbData      = 0;
     373                //pSection->pszPreamble = NULL;
     374                //pSection->cchPreamble = 0;
     375
     376                *ppNext = pSection;
     377                ppNext = &pSection->pNext;
     378
     379                /* Decode the section. */
     380                /** @todo copy the preamble as well. */
     381                int rc2 = rtCrPemDecodeBase64(pbContent + offBegin, offEnd - offBegin,
     382                                              (void **)&pSection->pbData, &pSection->cbData);
     383                if (RT_FAILURE(rc2))
    360384                {
    361                     //pSection->pNext         = NULL;
    362                     pSection->pMarker           = pMatch;
    363                     //pSection->pbData        = NULL;
    364                     //pSection->cbData        = 0;
    365                     //pSection->pszPreamble   = NULL;
    366                     //pSection->cchPreamble   = 0;
    367 
    368                     *ppNext = pSection;
    369                     ppNext = &pSection->pNext;
    370 
    371                     /* Decode the section. */
    372                     /** @todo copy the preamble as well. */
    373                     int rc2 = rtCrPemDecodeBase64(pbContent + offBegin, offEnd - offBegin,
    374                                                   (void **)&pSection->pbData, &pSection->cbData);
    375                     if (RT_FAILURE(rc2))
     385                    pSection->pbData = NULL;
     386                    pSection->cbData = 0;
     387                    if (   rc2 == VERR_INVALID_BASE64_ENCODING
     388                        && (fFlags & RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR))
     389                        rc = -rc2;
     390                    else
    376391                    {
    377                         pSection->pbData = NULL;
    378                         pSection->cbData = 0;
    379                         if (   rc2 == VERR_INVALID_BASE64_ENCODING
    380                             && (fFlags & RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR))
    381                             rc = -rc2;
    382                         else
    383                         {
    384                             rc = rc2;
    385                             break;
    386                         }
    387                     }
    388 
    389                     /* More sections? */
    390                     if (   offResume + 12 >= cbContent
    391                         || offResume      >= cbContent
    392                         || !rtCrPemFindMarkerSection(pbContent, cbContent, offResume, paMarkers, cMarkers,
    393                                                      &pMatch, &offBegin, &offEnd, &offResume) )
    394                         break; /* No. */
    395 
    396                     /* Ok, allocate a new record for it. */
    397                     pSection = (PRTCRPEMSECTION)RTMemAllocZ(sizeof(*pSection));
    398                     if (RT_UNLIKELY(!pSection))
    399                     {
    400                         rc = VERR_NO_MEMORY;
     392                        rc = rc2;
    401393                        break;
    402394                    }
    403395                }
    404                 if (RT_SUCCESS(rc))
     396
     397                /* More sections? */
     398                if (   offResume + 12 >= cbContent
     399                    || offResume      >= cbContent
     400                    || !rtCrPemFindMarkerSection(pbContent, cbContent, offResume, paMarkers, cMarkers,
     401                                                 &pMatch, &offBegin, &offEnd, &offResume) )
     402                    break; /* No. */
     403
     404                /* Ok, allocate a new record for it. */
     405                pSection = (PRTCRPEMSECTION)RTMemAllocZ(sizeof(*pSection));
     406                if (RT_UNLIKELY(!pSection))
    405407                {
    406                     RTFileReadAllFree(pbContent, cbContent);
    407                     return rc;
     408                    rc = VERR_NO_MEMORY;
     409                    break;
    408410                }
    409 
    410                 RTCrPemFreeSections(*ppSectionHead);
    411411            }
    412             else
     412            if (RT_SUCCESS(rc))
     413                return rc;
     414
     415            RTCrPemFreeSections(*ppSectionHead);
     416        }
     417        else
     418        {
     419            /*
     420             * No PEM section found.  Return the whole file as one binary section.
     421             */
     422            //pSection->pNext       = NULL;
     423            //pSection->pMarker     = NULL;
     424            pSection->pbData        = (uint8_t *)RTMemDup(pbContent, cbContent);
     425            pSection->cbData        = cbContent;
     426            //pSection->pszPreamble = NULL;
     427            //pSection->cchPreamble = 0;
     428            if (pSection->pbData)
    413429            {
    414                 /*
    415                  * No PEM section found.  Return the whole file as one binary section.
    416                  */
    417                 //pSection->pNext         = NULL;
    418                 //pSection->pMarker       = NULL;
    419                 pSection->pbData        = pbContent;
    420                 pSection->cbData        = cbContent;
    421                 //pSection->pszPreamble   = NULL;
    422                 //pSection->cchPreamble   = 0;
    423430                *ppSectionHead = pSection;
    424431                return VINF_SUCCESS;
    425432            }
    426         }
    427         else
     433
    428434            rc = VERR_NO_MEMORY;
    429         RTFileReadAllFree(pbContent, cbContent);
    430     }
     435            RTMemFree(pSection);
     436        }
     437    }
     438    else
     439        rc = VERR_NO_MEMORY;
    431440    *ppSectionHead = NULL;
    432441    return rc;
    433442}
    434443
     444
     445
     446RTDECL(int) RTCrPemReadFile(const char *pszFilename, uint32_t fFlags, PCRTCRPEMMARKER paMarkers, size_t cMarkers,
     447                            PCRTCRPEMSECTION *ppSectionHead, PRTERRINFO pErrInfo)
     448{
     449    *ppSectionHead = NULL;
     450    AssertReturn(!(fFlags & ~RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR), VERR_INVALID_FLAGS);
     451
     452    size_t      cbContent;
     453    void        *pvContent;
     454    int rc = RTFileReadAllEx(pszFilename, 0, 64U*_1M, RTFILE_RDALL_O_DENY_WRITE, &pvContent, &cbContent);
     455    if (RT_SUCCESS(rc))
     456    {
     457        rc = RTCrPemParseContent(pvContent, cbContent, fFlags, paMarkers, cMarkers, ppSectionHead, pErrInfo);
     458        RTFileReadAllFree(pvContent, cbContent);
     459    }
     460    else
     461        rc = RTErrInfoSetF(pErrInfo, rc, "RTFileReadAllEx failed with %Rrc on '%s'", rc, pszFilename);
     462    return rc;
     463}
     464
  • trunk/src/VBox/Runtime/common/misc/http.cpp

    r57516 r57577  
    4141
    4242#include <curl/curl.h>
    43 #include <openssl/ssl.h>
    4443#include "internal/magics.h"
    4544
     
    6968typedef struct RTHTTPMEMCHUNK
    7069{
    71     uint8_t *pu8Mem;
    72     size_t cb;
     70    uint8_t    *pu8Mem;
     71    size_t      cb;
    7372} RTHTTPMEMCHUNK;
    7473typedef RTHTTPMEMCHUNK *PRTHTTPMEMCHUNK;
     
    122121}
    123122
     123
    124124RTR3DECL(void) RTHttpDestroy(RTHTTP hHttp)
    125125{
     
    147147    curl_global_cleanup();
    148148}
     149
    149150
    150151static DECLCALLBACK(size_t) rtHttpWriteData(void *pvBuf, size_t cb, size_t n, void *pvUser)
     
    163164}
    164165
    165 static DECLCALLBACK(int) rtHttpProgress(void *pData, double DlTotal, double DlNow,
    166                                         double UlTotal, double UlNow)
     166
     167static DECLCALLBACK(int) rtHttpProgress(void *pData, double DlTotal, double DlNow, double UlTotal, double UlNow)
    167168{
    168169    PRTHTTPINTERNAL pHttpInt = (PRTHTTPINTERNAL)pData;
     
    172173}
    173174
     175
    174176RTR3DECL(int) RTHttpAbort(RTHTTP hHttp)
    175177{
     
    181183    return VINF_SUCCESS;
    182184}
     185
    183186
    184187RTR3DECL(int) RTHttpGetRedirLocation(RTHTTP hHttp, char **ppszRedirLocation)
     
    193196    return VINF_SUCCESS;
    194197}
     198
    195199
    196200RTR3DECL(int) RTHttpUseSystemProxySettings(RTHTTP hHttp)
     
    229233}
    230234
     235
    231236RTR3DECL(int) RTHttpSetProxy(RTHTTP hHttp, const char *pcszProxy, uint32_t uPort,
    232237                             const char *pcszProxyUser, const char *pcszProxyPwd)
     
    260265    return VINF_SUCCESS;
    261266}
     267
    262268
    263269RTR3DECL(int) RTHttpSetHeaders(RTHTTP hHttp, size_t cHeaders, const char * const *papszHeaders)
     
    286292}
    287293
    288 RTR3DECL(int) RTHttpCertDigest(RTHTTP hHttp, char *pcszCert, size_t cbCert,
    289                                uint8_t **pabSha1,   size_t *pcbSha1,
    290                                uint8_t **pabSha512, size_t *pcbSha512)
    291 {
    292     int rc = VINF_SUCCESS;
    293 
    294     BIO *cert = BIO_new_mem_buf(pcszCert, (int)cbCert);
    295     if (cert)
    296     {
    297         X509 *crt = NULL;
    298         if (PEM_read_bio_X509(cert, &crt, NULL, NULL))
    299         {
    300             unsigned cb;
    301             unsigned char md[EVP_MAX_MD_SIZE];
    302 
    303             int rc1 = X509_digest(crt, EVP_sha1(), md, &cb);
    304             if (rc1 > 0)
    305             {
    306                 *pabSha1 = (uint8_t*)RTMemAlloc(cb);
    307                 if (*pabSha1)
    308                 {
    309                     memcpy(*pabSha1, md, cb);
    310                     *pcbSha1 = cb;
    311 
    312                     rc1 = X509_digest(crt, EVP_sha512(), md, &cb);
    313                     if (rc1 > 0)
    314                     {
    315                         *pabSha512 = (uint8_t*)RTMemAlloc(cb);
    316                         if (*pabSha512)
    317                         {
    318                             memcpy(*pabSha512, md, cb);
    319                             *pcbSha512 = cb;
    320                         }
    321                         else
    322                             rc = VERR_NO_MEMORY;
    323                     }
    324                     else
    325                         rc = VERR_HTTP_CACERT_WRONG_FORMAT;
    326 
    327                     if (RT_FAILURE(rc))
    328                         RTMemFree(*pabSha1);
    329                 }
    330                 else
    331                     rc = VERR_NO_MEMORY;
    332             }
    333             else
    334                 rc = VERR_HTTP_CACERT_WRONG_FORMAT;
    335             X509_free(crt);
    336         }
    337         else
    338             rc = VERR_HTTP_CACERT_WRONG_FORMAT;
    339         BIO_free(cert);
    340     }
    341     else
    342         rc = VERR_INTERNAL_ERROR;
    343 
    344     return rc;
    345 }
    346294
    347295RTR3DECL(int) RTHttpSetCAFile(RTHTTP hHttp, const char *pcszCAFile)
     
    449397}
    450398
     399
     400/**
     401 * Internal worker that performs a HTTP GET.
     402 *
     403 * @returns IPRT status code.
     404 * @param   hHttp               The HTTP instance.
     405 * @param   pcszUrl             The URL.
     406 * @param   ppvResponse         Where to return the pointer to the allocated
     407 *                              response data (RTMemFree).  There will always be
     408 *                              an zero terminator char after the response, that
     409 *                              is not part of the size returned via @a pcb.
     410 * @param   pcb                 The size of the response data.
     411 */
    451412RTR3DECL(int) rtHttpGet(RTHTTP hHttp, const char *pcszUrl, uint8_t **ppvResponse, size_t *pcb)
    452413{
     
    476437    }
    477438
    478     RTHTTPMEMCHUNK chunk = { NULL, 0 };
     439    RTHTTPMEMCHUNK Chunk = { NULL, 0 };
    479440    rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEFUNCTION, &rtHttpWriteData);
    480441    if (CURL_FAILED(rcCurl))
    481442        return VERR_INTERNAL_ERROR;
    482     rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEDATA, (void*)&chunk);
     443    rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEDATA, (void *)&Chunk);
    483444    if (CURL_FAILED(rcCurl))
    484445        return VERR_INTERNAL_ERROR;
     
    486447    if (CURL_FAILED(rcCurl))
    487448        return VERR_INTERNAL_ERROR;
    488     rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSDATA, (void*)pHttpInt);
     449    rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSDATA, (void *)pHttpInt);
    489450    if (CURL_FAILED(rcCurl))
    490451        return VERR_INTERNAL_ERROR;
     
    497458
    498459    rcCurl = curl_easy_perform(pHttpInt->pCurl);
     460
    499461    int rc = rtHttpGetCalcStatus(pHttpInt, rcCurl);
    500     *ppvResponse = chunk.pu8Mem;
    501     *pcb = chunk.cb;
     462    if (RT_SUCCESS(rc))
     463    {
     464        *ppvResponse = Chunk.pu8Mem;
     465        *pcb         = Chunk.cb;
     466    }
     467    else
     468    {
     469        if (Chunk.pu8Mem)
     470            RTMemFree(Chunk.pu8Mem);
     471        *ppvResponse = NULL;
     472        *pcb         = 0;
     473    }
    502474
    503475    return rc;
     
    505477
    506478
    507 RTR3DECL(int) RTHttpGetText(RTHTTP hHttp, const char *pcszUrl, char **ppszResponse)
     479RTR3DECL(int) RTHttpGetText(RTHTTP hHttp, const char *pcszUrl, char **ppszNotUtf8)
    508480{
    509481    uint8_t *pv;
    510     size_t cb;
     482    size_t   cb;
    511483    int rc = rtHttpGet(hHttp, pcszUrl, &pv, &cb);
    512     *ppszResponse = (char*)pv;
     484    if (RT_SUCCESS(rc))
     485    {
     486        if (pv) /* paranoia */
     487            *ppszNotUtf8 = (char *)pv;
     488        else
     489            *ppszNotUtf8 = (char *)RTMemDup("", 1);
     490    }
     491    else
     492        *ppszNotUtf8 = NULL;
    513493    return rc;
    514494}
    515495
    516496
     497RTR3DECL(void) RTHttpFreeResponseText(char *pszNotUtf8)
     498{
     499    RTMemFree(pszNotUtf8);
     500}
     501
     502
    517503RTR3DECL(int) RTHttpGetBinary(RTHTTP hHttp, const char *pcszUrl, void **ppvResponse, size_t *pcb)
    518504{
    519     return rtHttpGet(hHttp, pcszUrl, (uint8_t**)ppvResponse, pcb);
     505    return rtHttpGet(hHttp, pcszUrl, (uint8_t **)ppvResponse, pcb);
     506}
     507
     508
     509RTR3DECL(void) RTHttpFreeResponse(void *pvResponse)
     510{
     511    RTMemFree(pvResponse);
    520512}
    521513
     
    570562    if (CURL_FAILED(rcCurl))
    571563        return VERR_INTERNAL_ERROR;
    572     rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSDATA, (void*)pHttpInt);
     564    rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_PROGRESSDATA, (void *)pHttpInt);
    573565    if (CURL_FAILED(rcCurl))
    574566        return VERR_INTERNAL_ERROR;
  • trunk/src/VBox/Runtime/testcase/tstRTHttp.cpp

    r57358 r57577  
    2929*   Header Files                                                                                                                 *
    3030*********************************************************************************************************************************/
     31#include <iprt/http.h>
     32
    3133#include <iprt/err.h>
    32 #include <iprt/http.h>
     34#include <iprt/file.h>
     35#include <iprt/initterm.h>
    3336#include <iprt/mem.h>
    34 #include <iprt/file.h>
     37#include <iprt/message.h>
    3538#include <iprt/stream.h>
    3639#include <iprt/string.h>
    37 #include <iprt/initterm.h>
    3840#include <iprt/vfslowlevel.h>
    3941#include <iprt/zip.h>
     
    4143#define CAFILE_NAME "tstHttp-tempcafile.crt"
    4244
     45#if 0
    4346static int extractPCA3G5(RTHTTP hHttp, PRTSTREAM CAFile, uint8_t *pu8Buf, size_t cbBuf)
    4447{
     
    188191        RTPrintf("Error %Rrc trying to fetch '%s'\n", rc, pszFile);
    189192}
     193#endif
    190194
    191195int main(int argc, char **argv)
     
    200204        return 1;
    201205    }
     206
     207#if 0 /* rewrite to modified API and use test.h! */
    202208
    203209    for (int i = 1; i < argc; i++)
     
    343349
    344350    return !!cErrors;
     351#else
     352    RTMsgError("Needs rewriting. You're better off debugging the actual code in the GUI!\n");
     353    return RTEXITCODE_SKIPPED;
     354#endif
    345355}
     356
Note: See TracChangeset for help on using the changeset viewer.

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