Add options for specifying the TLS version (#1315)
This commit is contained in:
@@ -37,7 +37,7 @@ use crate::error;
|
||||
use crate::into_url::{expect_uri, try_uri};
|
||||
use crate::redirect::{self, remove_sensitive_headers};
|
||||
#[cfg(feature = "__tls")]
|
||||
use crate::tls::TlsBackend;
|
||||
use crate::tls::{self, TlsBackend};
|
||||
#[cfg(feature = "__tls")]
|
||||
use crate::Certificate;
|
||||
#[cfg(any(feature = "native-tls", feature = "__rustls"))]
|
||||
@@ -99,6 +99,10 @@ struct Config {
|
||||
#[cfg(feature = "__tls")]
|
||||
tls_built_in_root_certs: bool,
|
||||
#[cfg(feature = "__tls")]
|
||||
min_tls_version: Option<tls::Version>,
|
||||
#[cfg(feature = "__tls")]
|
||||
max_tls_version: Option<tls::Version>,
|
||||
#[cfg(feature = "__tls")]
|
||||
tls: TlsBackend,
|
||||
http_version_pref: HttpVersionPref,
|
||||
http1_title_case_headers: bool,
|
||||
@@ -158,6 +162,10 @@ impl ClientBuilder {
|
||||
#[cfg(any(feature = "native-tls", feature = "__rustls"))]
|
||||
identity: None,
|
||||
#[cfg(feature = "__tls")]
|
||||
min_tls_version: None,
|
||||
#[cfg(feature = "__tls")]
|
||||
max_tls_version: None,
|
||||
#[cfg(feature = "__tls")]
|
||||
tls: TlsBackend::default(),
|
||||
http_version_pref: HttpVersionPref::All,
|
||||
http1_title_case_headers: false,
|
||||
@@ -262,6 +270,27 @@ impl ClientBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(min_tls_version) = config.min_tls_version {
|
||||
let protocol = min_tls_version.to_native_tls().ok_or_else(|| {
|
||||
// TLS v1.3. This would be entirely reasonable,
|
||||
// native-tls just doesn't support it.
|
||||
// https://github.com/sfackler/rust-native-tls/issues/140
|
||||
crate::error::builder("invalid minimum TLS version for backend")
|
||||
})?;
|
||||
tls.min_protocol_version(Some(protocol));
|
||||
}
|
||||
|
||||
if let Some(max_tls_version) = config.max_tls_version {
|
||||
let protocol = max_tls_version.to_native_tls().ok_or_else(|| {
|
||||
// TLS v1.3.
|
||||
// We could arguably do max_protocol_version(None), given
|
||||
// that 1.4 does not exist yet, but that'd get messy in the
|
||||
// future.
|
||||
crate::error::builder("invalid maximum TLS version for backend")
|
||||
})?;
|
||||
tls.max_protocol_version(Some(protocol));
|
||||
}
|
||||
|
||||
Connector::new_default_tls(
|
||||
http,
|
||||
tls,
|
||||
@@ -329,6 +358,34 @@ impl ClientBuilder {
|
||||
id.add_to_rustls(&mut tls)?;
|
||||
}
|
||||
|
||||
// rustls does not support TLS versions <1.2 and this is unlikely to change.
|
||||
// https://github.com/rustls/rustls/issues/33
|
||||
|
||||
// As of writing, TLS 1.2 and 1.3 are the only implemented versions and are both
|
||||
// enabled by default.
|
||||
// rustls 0.20 will add ALL_VERSIONS and DEFAULT_VERSIONS. That will enable a more
|
||||
// sophisticated approach.
|
||||
// For now we assume the default tls.versions matches the future ALL_VERSIONS and
|
||||
// act based on that.
|
||||
|
||||
if let Some(min_tls_version) = config.min_tls_version {
|
||||
tls.versions
|
||||
.retain(|&version| match tls::Version::from_rustls(version) {
|
||||
Some(version) => version >= min_tls_version,
|
||||
// Assume it's so new we don't know about it, allow it
|
||||
// (as of writing this is unreachable)
|
||||
None => true,
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(max_tls_version) = config.max_tls_version {
|
||||
tls.versions
|
||||
.retain(|&version| match tls::Version::from_rustls(version) {
|
||||
Some(version) => version <= max_tls_version,
|
||||
None => false,
|
||||
});
|
||||
}
|
||||
|
||||
Connector::new_rustls_tls(
|
||||
http,
|
||||
tls,
|
||||
@@ -957,6 +1014,64 @@ impl ClientBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the minimum required TLS version for connections.
|
||||
///
|
||||
/// By default the TLS backend's own default is used.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// A value of `tls::Version::TLS_1_3` will cause an error with the
|
||||
/// `native-tls`/`default-tls` backend. This does not mean the version
|
||||
/// isn't supported, just that it can't be set as a minimum due to
|
||||
/// technical limitations.
|
||||
///
|
||||
/// # Optional
|
||||
///
|
||||
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
||||
/// feature to be enabled.
|
||||
#[cfg(feature = "__tls")]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(any(
|
||||
feature = "default-tls",
|
||||
feature = "native-tls",
|
||||
feature = "rustls-tls"
|
||||
)))
|
||||
)]
|
||||
pub fn min_tls_version(mut self, version: tls::Version) -> ClientBuilder {
|
||||
self.config.min_tls_version = Some(version);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the maximum allowed TLS version for connections.
|
||||
///
|
||||
/// By default there's no maximum.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// A value of `tls::Version::TLS_1_3` will cause an error with the
|
||||
/// `native-tls`/`default-tls` backend. This does not mean the version
|
||||
/// isn't supported, just that it can't be set as a maximum due to
|
||||
/// technical limitations.
|
||||
///
|
||||
/// # Optional
|
||||
///
|
||||
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
||||
/// feature to be enabled.
|
||||
#[cfg(feature = "__tls")]
|
||||
#[cfg_attr(
|
||||
docsrs,
|
||||
doc(cfg(any(
|
||||
feature = "default-tls",
|
||||
feature = "native-tls",
|
||||
feature = "rustls-tls"
|
||||
)))
|
||||
)]
|
||||
pub fn max_tls_version(mut self, version: tls::Version) -> ClientBuilder {
|
||||
self.config.max_tls_version = Some(version);
|
||||
self
|
||||
}
|
||||
|
||||
/// Force using the native TLS backend.
|
||||
///
|
||||
/// Since multiple TLS backends can be optionally enabled, this option will
|
||||
@@ -1399,6 +1514,14 @@ impl Config {
|
||||
if !self.certs_verification {
|
||||
f.field("danger_accept_invalid_certs", &true);
|
||||
}
|
||||
|
||||
if let Some(ref min_tls_version) = self.min_tls_version {
|
||||
f.field("min_tls_version", min_tls_version);
|
||||
}
|
||||
|
||||
if let Some(ref max_tls_version) = self.max_tls_version {
|
||||
f.field("max_tls_version", max_tls_version);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "native-tls-crate", feature = "__rustls"))]
|
||||
|
||||
Reference in New Issue
Block a user