diff options
-rw-r--r-- | components/net/http_loader.rs | 40 | ||||
-rw-r--r-- | components/net/resource_thread.rs | 4 | ||||
-rw-r--r-- | components/net_traits/lib.rs | 2 | ||||
-rw-r--r-- | components/script/dom/servohtmlparser.rs | 9 | ||||
-rw-r--r-- | resources/badcert.html | 3 |
5 files changed, 46 insertions, 12 deletions
diff --git a/components/net/http_loader.rs b/components/net/http_loader.rs index 2855e38bf45..593ae3e1ead 100644 --- a/components/net/http_loader.rs +++ b/components/net/http_loader.rs @@ -33,6 +33,7 @@ use net_traits::hosts::replace_hosts; use net_traits::response::HttpsState; use net_traits::{CookieSource, IncludeSubdomains, LoadConsumer, LoadContext, LoadData}; use net_traits::{Metadata, NetworkError, RequestSource, CustomResponse}; +use openssl; use openssl::ssl::error::{SslError, OpensslError}; use profile_traits::time::{ProfilerCategory, profile, ProfilerChan, TimerMetadata}; use profile_traits::time::{TimerMetadataReflowType, TimerMetadataFrameType}; @@ -143,8 +144,8 @@ fn load_for_consumer(load_data: LoadData, Err(error) => { match error.error { LoadErrorType::ConnectionAborted { .. } => unreachable!(), - LoadErrorType::Ssl { .. } => send_error(error.url.clone(), - NetworkError::SslValidation(error.url), + LoadErrorType::Ssl { reason } => send_error(error.url.clone(), + NetworkError::SslValidation(error.url, reason), start_chan), LoadErrorType::Cancelled => send_error(error.url, NetworkError::LoadCancelled, start_chan), _ => send_error(error.url, NetworkError::Internal(error.error.description().to_owned()), start_chan) @@ -259,8 +260,21 @@ impl HttpRequestFactory for NetworkHttpRequestFactory { let error: &(Error + Send + 'static) = &**error; if let Some(&SslError::OpenSslErrors(ref errors)) = error.downcast_ref::<SslError>() { if errors.iter().any(is_cert_verify_error) { - let msg = format!("ssl error: {:?} {:?}", error.description(), error.cause()); - return Err(LoadError::new(url, LoadErrorType::Ssl { reason: msg })); + let mut error_report = vec![format!("ssl error ({}):", openssl::version::version())]; + let mut suggestion = None; + for err in errors { + if is_unknown_message_digest_err(err) { + suggestion = Some("<b>Servo recommends upgrading to a newer OpenSSL version.</b>"); + } + error_report.push(format_ssl_error(err)); + } + + if let Some(suggestion) = suggestion { + error_report.push(suggestion.to_owned()); + } + + let error_report = error_report.join("<br>\n"); + return Err(LoadError::new(url, LoadErrorType::Ssl { reason: error_report })); } } } @@ -1126,6 +1140,24 @@ fn is_cert_verify_error(error: &OpensslError) -> bool { } } +fn is_unknown_message_digest_err(error: &OpensslError) -> bool { + match error { + &OpensslError::UnknownError { ref library, ref function, ref reason } => { + library == "asn1 encoding routines" && + function == "ASN1_item_verify" && + reason == "unknown message digest algorithm" + } + } +} + +fn format_ssl_error(error: &OpensslError) -> String { + match error { + &OpensslError::UnknownError { ref library, ref function, ref reason } => { + format!("{}: {} - {}", library, function, reason) + } + } +} + fn to_resource_type(context: &LoadContext) -> ResourceType { match *context { LoadContext::Browsing => ResourceType::Document, diff --git a/components/net/resource_thread.rs b/components/net/resource_thread.rs index 6825437e162..4cb046566af 100644 --- a/components/net/resource_thread.rs +++ b/components/net/resource_thread.rs @@ -158,8 +158,8 @@ fn start_sending_opt(start_chan: LoadConsumer, metadata: Metadata, } LoadConsumer::Listener(target) => { match network_error { - Some(NetworkError::SslValidation(url)) => { - let error = NetworkError::SslValidation(url); + Some(NetworkError::SslValidation(url, reason)) => { + let error = NetworkError::SslValidation(url, reason); target.invoke_with_listener(ResponseAction::HeadersAvailable(Err(error))); } _ => target.invoke_with_listener(ResponseAction::HeadersAvailable(Ok(metadata))), diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index bb9e31ad160..d4da6d0d058 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -667,7 +667,7 @@ pub enum NetworkError { Internal(String), LoadCancelled, /// SSL validation error that has to be handled in the HTML parser - SslValidation(Url), + SslValidation(Url, String), } /// Normalize `slice`, as defined by diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs index 75d6a5e502f..884ac6c8653 100644 --- a/components/script/dom/servohtmlparser.rs +++ b/components/script/dom/servohtmlparser.rs @@ -81,11 +81,11 @@ impl ParserContext { impl AsyncResponseListener for ParserContext { fn headers_available(&mut self, meta_result: Result<Metadata, NetworkError>) { - let mut is_ssl_error = false; + let mut ssl_error = None; let metadata = match meta_result { Ok(meta) => Some(meta), - Err(NetworkError::SslValidation(url)) => { - is_ssl_error = true; + Err(NetworkError::SslValidation(url, reason)) => { + ssl_error = Some(reason); let mut meta = Metadata::default(url); let mime: Option<Mime> = "text/html".parse().ok(); meta.set_content_type(mime.as_ref()); @@ -124,10 +124,11 @@ impl AsyncResponseListener for ParserContext { parser.set_plaintext_state(); }, Some(ContentType(Mime(TopLevel::Text, SubLevel::Html, _))) => { // Handle text/html - if is_ssl_error { + if let Some(reason) = ssl_error { self.is_synthesized_document = true; let page_bytes = read_resource_file("badcert.html").unwrap(); let page = String::from_utf8(page_bytes).unwrap(); + let page = page.replace("${reason}", &reason); parser.pending_input().borrow_mut().push(page); parser.parse_sync(); } diff --git a/resources/badcert.html b/resources/badcert.html index 9bb98db2148..fca069fac2a 100644 --- a/resources/badcert.html +++ b/resources/badcert.html @@ -3,6 +3,7 @@ <title>Certificate error</title> </head> <body> - <img src="chrome://resources/badcert.jpg"> + <img src="chrome://resources/itried.jpg"> + <p>${reason}</p> </body> </html> |