Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ http3 = ["rustls", "dep:h3", "dep:h3-quinn", "dep:quinn", "tokio/macros"]
__tls = ["dep:rustls-pki-types", "tokio/io-util"]

# Enables common rustls code.
__rustls = ["dep:hyper-rustls", "dep:tokio-rustls", "dep:rustls", "__tls"]
__rustls-aws-lc-rs = ["hyper-rustls?/aws-lc-rs", "tokio-rustls?/aws-lc-rs", "rustls?/aws-lc-rs", "quinn?/rustls-aws-lc-rs"]
__rustls = ["dep:hyper-rustls", "dep:tokio-rustls", "dep:rustls", "dep:rustls-util", "__tls"]
__rustls-aws-lc-rs = ["hyper-rustls?/aws-lc-rs", "tokio-rustls?/aws-lc-rs", "dep:rustls-aws-lc-rs", "quinn?/rustls-aws-lc-rs"]

# Enables common native-tls code.
__native-tls = ["dep:hyper-tls", "dep:native-tls-crate", "__tls", "dep:tokio-native-tls"]
Expand Down Expand Up @@ -138,10 +138,12 @@ native-tls-crate = { version = "0.2.16", optional = true, package = "native-tls"
tokio-native-tls = { version = "0.3.0", optional = true }

# default rustls
hyper-rustls = { version = "0.27.0", default-features = false, optional = true, features = ["http1", "tls12"] }
rustls = { version = "0.23.4", optional = true, default-features = false, features = ["std", "tls12"] }
tokio-rustls = { version = "0.26", optional = true, default-features = false, features = ["tls12"] }
rustls-platform-verifier = { version = ">=0.6.0, <0.8.0", optional = true }
hyper-rustls = { git = "https://github.com/rustls/hyper-rustls.git", rev = "836e95c4d3b111973ce0e718b8e0035a97658d01", version = "0.27.10", default-features = false, optional = true, features = ["http1", "tls12"] }
rustls = { git = "https://github.com/rustls/rustls.git", branch = "main", version = "0.24.0-dev.0", optional = true, default-features = false, features = ["log", "webpki"] }
tokio-rustls = { git = "https://github.com/rustls/tokio-rustls.git", rev = "be34e90bfe59f124363d725ceb739a435bfafa1e", version = "0.26.4", optional = true, default-features = false, features = ["tls12"] }
rustls-platform-verifier = { git = "https://github.com/rustls/rustls-platform-verifier.git", rev = "733494d8ade721f249dc1b4e93196adf409ae8c0", version = "0.7", optional = true }
rustls-aws-lc-rs = { git = "https://github.com/rustls/rustls.git", branch = "main", version = "0.1.0-dev.0", default-features = false, features = ["aws-lc-sys", "std"], optional = true }
rustls-util = { git = "https://github.com/rustls/rustls.git", branch = "main", version = "0.1.0", optional = true }

## cookies
cookie_crate = { version = "0.18.0", package = "cookie", optional = true }
Expand Down
65 changes: 44 additions & 21 deletions src/async_impl/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ impl ClientBuilder {

if let Some(min_tls_version) = config.min_tls_version {
versions.retain(|&supported_version| {
match tls::Version::from_rustls(supported_version.version) {
match tls::Version::from_rustls(supported_version.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)
Expand All @@ -703,7 +703,7 @@ impl ClientBuilder {

if let Some(max_tls_version) = config.max_tls_version {
versions.retain(|&supported_version| {
match tls::Version::from_rustls(supported_version.version) {
match tls::Version::from_rustls(supported_version.version()) {
Some(version) => version <= max_tls_version,
None => false,
}
Expand All @@ -716,16 +716,26 @@ impl ClientBuilder {

// Allow user to have installed a runtime default.
// If not, we ship with _our_ recommended default.
let provider = rustls::crypto::CryptoProvider::get_default()
.map(|arc| arc.clone())
.unwrap_or_else(default_rustls_crypto_provider);
let mut provider = rustls::crypto::CryptoProvider::get_default()
.map(|arc| arc.as_ref().clone())
.unwrap_or_else(|| default_rustls_crypto_provider().as_ref().clone());
if !versions
.iter()
.any(|version| version.version() == rustls::enums::ProtocolVersion::TLSv1_2)
{
provider.tls12_cipher_suites = std::borrow::Cow::Borrowed(&[]);
}
if !versions
.iter()
.any(|version| version.version() == rustls::enums::ProtocolVersion::TLSv1_3)
{
provider.tls13_cipher_suites = std::borrow::Cow::Borrowed(&[]);
}
let provider = Arc::new(provider);

// Build TLS config
let signature_algorithms = provider.signature_verification_algorithms;
let config_builder =
rustls::ClientConfig::builder_with_provider(provider.clone())
.with_protocol_versions(&versions)
.map_err(|_| crate::error::builder("invalid TLS versions"))?;
let config_builder = rustls::ClientConfig::builder(provider.clone());

let config_builder = if !config.certs_verification {
config_builder
Expand All @@ -739,11 +749,22 @@ impl ClientBuilder {
));
}

let roots = crate::tls::rustls_store(config.root_certs)?;
let signature_verifier =
rustls::client::WebPkiServerVerifier::builder(
Arc::new(roots.clone()),
provider.as_ref(),
)
.build()
.map_err(|_| {
crate::error::builder("invalid TLS verification settings")
})?;
config_builder
.dangerous()
.with_custom_certificate_verifier(Arc::new(IgnoreHostname::new(
crate::tls::rustls_store(config.root_certs)?,
roots,
signature_algorithms,
Arc::new(signature_verifier),
)))
} else if !config.tls_certs_only {
// Check for some misconfigurations and report them.
Expand Down Expand Up @@ -793,40 +814,42 @@ impl ClientBuilder {
.map(|e| e.as_rustls_crl())
.collect::<Vec<_>>();
let verifier =
rustls::client::WebPkiServerVerifier::builder_with_provider(
rustls::client::WebPkiServerVerifier::builder(
Arc::new(crate::tls::rustls_store(config.root_certs)?),
provider,
provider.as_ref(),
)
.with_crls(crls)
.build()
.map_err(|_| {
crate::error::builder("invalid TLS verification settings")
})?;
config_builder.with_webpki_verifier(verifier)
config_builder.with_webpki_verifier(verifier.into())
}
};

// Finalize TLS config
let mut tls = if let Some(id) = config.identity {
id.add_to_rustls(config_builder)?
} else {
config_builder.with_no_client_auth()
config_builder
.with_no_client_auth()
.map_err(crate::error::builder)?
};

tls.enable_sni = config.tls_sni;

if config.tls_sslkeylogfile {
tls.key_log = Arc::new(rustls::KeyLogFile::new());
tls.key_log = Arc::new(rustls_util::KeyLogFile::new());
}

// ALPN protocol
match config.http_version_pref {
HttpVersionPref::Http1 => {
tls.alpn_protocols = vec!["http/1.1".into()];
tls.alpn_protocols = vec![b"http/1.1".into()];
}
#[cfg(feature = "http2")]
HttpVersionPref::Http2 => {
tls.alpn_protocols = vec!["h2".into()];
tls.alpn_protocols = vec![b"h2".into()];
}
#[cfg(feature = "http3")]
HttpVersionPref::Http3 => {
Expand All @@ -835,8 +858,8 @@ impl ClientBuilder {
HttpVersionPref::All => {
tls.alpn_protocols = vec![
#[cfg(feature = "http2")]
"h2".into(),
"http/1.1".into(),
b"h2".into(),
b"http/1.1".into(),
];
}
}
Expand Down Expand Up @@ -2485,12 +2508,12 @@ fn default_rustls_crypto_provider() -> Arc<rustls::crypto::CryptoProvider> {
"No rustls crypto provider is configured. \
When using the `rustls-no-provider` feature you must install a \
crypto provider before building a Client. For example: \
`rustls::crypto::aws_lc_rs::default_provider().install_default().unwrap();` \
`rustls_aws_lc_rs::DEFAULT_PROVIDER.install_default().unwrap();` \
See https://docs.rs/rustls/latest/rustls/#cryptography-providers for details."
);

#[cfg(feature = "__rustls-aws-lc-rs")]
Arc::new(rustls::crypto::aws_lc_rs::default_provider())
Arc::new(rustls_aws_lc_rs::DEFAULT_PROVIDER)
}

impl Client {
Expand Down
71 changes: 28 additions & 43 deletions src/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,21 @@ impl<T: TlsInfoFactory> TlsInfoFactory for TokioIo<T> {
}
}

#[cfg(feature = "__rustls")]
fn rustls_peer_certificate(conn: &rustls::ClientConnection) -> Option<Vec<u8>> {
match conn.peer_identity()? {
rustls::crypto::Identity::X509(certificates) => Some(certificates.end_entity.to_vec()),
rustls::crypto::Identity::RawPublicKey(_) => None,
_ => None,
}
}

#[cfg(feature = "__rustls")]
fn rustls_is_h2(conn: &rustls::ClientConnection) -> bool {
conn.alpn_protocol()
.is_some_and(|protocol| protocol.as_ref() == b"h2")
}

// ===== TcpStream =====

#[cfg(feature = "__tls")]
Expand Down Expand Up @@ -1018,12 +1033,7 @@ impl TlsInfoFactory for hyper_tls::MaybeHttpsStream<TokioIo<tokio::net::TcpStrea
#[cfg(feature = "__rustls")]
impl TlsInfoFactory for tokio_rustls::client::TlsStream<TokioIo<TokioIo<tokio::net::TcpStream>>> {
fn tls_info(&self) -> Option<crate::tls::TlsInfo> {
let peer_certificate = self
.get_ref()
.1
.peer_certificates()
.and_then(|certs| certs.first())
.map(|c| c.to_vec());
let peer_certificate = rustls_peer_certificate(self.get_ref().1);
Some(crate::tls::TlsInfo { peer_certificate })
}
}
Expand All @@ -1035,12 +1045,7 @@ impl TlsInfoFactory
>
{
fn tls_info(&self) -> Option<crate::tls::TlsInfo> {
let peer_certificate = self
.get_ref()
.1
.peer_certificates()
.and_then(|certs| certs.first())
.map(|c| c.to_vec());
let peer_certificate = rustls_peer_certificate(self.get_ref().1);
Some(crate::tls::TlsInfo { peer_certificate })
}
}
Expand Down Expand Up @@ -1112,12 +1117,7 @@ impl TlsInfoFactory for hyper_tls::MaybeHttpsStream<TokioIo<tokio::net::UnixStre
#[cfg(unix)]
impl TlsInfoFactory for tokio_rustls::client::TlsStream<TokioIo<TokioIo<tokio::net::UnixStream>>> {
fn tls_info(&self) -> Option<crate::tls::TlsInfo> {
let peer_certificate = self
.get_ref()
.1
.peer_certificates()
.and_then(|certs| certs.first())
.map(|c| c.to_vec());
let peer_certificate = rustls_peer_certificate(self.get_ref().1);
Some(crate::tls::TlsInfo { peer_certificate })
}
}
Expand All @@ -1130,12 +1130,7 @@ impl TlsInfoFactory
>
{
fn tls_info(&self) -> Option<crate::tls::TlsInfo> {
let peer_certificate = self
.get_ref()
.1
.peer_certificates()
.and_then(|certs| certs.first())
.map(|c| c.to_vec());
let peer_certificate = rustls_peer_certificate(self.get_ref().1);
Some(crate::tls::TlsInfo { peer_certificate })
}
}
Expand Down Expand Up @@ -1220,12 +1215,7 @@ impl TlsInfoFactory
>
{
fn tls_info(&self) -> Option<crate::tls::TlsInfo> {
let peer_certificate = self
.get_ref()
.1
.peer_certificates()
.and_then(|certs| certs.first())
.map(|c| c.to_vec());
let peer_certificate = rustls_peer_certificate(self.get_ref().1);
Some(crate::tls::TlsInfo { peer_certificate })
}
}
Expand All @@ -1242,12 +1232,7 @@ impl TlsInfoFactory
>
{
fn tls_info(&self) -> Option<crate::tls::TlsInfo> {
let peer_certificate = self
.get_ref()
.1
.peer_certificates()
.and_then(|certs| certs.first())
.map(|c| c.to_vec());
let peer_certificate = rustls_peer_certificate(self.get_ref().1);
Some(crate::tls::TlsInfo { peer_certificate })
}
}
Expand Down Expand Up @@ -1640,7 +1625,7 @@ mod native_tls_conn {

#[cfg(feature = "__rustls")]
mod rustls_tls_conn {
use super::TlsInfoFactory;
use super::{rustls_is_h2, TlsInfoFactory};
use hyper::rt::{Read, ReadBufCursor, Write};
use hyper_rustls::MaybeHttpsStream;
use hyper_util::client::legacy::connect::{Connected, Connection};
Expand All @@ -1663,7 +1648,7 @@ mod rustls_tls_conn {

impl Connection for RustlsTlsConn<TokioIo<TokioIo<TcpStream>>> {
fn connected(&self) -> Connected {
if self.inner.inner().get_ref().1.alpn_protocol() == Some(b"h2") {
if rustls_is_h2(self.inner.inner().get_ref().1) {
self.inner
.inner()
.get_ref()
Expand All @@ -1678,7 +1663,7 @@ mod rustls_tls_conn {
}
impl Connection for RustlsTlsConn<TokioIo<MaybeHttpsStream<TokioIo<TcpStream>>>> {
fn connected(&self) -> Connected {
if self.inner.inner().get_ref().1.alpn_protocol() == Some(b"h2") {
if rustls_is_h2(self.inner.inner().get_ref().1) {
self.inner
.inner()
.get_ref()
Expand All @@ -1695,7 +1680,7 @@ mod rustls_tls_conn {
#[cfg(unix)]
impl Connection for RustlsTlsConn<TokioIo<TokioIo<tokio::net::UnixStream>>> {
fn connected(&self) -> Connected {
if self.inner.inner().get_ref().1.alpn_protocol() == Some(b"h2") {
if rustls_is_h2(self.inner.inner().get_ref().1) {
self.inner
.inner()
.get_ref()
Expand All @@ -1712,7 +1697,7 @@ mod rustls_tls_conn {
#[cfg(unix)]
impl Connection for RustlsTlsConn<TokioIo<MaybeHttpsStream<TokioIo<tokio::net::UnixStream>>>> {
fn connected(&self) -> Connected {
if self.inner.inner().get_ref().1.alpn_protocol() == Some(b"h2") {
if rustls_is_h2(self.inner.inner().get_ref().1) {
self.inner
.inner()
.get_ref()
Expand All @@ -1731,7 +1716,7 @@ mod rustls_tls_conn {
for RustlsTlsConn<TokioIo<TokioIo<tokio::net::windows::named_pipe::NamedPipeClient>>>
{
fn connected(&self) -> Connected {
if self.inner.inner().get_ref().1.alpn_protocol() == Some(b"h2") {
if rustls_is_h2(self.inner.inner().get_ref().1) {
self.inner
.inner()
.get_ref()
Expand All @@ -1752,7 +1737,7 @@ mod rustls_tls_conn {
>
{
fn connected(&self) -> Connected {
if self.inner.inner().get_ref().1.alpn_protocol() == Some(b"h2") {
if rustls_is_h2(self.inner.inner().get_ref().1) {
self.inner
.inner()
.get_ref()
Expand Down
Loading
Loading