Skip to content

Commit ce87cfa

Browse files
committed
Auto merge of #5069 - matklad:win7-y-u-no-tls, r=alexcrichton
Warn Windows 7 users about old TLS An eyepatch for #5066. @retep998 what would the best way to check for windows 7 specifically? Currently I use just `#[cfg(windows)]`, which might give false positives on 8 and 10.
2 parents 8830eca + 81e18de commit ce87cfa

File tree

3 files changed

+51
-13
lines changed

3 files changed

+51
-13
lines changed

src/cargo/sources/git/utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ pub fn with_fetch_options(git_config: &git2::Config,
591591
-> CargoResult<()>
592592
{
593593
let mut progress = Progress::new("Fetch", config);
594-
network::with_retry(config, || {
594+
network::with_retry(config, url, || {
595595
with_authentication(url.as_str(), git_config, |f| {
596596
let mut rcb = git2::RemoteCallbacks::new();
597597
rcb.credentials(f);

src/cargo/sources/registry/remote.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -224,14 +224,13 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
224224
// TODO: don't download into memory, but ensure that if we ctrl-c a
225225
// download we should resume either from the start or the middle
226226
// on the next time
227-
let url = url.to_string();
228227
let mut handle = self.config.http()?.borrow_mut();
229228
handle.get(true)?;
230-
handle.url(&url)?;
229+
handle.url(&url.to_string())?;
231230
handle.follow_location(true)?;
232231
let mut state = Sha256::new();
233232
let mut body = Vec::new();
234-
network::with_retry(self.config, || {
233+
network::with_retry(self.config, &url, || {
235234
state = Sha256::new();
236235
body = Vec::new();
237236
let mut pb = Progress::new("Fetch", self.config);
@@ -250,8 +249,10 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
250249
}
251250
let code = handle.response_code()?;
252251
if code != 200 && code != 0 {
253-
let url = handle.effective_url()?.unwrap_or(&url);
254-
Err(HttpNot200 { code, url: url.to_string() }.into())
252+
let url = handle.effective_url()?
253+
.map(|url| url.to_string())
254+
.unwrap_or_else(|| url.to_string());
255+
Err(HttpNot200 { code, url }.into())
255256
} else {
256257
Ok(())
257258
}

src/cargo/util/network.rs

+44-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use curl;
22
use git2;
3+
use url::Url;
34

45
use failure::Error;
56

@@ -33,6 +34,35 @@ fn maybe_spurious(err: &Error) -> bool {
3334
false
3435
}
3536

37+
38+
/// Suggest the user to update their windows 7 to support modern TLS versions.
39+
/// See https://github.com/rust-lang/cargo/issues/5066 for details.
40+
#[cfg(windows)]
41+
fn should_warn_about_old_tls_for_win7(url: &Url, err: &Error) -> bool {
42+
let is_github = url.host_str() == Some("github.com");
43+
let is_cert_error = err.causes()
44+
.filter_map(|e| e.downcast_ref::<git2::Error>())
45+
.find(|e| e.class() == git2::ErrorClass::Net && e.code() == git2::ErrorCode::Certificate)
46+
.is_some();
47+
is_github && is_cert_error
48+
}
49+
50+
#[cfg(not(windows))]
51+
fn should_warn_about_old_tls_for_win7(_url: &Url, _err: &Error) -> bool {
52+
false
53+
}
54+
55+
const WIN7_TLS_WARNING: &str = "\
56+
Certificate check failure might be caused by outdated TLS on older versions of Windows.
57+
If you are using Windows 7, Windows Server 2008 R2 or Windows Server 2012,
58+
please follow these instructions to enable more secure TLS:
59+
60+
https://support.microsoft.com/en-us/help/3140245/
61+
62+
See https://github.com/rust-lang/cargo/issues/5066 for details.
63+
";
64+
65+
3666
/// Wrapper method for network call retry logic.
3767
///
3868
/// Retry counts provided by Config object `net.retry`. Config shell outputs
@@ -44,19 +74,24 @@ fn maybe_spurious(err: &Error) -> bool {
4474
///
4575
/// ```ignore
4676
/// use util::network;
47-
/// cargo_result = network.with_retry(&config, || something.download());
77+
/// cargo_result = network::with_retry(&config, || something.download());
4878
/// ```
49-
pub fn with_retry<T, F>(config: &Config, mut callback: F) -> CargoResult<T>
79+
pub fn with_retry<T, F>(config: &Config, url: &Url, mut callback: F) -> CargoResult<T>
5080
where F: FnMut() -> CargoResult<T>
5181
{
5282
let mut remaining = config.net_retry()?;
5383
loop {
5484
match callback() {
5585
Ok(ret) => return Ok(ret),
5686
Err(ref e) if maybe_spurious(e) && remaining > 0 => {
57-
let msg = format!("spurious network error ({} tries \
58-
remaining): {}", remaining, e);
59-
config.shell().warn(msg)?;
87+
config.shell().warn(
88+
format!("spurious network error ({} tries remaining): {}", remaining, e)
89+
)?;
90+
91+
if should_warn_about_old_tls_for_win7(url, e) {
92+
config.shell().warn(WIN7_TLS_WARNING)?;
93+
}
94+
6095
remaining -= 1;
6196
}
6297
//todo impl from
@@ -71,7 +106,8 @@ fn with_retry_repeats_the_call_then_works() {
71106
let error2 = HttpNot200 { code: 502, url: "Uri".to_string() }.into();
72107
let mut results: Vec<CargoResult<()>> = vec![Ok(()), Err(error1), Err(error2)];
73108
let config = Config::default().unwrap();
74-
let result = with_retry(&config, || results.pop().unwrap());
109+
let url = "http://example.com".parse().unwrap();
110+
let result = with_retry(&config, &url, || results.pop().unwrap());
75111
assert_eq!(result.unwrap(), ())
76112
}
77113

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

0 commit comments

Comments
 (0)