Skip to content

Commit 946632f

Browse files
orthoxeroxМарьин Алексей Юрьевич
authored and
Марьин Алексей Юрьевич
committed
Workaround for proxies with MITM root certificates
Added RUSTUP_USE_UNSAFE_SSL environment variable.
1 parent b697df1 commit 946632f

14 files changed

+297
-16
lines changed

Cargo.lock

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

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,13 @@ Command | Description
580580
- `RUSTUP_UPDATE_ROOT` (default `https://static.rust-lang.org/rustup`)
581581
Sets the root URL for downloading self-updates.
582582

583+
- `RUSTUP_USE_UNSAFE_SSL` (default: none)
584+
If set to "ACCEPT_RISKS", rustup will not validate the SSL certificate
585+
when downloading files. This parameter should be used only in exceptional
586+
circumstances when your computer is behind a corporate proxy that injects
587+
its own certificates into HTTPS connections and you're unable to add these
588+
certificates to your root set.
589+
583590
## Other installation methods
584591

585592
The primary installation method, as described at

rustup-init.sh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,13 +385,21 @@ downloader() {
385385
else
386386
_dld='curl or wget' # to be used in error message of need_cmd
387387
fi
388+
389+
if [ "$RUSTUP_USE_UNSAFE_SSL" = "ACCEPT_RISKS" ]; then
390+
_curl_unsafe = "--insecure"
391+
_wget_unsafe = "--no-check-certificate"
392+
else
393+
_curl_unsafe = ""
394+
_wget_unsafe = ""
395+
fi
388396

389397
if [ "$1" = --check ]; then
390398
need_cmd "$_dld"
391399
elif [ "$_dld" = curl ]; then
392-
curl -sSfL "$1" -o "$2"
400+
curl -sSfL "$_curl_unsafe" "$1" -o "$2"
393401
elif [ "$_dld" = wget ]; then
394-
wget "$1" -O "$2"
402+
wget "$1" "$_wget_unsafe" -O "$2"
395403
else
396404
err "Unknown downloader" # should not reach here
397405
fi

src/download/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ reqwest = { version = "0.9", optional = true }
2626
futures = "0.1"
2727
hyper = "0.12"
2828
tempdir = "0.3.4"
29+
tokio = "0.1.11"
30+
tokio-tls = "0.2.1"
31+
native-tls = "0.2.1"

src/download/src/lib.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ extern crate lazy_static;
1010
#[cfg(feature = "reqwest-backend")]
1111
extern crate reqwest;
1212

13+
use std::env;
1314
use std::path::Path;
1415
use url::Url;
1516

@@ -128,6 +129,10 @@ pub fn download_to_path_with_backend(
128129
})
129130
}
130131

