mirror of https://github.com/rwf2/Rocket.git
Update 'rustls' to 0.20.
Also updates 'tokio-rustls' to a compatible version. Additionally depends on 'rustls-pemfile' which includes functionality that was previously part of 'rustls' itself.
This commit is contained in:
parent
502b11c177
commit
fda05bddd2
|
@ -16,7 +16,7 @@ edition = "2018"
|
|||
|
||||
[features]
|
||||
default = []
|
||||
tls = ["rustls", "tokio-rustls"]
|
||||
tls = ["rustls", "tokio-rustls", "rustls-pemfile"]
|
||||
mtls = ["tls", "x509-parser"]
|
||||
private-cookies = ["cookie/private", "cookie/key-expansion"]
|
||||
serde = ["uncased/with-serde-alloc", "serde_"]
|
||||
|
@ -28,8 +28,9 @@ percent-encoding = "2"
|
|||
http = "0.2"
|
||||
time = { version = "0.3", features = ["formatting", "macros"] }
|
||||
indexmap = { version = "1.5.2", features = ["std"] }
|
||||
rustls = { version = "0.19", optional = true }
|
||||
tokio-rustls = { version = "0.22.0", optional = true }
|
||||
rustls = { version = "0.20", optional = true }
|
||||
tokio-rustls = { version = "0.23.0", optional = true }
|
||||
rustls-pemfile = { version = "0.3", optional = true }
|
||||
tokio = { version = "1.6.1", features = ["net", "sync", "time"] }
|
||||
log = "0.4"
|
||||
ref-cast = "1.0"
|
||||
|
|
|
@ -54,7 +54,7 @@ pub trait Connection: AsyncRead + AsyncWrite {
|
|||
///
|
||||
/// Defaults to an empty vector to indicate that no certificates were
|
||||
/// presented.
|
||||
fn peer_certificates(&self) -> Option<Vec<RawCertificate>> { None }
|
||||
fn peer_certificates(&self) -> Option<&[RawCertificate]> { None }
|
||||
}
|
||||
|
||||
pin_project_lite::pin_project! {
|
||||
|
|
|
@ -5,7 +5,6 @@ use std::task::{Context, Poll};
|
|||
use std::net::SocketAddr;
|
||||
use std::future::Future;
|
||||
|
||||
use rustls::{ServerConfig, SupportedCipherSuite};
|
||||
use tokio_rustls::{TlsAcceptor, Accept, server::TlsStream};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
||||
|
@ -27,7 +26,7 @@ enum State {
|
|||
pub struct Config<R> {
|
||||
pub cert_chain: R,
|
||||
pub private_key: R,
|
||||
pub ciphersuites: Vec<&'static SupportedCipherSuite>,
|
||||
pub ciphersuites: Vec<rustls::SupportedCipherSuite>,
|
||||
pub prefer_server_order: bool,
|
||||
pub ca_certs: Option<R>,
|
||||
pub mandatory_mtls: bool,
|
||||
|
@ -37,40 +36,38 @@ impl TlsListener {
|
|||
pub async fn bind<R>(addr: SocketAddr, mut c: Config<R>) -> io::Result<TlsListener>
|
||||
where R: io::BufRead
|
||||
{
|
||||
let cert_chain = load_certs(&mut c.cert_chain).map_err(|e| {
|
||||
let msg = format!("malformed TLS certificate chain: {}", e);
|
||||
io::Error::new(e.kind(), msg)
|
||||
})?;
|
||||
use rustls::server::{AllowAnyAuthenticatedClient, AllowAnyAnonymousOrAuthenticatedClient};
|
||||
use rustls::server::{NoClientAuth, ServerSessionMemoryCache, ServerConfig};
|
||||
|
||||
let key = load_private_key(&mut c.private_key).map_err(|e| {
|
||||
let msg = format!("malformed TLS private key: {}", e);
|
||||
io::Error::new(e.kind(), msg)
|
||||
})?;
|
||||
let cert_chain = load_certs(&mut c.cert_chain)
|
||||
.map_err(|e| io::Error::new(e.kind(), format!("bad TLS cert chain: {}", e)))?;
|
||||
|
||||
let key = load_private_key(&mut c.private_key)
|
||||
.map_err(|e| io::Error::new(e.kind(), format!("bad TLS private key: {}", e)))?;
|
||||
|
||||
let client_auth = match c.ca_certs {
|
||||
Some(ref mut ca_certs) => {
|
||||
let roots = load_ca_certs(ca_certs).map_err(|e| {
|
||||
let msg = format!("malformed CA certificate(s): {}", e);
|
||||
io::Error::new(e.kind(), msg)
|
||||
})?;
|
||||
|
||||
if c.mandatory_mtls {
|
||||
rustls::AllowAnyAuthenticatedClient::new(roots)
|
||||
} else {
|
||||
rustls::AllowAnyAnonymousOrAuthenticatedClient::new(roots)
|
||||
}
|
||||
}
|
||||
None => rustls::NoClientAuth::new(),
|
||||
Some(ref mut ca_certs) => match load_ca_certs(ca_certs) {
|
||||
Ok(ca_roots) if c.mandatory_mtls => AllowAnyAuthenticatedClient::new(ca_roots),
|
||||
Ok(ca_roots) => AllowAnyAnonymousOrAuthenticatedClient::new(ca_roots),
|
||||
Err(e) => return Err(io::Error::new(e.kind(), format!("bad CA cert(s): {}", e))),
|
||||
},
|
||||
None => NoClientAuth::new(),
|
||||
};
|
||||
|
||||
let mut tls_config = ServerConfig::new(client_auth);
|
||||
let cache = rustls::ServerSessionMemoryCache::new(1024);
|
||||
tls_config.set_persistence(cache);
|
||||
tls_config.ticketer = rustls::Ticketer::new();
|
||||
tls_config.ciphersuites = c.ciphersuites;
|
||||
let mut tls_config = ServerConfig::builder()
|
||||
.with_cipher_suites(&c.ciphersuites)
|
||||
.with_safe_default_kx_groups()
|
||||
.with_safe_default_protocol_versions()
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("bad TLS config: {}", e)))?
|
||||
.with_client_cert_verifier(client_auth)
|
||||
.with_single_cert(cert_chain, key)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("bad TLS config: {}", e)))?;
|
||||
|
||||
tls_config.ignore_client_order = c.prefer_server_order;
|
||||
tls_config.set_single_cert(cert_chain, key).expect("invalid key");
|
||||
tls_config.set_protocols(&[b"h2".to_vec(), b"http/1.1".to_vec()]);
|
||||
tls_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
|
||||
tls_config.session_storage = ServerSessionMemoryCache::new(1024);
|
||||
tls_config.ticketer = rustls::Ticketer::new()
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("bad TLS ticketer: {}", e)))?;
|
||||
|
||||
let listener = TcpListener::bind(addr).await?;
|
||||
let acceptor = TlsAcceptor::from(Arc::new(tls_config));
|
||||
|
@ -120,9 +117,7 @@ impl Connection for TlsStream<TcpStream> {
|
|||
self.get_ref().0.peer_address()
|
||||
}
|
||||
|
||||
fn peer_certificates(&self) -> Option<Vec<RawCertificate>> {
|
||||
use rustls::Session;
|
||||
|
||||
self.get_ref().1.get_peer_certificates()
|
||||
fn peer_certificates(&self) -> Option<&[RawCertificate]> {
|
||||
self.get_ref().1.peer_certificates()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::io::{self, Cursor, Read};
|
||||
|
||||
use rustls::{internal::pemfile, Certificate, PrivateKey, RootCertStore};
|
||||
use rustls::{Certificate, PrivateKey, RootCertStore};
|
||||
|
||||
fn err(message: impl Into<std::borrow::Cow<'static, str>>) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, message.into())
|
||||
|
@ -8,7 +8,8 @@ fn err(message: impl Into<std::borrow::Cow<'static, str>>) -> io::Error {
|
|||
|
||||
/// Loads certificates from `reader`.
|
||||
pub fn load_certs(reader: &mut dyn io::BufRead) -> io::Result<Vec<Certificate>> {
|
||||
pemfile::certs(reader).map_err(|_| err("invalid certificate"))
|
||||
let certs = rustls_pemfile::certs(reader).map_err(|_| err("invalid certificate"))?;
|
||||
Ok(certs.into_iter().map(Certificate).collect())
|
||||
}
|
||||
|
||||
/// Load and decode the private key from `reader`.
|
||||
|
@ -19,8 +20,8 @@ pub fn load_private_key(reader: &mut dyn io::BufRead) -> io::Result<PrivateKey>
|
|||
reader.read_line(&mut first_line)?;
|
||||
|
||||
let private_keys_fn = match first_line.trim_end() {
|
||||
"-----BEGIN RSA PRIVATE KEY-----" => pemfile::rsa_private_keys,
|
||||
"-----BEGIN PRIVATE KEY-----" => pemfile::pkcs8_private_keys,
|
||||
"-----BEGIN RSA PRIVATE KEY-----" => rustls_pemfile::rsa_private_keys,
|
||||
"-----BEGIN PRIVATE KEY-----" => rustls_pemfile::pkcs8_private_keys,
|
||||
_ => return Err(err("invalid key header"))
|
||||
};
|
||||
|
||||
|
@ -28,7 +29,7 @@ pub fn load_private_key(reader: &mut dyn io::BufRead) -> io::Result<PrivateKey>
|
|||
.map_err(|_| err("invalid key file"))
|
||||
.and_then(|mut keys| match keys.len() {
|
||||
0 => Err(err("no valid keys found; is the file malformed?")),
|
||||
1 => Ok(keys.remove(0)),
|
||||
1 => Ok(PrivateKey(keys.remove(0))),
|
||||
n => Err(err(format!("expected 1 key, found {}", n))),
|
||||
})?;
|
||||
|
||||
|
@ -41,9 +42,8 @@ pub fn load_private_key(reader: &mut dyn io::BufRead) -> io::Result<PrivateKey>
|
|||
/// Load and decode CA certificates from `reader`.
|
||||
pub fn load_ca_certs(reader: &mut dyn io::BufRead) -> io::Result<RootCertStore> {
|
||||
let mut roots = rustls::RootCertStore::empty();
|
||||
let (_, e) = roots.add_pem_file(reader).map_err(|_| err("PEM format error"))?;
|
||||
if e != 0 {
|
||||
return Err(err("validity checks failed"));
|
||||
for cert in load_certs(reader)? {
|
||||
roots.add(&cert).map_err(|e| err(format!("CA cert error: {}", e)))?;
|
||||
}
|
||||
|
||||
Ok(roots)
|
||||
|
|
|
@ -630,7 +630,7 @@ mod with_tls_feature {
|
|||
|
||||
use crate::http::tls::Config;
|
||||
use crate::http::tls::rustls::SupportedCipherSuite as RustlsCipher;
|
||||
use crate::http::tls::rustls::ciphersuite as rustls;
|
||||
use crate::http::tls::rustls::cipher_suite;
|
||||
|
||||
use yansi::Paint;
|
||||
|
||||
|
@ -675,26 +675,26 @@ mod with_tls_feature {
|
|||
})
|
||||
}
|
||||
|
||||
fn rustls_ciphers(&self) -> impl Iterator<Item = &'static RustlsCipher> + '_ {
|
||||
fn rustls_ciphers(&self) -> impl Iterator<Item = RustlsCipher> + '_ {
|
||||
self.ciphers().map(|ciphersuite| match ciphersuite {
|
||||
CipherSuite::TLS_CHACHA20_POLY1305_SHA256 =>
|
||||
&rustls::TLS13_CHACHA20_POLY1305_SHA256,
|
||||
cipher_suite::TLS13_CHACHA20_POLY1305_SHA256,
|
||||
CipherSuite::TLS_AES_256_GCM_SHA384 =>
|
||||
&rustls::TLS13_AES_256_GCM_SHA384,
|
||||
cipher_suite::TLS13_AES_256_GCM_SHA384,
|
||||
CipherSuite::TLS_AES_128_GCM_SHA256 =>
|
||||
&rustls::TLS13_AES_128_GCM_SHA256,
|
||||
cipher_suite::TLS13_AES_128_GCM_SHA256,
|
||||
CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 =>
|
||||
&rustls::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
cipher_suite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 =>
|
||||
&rustls::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
cipher_suite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 =>
|
||||
&rustls::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 =>
|
||||
&rustls::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 =>
|
||||
&rustls::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
cipher_suite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 =>
|
||||
&rustls::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
cipher_suite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -298,7 +298,7 @@ impl<F: Future, C: Connection> Connection for CancellableIo<F, C> {
|
|||
self.io.peer_address()
|
||||
}
|
||||
|
||||
fn peer_certificates(&self) -> Option<Vec<RawCertificate>> {
|
||||
fn peer_certificates(&self) -> Option<&[RawCertificate]> {
|
||||
self.io.peer_certificates()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -444,7 +444,7 @@ impl Rocket<Orbit> {
|
|||
let rocket = rocket.clone();
|
||||
let connection = ConnectionMeta {
|
||||
remote: conn.peer_address(),
|
||||
client_certificates: conn.peer_certificates().map(Arc::new),
|
||||
client_certificates: conn.peer_certificates().map(|certs| Arc::new(certs.to_vec())),
|
||||
};
|
||||
|
||||
async move {
|
||||
|
|
Loading…
Reference in New Issue