Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate default-tls and native-tls features #749

Merged
merged 1 commit into from Dec 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Expand Up @@ -55,6 +55,7 @@ jobs:
- windows / stable-i686-gnu
- "feat.: default-tls disabled"
- "feat.: rustls-tls"
- "feat.: native-tls"
- "feat.: default-tls and rustls-tls"
- "feat.: cookies"
- "feat.: blocking"
Expand Down Expand Up @@ -100,6 +101,8 @@ jobs:
features: "--no-default-features"
- name: "feat.: rustls-tls"
features: "--no-default-features --features rustls-tls"
- name: "feat.: native-tls"
features: "--features native-tls"
- name: "feat.: default-tls and rustls-tls"
features: "--features rustls-tls"
- name: "feat.: cookies"
Expand Down
16 changes: 11 additions & 5 deletions Cargo.toml
Expand Up @@ -18,12 +18,15 @@ all-features = true
[features]
default = ["default-tls"]

tls = []
# Note: this doesn't enable the 'native-tls' feature, which adds specific
# functionality for it.
default-tls = ["hyper-tls", "native-tls-crate", "__tls", "tokio-tls"]

default-tls = ["hyper-tls", "native-tls", "tls", "tokio-tls"]
default-tls-vendored = ["default-tls", "native-tls/vendored"]
# Enables native-tls specific functionality not available by default.
native-tls = ["default-tls"]
native-tls-vendored = ["native-tls", "native-tls-crate/vendored"]

rustls-tls = ["hyper-rustls", "tokio-rustls", "webpki-roots", "rustls", "tls"]
rustls-tls = ["hyper-rustls", "tokio-rustls", "webpki-roots", "rustls", "__tls"]

blocking = ["futures-channel", "futures-util/io", "tokio/rt-threaded", "tokio/rt-core"]

Expand All @@ -40,6 +43,9 @@ stream = []
# Internal (PRIVATE!) features used to aid testing.
# Don't rely on these whatsoever. They may disappear at anytime.

# Enables common types used for TLS. Useless on its own.
__tls = []

# When enabled, disable using the cached SYS_PROXIES.
__internal_proxy_sys_no_cache = []

Expand Down Expand Up @@ -74,7 +80,7 @@ serde_urlencoded = "0.6.1"

## default-tls
hyper-tls = { version = "0.4", optional = true }
native-tls = { version = "0.2", optional = true }
native-tls-crate = { version = "0.2", optional = true, package = "native-tls" }
tokio-tls = { version = "0.3.0", optional = true }

