From e1fc1f9f21d03bfaba498aa6022497e465e4cfdf Mon Sep 17 00:00:00 2001 From: Hannes de Jager Date: Fri, 31 May 2024 23:38:57 +0200 Subject: [PATCH] Upgrade libunftp dependencies This includes those with breaking changes like rustls, rustls-pemfile and tokio-rustls. --- .github/workflows/rust.yml | 1 + Cargo.toml | 16 +++--- crates/unftp-auth-jsonfile/Cargo.toml | 6 +-- crates/unftp-auth-pam/Cargo.toml | 2 +- crates/unftp-auth-rest/Cargo.toml | 6 +-- crates/unftp-sbe-fs/Cargo.toml | 8 +-- crates/unftp-sbe-gcs/Cargo.toml | 6 +-- src/server/controlchan/control_loop.rs | 2 +- src/server/tls.rs | 70 ++++++++++++++------------ 9 files changed, 61 insertions(+), 56 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7d282956..8d9392c4 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -134,6 +134,7 @@ jobs: env: trget: x86_64-pc-windows-msvc steps: + - uses: ilammy/setup-nasm@v1 - name: Checkout code uses: actions/checkout@v3 with: diff --git a/Cargo.toml b/Cargo.toml index 1b4d86d8..e54f2b22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,17 +46,17 @@ futures-util = { version = "0.3.30", default-features = false, features = ["allo getrandom = "0.2.15" lazy_static = "1.4.0" md-5 = "0.10.6" -moka = { version = "0.11.3", default-features = false, features = ["sync"] } -nix = { version = "0.28.0", default-features = false, features = ["fs"] } +moka = { version = "0.12.7", default-features = false, features = ["sync"] } +nix = { version = "0.29.0", default-features = false, features = ["fs"] } prometheus = { version = "0.13.4", default-features = false } proxy-protocol = "0.5.0" -rustls = "0.21.12" -rustls-pemfile = "1.0.4" +rustls = "0.23.8" +rustls-pemfile = "2.1.2" slog = { version = "2.7.0", features = ["max_level_trace", "release_max_level_info"] } slog-stdlog = "4.1.1" -thiserror = "1.0.60" -tokio = { version = "1.37.0", features = ["macros", "rt", "net", "process", "sync", "io-util", "time"] } -tokio-rustls = "0.24.1" +thiserror = "1.0.61" +tokio = { version = "1.38.0", features = ["macros", "rt", "net", "process", "sync", "io-util", "time"] } +tokio-rustls = "0.26.0" tokio-util = { version = "0.7.11", features = ["codec"] } tracing = { version = "0.1.40", default-features = false } tracing-attributes = "0.1.27" @@ -67,7 +67,7 @@ libc = "0.2" [dev-dependencies] pretty_assertions = "1.4.0" -tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread"] } unftp-sbe-fs = { path = "../libunftp/crates/unftp-sbe-fs" } [patch.crates-io] diff --git a/crates/unftp-auth-jsonfile/Cargo.toml b/crates/unftp-auth-jsonfile/Cargo.toml index 986725d8..8cba3976 100644 --- a/crates/unftp-auth-jsonfile/Cargo.toml +++ b/crates/unftp-auth-jsonfile/Cargo.toml @@ -25,9 +25,9 @@ ipnet = "2.9.0" iprange = "0.6.7" libunftp = { version = "0.20.0", path = "../../" } ring = "0.16.20" -serde = { version = "1.0.202", features = ["derive"] } +serde = { version = "1.0.203", features = ["derive"] } serde_json = "1.0.117" -tokio = { version = "1.37.0", features = ["rt", "time"] } +tokio = { version = "1.38.0", features = ["rt", "time"] } tracing = { version = "0.1.40", default-features = false } tracing-attributes = "0.1.27" valid = "0.3.1" @@ -35,7 +35,7 @@ flate2 = "1.0.30" [dev-dependencies] pretty_env_logger = "0.5.0" -tokio = { version = "1.37.0", features = ["macros"] } +tokio = { version = "1.38.0", features = ["macros"] } unftp-sbe-fs = { version = "0.2.2", path = "../unftp-sbe-fs" } [lints] diff --git a/crates/unftp-auth-pam/Cargo.toml b/crates/unftp-auth-pam/Cargo.toml index 441e7675..03ef3fea 100644 --- a/crates/unftp-auth-pam/Cargo.toml +++ b/crates/unftp-auth-pam/Cargo.toml @@ -28,7 +28,7 @@ tracing-attributes = "0.1.27" pam-auth = { package = "pam", version = "0.7.0" } [dev-dependencies] -tokio = { version = "1.37.0", features = ["macros"] } +tokio = { version = "1.38.0", features = ["macros"] } [lints] workspace = true diff --git a/crates/unftp-auth-rest/Cargo.toml b/crates/unftp-auth-rest/Cargo.toml index 19d6334c..0bacdd0d 100644 --- a/crates/unftp-auth-rest/Cargo.toml +++ b/crates/unftp-auth-rest/Cargo.toml @@ -24,16 +24,16 @@ hyper-rustls = "0.24.2" libunftp = { version = "0.20.0", path = "../../" } percent-encoding = "2.3.1" regex = "1.10.4" -serde = { version = "1.0.202", features = ["derive"] } +serde = { version = "1.0.203", features = ["derive"] } serde_json = "1.0.117" -tokio = { version = "1.37.0", features = ["rt", "net", "sync", "io-util", "time"] } +tokio = { version = "1.38.0", features = ["rt", "net", "sync", "io-util", "time"] } tracing = { version = "0.1.40", default-features = false } tracing-attributes = "0.1.27" [dev-dependencies] pretty_env_logger = "0.5.0" -tokio = { version = "1.37.0", features = ["macros"] } +tokio = { version = "1.38.0", features = ["macros"] } unftp-sbe-fs = { version = "0.2.2", path = "../unftp-sbe-fs" } [lints] diff --git a/crates/unftp-sbe-fs/Cargo.toml b/crates/unftp-sbe-fs/Cargo.toml index 848ad96b..0c3399c7 100644 --- a/crates/unftp-sbe-fs/Cargo.toml +++ b/crates/unftp-sbe-fs/Cargo.toml @@ -26,7 +26,7 @@ futures = { version = "0.3.30", default-features = false, features = ["std"] } lazy_static = "1.4.0" libunftp = { version = "0.20.0", path = "../../" } path_abs = "0.5.1" -tokio = { version = "1.37.0", features = ["rt", "net", "sync", "io-util", "time", "fs"] } +tokio = { version = "1.38.0", features = ["rt", "net", "sync", "io-util", "time", "fs"] } tokio-stream = "0.1.15" tracing = { version = "0.1.40", default-features = false } tracing-attributes = "0.1.27" @@ -35,17 +35,17 @@ tracing-attributes = "0.1.27" async_ftp = "6.0.0" async-trait = "0.1.80" more-asserts = "0.3.1" -nix = { version = "0.26.4", default-features = false, features = ["user"] } +nix = { version = "0.29.0", default-features = false, features = ["user"] } pretty_assertions = "1.4.0" pretty_env_logger = "0.5.0" regex = "1.10.4" rstest = "0.18.2" -serde = { version = "1.0.202", features = ["derive"] } +serde = { version = "1.0.203", features = ["derive"] } serde_json = "1.0.117" slog-async = "2.8.0" slog-term = "2.9.1" tempfile = "3.10.1" -tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread"] } tracing-subscriber = "0.3.18" getrandom = "0.2.15" diff --git a/crates/unftp-sbe-gcs/Cargo.toml b/crates/unftp-sbe-gcs/Cargo.toml index 10098252..e8917754 100644 --- a/crates/unftp-sbe-gcs/Cargo.toml +++ b/crates/unftp-sbe-gcs/Cargo.toml @@ -28,10 +28,10 @@ hyper-rustls = "0.24.2" libunftp = { version = "0.20.0", path = "../../" } mime = "0.3.17" percent-encoding = "2.3.1" -serde = { version = "1.0.202", features = ["derive"] } +serde = { version = "1.0.203", features = ["derive"] } serde_json = "1.0.117" time = "0.3.36" -tokio = { version = "1.37.0", features = ["rt", "net", "sync", "io-util", "time", "fs"] } +tokio = { version = "1.38.0", features = ["rt", "net", "sync", "io-util", "time", "fs"] } tokio-stream = "0.1.15" tokio-util = { version = "0.7.11", features = ["codec", "compat"] } tracing = { version = "0.1.40", default-features = false } @@ -51,5 +51,5 @@ slog-async = "2.8.0" slog-stdlog = "4.1.1" slog-term = "2.9.1" tempfile = "3.10.1" -tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"] } +tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread"] } tracing-subscriber = "0.3.18" diff --git a/src/server/controlchan/control_loop.rs b/src/server/controlchan/control_loop.rs index 57b7734a..d2387d22 100644 --- a/src/server/controlchan/control_loop.rs +++ b/src/server/controlchan/control_loop.rs @@ -251,7 +251,7 @@ where let s: &ServerConnection = stream.get_ref().1; if let Some(certs) = s.peer_certificates() { let mut session = shared_session.lock().await; - session.cert_chain = Some(certs.iter().map(|c| crate::auth::ClientCert(c.0.clone())).collect()); + session.cert_chain = Some(certs.iter().map(|c| crate::auth::ClientCert(c.as_ref().to_vec())).collect()); } Box::new(stream) } diff --git a/src/server/tls.rs b/src/server/tls.rs index eeabc9c2..4c61d8c7 100644 --- a/src/server/tls.rs +++ b/src/server/tls.rs @@ -1,8 +1,10 @@ use crate::options::{FtpsClientAuth, TlsFlags}; use rustls::{ - server::{AllowAnyAnonymousOrAuthenticatedClient, AllowAnyAuthenticatedClient, NoClientAuth, NoServerSessionStorage, StoresServerSessions}, + crypto::{aws_lc_rs, aws_lc_rs::Ticketer}, + pki_types::{CertificateDer, PrivateKeyDer}, + server::{ClientCertVerifierBuilder, NoServerSessionStorage, StoresServerSessions, WebPkiClientVerifier}, version::{TLS12, TLS13}, - Certificate, NoKeyLog, PrivateKey, RootCertStore, ServerConfig, SupportedProtocolVersion, Ticketer, + NoKeyLog, RootCertStore, ServerConfig, SupportedProtocolVersion, }; use std::{ fmt::{self, Display, Formatter}, @@ -58,6 +60,9 @@ pub enum ConfigError { #[error("error initialising Rustls")] RustlsInit(#[from] rustls::Error), + + #[error("error initialising the client cert verifier")] + ClientVerifier(#[from] rustls::server::VerifierBuilderError), } pub fn new_config>( @@ -67,20 +72,17 @@ pub fn new_config>( client_auth: FtpsClientAuth, trust_store: P, ) -> Result, ConfigError> { - let certs: Vec = load_certs(certs_file)?; - let privkey: PrivateKey = load_private_key(key_file)?; + let certs: Vec = load_certs(certs_file)?; + let privkey: PrivateKeyDer = load_private_key(key_file)?; + + let builder: ClientCertVerifierBuilder = WebPkiClientVerifier::builder(Arc::new(root_cert_store(trust_store)?)); let client_auther = match client_auth { - FtpsClientAuth::Off => NoClientAuth::boxed(), - FtpsClientAuth::Request => { - let store: RootCertStore = root_cert_store(trust_store)?; - AllowAnyAnonymousOrAuthenticatedClient::new(store).boxed() - } - FtpsClientAuth::Require => { - let store: RootCertStore = root_cert_store(trust_store)?; - AllowAnyAuthenticatedClient::new(store).boxed() - } - }; + FtpsClientAuth::Off => Ok(WebPkiClientVerifier::no_client_auth()), + FtpsClientAuth::Request => builder.allow_unauthenticated().build(), + FtpsClientAuth::Require => builder.build(), + } + .map_err(ConfigError::ClientVerifier)?; let mut versions: Vec<&SupportedProtocolVersion> = vec![]; if flags.contains(TlsFlags::V1_2) { @@ -90,13 +92,13 @@ pub fn new_config>( versions.push(&TLS13) } - let mut config = ServerConfig::builder() - .with_safe_default_cipher_suites() - .with_safe_default_kx_groups() - .with_protocol_versions(&versions).map_err(ConfigError::RustlsInit)? + let provider = Arc::new(aws_lc_rs::default_provider()); + let mut config = ServerConfig::builder_with_provider(provider) + .with_protocol_versions(&versions) + .map_err(ConfigError::RustlsInit)? .with_client_cert_verifier(client_auther) - // No SNI, single certificate - .with_single_cert(certs, privkey).map_err(ConfigError::RustlsInit)?; + .with_single_cert(certs, privkey) + .map_err(ConfigError::RustlsInit)?; // No SNI, single certificate // Support session resumption with server side state (Session IDs) config.session_storage = if flags.contains(TlsFlags::RESUMPTION_SESS_ID) { @@ -118,24 +120,25 @@ fn root_cert_store>(trust_pem: P) -> Result>(filename: P) -> Result, ConfigError> { +fn load_certs>(filename: P) -> Result>, ConfigError> { let certfile: File = File::open(filename)?; let mut reader: BufReader = BufReader::new(certfile); - rustls_pemfile::certs(&mut reader).map_err(ConfigError::Load).map(|v| { - let mut res = Vec::with_capacity(v.len()); - for e in v { - res.push(Certificate(e)); - } - res - }) + let certs = rustls_pemfile::certs(&mut reader); + let mut res = Vec::new(); + for cert in certs { + let cert = cert.map_err(ConfigError::Load)?; + res.push(cert); + } + Ok(res) } -fn load_private_key>(filename: P) -> Result { +fn load_private_key>(filename: P) -> Result, ConfigError> { + use rustls::pki_types::PrivateKeyDer; use rustls_pemfile::{read_one, Item}; use std::iter; @@ -144,9 +147,9 @@ fn load_private_key>(filename: P) -> Result return Ok(PrivateKey(key)), - Ok(Item::PKCS8Key(key)) => return Ok(PrivateKey(key)), - Ok(Item::ECKey(key)) => return Ok(PrivateKey(key)), + Ok(Item::Pkcs1Key(key)) => return Ok(PrivateKeyDer::Pkcs1(key)), + Ok(Item::Pkcs8Key(key)) => return Ok(PrivateKeyDer::Pkcs8(key)), + Ok(Item::Sec1Key(key)) => return Ok(PrivateKeyDer::Sec1(key)), Err(e) => return Err(ConfigError::Load(e)), _ => {} } @@ -156,6 +159,7 @@ fn load_private_key>(filename: P) -> Result, Vec>, }