Changeset 57577 in vbox for trunk/src/VBox
- Timestamp:
- Aug 28, 2015 6:57:36 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 102405
- Location:
- trunk/src/VBox
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/net/UINetworkReply.cpp
r57573 r57577 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UINetworkReply stuff implementation.3 * VBox Qt GUI - UINetworkReply, i.e. HTTP/HTTPS for update pings++. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2012-201 3Oracle Corporation7 * Copyright (C) 2012-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 37 37 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 38 38 39 #include <iprt/crypto/pem.h> 39 40 #include <iprt/crypto/store.h> 40 41 #include <iprt/err.h> … … 44 45 #include <iprt/zip.h> 45 46 46 /* Our network-reply thread: */ 47 48 /** 49 * Our network-reply thread 50 */ 47 51 class UINetworkReplyPrivateThread : public QThread 48 52 { … … 73 77 /** The certificate subject name. */ 74 78 const char *pszSubject; 75 /** @todo add zip path and direct URLs. */76 79 /** The size of the DER (ASN.1) encoded certificate. */ 77 80 uint16_t cbEncoded; … … 86 89 /** The SHA-512 fingerprint (of the encoded data). */ 87 90 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]; 88 95 } CERTINFO; 89 96 … … 103 110 * @{ */ 104 111 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); 110 116 static bool checkCertificatesInFile(const char *pszCaCertFile); 111 117 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); 116 121 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);122 122 /** @} */ 123 123 … … 128 128 QNetworkRequest m_request; 129 129 int m_iError; 130 RTHTTP m_pHttp; 130 /** IPRT HTTP client instance handle. */ 131 RTHTTP m_hHttp; 131 132 QByteArray m_reply; 132 133 … … 162 163 0x77, 0xa5, 0x40, 0x22, 0x18, 0x12, 0xcb, 0x3d, 163 164 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 }, 165 175 }, 166 176 /*[1] =*/ /* The original version with the MD2 signature. */ … … 185 195 0xce, 0xef, 0xb2, 0x71, 0x8e, 0x91, 0x60, 0xa2, 186 196 0xc8, 0x0c, 0x5a, 0xe7, 0x8b, 0x33, 0xf2, 0xaa 187 } 197 }, 198 /*.pszZipFile =*/ NULL, 199 /*.apszUrls[3] =*/ { NULL, NULL, NULL }, 188 200 }, 189 201 /*[2] =*/ … … 209 221 0x44, 0xeb, 0x2c, 0x74, 0x25, 0x9e, 0x5d, 0xfb, 210 222 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 }, 212 233 }, 213 234 }; … … 221 242 : m_request(request) 222 243 , m_iError(VINF_SUCCESS) 223 , m_ pHttp(0)244 , m_hHttp(NIL_RTHTTP) 224 245 { 225 246 } … … 228 249 { 229 250 /* Call for abort: */ 230 abort(m_pHttp); 251 if (m_hHttp != NIL_RTHTTP) 252 RTHttpAbort(m_hHttp); 231 253 } 232 254 … … 242 264 243 265 /* Apply proxy rules: */ 244 return applyProxyRules(m_ pHttp,266 return applyProxyRules(m_hHttp, 245 267 proxyManager.proxyHost(), 246 268 proxyManager.proxyPort().toUInt()); … … 264 286 int rc; 265 287 if (checkCertificatesInFile(pszCaCertFile)) 266 rc = RTHttpSetCAFile(m_ pHttp, pszCaCertFile);288 rc = RTHttpSetCAFile(m_hHttp, pszCaCertFile); 267 289 else 268 290 { … … 274 296 rc = retrieveCertificatesFromSystem(pszCaCertFile); 275 297 if (RT_FAILURE(rc)) 276 rc = downloadCertificates(m_ pHttp, strFullCertificateFileName);298 rc = downloadCertificates(m_hHttp, pszCaCertFile); 277 299 278 300 if (RT_SUCCESS(rc)) 279 rc = RTHttpSetCAFile(m_ pHttp, pszCaCertFile);301 rc = RTHttpSetCAFile(m_hHttp, pszCaCertFile); 280 302 } 281 303 … … 294 316 295 317 /* Apply raw headers: */ 296 return applyRawHeaders(m_ pHttp, headers, m_request);318 return applyRawHeaders(m_hHttp, headers, m_request); 297 319 } 298 320 … … 302 324 m_strContext = tr("During network request"); 303 325 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; 306 340 } 307 341 … … 309 343 { 310 344 /* Init: */ 311 RTR3InitExeNoArguments(RTR3INIT_FLAGS_SUPLIB); 345 RTR3InitExeNoArguments(RTR3INIT_FLAGS_SUPLIB); /** @todo r=bird: WTF? */ 312 346 313 347 /* Create HTTP object: */ 314 348 if (RT_SUCCESS(m_iError)) 315 m_iError = RTHttpCreate(&m_ pHttp);349 m_iError = RTHttpCreate(&m_hHttp); 316 350 317 351 /* Apply proxy-rules: */ … … 331 365 m_iError = performMainRequest(); 332 366 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); 338 374 } 339 375 } … … 347 383 348 384 /* static */ 349 int UINetworkReplyPrivateThread::a bort(RTHTTP pHttp)385 int UINetworkReplyPrivateThread::applyProxyRules(RTHTTP hHttp, const QString &strHostName, int iPort) 350 386 { 351 387 /* 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; 365 390 366 391 /* Apply HTTP proxy: */ 367 return RTHttpSetProxy( pHttp,392 return RTHttpSetProxy(hHttp, 368 393 strHostName.toAscii().constData(), 369 394 iPort, … … 372 397 373 398 /* static */ 374 int UINetworkReplyPrivateThread::applyRawHeaders(RTHTTP pHttp, const QList<QByteArray> &headers, const QNetworkRequest &request)399 int UINetworkReplyPrivateThread::applyRawHeaders(RTHTTP hHttp, const QList<QByteArray> &headers, const QNetworkRequest &request) 375 400 { 376 401 /* Make sure HTTP is created: */ 377 if ( !pHttp)378 return VERR_INVALID_ POINTER;402 if (hHttp == NIL_RTHTTP) 403 return VERR_INVALID_HANDLE; 379 404 380 405 /* We should format them first: */ … … 391 416 392 417 /* 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); 429 419 } 430 420 … … 436 426 * @param pszCaCertFile The path to the certificate file. 437 427 */ 438 /* static*/ bool428 /*static*/ bool 439 429 UINetworkReplyPrivateThread::checkCertificatesInFile(const char *pszCaCertFile) 440 430 { … … 483 473 484 474 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 483 UINetworkReplyPrivateThread::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 496 UINetworkReplyPrivateThread::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; 485 520 } 486 521 … … 528 563 if (RTSha512Check(pCertCtx->pabEncoded, pCertCtx->cbEncoded, s_aCerts[i].abSha512)) 529 564 { 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); 549 566 break; 550 567 } … … 565 582 * Did we locate all of them? 566 583 */ 567 AssertCompile(RT_ELEMENTS(s_aCerts) < 64); 568 if (fFoundCerts == RT_BIT_64(RT_ELEMENTS(s_aCerts)) - UINT64_C(1)) 584 if (fFoundCerts == certAllFoundMask()) 569 585 return true; 570 586 } … … 573 589 } 574 590 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 592 UINetworkReplyPrivateThread::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 690 UINetworkReplyPrivateThread::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)); 582 706 if (RT_SUCCESS(rc)) 583 707 { 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 } 671 741 return rc; 672 742 } … … 679 749 * @param pszCaCertFile Where to store the certificates. 680 750 */ 681 int UINetworkReplyPrivateThread::retrieveCertificatesFromSystem(const char *pszCaCertFile) 751 /*static*/ int 752 UINetworkReplyPrivateThread::retrieveCertificatesFromSystem(const char *pszCaCertFile) 682 753 { 683 754 /* … … 711 782 712 783 /* 713 * See if we've got the certificates we want .784 * See if we've got the certificates we want, save it we do. 714 785 */ 715 786 if (checkCertificatesInStore(hUserStore)) … … 722 793 723 794 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 */ 824 799 class UINetworkReplyPrivate : public QObject 825 800 { -
trunk/src/VBox/Runtime/common/crypto/pemfile.cpp
r57572 r57577 264 264 * @param cbFile The number of bytes. 265 265 */ 266 static bool rtCrPemIsBinary File(uint8_t *pbFile, size_t cbFile)266 static bool rtCrPemIsBinaryBlob(uint8_t const *pbFile, size_t cbFile) 267 267 { 268 268 /* … … 334 334 335 335 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) ) 336 RTDECL(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 (;;) 357 368 { 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)) 360 384 { 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 376 391 { 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; 401 393 break; 402 394 } 403 395 } 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)) 405 407 { 406 RTFileReadAllFree(pbContent, cbContent);407 return rc;408 rc = VERR_NO_MEMORY; 409 break; 408 410 } 409 410 RTCrPemFreeSections(*ppSectionHead);411 411 } 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) 413 429 { 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;423 430 *ppSectionHead = pSection; 424 431 return VINF_SUCCESS; 425 432 } 426 } 427 else 433 428 434 rc = VERR_NO_MEMORY; 429 RTFileReadAllFree(pbContent, cbContent); 430 } 435 RTMemFree(pSection); 436 } 437 } 438 else 439 rc = VERR_NO_MEMORY; 431 440 *ppSectionHead = NULL; 432 441 return rc; 433 442 } 434 443 444 445 446 RTDECL(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 41 41 42 42 #include <curl/curl.h> 43 #include <openssl/ssl.h>44 43 #include "internal/magics.h" 45 44 … … 69 68 typedef struct RTHTTPMEMCHUNK 70 69 { 71 uint8_t *pu8Mem;72 size_t cb;70 uint8_t *pu8Mem; 71 size_t cb; 73 72 } RTHTTPMEMCHUNK; 74 73 typedef RTHTTPMEMCHUNK *PRTHTTPMEMCHUNK; … … 122 121 } 123 122 123 124 124 RTR3DECL(void) RTHttpDestroy(RTHTTP hHttp) 125 125 { … … 147 147 curl_global_cleanup(); 148 148 } 149 149 150 150 151 static DECLCALLBACK(size_t) rtHttpWriteData(void *pvBuf, size_t cb, size_t n, void *pvUser) … … 163 164 } 164 165 165 static DECLCALLBACK(int) rtHttpProgress(void *pData, double DlTotal, double DlNow, 166 166 167 static DECLCALLBACK(int) rtHttpProgress(void *pData, double DlTotal, double DlNow, double UlTotal, double UlNow) 167 168 { 168 169 PRTHTTPINTERNAL pHttpInt = (PRTHTTPINTERNAL)pData; … … 172 173 } 173 174 175 174 176 RTR3DECL(int) RTHttpAbort(RTHTTP hHttp) 175 177 { … … 181 183 return VINF_SUCCESS; 182 184 } 185 183 186 184 187 RTR3DECL(int) RTHttpGetRedirLocation(RTHTTP hHttp, char **ppszRedirLocation) … … 193 196 return VINF_SUCCESS; 194 197 } 198 195 199 196 200 RTR3DECL(int) RTHttpUseSystemProxySettings(RTHTTP hHttp) … … 229 233 } 230 234 235 231 236 RTR3DECL(int) RTHttpSetProxy(RTHTTP hHttp, const char *pcszProxy, uint32_t uPort, 232 237 const char *pcszProxyUser, const char *pcszProxyPwd) … … 260 265 return VINF_SUCCESS; 261 266 } 267 262 268 263 269 RTR3DECL(int) RTHttpSetHeaders(RTHTTP hHttp, size_t cHeaders, const char * const *papszHeaders) … … 286 292 } 287 293 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 else322 rc = VERR_NO_MEMORY;323 }324 else325 rc = VERR_HTTP_CACERT_WRONG_FORMAT;326 327 if (RT_FAILURE(rc))328 RTMemFree(*pabSha1);329 }330 else331 rc = VERR_NO_MEMORY;332 }333 else334 rc = VERR_HTTP_CACERT_WRONG_FORMAT;335 X509_free(crt);336 }337 else338 rc = VERR_HTTP_CACERT_WRONG_FORMAT;339 BIO_free(cert);340 }341 else342 rc = VERR_INTERNAL_ERROR;343 344 return rc;345 }346 294 347 295 RTR3DECL(int) RTHttpSetCAFile(RTHTTP hHttp, const char *pcszCAFile) … … 449 397 } 450 398 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 */ 451 412 RTR3DECL(int) rtHttpGet(RTHTTP hHttp, const char *pcszUrl, uint8_t **ppvResponse, size_t *pcb) 452 413 { … … 476 437 } 477 438 478 RTHTTPMEMCHUNK chunk = { NULL, 0 };439 RTHTTPMEMCHUNK Chunk = { NULL, 0 }; 479 440 rcCurl = curl_easy_setopt(pHttpInt->pCurl, CURLOPT_WRITEFUNCTION, &rtHttpWriteData); 480 441 if (CURL_FAILED(rcCurl)) 481 442 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); 483 444 if (CURL_FAILED(rcCurl)) 484 445 return VERR_INTERNAL_ERROR; … … 486 447 if (CURL_FAILED(rcCurl)) 487 448 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); 489 450 if (CURL_FAILED(rcCurl)) 490 451 return VERR_INTERNAL_ERROR; … … 497 458 498 459 rcCurl = curl_easy_perform(pHttpInt->pCurl); 460 499 461 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 } 502 474 503 475 return rc; … … 505 477 506 478 507 RTR3DECL(int) RTHttpGetText(RTHTTP hHttp, const char *pcszUrl, char **ppsz Response)479 RTR3DECL(int) RTHttpGetText(RTHTTP hHttp, const char *pcszUrl, char **ppszNotUtf8) 508 480 { 509 481 uint8_t *pv; 510 size_t cb;482 size_t cb; 511 483 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; 513 493 return rc; 514 494 } 515 495 516 496 497 RTR3DECL(void) RTHttpFreeResponseText(char *pszNotUtf8) 498 { 499 RTMemFree(pszNotUtf8); 500 } 501 502 517 503 RTR3DECL(int) RTHttpGetBinary(RTHTTP hHttp, const char *pcszUrl, void **ppvResponse, size_t *pcb) 518 504 { 519 return rtHttpGet(hHttp, pcszUrl, (uint8_t**)ppvResponse, pcb); 505 return rtHttpGet(hHttp, pcszUrl, (uint8_t **)ppvResponse, pcb); 506 } 507 508 509 RTR3DECL(void) RTHttpFreeResponse(void *pvResponse) 510 { 511 RTMemFree(pvResponse); 520 512 } 521 513 … … 570 562 if (CURL_FAILED(rcCurl)) 571 563 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); 573 565 if (CURL_FAILED(rcCurl)) 574 566 return VERR_INTERNAL_ERROR; -
trunk/src/VBox/Runtime/testcase/tstRTHttp.cpp
r57358 r57577 29 29 * Header Files * 30 30 *********************************************************************************************************************************/ 31 #include <iprt/http.h> 32 31 33 #include <iprt/err.h> 32 #include <iprt/http.h> 34 #include <iprt/file.h> 35 #include <iprt/initterm.h> 33 36 #include <iprt/mem.h> 34 #include <iprt/ file.h>37 #include <iprt/message.h> 35 38 #include <iprt/stream.h> 36 39 #include <iprt/string.h> 37 #include <iprt/initterm.h>38 40 #include <iprt/vfslowlevel.h> 39 41 #include <iprt/zip.h> … … 41 43 #define CAFILE_NAME "tstHttp-tempcafile.crt" 42 44 45 #if 0 43 46 static int extractPCA3G5(RTHTTP hHttp, PRTSTREAM CAFile, uint8_t *pu8Buf, size_t cbBuf) 44 47 { … … 188 191 RTPrintf("Error %Rrc trying to fetch '%s'\n", rc, pszFile); 189 192 } 193 #endif 190 194 191 195 int main(int argc, char **argv) … … 200 204 return 1; 201 205 } 206 207 #if 0 /* rewrite to modified API and use test.h! */ 202 208 203 209 for (int i = 1; i < argc; i++) … … 343 349 344 350 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 345 355 } 356
Note:
See TracChangeset
for help on using the changeset viewer.