aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/net/http_loader.rs40
-rw-r--r--components/net/resource_thread.rs4
-rw-r--r--components/net_traits/lib.rs2
-rw-r--r--components/script/dom/servohtmlparser.rs9
-rw-r--r--resources/badcert.html3
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>