Skip to content

Commit

Permalink
Update to rustls alpha releases
Browse files Browse the repository at this point in the history
  • Loading branch information
djc committed Nov 27, 2023
1 parent 77154da commit 38e0e1b
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 66 deletions.
16 changes: 9 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,28 @@ documentation = "https://docs.rs/hyper-rustls/"
http = "0.2"
hyper = { version = "0.14", default-features = false, features = ["client"] }
log = { version = "0.4.4", optional = true }
rustls-native-certs = { version = "0.6", optional = true }
rustls = { version = "0.21.6", default-features = false }
pki-types = { package = "rustls-pki-types", version = "0.2" }
rustls-native-certs = { version = "=0.7.0-alpha.2", optional = true }
rustls = { version = "=0.22.0-alpha.5", default-features = false }
tokio = "1.0"
tokio-rustls = { version = "0.24.0", default-features = false }
webpki-roots = { version = "0.25", optional = true }
tokio-rustls = { version = "=0.25.0-alpha.3", default-features = false }
webpki-roots = { version = "=0.26.0-alpha.2", optional = true }
futures-util = { version = "0.3", default-features = false }

[dev-dependencies]
hyper = { version = "0.14", features = ["full"] }
rustls = { version = "0.21.0", default-features = false, features = ["tls12"] }
rustls-pemfile = "1.0.0"
rustls = { version = "=0.22.0-alpha.5", default-features = false, features = ["tls12"] }
rustls-pemfile = "=2.0.0-alpha.2"
tokio = { version = "1.0", features = ["io-std", "macros", "net", "rt-multi-thread"] }

