From b856745048212175eac19536e40cf563b874f6b4 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 21 Aug 2020 20:14:26 +0300 Subject: SL-13835 SSL verification should not crash on invalid certificate --- indra/newview/llappcorehttp.cpp | 22 +++++++++++----------- indra/newview/llsecapi.h | 10 ++++++++++ indra/newview/llsechandler_basic.cpp | 6 ++++-- indra/newview/llstartup.cpp | 21 +++++++++++++++++++-- indra/newview/skins/default/xui/en/strings.xml | 1 + 5 files changed, 45 insertions(+), 15 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index afa4414968..134a34137b 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -522,20 +522,20 @@ void LLAppCoreHttp::refreshSettings(bool initial) LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url, const LLCore::HttpHandler::ptr_t &handler, void *appdata) { - X509_STORE_CTX *ctx = static_cast(appdata); - LLCore::HttpStatus result; - LLPointer store = gSecAPIHandler->getCertificateStore(""); - LLPointer chain = gSecAPIHandler->getCertificateChain(ctx); - LLSD validation_params = LLSD::emptyMap(); - LLURI uri(url); + LLCore::HttpStatus result; + try + { + X509_STORE_CTX *ctx = static_cast(appdata); + LLPointer store = gSecAPIHandler->getCertificateStore(""); + LLPointer chain = gSecAPIHandler->getCertificateChain(ctx); + LLSD validation_params = LLSD::emptyMap(); + LLURI uri(url); - validation_params[CERT_HOSTNAME] = uri.hostName(); + validation_params[CERT_HOSTNAME] = uri.hostName(); - // *TODO: In the case of an exception while validating the cert, we need a way - // to pass the offending(?) cert back out. *Rider* + // *TODO: In the case of an exception while validating the cert, we need a way + // to pass the offending(?) cert back out. *Rider* - try - { // don't validate hostname. Let libcurl do it instead. That way, it'll handle redirects store->validate(VALIDATION_POLICY_SSL & (~VALIDATION_POLICY_HOSTNAME), chain, validation_params); } diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 69b6b32923..ae87cac53c 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -345,6 +345,16 @@ protected: LLSD mCertData; }; +class LLAllocationCertException : public LLCertException +{ +public: + LLAllocationCertException(const LLSD& cert_data) : LLCertException(cert_data, "CertAllocationFailure") + { + } + virtual ~LLAllocationCertException() throw() {} +protected: +}; + class LLInvalidCertificate : public LLCertException { public: diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 8e52480644..8a922aee4f 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -78,14 +78,16 @@ LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert, BIO * pem_bio = BIO_new_mem_buf((void*)pem_cert.c_str(), pem_cert.length()); if(pem_bio == NULL) { - LL_ERRS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL; + LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL; + LLTHROW(LLAllocationCertException(LLSD::emptyMap())); } mCert = NULL; PEM_read_bio_X509(pem_bio, &mCert, 0, NULL); BIO_free(pem_bio); if (!mCert) { - LL_ERRS("SECAPI") << "Could not decode certificate to x509." << LL_ENDL; + LL_WARNS("SECAPI") << "Could not decode certificate to x509." << LL_ENDL; + LLTHROW(LLInvalidCertificate(LLSD::emptyMap())); } } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 1257add71d..b130fd281c 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1106,7 +1106,7 @@ bool idle_startup() // If optional was skipped this case shouldn't // be reached. - LL_INFOS() << "Forcing a quit due to update." << LL_ENDL; + LL_INFOS("LLStartup") << "Forcing a quit due to update." << LL_ENDL; LLLoginInstance::getInstance()->disconnect(); LLAppViewer::instance()->forceQuit(); } @@ -1127,7 +1127,24 @@ bool idle_startup() { // This was a certificate error, so grab the certificate // and throw up the appropriate dialog. - LLPointer certificate = gSecAPIHandler->getCertificate(response["certificate"]); + LLPointer certificate; + try + { + certificate = gSecAPIHandler->getCertificate(response["certificate"]); + } + catch (LLCertException &cert_exception) + { + LL_WARNS("LLStartup", "SECAPI") << "Caught " << cert_exception.what() << " certificate expception on getCertificate()" << LL_ENDL; + LLSD args; + args["REASON"] = LLTrans::getString(cert_exception.what()); + + LLNotificationsUtil::add("GeneralCertificateError", args, response, + general_cert_done); + + reset_login(); + gSavedSettings.setBOOL("AutoLogin", FALSE); + show_connect_box = true; + } if(certificate) { LLSD args = transform_cert_args(certificate); diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 73ee8332cc..30416768cd 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -108,6 +108,7 @@ Voice Server Version: [VOICE_VERSION] The certificate returned by the server could not be used for SSL. Please contact your Grid administrator. Too many certificates were in the servers Certificate chain. Please contact your Grid administrator. The certificate signature returned by the Grid server could not be verified. Please contact your Grid administrator. + Failed to allocate openssl memory for certificate. Network error: Could not establish connection, please check your network connection. Login failed. -- cgit v1.2.3