Skip to content

Commit

Permalink
Workaround for proxies with MITM root certificates
Browse files Browse the repository at this point in the history
Added RUSTUP_USE_UNSAFE_SSL environment variable.
  • Loading branch information
orthoxerox authored and Марьин Алексей Юрьевич committed Feb 8, 2019
1 parent b697df1 commit 946632f
Show file tree
Hide file tree
Showing 14 changed files with 297 additions and 16 deletions.
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,13 @@ Command | Description
- `RUSTUP_UPDATE_ROOT` (default `https://static.rust-lang.org/rustup`)
Sets the root URL for downloading self-updates.

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

## Other installation methods

The primary installation method, as described at
Expand Down
12 changes: 10 additions & 2 deletions rustup-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -385,13 +385,21 @@ downloader() {
else
_dld='curl or wget' # to be used in error message of need_cmd
fi

if [ "$RUSTUP_USE_UNSAFE_SSL" = "ACCEPT_RISKS" ]; then
_curl_unsafe = "--insecure"
_wget_unsafe = "--no-check-certificate"
else
_curl_unsafe = ""
_wget_unsafe = ""
fi

if [ "$1" = --check ]; then
need_cmd "$_dld"
elif [ "$_dld" = curl ]; then
curl -sSfL "$1" -o "$2"
curl -sSfL "$_curl_unsafe" "$1" -o "$2"
elif [ "$_dld" = wget ]; then
wget "$1" -O "$2"
wget "$1" "$_wget_unsafe" -O "$2"
else
err "Unknown downloader" # should not reach here
fi
Expand Down
3 changes: 3 additions & 0 deletions src/download/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ reqwest = { version = "0.9", optional = true }
futures = "0.1"
hyper = "0.12"
tempdir = "0.3.4"
tokio = "0.1.11"
tokio-tls = "0.2.1"
native-tls = "0.2.1"
18 changes: 16 additions & 2 deletions src/download/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ extern crate lazy_static;
#[cfg(feature = "reqwest-backend")]
extern crate reqwest;

use std::env;
use std::path::Path;
use url::Url;

Expand Down Expand Up @@ -128,6 +129,10 @@ pub fn download_to_path_with_backend(
})
}

fn use_unsafe_ssl() -> bool {
env::var_os("RUSTUP_USE_UNSAFE_SSL").unwrap_or("NO".into()) == "ACCEPT_RISKS"
}

