Skip to content

Commit 81278ef

Browse files
committed
Upgrade to rustls 0.20
1 parent 3f16ac4 commit 81278ef

File tree

5 files changed

+66
-46
lines changed

5 files changed

+66
-46
lines changed

Cargo.toml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ repository = "https://github.com/ctz/hyper-rustls"
1111

1212
[dependencies]
1313
log = "0.4.4"
14-
ct-logs = { version = "^0.8", optional = true }
14+
ct-logs = { version = "^0.9", optional = true }
1515
hyper = { version = "0.14", default-features = false, features = ["client", "http1"] }
16-
rustls = "0.19"
17-
rustls-native-certs = { version = "0.5.0", optional = true }
16+
rustls = { git = "https://github.com/ctz/rustls" }
17+
rustls-native-certs = { git = "https://github.com/djc/rustls-native-certs", rev = "c862ff371d8766deab109990f3e7b2e89d9af168", optional = true }
18+
rustls-pemfile = { version = "0.2.1" }
1819
tokio = "1.0"
19-
tokio-rustls = "0.22"
20-
webpki = "0.21.0"
21-
webpki-roots = { version = "0.21", optional = true }
20+
tokio-rustls = { version = "0.23", git = "https://github.com/tokio-rs/tls", rev = "b433932bf1025960e5b99f353cf8eee4ce2f08f3" }
21+
webpki = "0.22.0"
22+
webpki-roots = { version = "0.22", optional = true }
2223

2324
[dev-dependencies]
2425
async-stream = "0.3.0"
@@ -45,3 +46,6 @@ required-features = ["tokio-runtime"]
4546
[package.metadata.docs.rs]
4647
all-features = true
4748
rustdoc-args = ["--cfg", "docsrs"]
49+
50+
[patch."crates-io"]
51+
rustls = { git = "https://github.com/ctz/rustls" }

examples/client.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
//! First parameter is the mandatory URL to GET.
44
//! Second parameter is an optional path to CA store.
55
use hyper::{body::to_bytes, client, Body, Uri};
6+
use rustls::RootCertStore;
7+
68
use std::str::FromStr;
79
use std::{env, fs, io};
810

@@ -46,11 +48,16 @@ async fn run_client() -> io::Result<()> {
4648
// Build an HTTP connector which supports HTTPS too.
4749
let mut http = client::HttpConnector::new();
4850
http.enforce_http(false);
49-
// Build a TLS client, using the custom CA store for lookups.
50-
let mut tls = rustls::ClientConfig::new();
51-
tls.root_store
52-
.add_pem_file(rd)
51+
// Read trust roots
52+
let certs = rustls_pemfile::certs(rd)
5353
.map_err(|_| error("failed to load custom CA store".into()))?;
54+
let mut roots = RootCertStore::empty();
55+
roots.add_parsable_certificates(&certs);
56+
// Build a TLS client, using the custom CA store for lookups.
57+
let tls = rustls::ClientConfig::builder()
58+
.with_safe_defaults()
59+
.with_root_certificates(roots, &ct_logs::LOGS)
60+
.with_no_client_auth();
5461
// Join the above part into an HTTPS connector.
5562
hyper_rustls::HttpsConnector::from((http, tls))
5663
}

examples/server.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
//! Certificate and private key are hardcoded to sample files.
55
//! hyper will automatically use HTTP/2 if a client starts talking HTTP/2,
66
//! otherwise HTTP/1.1 will be used.
7+
use std::pin::Pin;
8+
use std::vec::Vec;
9+
use std::{env, fs, io, sync};
10+
711
use async_stream::stream;
812
use core::task::{Context, Poll};
913
use futures_util::{future::TryFutureExt, stream::Stream};
1014
use hyper::service::{make_service_fn, service_fn};
1115
use hyper::{Body, Method, Request, Response, Server, StatusCode};
12-
use rustls::internal::pemfile;
13-
use std::pin::Pin;
14-
use std::vec::Vec;
15-
use std::{env, fs, io, sync};
1616
use tokio::net::{TcpListener, TcpStream};
1717
use tokio_rustls::server::TlsStream;
1818
use tokio_rustls::TlsAcceptor;
@@ -45,12 +45,13 @@ async fn run_server() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
4545
// Load private key.
4646
let key = load_private_key("examples/sample.rsa")?;
4747
// Do not use client certificate authentication.
48-
let mut cfg = rustls::ServerConfig::new(rustls::NoClientAuth::new());
49-
// Select a certificate to use.
50-
cfg.set_single_cert(certs, key)
48+
let mut cfg = rustls::ServerConfig::builder()
49+
.with_safe_defaults()
50+
.with_no_client_auth()
51+
.with_single_cert(certs, key)
5152
.map_err(|e| error(format!("{}", e)))?;
5253
// Configure ALPN to accept HTTP/2, HTTP/1.1 in that order.
53-
cfg.set_protocols(&[b"h2".to_vec(), b"http/1.1".to_vec()]);
54+
cfg.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
5455
sync::Arc::new(cfg)
5556
};
5657

@@ -127,7 +128,9 @@ fn load_certs(filename: &str) -> io::Result<Vec<rustls::Certificate>> {
127128
let mut reader = io::BufReader::new(certfile);
128129

129130
// Load and return certificate.
130-
pemfile::certs(&mut reader).map_err(|_| error("failed to load certificate".into()))
131+
let certs = rustls_pemfile::certs(&mut reader)
132+
.map_err(|_| error("failed to load certificate".into()))?;
133+
Ok(certs.into_iter().map(rustls::Certificate).collect())
131134
}
132135

