Skip to content

Commit a3b4b9e

Browse files
committed
Re-add rustls support and enable it by default
rustls is seen as mature enough for curl to depend on it optionally, and it recently has had an audit. This commit adds back rustls support removed by 86bb185 and enables it by default. You can opt out of rustls use by setting the RUSTUP_AVOID_RUSTLS env variable.
1 parent 243b453 commit a3b4b9e

File tree

6 files changed

+186
-21
lines changed

6 files changed

+186
-21
lines changed

Cargo.lock

Lines changed: 95 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@ version = "1.22.1"
1313

1414
[features]
1515
curl-backend = ["download/curl-backend"]
16-
default = ["curl-backend", "reqwest-backend"]
16+
default = ["curl-backend", "reqwest-backend", "reqwest-default-tls", "reqwest-rustls-tls"]
17+
1718
reqwest-backend = ["download/reqwest-backend"]
1819
vendored-openssl = ['openssl/vendored']
20+
21+
reqwest-default-tls = ["download/reqwest-default-tls"]
22+
reqwest-rustls-tls = ["download/reqwest-rustls-tls"]
23+
1924
# Include in the default set to disable self-update and uninstall.
2025
no-self-update = []
2126

@@ -25,7 +30,7 @@ anyhow = "1.0.31"
2530
cfg-if = "0.1"
2631
chrono = "0.4"
2732
clap = "2"
28-
download = {path = "download"}
33+
download = { path = "download", default-features = false }
2934
error-chain = "0.12"
3035
flate2 = "1"
3136
git-testament = "0.1.4"

download/Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,20 @@ license = "MIT/Apache-2.0"
99

1010
[features]
1111

12-
default = ["reqwest-backend"]
12+
default = ["reqwest-backend", "reqwest-rustls-tls", "reqwest-default-tls"]
1313

1414
curl-backend = ["curl"]
1515
reqwest-backend = ["reqwest", "env_proxy", "lazy_static"]
16+
reqwest-default-tls = ["reqwest/default-tls"]
17+
reqwest-rustls-tls = ["reqwest/rustls-tls"]
1618

1719
[dependencies]
1820
error-chain = "0.12"
1921
url = "2.1"
2022
curl = { version = "0.4.11", optional = true }
2123
env_proxy = { version = "0.4.1", optional = true }
2224
lazy_static = { version = "1.0", optional = true }
23-
reqwest = { version = "0.10", features = ["blocking", "gzip", "socks"], optional = true }
25+
reqwest = { version = "0.10", default-features = false, features = ["blocking", "gzip", "socks"], optional = true }
2426

2527
[dev-dependencies]
2628
hyper = { version = "0.13", default-features = false, features = ["tcp"] }

download/src/lib.rs

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ pub use crate::errors::*;
1010
#[derive(Debug, Copy, Clone)]
1111
pub enum Backend {
1212
Curl,
13-
Reqwest,
13+
Reqwest(TlsBackend),
14+
}
15+
16+
#[derive(Debug, Copy, Clone)]
17+
pub enum TlsBackend {
18+
Rustls,
19+
Default,
1420
}
1521

1622
#[derive(Debug, Copy, Clone)]
@@ -30,7 +36,7 @@ fn download_with_backend(
3036
) -> Result<()> {
3137
match backend {
3238
Backend::Curl => curl::download(url, resume_from, callback),
33-
Backend::Reqwest => reqwest_be::download(url, resume_from, callback),
39+
Backend::Reqwest(tls) => reqwest_be::download(url, resume_from, callback, tls),
3440
}
3541
}
3642