# rustls-tls
Expand Down
81 changes: 45 additions & 36 deletions src/async_impl/client.rs
Expand Up @@ -13,8 +13,8 @@ use http::header::{
use http::Uri;
use http::uri::Scheme;
use hyper::client::ResponseFuture;
#[cfg(feature = "default-tls")]
use native_tls::TlsConnector;
#[cfg(feature = "native-tls-crate")]
use native_tls_crate::TlsConnector;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
Expand All @@ -30,9 +30,9 @@ use crate::connect::Connector;
use crate::cookie;
use crate::into_url::{expect_uri, try_uri};
use crate::redirect::{self, remove_sensitive_headers};
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
use crate::tls::TlsBackend;
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
use crate::{Certificate, Identity};
use crate::{IntoUrl, Method, Proxy, StatusCode, Url};

Expand Down Expand Up @@ -60,22 +60,22 @@ struct Config {
// NOTE: When adding a new field, update `fmt::Debug for ClientBuilder`
gzip: bool,
headers: HeaderMap,
#[cfg(feature = "default-tls")]
#[cfg(feature = "native-tls")]
hostname_verification: bool,
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
certs_verification: bool,
connect_timeout: Option<Duration>,
max_idle_per_host: usize,
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
identity: Option<Identity>,
proxies: Vec<Proxy>,
auto_sys_proxy: bool,
redirect_policy: redirect::Policy,
referer: bool,
timeout: Option<Duration>,
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
root_certs: Vec<Certificate>,
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
tls: TlsBackend,
http2_only: bool,
http1_title_case_headers: bool,
Expand Down Expand Up @@ -106,9 +106,9 @@ impl ClientBuilder {
config: Config {
gzip: cfg!(feature = "gzip"),
headers,
#[cfg(feature = "default-tls")]
#[cfg(feature = "native-tls")]
hostname_verification: true,
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
certs_verification: true,
connect_timeout: None,
max_idle_per_host: std::usize::MAX,
Expand All @@ -117,11 +117,11 @@ impl ClientBuilder {
redirect_policy: redirect::Policy::default(),
referer: true,
timeout: None,
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
root_certs: Vec::new(),
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
identity: None,
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
tls: TlsBackend::default(),
http2_only: false,
http1_title_case_headers: false,
Expand Down Expand Up @@ -150,25 +150,34 @@ impl ClientBuilder {
let proxies = Arc::new(proxies);

let mut connector = {
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
fn user_agent(headers: &HeaderMap) -> HeaderValue {
headers[USER_AGENT].clone()
}

#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
match config.tls {
#[cfg(feature = "default-tls")]
TlsBackend::Default => {
let mut tls = TlsConnector::builder();
tls.danger_accept_invalid_hostnames(!config.hostname_verification);

#[cfg(feature = "native-tls")]
{
tls.danger_accept_invalid_hostnames(!config.hostname_verification);
}

tls.danger_accept_invalid_certs(!config.certs_verification);

for cert in config.root_certs {
cert.add_to_native_tls(&mut tls);
}

if let Some(id) = config.identity {
id.add_to_native_tls(&mut tls)?;

#[cfg(feature = "native-tls")]
{
if let Some(id) = config.identity {
id.add_to_native_tls(&mut tls)?;
}
}

Connector::new_default_tls(
Expand Down Expand Up @@ -215,7 +224,7 @@ impl ClientBuilder {
}
}

#[cfg(not(feature = "tls"))]
#[cfg(not(feature = "__tls"))]
Connector::new(proxies.clone(), config.local_address, config.nodelay)?
};

Expand Down Expand Up @@ -511,9 +520,9 @@ impl ClientBuilder {
///
/// # Optional
///
/// This requires the optional `default-tls` or `rustls-tls` feature to be
/// enabled.
#[cfg(feature = "tls")]
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls`
/// feature to be enabled.
#[cfg(feature = "__tls")]
pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder {
self.config.root_certs.push(cert);
self
Expand All @@ -523,9 +532,9 @@ impl ClientBuilder {
///
/// # Optional
///
/// This requires the optional `default-tls` or `rustls-tls` feature to be
/// This requires the optional `native-tls` or `rustls-tls` feature to be
/// enabled.
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
pub fn identity(mut self, identity: Identity) -> ClientBuilder {
self.config.identity = Some(identity);
self
Expand All @@ -544,8 +553,8 @@ impl ClientBuilder {
///
/// # Optional
///
/// This requires the optional `default-tls` feature to be enabled.
#[cfg(feature = "default-tls")]
/// This requires the optional `native-tls` feature to be enabled.
#[cfg(feature = "native-tls")]
pub fn danger_accept_invalid_hostnames(
mut self,
accept_invalid_hostname: bool,
Expand All @@ -568,9 +577,9 @@ impl ClientBuilder {
///
/// # Optional
///
/// This requires the optional `default-tls` or `rustls-tls` feature to be
/// enabled.
#[cfg(feature = "tls")]
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls`
/// feature to be enabled.
#[cfg(feature = "__tls")]
pub fn danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder {
self.config.certs_verification = !accept_invalid_certs;
self
Expand All @@ -583,9 +592,9 @@ impl ClientBuilder {
///
/// # Optional
///
/// This requires the optional `default-tls` feature to be enabled.
#[cfg(feature = "default-tls")]
pub fn use_default_tls(mut self) -> ClientBuilder {
/// This requires the optional `native-tls` feature to be enabled.
#[cfg(feature = "native-tls")]
pub fn use_native_tls(mut self) -> ClientBuilder {
self.config.tls = TlsBackend::Default;
self
}
Expand Down Expand Up @@ -888,21 +897,21 @@ impl Config {
f.field("tcp_nodelay", &true);
}

#[cfg(feature = "default-tls")]
#[cfg(feature = "native-tls")]
{
if !self.hostname_verification {
f.field("danger_accept_invalid_hostnames", &true);
}
}

#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
{
if !self.certs_verification {
f.field("danger_accept_invalid_certs", &true);
}
}

#[cfg(all(feature = "default-tls", feature = "rustls-tls"))]
#[cfg(all(feature = "native-tls-crate", feature = "rustls-tls"))]
{
f.field("tls_backend", &self.tls);
}
Expand Down
56 changes: 15 additions & 41 deletions src/blocking/client.rs
Expand Up @@ -14,7 +14,7 @@ use super::request::{Request, RequestBuilder};
use super::response::Response;
use super::wait;
use crate::{async_impl, header, IntoUrl, Method, Proxy, redirect};
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
use crate::{Certificate, Identity};

/// A `Client` to make Requests with.
Expand Down Expand Up @@ -331,45 +331,15 @@ impl ClientBuilder {
///
/// # Optional
///
/// This requires the optional `default-tls` or `rustls-tls` feature to be
/// enabled.
#[cfg(feature = "tls")]
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls`
/// feature to be enabled.
#[cfg(feature = "__tls")]
pub fn add_root_certificate(self, cert: Certificate) -> ClientBuilder {
self.with_inner(move |inner| inner.add_root_certificate(cert))
}

/// Sets the identity to be used for client certificate authentication.
///
/// # Example
///
/// ```
/// # use std::fs::File;
/// # use std::io::Read;
/// # fn build_client() -> Result<(), Box<std::error::Error>> {
/// // read a local PKCS12 bundle
/// let mut buf = Vec::new();
///
/// #[cfg(feature = "default-tls")]
/// File::open("my-ident.pfx")?.read_to_end(&mut buf)?;
/// #[cfg(feature = "rustls-tls")]
/// File::open("my-ident.pem")?.read_to_end(&mut buf)?;
///
/// #[cfg(feature = "default-tls")]
/// // create an Identity from the PKCS#12 archive
/// let pkcs12 = reqwest::Identity::from_pkcs12_der(&buf, "my-privkey-password")?;
/// #[cfg(feature = "rustls-tls")]
/// // create an Identity from the PEM file
/// let pkcs12 = reqwest::Identity::from_pem(&buf)?;
///
/// // get a client builder
/// let client = reqwest::blocking::Client::builder()
/// .identity(pkcs12)
/// .build()?;
/// # drop(client);
/// # Ok(())
/// # }
/// ```
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
pub fn identity(self, identity: Identity) -> ClientBuilder {
self.with_inner(move |inner| inner.identity(identity))
}
Expand All @@ -384,7 +354,11 @@ impl ClientBuilder {
/// hostname verification is not used, any valid certificate for any
/// site will be trusted for use from any other. This introduces a
/// significant vulnerability to man-in-the-middle attacks.
#[cfg(feature = "default-tls")]
///
/// # Optional
///
/// This requires the optional `native-tls` feature to be enabled.
#[cfg(feature = "native-tls")]
pub fn danger_accept_invalid_hostnames(self, accept_invalid_hostname: bool) -> ClientBuilder {
self.with_inner(|inner| inner.danger_accept_invalid_hostnames(accept_invalid_hostname))
}
Expand All @@ -400,7 +374,7 @@ impl ClientBuilder {
/// will be trusted for use. This includes expired certificates. This
/// introduces significant vulnerabilities, and should only be used
/// as a last resort.
#[cfg(feature = "tls")]
#[cfg(feature = "__tls")]
pub fn danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder {
self.with_inner(|inner| inner.danger_accept_invalid_certs(accept_invalid_certs))
}
Expand All @@ -412,10 +386,10 @@ impl ClientBuilder {
///
/// # Optional
///
/// This requires the optional `default-tls` feature to be enabled.
#[cfg(feature = "default-tls")]
pub fn use_default_tls(self) -> ClientBuilder {
self.with_inner(move |inner| inner.use_default_tls())
/// This requires the optional `native-tls` feature to be enabled.
#[cfg(feature = "native-tls")]
pub fn use_native_tls(self) -> ClientBuilder {
self.with_inner(move |inner| inner.use_native_tls())
}

/// Force using the Rustls TLS backend.
Expand Down