/// Download via libcurl; encrypt with the native (or OpenSSl) TLS
/// stack via libcurl
#[cfg(feature = "curl-backend")]
Expand All @@ -136,6 +141,7 @@ pub mod curl {
extern crate curl;

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

if use_unsafe_ssl() {
handle
.ssl_verify_peer(false)
.chain_err(|| "failed to configure unsafe SSL mode")?;
}

{
let cberr = RefCell::new(None);
let mut transfer = handle.transfer();
Expand Down Expand Up @@ -254,6 +266,7 @@ pub mod curl {
pub mod reqwest_be {
extern crate env_proxy;

use super::use_unsafe_ssl;
use super::Event;
use crate::errors::*;
use reqwest::{header, Client, Proxy, Response};
Expand Down Expand Up @@ -302,6 +315,7 @@ pub mod reqwest_be {
.gzip(false)
.proxy(Proxy::custom(env_proxy))
.timeout(Duration::from_secs(30))
.danger_accept_invalid_certs(use_unsafe_ssl())
.build()
};

Expand Down Expand Up @@ -374,7 +388,7 @@ pub mod reqwest_be {
pub mod curl {

use super::Event;
use errors::*;
use crate::errors::*;
use url::Url;

pub fn download(
Expand All @@ -390,7 +404,7 @@ pub mod curl {
pub mod reqwest_be {

use super::Event;
use errors::*;
use crate::errors::*;
use url::Url;

pub fn download(
Expand Down
2 changes: 1 addition & 1 deletion src/download/tests/download-curl-resume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn callback_gets_all_data_as_if_the_download_happened_all_at_once() {
let target_path = tmpdir.path().join("downloaded");
write_file(&target_path, "123");

let addr = serve_file(b"xxx45".to_vec());
let addr = serve_file(b"xxx45".to_vec(), false);

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

Expand Down
62 changes: 62 additions & 0 deletions src/download/tests/download-curl-safe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#![cfg(feature = "curl-backend")]

use download::*;

mod support;
use crate::support::{file_contents, serve_file, tmp_dir};

// There are two separate files because this crate caches curl handles
// and all tests in one file use either the safe or the unsafe handle.
// See download-curl-unsafe.rs for the complementary test case.

#[test]
fn downloading_with_no_certificate() {
let tmpdir = tmp_dir();
let target_path = tmpdir.path().join("downloaded");

let addr = serve_file(b"12345".to_vec(), false);
let from_url = format!("http://{}", addr).parse().unwrap();

download_to_path_with_backend(Backend::Curl, &from_url, &target_path, false, None)
.expect("Test download failed");

assert_eq!(file_contents(&target_path), "12345");
}

#[test]
#[should_panic]
fn downloading_with_bad_certificate() {
let tmpdir = tmp_dir();
let target_path = tmpdir.path().join("downloaded");

let addr = serve_file(b"12345".to_vec(), true);
let from_url = format!("https://{}", addr).parse().unwrap();

std::env::remove_var("RUSTUP_USE_UNSAFE_SSL");

assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_none(), true);

download_to_path_with_backend(Backend::Curl, &from_url, &target_path, false, None)
.expect("Test download failed");

assert_eq!(file_contents(&target_path), "12345");
}

#[test]
#[should_panic]
fn downloading_with_bad_certificate_using_wrong_env_value() {
let tmpdir = tmp_dir();
let target_path = tmpdir.path().join("downloaded");

let addr = serve_file(b"12345".to_vec(), true);
let from_url = format!("https://{}", addr).parse().unwrap();

std::env::set_var("RUSTUP_USE_UNSAFE_SSL", "FOOBAR");

assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_some(), true);

download_to_path_with_backend(Backend::Curl, &from_url, &target_path, false, None)
.expect("Test download failed");

assert_eq!(file_contents(&target_path), "12345");
}
28 changes: 28 additions & 0 deletions src/download/tests/download-curl-unsafe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#![cfg(feature = "curl-backend")]

use download::*;

mod support;
use crate::support::{file_contents, serve_file, tmp_dir};

// There are two separate files because this crate caches curl handles
// and all tests in one file use either the safe or the unsafe handle.
// See download-curl-safe.rs for the complementary test case.

#[test]
fn downloading_with_bad_certificate_unsafely() {
let tmpdir = tmp_dir();
let target_path = tmpdir.path().join("downloaded");

let addr = serve_file(b"12345".to_vec(), true);
let from_url = format!("https://{}", addr).parse().unwrap();

std::env::set_var("RUSTUP_USE_UNSAFE_SSL", "ACCEPT_RISKS");

assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_some(), true);

download_to_path_with_backend(Backend::Curl, &from_url, &target_path, false, None)
.expect("Test download failed");

assert_eq!(file_contents(&target_path), "12345");
}
2 changes: 1 addition & 1 deletion src/download/tests/download-reqwest-resume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn callback_gets_all_data_as_if_the_download_happened_all_at_once() {
let target_path = tmpdir.path().join("downloaded");
write_file(&target_path, "123");

let addr = serve_file(b"xxx45".to_vec());
let addr = serve_file(b"xxx45".to_vec(), false);

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

Expand Down
62 changes: 62 additions & 0 deletions src/download/tests/download-reqwest-safe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#![cfg(feature = "reqwest-backend")]

use download::*;

mod support;
use crate::support::{file_contents, serve_file, tmp_dir};

// There are two separate files because this crate caches reqwest clients
// and all tests in one file use either the safe or the unsafe client.
// See download-reqwest-unsafe.rs for the complementary test case.

#[test]
fn downloading_with_no_certificate() {
let tmpdir = tmp_dir();
let target_path = tmpdir.path().join("downloaded");

let addr = serve_file(b"12345".to_vec(), false);
let from_url = format!("http://{}", addr).parse().unwrap();

download_to_path_with_backend(Backend::Reqwest, &from_url, &target_path, false, None)
.expect("Test download failed");

assert_eq!(file_contents(&target_path), "12345");
}

#[test]
#[should_panic]
fn downloading_with_bad_certificate() {
let tmpdir = tmp_dir();
let target_path = tmpdir.path().join("downloaded");

let addr = serve_file(b"12345".to_vec(), true);
let from_url = format!("https://{}", addr).parse().unwrap();

std::env::remove_var("RUSTUP_USE_UNSAFE_SSL");

assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_none(), true);

download_to_path_with_backend(Backend::Reqwest, &from_url, &target_path, false, None)
.expect("Test download failed");

assert_eq!(file_contents(&target_path), "12345");
}

#[test]
#[should_panic]
fn downloading_with_bad_certificate_using_wrong_env_value() {
let tmpdir = tmp_dir();
let target_path = tmpdir.path().join("downloaded");

let addr = serve_file(b"12345".to_vec(), true);
let from_url = format!("https://{}", addr).parse().unwrap();

std::env::set_var("RUSTUP_USE_UNSAFE_SSL", "FOOBAR");

assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_some(), true);

download_to_path_with_backend(Backend::Reqwest, &from_url, &target_path, false, None)
.expect("Test download failed");

assert_eq!(file_contents(&target_path), "12345");
}
28 changes: 28 additions & 0 deletions src/download/tests/download-reqwest-unsafe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#![cfg(feature = "reqwest-backend")]

use download::*;

mod support;
use crate::support::{file_contents, serve_file, tmp_dir};

// There are two separate files because this crate caches reqwest clients
// and all tests in one file use either the safe or the unsafe client.
// See download-reqwest-safe.rs for the complementary test case.

#[test]
fn downloading_with_bad_certificate_unsafely() {
let tmpdir = tmp_dir();
let target_path = tmpdir.path().join("downloaded");

let addr = serve_file(b"12345".to_vec(), true);
let from_url = format!("https://{}", addr).parse().unwrap();

std::env::set_var("RUSTUP_USE_UNSAFE_SSL", "ACCEPT_RISKS");

assert_eq!(std::env::var_os("RUSTUP_USE_UNSAFE_SSL").is_some(), true);

download_to_path_with_backend(Backend::Reqwest, &from_url, &target_path, false, None)
.expect("Test download failed");

assert_eq!(file_contents(&target_path), "12345");
}
Binary file added src/download/tests/support/cert.p12
Binary file not shown.
Loading

0 comments on commit 946632f

Please sign in to comment.