@@ -249,9 +255,10 @@ pub mod curl {
249255
#[cfg(feature = "reqwest-backend")]
250256
pub mod reqwest_be {
251257
use super::Event;
258+
use super::TlsBackend;
252259
use crate::errors::*;
253260
use lazy_static::lazy_static;
254-
use reqwest::blocking::{Client, Response};
261+
use reqwest::blocking::{Client, ClientBuilder, Response};
255262
use reqwest::{header, Proxy};
256263
use std::io;
257264
use std::time::Duration;
@@ -261,13 +268,15 @@ pub mod reqwest_be {
261268
url: &Url,
262269
resume_from: u64,
263270
callback: &dyn Fn(Event<'_>) -> Result<()>,
271+
tls: TlsBackend,
264272
) -> Result<()> {
265273
// Short-circuit reqwest for the "file:" URL scheme
266274
if download_from_file_url(url, resume_from, callback)? {
267275
return Ok(());
268276
}
269277

270-
let mut res = request(url, resume_from).chain_err(|| "failed to make network request")?;
278+
let mut res =
279+
request(url, resume_from, tls).chain_err(|| "failed to make network request")?;
271280

272281
if !res.status().is_success() {
273282
let code: u16 = res.status().into();
@@ -295,13 +304,34 @@ pub mod reqwest_be {
295304
}
296305
}
297306

307+
fn client_generic() -> ClientBuilder {
308+
Client::builder()
309+
.gzip(false)
310+
.proxy(Proxy::custom(env_proxy))
311+
.timeout(Duration::from_secs(30))
312+
}
313+
#[cfg(feature = "reqwest-rustls-tls")]
298314
lazy_static! {
299-
static ref CLIENT: Client = {
315+
static ref CLIENT_RUSTLS_TLS: Client = {
300316
let catcher = || {
301-
Client::builder()
302-
.gzip(false)
303-
.proxy(Proxy::custom(env_proxy))
304-
.timeout(Duration::from_secs(30))
317+
client_generic().use_rustls_tls()
318+
.build()
319+
};
320+
321+
// woah, an unwrap?!
322+
// It's OK. This is the same as what is happening in curl.
323+
//
324+
// The curl::Easy::new() internally assert!s that the initialized
325+
// Easy is not null. Inside reqwest, the errors here would be from
326+
// the TLS library returning a null pointer as well.
327+
catcher().unwrap()
328+
};
329+
}
330+
#[cfg(feature = "reqwest-default-tls")]
331+
lazy_static! {
332+
static ref CLIENT_DEFAULT_TLS: Client = {
333+
let catcher = || {
334+
client_generic()
305335
.build()
306336
};
307337

@@ -319,8 +349,22 @@ pub mod reqwest_be {
319349
env_proxy::for_url(url).to_url()
320350
}
321351

322-
fn request(url: &Url, resume_from: u64) -> reqwest::Result<Response> {
323-
let mut req = CLIENT.get(url.as_str());
352+
fn request(url: &Url, resume_from: u64, backend: TlsBackend) -> reqwest::Result<Response> {
353+
let client: &Client = match backend {
354+
#[cfg(feature = "reqwest-rustls-tls")]
355+
TlsBackend::Rustls => &CLIENT_RUSTLS_TLS,
356+
#[cfg(not(feature = "reqwest-rustls-tls"))]
357+
TlsBackend::Default => {
358+
panic!("Instructed to use rustls TLS, but not enabled at build time")
359+
}
360+
#[cfg(feature = "reqwest-default-tls")]
361+
TlsBackend::Default => &CLIENT_DEFAULT_TLS,
362+
#[cfg(not(feature = "reqwest-default-tls"))]
363+
TlsBackend::Default => {
364+
panic!("Instructed to use default TLS, but not enabled at build time")
365+
}
366+
};
367+
let mut req = client.get(url.as_str());
324368

325369
if resume_from != 0 {
326370
req = req.header(header::RANGE, format!("bytes={}-", resume_from));

download/tests/download-reqwest-resume.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,14 @@ fn resume_partial_from_file_url() {
2020
write_file(&target_path, "123");
2121

2222
let from_url = Url::from_file_path(&from_path).unwrap();
23-
download_to_path_with_backend(Backend::Reqwest, &from_url, &target_path, true, None)
24-
.expect("Test download failed");
23+
download_to_path_with_backend(
24+
Backend::Reqwest(TlsBackend::Default),
25+
&from_url,
26+
&target_path,
27+
true,
28+
None,
29+
)
30+
.expect("Test download failed");
2531

2632
assert_eq!(std::fs::read_to_string(&target_path).unwrap(), "12345");
2733
}
@@ -41,7 +47,7 @@ fn callback_gets_all_data_as_if_the_download_happened_all_at_once() {
4147
let received_in_callback = Mutex::new(Vec::new());
4248

4349
download_to_path_with_backend(
44-
Backend::Reqwest,
50+
Backend::Reqwest(TlsBackend::Default),
4551
&from_url,
4652
&target_path,
4753
true,

src/utils/utils.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ fn download_file_(
207207
notify_handler: &dyn Fn(Notification<'_>),
208208
) -> Result<()> {
209209
use download::download_to_path_with_backend;
210-
use download::{Backend, Event};
210+
use download::{Backend, Event, TlsBackend};
211211
use sha2::Digest;
212212
use std::cell::RefCell;
213213

@@ -241,12 +241,25 @@ fn download_file_(
241241

242242
// Download the file
243243

244-
// Keep the hyper env var around for a bit
244+
// Keep the curl env var around for a bit
245245
let use_curl_backend = process().var_os("RUSTUP_USE_CURL").is_some();
246+
let avoid_rustls = process().var_os("RUSTUP_AVOID_RUSTLS").is_some();
246247
let (backend, notification) = if use_curl_backend {
247248
(Backend::Curl, Notification::UsingCurl)
248249
} else {
249-
(Backend::Reqwest, Notification::UsingReqwest)
250+
let tls_backend = if avoid_rustls {
251+
TlsBackend::Default
252+
} else {
253+
#[cfg(feature = "reqwest-rustls-tls")]
254+
{
255+
TlsBackend::Rustls
256+
}
257+
#[cfg(not(feature = "reqwest-rustls-tls"))]
258+
{
259+
TlsBackend::Default
260+
}
261+
};
262+
(Backend::Reqwest(tls_backend), Notification::UsingReqwest)
250263
};
251264
notify_handler(notification);
252265
let res =

0 commit comments

Comments
 (0)