133136
// Load private key from file.
@@ -138,10 +141,11 @@ fn load_private_key(filename: &str) -> io::Result<rustls::PrivateKey> {
138141
let mut reader = io::BufReader::new(keyfile);
139142

140143
// Load and return a single private key.
141-
let keys = pemfile::rsa_private_keys(&mut reader)
144+
let keys = rustls_pemfile::rsa_private_keys(&mut reader)
142145
.map_err(|_| error("failed to load private key".into()))?;
143146
if keys.len() != 1 {
144147
return Err(error("expected a single private key".into()));
145148
}
146-
Ok(keys[0].clone())
149+
150+
Ok(rustls::PrivateKey(keys[0].clone()))
147151
}

src/connector.rs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
#[cfg(feature = "tokio-runtime")]
2-
use hyper::client::connect::HttpConnector;
3-
use hyper::{client::connect::Connection, service::Service, Uri};
4-
use rustls::ClientConfig;
51
use std::future::Future;
62
use std::pin::Pin;
73
use std::sync::Arc;
84
use std::task::{Context, Poll};
95
use std::{fmt, io};
6+
use std::convert::TryFrom;
7+
8+
#[cfg(feature = "tokio-runtime")]
9+
use hyper::client::connect::HttpConnector;
10+
use hyper::{client::connect::Connection, service::Service, Uri};
11+
use rustls::{ClientConfig, RootCertStore};
1012
use tokio::io::{AsyncRead, AsyncWrite};
1113
use tokio_rustls::TlsConnector;
12-
use webpki::DNSNameRef;
1314

1415
use crate::stream::MaybeHttpsStream;
1516

@@ -31,38 +32,42 @@ impl HttpsConnector<HttpConnector> {
3132
#[cfg(feature = "rustls-native-certs")]
3233
#[cfg_attr(docsrs, doc(cfg(feature = "rustls-native-certs")))]
3334
pub fn with_native_roots() -> Self {
34-
let mut config = ClientConfig::new();
35-
config.root_store = match rustls_native_certs::load_native_certs() {
36-
Ok(store) => store,
37-
Err((Some(store), err)) => {
38-
log::warn!("Could not load all certificates: {:?}", err);
39-
store
40-
}
41-
Err((None, err)) => Err(err).expect("cannot access native cert store"),
35+
let certs = match rustls_native_certs::load_native_certs() {
36+
Ok(certs) => certs,
37+
Err(err) => Err(err).expect("cannot access native cert store"),
4238
};
43-
if config.root_store.is_empty() {
39+
40+
if certs.is_empty() {
4441
panic!("no CA certificates found");
4542
}
46-
Self::build(config)
43+
44+
let mut roots = RootCertStore::empty();
45+
for cert in certs {
46+
roots.add_parsable_certificates(&[cert.0]);
47+
}
48+
49+
Self::build(roots)
4750
}
4851

4952
/// Construct a new `HttpsConnector` using the `webpki_roots`
5053
#[cfg(feature = "webpki-roots")]
5154
#[cfg_attr(docsrs, doc(cfg(feature = "webpki-roots")))]
5255
pub fn with_webpki_roots() -> Self {
53-
let mut config = ClientConfig::new();
54-
config
55-
.root_store
56-
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
57-
Self::build(config)
56+
let mut roots = rustls::RootCertStore::empty();
57+
roots.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0);
58+
Self::build(roots)
5859
}
5960

60-
fn build(mut config: ClientConfig) -> Self {
61+
fn build(roots: rustls::RootCertStore) -> Self {
6162
let mut http = HttpConnector::new();
6263
http.enforce_http(false);
6364

65+
let mut config = ClientConfig::builder()
66+
.with_safe_defaults()
67+
.with_root_certificates(roots, &ct_logs::LOGS)
68+
.with_no_client_auth();
69+
6470
config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
65-
config.ct_logs = Some(&ct_logs::LOGS);
6671
(http, config).into()
6772
}
6873
}
@@ -127,7 +132,7 @@ where
127132
let f = async move {
128133
let tcp = connecting_future.await.map_err(Into::into)?;
129134
let connector = TlsConnector::from(cfg);
130-
let dnsname = DNSNameRef::try_from_ascii_str(&hostname)
135+
let dnsname = rustls::ServerName::try_from(hostname.as_str())
131136
.map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid dnsname"))?;
132137
let tls = connector
133138
.connect(dnsname, tcp)

src/stream.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ use std::task::{Context, Poll};
66

77
use hyper::client::connect::{Connected, Connection};
88

9-
use rustls::Session;
109
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
1110
use tokio_rustls::client::TlsStream;
11+
use tokio_rustls::rustls::{Connection as _};
1212

1313
/// A stream that might be protected with TLS.
1414
pub enum MaybeHttpsStream<T> {
@@ -24,7 +24,7 @@ impl<T: AsyncRead + AsyncWrite + Connection + Unpin> Connection for MaybeHttpsSt
2424
MaybeHttpsStream::Http(s) => s.connected(),
2525
MaybeHttpsStream::Https(s) => {
2626
let (tcp, tls) = s.get_ref();
27-
if tls.get_alpn_protocol() == Some(b"h2") {
27+
if tls.alpn_protocol() == Some(b"h2") {
2828
tcp.connected().negotiated_h2()
2929
} else {
3030
tcp.connected()

0 commit comments

Comments
 (0)