132+
fn use_unsafe_ssl() -> bool {
133+
env::var_os("RUSTUP_USE_UNSAFE_SSL").unwrap_or("NO".into()) == "ACCEPT_RISKS"
134+
}
135+
131136
/// Download via libcurl; encrypt with the native (or OpenSSl) TLS
132137
/// stack via libcurl
133138
#[cfg(feature = "curl-backend")]
@@ -136,6 +141,7 @@ pub mod curl {
136141
extern crate curl;
137142

138143
use self::curl::easy::Easy;
144+
use super::use_unsafe_ssl;
139145
use super::Event;
140146
use crate::errors::*;
141147
use std::cell::RefCell;
@@ -175,6 +181,12 @@ pub mod curl {
175181
.connect_timeout(Duration::new(30, 0))
176182
.chain_err(|| "failed to set connect timeout")?;
177183

184+
if use_unsafe_ssl() {
185+
handle
186+
.ssl_verify_peer(false)
187+
.chain_err(|| "failed to configure unsafe SSL mode")?;
188+
}
189+
178190
{
179191
let cberr = RefCell::new(None);
180192
let mut transfer = handle.transfer();
@@ -254,6 +266,7 @@ pub mod curl {
254266
pub mod reqwest_be {
255267
extern crate env_proxy;
256268

269+
use super::use_unsafe_ssl;
257270
use super::Event;
258271
use crate::errors::*;
259272
use reqwest::{header, Client, Proxy, Response};
@@ -302,6 +315,7 @@ pub mod reqwest_be {
302315
.gzip(false)
303316
.proxy(Proxy::custom(env_proxy))
304317
.timeout(Duration::from_secs(30))
318+
.danger_accept_invalid_certs(use_unsafe_ssl())
305319
.build()
306320
};
307321

@@ -374,7 +388,7 @@ pub mod reqwest_be {
374388
pub mod curl {
375389

376390
use super::Event;
377-
use errors::*;
391+
use crate::errors::*;
378392
use url::Url;
379393

380394
pub fn download(
@@ -390,7 +404,7 @@ pub mod curl {
390404
pub mod reqwest_be {
391405

392406
use super::Event;
393-
use errors::*;
407+
use crate::errors::*;
394408
use url::Url;
395409

396410
pub fn download(

src/download/tests/download-curl-resume.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn callback_gets_all_data_as_if_the_download_happened_all_at_once() {
3434
let target_path = tmpdir.path().join("downloaded");
3535
write_file(&target_path, "123");
3636

37-
let addr = serve_file(b"xxx45".to_vec());
37+
let addr = serve_file(b"xxx45".to_vec(), false);
3838

3939
let from_url = format!("http://{}", addr).parse().unwrap();
4040

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#![cfg(feature = "curl-backend")]
2+
3+
use download::*;
4+
5+
mod support;
6+
use crate::support::{file_contents, serve_file, tmp_dir};
7+
8+
// There are two separate files because this crate caches curl handles
9+
// and all tests in one file use either the safe or the unsafe handle.
10+
// See download-curl-unsafe.rs for the complementary test case.
11+
12+
#[test]
13+
fn downloading_with_no_certificate() {
14+
let tmpdir = tmp_dir();
15+
let target_path = tmpdir.path().join("downloaded");
16+
17+
let addr = serve_file(b"12345".to_vec(), false);
18+
let from_url = format!("http://{}", addr).parse().unwrap();
19+
20+
download_to_path_with_backend(Backend::Curl, &from_url, &target_path, false, None)
21+
.expect("Test download failed");
22+
23+
assert_eq!(file_contents(&target_path), "12345");
24+
}
25+
26+
#[test]
27+
#[should_panic]
28+
fn downloading_with_bad_certificate() {
29+
let tmpdir = tmp_dir();
30+
let target_path = tmpdir.path().join("downloaded");
31+
32+
let addr = serve_file(b"12345".to_vec(), true);
33+
let from_url = format!("https://{}", addr).parse().unwrap();
34+
35+
std::env::remove_var("RUSTUP_USE_UNSAFE_SSL");
36+
37+
assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_none(), true);
38+
39+
download_to_path_with_backend(Backend::Curl, &from_url, &target_path, false, None)
40+
.expect("Test download failed");
41+
42+
assert_eq!(file_contents(&target_path), "12345");
43+
}
44+
45+
#[test]
46+
#[should_panic]
47+
fn downloading_with_bad_certificate_using_wrong_env_value() {
48+
let tmpdir = tmp_dir();
49+
let target_path = tmpdir.path().join("downloaded");
50+
51+
let addr = serve_file(b"12345".to_vec(), true);
52+
let from_url = format!("https://{}", addr).parse().unwrap();
53+
54+
std::env::set_var("RUSTUP_USE_UNSAFE_SSL", "FOOBAR");
55+
56+
assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_some(), true);
57+
58+
download_to_path_with_backend(Backend::Curl, &from_url, &target_path, false, None)
59+
.expect("Test download failed");
60+
61+
assert_eq!(file_contents(&target_path), "12345");
62+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![cfg(feature = "curl-backend")]
2+
3+
use download::*;
4+
5+
mod support;
6+
use crate::support::{file_contents, serve_file, tmp_dir};
7+
8+
// There are two separate files because this crate caches curl handles
9+
// and all tests in one file use either the safe or the unsafe handle.
10+
// See download-curl-safe.rs for the complementary test case.
11+
12+
#[test]
13+
fn downloading_with_bad_certificate_unsafely() {
14+
let tmpdir = tmp_dir();
15+
let target_path = tmpdir.path().join("downloaded");
16+
17+
let addr = serve_file(b"12345".to_vec(), true);
18+
let from_url = format!("https://{}", addr).parse().unwrap();
19+
20+
std::env::set_var("RUSTUP_USE_UNSAFE_SSL", "ACCEPT_RISKS");
21+
22+
assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_some(), true);
23+
24+
download_to_path_with_backend(Backend::Curl, &from_url, &target_path, false, None)
25+
.expect("Test download failed");
26+
27+
assert_eq!(file_contents(&target_path), "12345");
28+
}

src/download/tests/download-reqwest-resume.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn callback_gets_all_data_as_if_the_download_happened_all_at_once() {
3434
let target_path = tmpdir.path().join("downloaded");
3535
write_file(&target_path, "123");
3636

37-
let addr = serve_file(b"xxx45".to_vec());
37+
let addr = serve_file(b"xxx45".to_vec(), false);
3838

3939
let from_url = format!("http://{}", addr).parse().unwrap();
4040

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#![cfg(feature = "reqwest-backend")]
2+
3+
use download::*;
4+
5+
mod support;
6+
use crate::support::{file_contents, serve_file, tmp_dir};
7+
8+
// There are two separate files because this crate caches reqwest clients
9+
// and all tests in one file use either the safe or the unsafe client.
10+
// See download-reqwest-unsafe.rs for the complementary test case.
11+
12+
#[test]
13+
fn downloading_with_no_certificate() {
14+
let tmpdir = tmp_dir();
15+
let target_path = tmpdir.path().join("downloaded");
16+
17+
let addr = serve_file(b"12345".to_vec(), false);
18+
let from_url = format!("http://{}", addr).parse().unwrap();
19+
20+
download_to_path_with_backend(Backend::Reqwest, &from_url, &target_path, false, None)
21+
.expect("Test download failed");
22+
23+
assert_eq!(file_contents(&target_path), "12345");
24+
}
25+
26+
#[test]
27+
#[should_panic]
28+
fn downloading_with_bad_certificate() {
29+
let tmpdir = tmp_dir();
30+
let target_path = tmpdir.path().join("downloaded");
31+
32+
let addr = serve_file(b"12345".to_vec(), true);
33+
let from_url = format!("https://{}", addr).parse().unwrap();
34+
35+
std::env::remove_var("RUSTUP_USE_UNSAFE_SSL");
36+
37+
assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_none(), true);
38+
39+
download_to_path_with_backend(Backend::Reqwest, &from_url, &target_path, false, None)
40+
.expect("Test download failed");
41+
42+
assert_eq!(file_contents(&target_path), "12345");
43+
}
44+
45+
#[test]
46+
#[should_panic]
47+
fn downloading_with_bad_certificate_using_wrong_env_value() {
48+
let tmpdir = tmp_dir();
49+
let target_path = tmpdir.path().join("downloaded");
50+
51+
let addr = serve_file(b"12345".to_vec(), true);
52+
let from_url = format!("https://{}", addr).parse().unwrap();
53+
54+
std::env::set_var("RUSTUP_USE_UNSAFE_SSL", "FOOBAR");
55+
56+
assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_some(), true);
57+
58+
download_to_path_with_backend(Backend::Reqwest, &from_url, &target_path, false, None)
59+
.expect("Test download failed");
60+
61+
assert_eq!(file_contents(&target_path), "12345");
62+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![cfg(feature = "reqwest-backend")]
2+
3+
use download::*;
4+
5+
mod support;
6+
use crate::support::{file_contents, serve_file, tmp_dir};
7+
8+
// There are two separate files because this crate caches reqwest clients
9+
// and all tests in one file use either the safe or the unsafe client.
10+
// See download-reqwest-safe.rs for the complementary test case.
11+
12+
#[test]
13+
fn downloading_with_bad_certificate_unsafely() {
14+
let tmpdir = tmp_dir();
15+
let target_path = tmpdir.path().join("downloaded");
16+
17+
let addr = serve_file(b"12345".to_vec(), true);
18+
let from_url = format!("https://{}", addr).parse().unwrap();
19+
20+
std::env::set_var("RUSTUP_USE_UNSAFE_SSL", "ACCEPT_RISKS");
21+
22+
assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_some(), true);
23+
24+
download_to_path_with_backend(Backend::Reqwest, &from_url, &target_path, false, None)
25+
.expect("Test download failed");
26+
27+
assert_eq!(file_contents(&target_path), "12345");
28+
}

src/download/tests/support/cert.p12

2.35 KB
Binary file not shown.

0 commit comments

Comments
 (0)