[features]
default = ["native-tokio", "http1", "tls12", "logging", "acceptor"]
default = ["native-tokio", "http1", "tls12", "logging", "acceptor", "ring"]
acceptor = ["hyper/server", "tokio-runtime"]
http1 = ["hyper/http1"]
http2 = ["hyper/http2"]
webpki-tokio = ["tokio-runtime", "webpki-roots"]
native-tokio = ["tokio-runtime", "rustls-native-certs"]
ring = ["rustls/ring"]
tokio-runtime = ["hyper/runtime"]
tls12 = ["tokio-rustls/tls12", "rustls/tls12"]
logging = ["log", "tokio-rustls/logging", "rustls/logging"]
Expand Down
5 changes: 2 additions & 3 deletions examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,9 @@ async fn run_client() -> io::Result<()> {
let tls = match ca {
Some(ref mut rd) => {
// Read trust roots
let certs = rustls_pemfile::certs(rd)
.map_err(|_| error("failed to load custom CA store".into()))?;
let certs = rustls_pemfile::certs(rd).collect::<Result<Vec<_>, _>>()?;
let mut roots = RootCertStore::empty();
roots.add_parsable_certificates(&certs);
roots.add_parsable_certificates(certs);
// TLS client config using the custom CA store for lookups
rustls::ClientConfig::builder()
.with_safe_defaults()
Expand Down
20 changes: 5 additions & 15 deletions examples/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use hyper::server::conn::AddrIncoming;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Method, Request, Response, Server, StatusCode};
use hyper_rustls::TlsAcceptor;
use pki_types::{CertificateDer, PrivateKeyDer};

fn main() {
// Serve an echo service over HTTPS, with proper error handling.
Expand Down Expand Up @@ -80,34 +81,23 @@ async fn echo(req: Request<Body>) -> Result<Response<Body>, hyper::Error> {
}

// Load public certificate from file.
fn load_certs(filename: &str) -> io::Result<Vec<rustls::Certificate>> {
fn load_certs(filename: &str) -> io::Result<Vec<CertificateDer<'static>>> {
// Open certificate file.
let certfile = fs::File::open(filename)
.map_err(|e| error(format!("failed to open {}: {}", filename, e)))?;
let mut reader = io::BufReader::new(certfile);

// Load and return certificate.
let certs = rustls_pemfile::certs(&mut reader)
.map_err(|_| error("failed to load certificate".into()))?;
Ok(certs
.into_iter()
.map(rustls::Certificate)
.collect())
rustls_pemfile::certs(&mut reader).collect()
}

// Load private key from file.
fn load_private_key(filename: &str) -> io::Result<rustls::PrivateKey> {
fn load_private_key(filename: &str) -> io::Result<PrivateKeyDer<'static>> {
// Open keyfile.
let keyfile = fs::File::open(filename)
.map_err(|e| error(format!("failed to open {}: {}", filename, e)))?;
let mut reader = io::BufReader::new(keyfile);

// Load and return a single private key.
let keys = rustls_pemfile::rsa_private_keys(&mut reader)
.map_err(|_| error("failed to load private key".into()))?;
if keys.len() != 1 {
return Err(error("expected a single private key".into()));
}

Ok(rustls::PrivateKey(keys[0].clone()))
rustls_pemfile::private_key(&mut reader).map(|key| key.unwrap())
}
5 changes: 3 additions & 2 deletions src/acceptor/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::sync::Arc;

use hyper::server::conn::AddrIncoming;
use pki_types::{CertificateDer, PrivateKeyDer};
use rustls::ServerConfig;

use super::TlsAcceptor;
Expand All @@ -27,8 +28,8 @@ impl AcceptorBuilder<WantsTlsConfig> {
/// [with_no_client_auth]: rustls::ConfigBuilder::with_no_client_auth
pub fn with_single_cert(
self,
cert_chain: Vec<rustls::Certificate>,
key_der: rustls::PrivateKey,
cert_chain: Vec<CertificateDer<'static>>,
key_der: PrivateKeyDer<'static>,
) -> Result<AcceptorBuilder<WantsAlpn>, rustls::Error> {
Ok(AcceptorBuilder(WantsAlpn(
ServerConfig::builder()
Expand Down
29 changes: 9 additions & 20 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use rustls::client::WantsTransparencyPolicyOrClientCert;
#[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))]
use rustls::client::WantsClientCert;
use rustls::{ClientConfig, ConfigBuilder, WantsVerifier};

/// Methods for configuring roots
Expand All @@ -13,35 +14,29 @@ pub trait ConfigBuilderExt {
/// it's recommended to use `with_webpki_roots`.
#[cfg(feature = "rustls-native-certs")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls-native-certs")))]
fn with_native_roots(
self,
) -> std::io::Result<ConfigBuilder<ClientConfig, WantsTransparencyPolicyOrClientCert>>;
fn with_native_roots(self) -> std::io::Result<ConfigBuilder<ClientConfig, WantsClientCert>>;

/// This configures the webpki roots, which are Mozilla's set of
/// trusted roots as packaged by webpki-roots.
#[cfg(feature = "webpki-roots")]
#[cfg_attr(docsrs, doc(cfg(feature = "webpki-roots")))]
fn with_webpki_roots(self) -> ConfigBuilder<ClientConfig, WantsTransparencyPolicyOrClientCert>;
fn with_webpki_roots(self) -> ConfigBuilder<ClientConfig, WantsClientCert>;
}

impl ConfigBuilderExt for ConfigBuilder<ClientConfig, WantsVerifier> {
#[cfg(feature = "rustls-native-certs")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls-native-certs")))]
#[cfg_attr(not(feature = "logging"), allow(unused_variables))]
fn with_native_roots(
self,
) -> std::io::Result<ConfigBuilder<ClientConfig, WantsTransparencyPolicyOrClientCert>> {
fn with_native_roots(self) -> std::io::Result<ConfigBuilder<ClientConfig, WantsClientCert>> {
let mut roots = rustls::RootCertStore::empty();
let mut valid_count = 0;
let mut invalid_count = 0;

for cert in rustls_native_certs::load_native_certs().expect("could not load platform certs")
{
let cert = rustls::Certificate(cert.0);
match roots.add(&cert) {
match roots.add(cert) {
Ok(_) => valid_count += 1,
Err(err) => {
crate::log::trace!("invalid cert der {:?}", cert.0);
crate::log::debug!("certificate parsing failed: {:?}", err);
invalid_count += 1
}
Expand All @@ -65,18 +60,12 @@ impl ConfigBuilderExt for ConfigBuilder<ClientConfig, WantsVerifier> {

#[cfg(feature = "webpki-roots")]
#[cfg_attr(docsrs, doc(cfg(feature = "webpki-roots")))]
fn with_webpki_roots(self) -> ConfigBuilder<ClientConfig, WantsTransparencyPolicyOrClientCert> {
fn with_webpki_roots(self) -> ConfigBuilder<ClientConfig, WantsClientCert> {
let mut roots = rustls::RootCertStore::empty();
roots.add_trust_anchors(
roots.extend(
webpki_roots::TLS_SERVER_ROOTS
.iter()
.map(|ta| {
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
ta.subject,
ta.spki,
ta.name_constraints,
)
}),
.cloned(),
);
self.with_root_certificates(roots)
}
Expand Down
5 changes: 3 additions & 2 deletions src/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::task::{Context, Poll};
use std::{fmt, io};

use hyper::{client::connect::Connection, service::Service, Uri};
use pki_types::ServerName;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio_rustls::TlsConnector;

Expand Down Expand Up @@ -106,8 +107,8 @@ where
hostname = trimmed;
}

let hostname = match rustls::ServerName::try_from(hostname) {
Ok(dnsname) => dnsname,
let hostname = match ServerName::try_from(hostname) {
Ok(dnsname) => dnsname.to_owned(),
Err(_) => {
let err = io::Error::new(io::ErrorKind::Other, "invalid dnsname");
return Box::pin(async move { Err(Box::new(err).into()) });
Expand Down
58 changes: 51 additions & 7 deletions src/connector/builder.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#[cfg(feature = "tokio-runtime")]
use hyper::client::HttpConnector;
#[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))]
use rustls::crypto::CryptoProvider;
use rustls::ClientConfig;

use super::HttpsConnector;
#[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))]
use crate::config::ConfigBuilderExt;

#[cfg(feature = "tokio-runtime")]
use hyper::client::HttpConnector;

/// A builder for an [`HttpsConnector`]
///
/// This makes configuration flexible and explicit and ensures connector
Expand Down Expand Up @@ -57,8 +58,11 @@ impl ConnectorBuilder<WantsTlsConfig> {
/// See [`ConfigBuilderExt::with_native_roots`]
///
/// [with_safe_defaults]: rustls::ConfigBuilder::with_safe_defaults
#[cfg(feature = "rustls-native-certs")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls-native-certs")))]
#[cfg(all(feature = "ring", feature = "rustls-native-certs"))]
#[cfg_attr(
docsrs,
doc(cfg(all(feature = "ring", feature = "rustls-native-certs")))
)]
pub fn with_native_roots(self) -> std::io::Result<ConnectorBuilder<WantsSchemes>> {
Ok(self.with_tls_config(
ClientConfig::builder()
Expand All @@ -68,14 +72,34 @@ impl ConnectorBuilder<WantsTlsConfig> {
))
}

/// Shorthand for using rustls' [safe defaults][with_safe_defaults]
/// with a custom [`CryptoProvider`] and native roots
///
/// See [`ConfigBuilderExt::with_native_roots`]
///
/// [with_safe_defaults]: rustls::ConfigBuilder::with_safe_defaults
#[cfg(feature = "rustls-native-certs")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls-native-certs")))]
pub fn with_provider_and_native_roots(
self,
provider: &'static dyn CryptoProvider,
) -> std::io::Result<ConnectorBuilder<WantsSchemes>> {
Ok(self.with_tls_config(
ClientConfig::builder_with_provider(provider)
.with_safe_defaults()
.with_native_roots()?
.with_no_client_auth(),
))
}

/// Shorthand for using rustls' [safe defaults][with_safe_defaults]
/// and Mozilla roots
///
/// See [`ConfigBuilderExt::with_webpki_roots`]
///
/// [with_safe_defaults]: rustls::ConfigBuilder::with_safe_defaults
#[cfg(feature = "webpki-roots")]
#[cfg_attr(docsrs, doc(cfg(feature = "webpki-roots")))]
#[cfg(all(feature = "ring", feature = "webpki-roots"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "ring", feature = "webpki-roots"))))]
pub fn with_webpki_roots(self) -> ConnectorBuilder<WantsSchemes> {
self.with_tls_config(
ClientConfig::builder()
Expand All @@ -84,6 +108,26 @@ impl ConnectorBuilder<WantsTlsConfig> {
.with_no_client_auth(),
)
}

/// Shorthand for using rustls' [safe defaults][with_safe_defaults]
/// with a custom [`CryptoProvider`] and Mozilla roots
///
/// See [`ConfigBuilderExt::with_webpki_roots`]
///
/// [with_safe_defaults]: rustls::ConfigBuilder::with_safe_defaults
#[cfg(feature = "webpki-roots")]
#[cfg_attr(docsrs, doc(cfg(feature = "webpki-roots")))]
pub fn with_provider_and_webpki_roots(
self,
provider: &'static dyn CryptoProvider,
) -> ConnectorBuilder<WantsSchemes> {
self.with_tls_config(
ClientConfig::builder_with_provider(provider)
.with_safe_defaults()
.with_webpki_roots()
.with_no_client_auth(),
)
}
}

impl Default for ConnectorBuilder<WantsTlsConfig> {
Expand Down
22 changes: 12 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@
//! ```no_run
//! # #[cfg(all(feature = "rustls-native-certs", feature = "tokio-runtime", feature = "http1", feature = "acceptor"))]
//! # fn main() {
//! use std::io;
//! use std::fs::File;
//!
//! use hyper::server::conn::AddrIncoming;
//! use hyper::service::{make_service_fn, service_fn};
//! use hyper::{Body, Method, Request, Response, Server, StatusCode};
//! use hyper_rustls::TlsAcceptor;
//! use std::io;
//! use std::fs::File;
//! use pki_types::{CertificateDer, PrivateKeyDer};
//!
//! let mut rt = tokio::runtime::Runtime::new().unwrap();
//! let addr = "127.0.0.1:1337".parse().unwrap();
Expand All @@ -48,16 +50,14 @@
//! let mut reader = io::BufReader::new(certfile);
//!
//! // Load and return certificate.
//! let certs = rustls_pemfile::certs(&mut reader).unwrap();
//! let certs = certs.into_iter().map(rustls::Certificate).collect();
//! let certs = rustls_pemfile::certs(&mut reader).collect::<Result<Vec<_>, _>>().unwrap();
//!
//! // Load private key. (see `examples/server.rs`)
//! let keyfile = File::open("examples/sample.rsa").unwrap();
//! let mut reader = io::BufReader::new(keyfile);
//!
//! // Load and return a single private key.
//! let keys = rustls_pemfile::rsa_private_keys(&mut reader).unwrap();
//! let key = rustls::PrivateKey(keys[0].clone());
//! let key = rustls_pemfile::private_key(&mut reader).unwrap().unwrap();
//! let https = hyper_rustls::HttpsConnectorBuilder::new()
//! .with_native_roots()
//! .expect("no native root CA certificates found")
Expand All @@ -67,7 +67,7 @@
//!
//! let incoming = AddrIncoming::bind(&addr).unwrap();
//! let acceptor = TlsAcceptor::builder()
//! .with_single_cert(certs, key).unwrap()
//! .with_single_cert(certs, key.into()).unwrap()
//! .with_all_versions_alpn()
//! .with_incoming(incoming);
//! let service = make_service_fn(|_| async { Ok::<_, io::Error>(service_fn(|_req|async {Ok::<_, io::Error>(Response::new(Body::empty()))})) });
Expand All @@ -90,14 +90,16 @@ mod stream;

#[cfg(feature = "logging")]
mod log {
pub(crate) use log::{debug, trace};
#[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))]
pub(crate) use log::debug;
}

#[cfg(not(feature = "logging"))]
mod log {
macro_rules! trace ( ($($tt:tt)*) => {{}} );
#[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))]
macro_rules! debug ( ($($tt:tt)*) => {{}} );
pub(crate) use {debug, trace};
#[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))]
pub(crate) use debug;
}

#[cfg(feature = "acceptor")]
Expand Down

0 comments on commit 38e0e1b

Please sign in to comment.