From 8809f9378cec51a36ec1eaf14727efc62eefbe88 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Mon, 18 Dec 2023 07:56:52 -0800 Subject: [PATCH] Update to rustls 0.22 --- Cargo.lock | 45 +++++++-------------------------------------- Cargo.toml | 2 +- src/certificates.rs | 44 ++++++++++++++++++++++++++++++++------------ src/main.rs | 8 ++------ tests/tests.rs | 28 ++++++++++------------------ 5 files changed, 52 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 198cbc1..3bf4fa3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,7 +35,7 @@ dependencies = [ "rcgen", "rustls 0.22.1", "tokio", - "tokio-rustls 0.24.1", + "tokio-rustls 0.25.0", "url", ] @@ -492,22 +492,10 @@ dependencies = [ "base64 0.13.1", "log", "ring 0.16.20", - "sct 0.6.1", + "sct", "webpki", ] -[[package]] -name = "rustls" -version = "0.21.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" -dependencies = [ - "log", - "ring 0.17.7", - "rustls-webpki 0.101.7", - "sct 0.7.0", -] - [[package]] name = "rustls" version = "0.22.1" @@ -517,7 +505,7 @@ dependencies = [ "log", "ring 0.17.7", "rustls-pki-types", - "rustls-webpki 0.102.0", + "rustls-webpki", "subtle", "zeroize", ] @@ -528,16 +516,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7673e0aa20ee4937c6aacfc12bb8341cfbf054cdd21df6bec5fd0629fe9339b" -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring 0.17.7", - "untrusted 0.9.0", -] - [[package]] name = "rustls-webpki" version = "0.102.0" @@ -559,16 +537,6 @@ dependencies = [ "untrusted 0.7.1", ] -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", -] - [[package]] name = "serde" version = "1.0.192" @@ -740,11 +708,12 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.21.10", + "rustls 0.22.1", + "rustls-pki-types", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 64868d6..080518d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ once_cell = "1.19" percent-encoding = "2.3" rcgen = { version = "0.12.0" } rustls = "0.22.1" -tokio-rustls = "0.24.1" +tokio-rustls = "0.25.0" tokio = { version = "1.35", features = ["fs", "io-util", "net", "rt-multi-thread", "sync"] } url = "2.5.0" diff --git a/src/certificates.rs b/src/certificates.rs index fcad9c5..ab519ff 100644 --- a/src/certificates.rs +++ b/src/certificates.rs @@ -1,7 +1,9 @@ use { rustls::{ + crypto::ring::sign::any_supported_type, + pki_types::{self, CertificateDer, PrivateKeyDer}, server::{ClientHello, ResolvesServerCert}, - sign::{any_supported_type, CertifiedKey, SignError}, + sign::{CertifiedKey, SigningKey}, }, std::{ ffi::OsStr, @@ -13,6 +15,7 @@ use { /// A struct that holds all loaded certificates and the respective domain /// names. +#[derive(Debug)] pub(crate) struct CertStore { /// Stores the certificates and the domains they apply to, sorted by domain /// names, longest matches first @@ -30,7 +33,7 @@ pub enum CertLoadError { Empty, /// the key file for the specified domain is bad (e.g. does not contain a /// key or is invalid) - BadKey(String, SignError), + BadKey(String, rustls::Error), /// the key file for the specified domain is missing (but a certificate /// file was present) MissingKey(String), @@ -74,27 +77,44 @@ fn load_domain(certs_dir: &Path, domain: String) -> Result key, - Err(e) => return Err(CertLoadError::BadKey(domain, e)), - }; + let key = der_to_private_key(&der).map_err(|e| CertLoadError::BadKey(domain.clone(), e))?; + Ok(CertifiedKey::new(vec![cert], key)) } +/// We don't know the key type of the private key DER file, so try each +/// possible type until we find one that works. +/// +/// We should probably stop doing this and use a PEM file instead: +/// https://github.com/rustls/rustls/issues/1661 +fn der_to_private_key(der: &[u8]) -> Result, rustls::Error> { + let keys = [ + PrivateKeyDer::Pkcs1(pki_types::PrivatePkcs1KeyDer::from(der)), + PrivateKeyDer::Sec1(pki_types::PrivateSec1KeyDer::from(der)), + PrivateKeyDer::Pkcs8(pki_types::PrivatePkcs8KeyDer::from(der)), + ]; + + let mut err = None; + for key in keys { + match any_supported_type(&key) { + Ok(key) => return Ok(key), + Err(e) => err = Some(e), + } + } + Err(err.unwrap()) +} + impl CertStore { /// Load certificates from a certificate directory. /// Certificates should be stored in a folder for each hostname, for example diff --git a/src/main.rs b/src/main.rs index 8df888c..27b0ebe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -408,13 +408,9 @@ static TLS: Lazy = Lazy::new(acceptor); fn acceptor() -> TlsAcceptor { let config = if ARGS.only_tls13 { - ServerConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - .with_protocol_versions(&[&rustls::version::TLS13]) - .expect("could not build server config") + ServerConfig::builder_with_protocol_versions(&[&rustls::version::TLS13]) } else { - ServerConfig::builder().with_safe_defaults() + ServerConfig::builder() } .with_no_client_auth() .with_cert_resolver(ARGS.certs.clone()); diff --git a/tests/tests.rs b/tests/tests.rs index 4ec0e80..b020cc8 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -166,7 +166,7 @@ fn index_page() { #[cfg(unix)] #[test] fn index_page_unix() { - use rustls::{Certificate, ClientConnection, RootCertStore}; + use rustls::{pki_types::CertificateDer, ClientConnection, RootCertStore}; let sock_path = std::env::temp_dir().join("agate-test-unix-socket"); @@ -184,7 +184,7 @@ fn index_page_unix() { // set up TLS connection via unix socket let mut certs = RootCertStore::empty(); certs - .add(&Certificate( + .add(CertificateDer::from( include_bytes!(concat!( env!("CARGO_MANIFEST_DIR"), "/tests/data/multicert/example.com/cert.der" @@ -193,7 +193,6 @@ fn index_page_unix() { )) .unwrap(); let config = rustls::ClientConfig::builder() - .with_safe_defaults() .with_root_certificates(certs) .with_no_client_auth(); let mut session = ClientConnection::new( @@ -363,7 +362,7 @@ fn username() { #[test] /// - URLS with invalid hostnames are rejected fn percent_encode() { - use rustls::{Certificate, ClientConnection, RootCertStore}; + use rustls::{pki_types::CertificateDer, ClientConnection, RootCertStore}; use std::io::Write; use std::net::TcpStream; @@ -373,7 +372,7 @@ fn percent_encode() { let mut certs = RootCertStore::empty(); certs - .add(&Certificate( + .add(CertificateDer::from( include_bytes!(concat!( env!("CARGO_MANIFEST_DIR"), "/tests/data/multicert/example.com/cert.der" @@ -382,7 +381,6 @@ fn percent_encode() { )) .unwrap(); let config = rustls::ClientConfig::builder() - .with_safe_defaults() .with_root_certificates(certs) .with_no_client_auth(); @@ -533,12 +531,8 @@ fn explicit_tls_version() { let server = Server::new(&["-3"]); - let config = rustls::ClientConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - // try to connect using only TLS 1.2 - .with_protocol_versions(&[&rustls::version::TLS12]) - .unwrap() + // try to connect using only TLS 1.2 + let config = rustls::ClientConfig::builder_with_protocol_versions(&[&rustls::version::TLS12]) .with_root_certificates(RootCertStore::empty()) .with_no_client_auth(); @@ -636,7 +630,7 @@ mod multicert { #[test] fn example_com() { - use rustls::{Certificate, ClientConnection, RootCertStore}; + use rustls::{pki_types::CertificateDer, ClientConnection, RootCertStore}; use std::io::Write; use std::net::TcpStream; @@ -644,7 +638,7 @@ mod multicert { let mut certs = RootCertStore::empty(); certs - .add(&Certificate( + .add(CertificateDer::from( include_bytes!(concat!( env!("CARGO_MANIFEST_DIR"), "/tests/data/multicert/example.com/cert.der" @@ -653,7 +647,6 @@ mod multicert { )) .unwrap(); let config = rustls::ClientConfig::builder() - .with_safe_defaults() .with_root_certificates(certs) .with_no_client_auth(); @@ -675,7 +668,7 @@ mod multicert { #[test] fn example_org() { - use rustls::{Certificate, ClientConnection, RootCertStore}; + use rustls::{pki_types::CertificateDer, ClientConnection, RootCertStore}; use std::io::Write; use std::net::TcpStream; @@ -683,7 +676,7 @@ mod multicert { let mut certs = RootCertStore::empty(); certs - .add(&Certificate( + .add(CertificateDer::from( include_bytes!(concat!( env!("CARGO_MANIFEST_DIR"), "/tests/data/multicert/example.org/cert.der" @@ -692,7 +685,6 @@ mod multicert { )) .unwrap(); let config = rustls::ClientConfig::builder() - .with_safe_defaults() .with_root_certificates(certs) .with_no_client_auth();