Skip to content

Commit

Permalink
[stable] warn about TLS for github specifically
Browse files Browse the repository at this point in the history
  • Loading branch information
matklad committed Feb 26, 2018
1 parent 8c93e08 commit 2dfa4ce
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/cargo/sources/git/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ pub fn fetch(repo: &mut git2::Repository,
opts.remote_callbacks(cb)
.download_tags(git2::AutotagOption::All);

network::with_retry(config, || {
network::with_retry(config, url, || {
debug!("initiating fetch of {} from {}", refspec, url);
remote.fetch(&[refspec], Some(&mut opts), None)
.map_err(CargoError::from)
Expand Down
11 changes: 6 additions & 5 deletions src/cargo/sources/registry/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,14 +216,13 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
// TODO: don't download into memory, but ensure that if we ctrl-c a
// download we should resume either from the start or the middle
// on the next time
let url = url.to_string();
let mut handle = self.config.http()?.borrow_mut();
handle.get(true)?;
handle.url(&url)?;
handle.url(&url.to_string())?;
handle.follow_location(true)?;
let mut state = Sha256::new();
let mut body = Vec::new();
network::with_retry(self.config, || {
network::with_retry(self.config, &url, || {
state = Sha256::new();
body = Vec::new();
let mut pb = Progress::new("Fetch", self.config);
Expand All @@ -242,8 +241,10 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
}
let code = handle.response_code()?;
if code != 200 && code != 0 {
let url = handle.effective_url()?.unwrap_or(&url);
Err(HttpNot200 { code, url: url.to_string() }.into())
let url = handle.effective_url()?
.map(|url| url.to_string())
.unwrap_or_else(|| url.to_string());
Err(HttpNot200 { code, url }.into())
} else {
Ok(())
}
Expand Down
51 changes: 44 additions & 7 deletions src/cargo/util/network.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use curl;
use git2;
use url::Url;

use failure::Error;

Expand Down Expand Up @@ -33,6 +34,35 @@ fn maybe_spurious(err: &Error) -> bool {
false
}


/// Suggest the user to update their windows 7 to support modern TLS versions.
/// See https://github.com/rust-lang/cargo/issues/5066 for details.
#[cfg(windows)]
fn should_warn_about_old_tls_for_win7(url: &Url, err: &Error) -> bool {
let is_github = url.host_str() == Some("github.com");
let is_cert_error = err.causes()
.filter_map(|e| e.downcast_ref::<git2::Error>())
.find(|e| e.class() == git2::ErrorClass::Net && e.code() == git2::ErrorCode::Certificate)
.is_some();
is_github && is_cert_error
}

#[cfg(not(windows))]
fn should_warn_about_old_tls_for_win7(_url: &Url, _err: &Error) -> bool {
false
}

const WIN7_TLS_WARNING: &str = "\
Certificate check failure might be caused by outdated TLS on older versions of Windows.
If you are using Windows 7, Windows Server 2008 R2 or Windows Server 2012,
please follow these instructions to enable more secure TLS:
https://support.microsoft.com/en-us/help/3140245/
See https://github.com/rust-lang/cargo/issues/5066 for details.
";


/// Wrapper method for network call retry logic.
///
/// Retry counts provided by Config object `net.retry`. Config shell outputs
Expand All @@ -44,19 +74,24 @@ fn maybe_spurious(err: &Error) -> bool {
///
/// ```ignore
/// use util::network;
/// cargo_result = network.with_retry(&config, || something.download());
/// cargo_result = network::with_retry(&config, || something.download());
/// ```
pub fn with_retry<T, F>(config: &Config, mut callback: F) -> CargoResult<T>
pub fn with_retry<T, F>(config: &Config, url: &Url, mut callback: F) -> CargoResult<T>
where F: FnMut() -> CargoResult<T>
{
let mut remaining = config.net_retry()?;
loop {
match callback() {
Ok(ret) => return Ok(ret),
Err(ref e) if maybe_spurious(e) && remaining > 0 => {
let msg = format!("spurious network error ({} tries \
remaining): {}", remaining, e);
config.shell().warn(msg)?;
config.shell().warn(
format!("spurious network error ({} tries remaining): {}", remaining, e)
)?;

if should_warn_about_old_tls_for_win7(url, e) {
config.shell().warn(WIN7_TLS_WARNING)?;
}

remaining -= 1;
}
//todo impl from
Expand All @@ -71,7 +106,8 @@ fn with_retry_repeats_the_call_then_works() {
let error2 = HttpNot200 { code: 502, url: "Uri".to_string() }.into();
let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
let config = Config::default().unwrap();
let result = with_retry(&config, || results.pop().unwrap());
let url = "http://example.com".parse().unwrap();
let result = with_retry(&config, &url, || results.pop().unwrap());
assert_eq!(result.unwrap(), ())
}

Expand All @@ -87,6 +123,7 @@ fn with_retry_finds_nested_spurious_errors() {
let error2 = CargoError::from(error2.context("A second chained error"));
let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
let config = Config::default().unwrap();
let result = with_retry(&config, || results.pop().unwrap());
let url = "http://example.com".parse().unwrap();
let result = with_retry(&config, &url, || results.pop().unwrap());
assert_eq!(result.unwrap(), ())
}

0 comments on commit 2dfa4ce

Please sign in to comment.