Skip to content

Commit ac72082

Browse files
committed
Take rustls 0.23
rustls 0.21 is EOL for security support at the end of March 2025. - Drop rustls-pemfile, as it is now incorporated into rustls-pki-types; use the new iterator-based API. - Use the ring-based provider, to align with previous version's build-time requirements.
1 parent 1acffc4 commit ac72082

File tree

2 files changed

+110
-78
lines changed

2 files changed

+110
-78
lines changed

Cargo.toml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ exclude = [
3131
default = ["compat-3-0-0", "rustls-tls", "dns-resolver"]
3232
compat-3-0-0 = []
3333
sync = []
34-
rustls-tls = ["dep:rustls", "dep:rustls-pemfile", "dep:tokio-rustls"]
34+
rustls-tls = ["dep:rustls", "dep:tokio-rustls"]
3535
openssl-tls = ["dep:openssl", "dep:openssl-probe", "dep:tokio-openssl"]
3636
dns-resolver = ["dep:hickory-resolver", "dep:hickory-proto"]
3737
cert-key-password = ["dep:pem", "dep:pkcs8"]
@@ -102,7 +102,6 @@ pkcs8 = { version = "0.10.2", features = ["encryption", "pkcs5"], optional = tru
102102
rand = { version = "0.8.3", features = ["small_rng"] }
103103
rayon = { version = "1.5.3", optional = true }
104104
rustc_version_runtime = "0.3.0"
105-
rustls-pemfile = { version = "1.0.1", optional = true }
106105
serde_with = "3.8.1"
107106
sha-1 = "0.10.0"
108107
sha2 = "0.10.2"
@@ -115,7 +114,7 @@ thiserror = "1.0.24"
115114
tokio-openssl = { version = "0.6.3", optional = true }
116115
tracing = { version = "0.1.36", optional = true }
117116
typed-builder = "0.10.0"
118-
webpki-roots = "0.25.2"
117+
webpki-roots = "0.26"
119118
zstd = { version = "0.11.2", optional = true }
120119
macro_magic = "0.5.1"
121120

@@ -130,9 +129,10 @@ default-features = false
130129
features = ["json", "rustls-tls"]
131130

132131
[dependencies.rustls]
133-
version = "0.21.6"
132+
version = "0.23.20"
134133
optional = true
135-
features = ["dangerous_configuration"]
134+
default-features = false
135+
features = ["logging", "ring", "std", "tls12"]
136136

137137
[dependencies.serde]
138138
version = "1.0.125"
@@ -146,9 +146,10 @@ version = "1.17.0"
146146
features = ["io-util", "sync", "macros", "net", "process", "rt", "time", "fs"]
147147

148148
[dependencies.tokio-rustls]
149-
version = "0.24.1"
149+
version = "0.26"
150150
optional = true
151-
features = ["dangerous_configuration"]
151+
default-features = false
152+
features = ["logging", "ring", "tls12"]
152153

153154
[dependencies.tokio-util]
154155
version = "0.7.0"

src/runtime/tls_rustls.rs

Lines changed: 102 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@ use std::{
33
fs::File,
44
io::{BufReader, Seek},
55
sync::Arc,
6-
time::SystemTime,
76
};
87

98
use rustls::{
10-
client::{ClientConfig, ServerCertVerified, ServerCertVerifier, ServerName},
11-
Certificate,
9+
client::ClientConfig,
10+
crypto::ring as provider,
11+
pki_types::{pem::PemObject, CertificateDer, PrivateKeyDer, ServerName},
1212
Error as TlsError,
13-
OwnedTrustAnchor,
1413
RootCertStore,
1514
};
16-
use rustls_pemfile::{certs, read_one, Item};
1715
use tokio::net::TcpStream;
1816
use tokio_rustls::TlsConnector;
1917
use webpki_roots::TLS_SERVER_ROOTS;
@@ -49,9 +47,11 @@ pub(super) async fn tls_connect(
4947
tcp_stream: TcpStream,
5048
cfg: &TlsConfig,
5149
) -> Result<TlsStream> {
52-
let name = ServerName::try_from(host).map_err(|e| ErrorKind::DnsResolve {
53-
message: format!("could not resolve {:?}: {}", host, e),
54-
})?;
50+
let name = ServerName::try_from(host)
51+
.map_err(|e| ErrorKind::DnsResolve {
52+
message: format!("could not resolve {:?}: {}", host, e),
53+
})?
54+
.to_owned();
5555

5656
let conn = cfg
5757
.connector
@@ -66,110 +66,141 @@ pub(super) async fn tls_connect(
6666
fn make_rustls_config(cfg: TlsOptions) -> Result<rustls::ClientConfig> {
6767
let mut store = RootCertStore::empty();
6868
if let Some(path) = cfg.ca_file_path {
69-
let ders = certs(&mut BufReader::new(File::open(&path)?)).map_err(|_| {
70-
ErrorKind::InvalidTlsConfig {
69+
let ders = CertificateDer::pem_file_iter(&path)
70+
.map_err(|err| ErrorKind::InvalidTlsConfig {
7171
message: format!(
72-
"Unable to parse PEM-encoded root certificate from {}",
72+
"Unable to parse PEM-encoded root certificate from {}: {err}",
7373
path.display()
7474
),
75-
}
76-
})?;
77-
store.add_parsable_certificates(&ders);
75+
})?
76+
.flatten();
77+
store.add_parsable_certificates(ders);
7878
} else {
79-
let trust_anchors = TLS_SERVER_ROOTS.iter().map(|ta| {
80-
OwnedTrustAnchor::from_subject_spki_name_constraints(
81-
ta.subject,
82-
ta.spki,
83-
ta.name_constraints,
84-
)
85-
});
86-
store.add_trust_anchors(trust_anchors);
79+
store.extend(TLS_SERVER_ROOTS.iter().cloned());
8780
}
8881

82+
let config_builder = ClientConfig::builder_with_provider(provider::default_provider().into())
83+
.with_safe_default_protocol_versions()
84+
.expect("built-in provider should support default protocol versions")
85+
.with_root_certificates(store);
86+
8987
let mut config = if let Some(path) = cfg.cert_key_file_path {
9088
let mut file = BufReader::new(File::open(&path)?);
91-
let certs = match certs(&mut file) {
92-
Ok(certs) => certs.into_iter().map(Certificate).collect(),
93-
Err(error) => {
94-
return Err(ErrorKind::InvalidTlsConfig {
95-
message: format!(
96-
"Unable to parse PEM-encoded client certificate from {}: {}",
97-
path.display(),
98-
error,
99-
),
100-
}
101-
.into())
102-
}
103-
};
89+
let mut certs = vec![];
90+
91+
for cert in CertificateDer::pem_reader_iter(&mut file) {
92+
let cert = cert.map_err(|error| ErrorKind::InvalidTlsConfig {
93+
message: format!(
94+
"Unable to parse PEM-encoded client certificate from {}: {error}",
95+
path.display(),
96+
),
97+
})?;
98+
certs.push(cert);
99+
}
104100

105101
file.rewind()?;
106102
let key = loop {
107103
#[cfg(feature = "cert-key-password")]
108104
if let Some(key_pw) = cfg.tls_certificate_key_file_password.as_deref() {
105+
use rustls::pki_types::PrivatePkcs8KeyDer;
109106
use std::io::Read;
110107
let mut contents = vec![];
111108
file.read_to_end(&mut contents)?;
112-
break rustls::PrivateKey(super::pem::decrypt_private_key(&contents, key_pw)?);
109+
break PrivatePkcs8KeyDer::from(super::pem::decrypt_private_key(
110+
&contents, key_pw,
111+
)?)
112+
.into();
113113
}
114-
match read_one(&mut file) {
115-
Ok(Some(Item::PKCS8Key(bytes))) | Ok(Some(Item::RSAKey(bytes))) => {
116-
break rustls::PrivateKey(bytes)
117-
}
118-
Ok(Some(_)) => continue,
119-
Ok(None) => {
120-
return Err(ErrorKind::InvalidTlsConfig {
121-
message: format!("No PEM-encoded keys in {}", path.display()),
122-
}
123-
.into())
124-
}
125-
Err(_) => {
114+
match PrivateKeyDer::from_pem_reader(&mut file) {
115+
Ok(key) => break key,
116+
Err(err) => {
126117
return Err(ErrorKind::InvalidTlsConfig {
127118
message: format!(
128-
"Unable to parse PEM-encoded item from {}",
129-
path.display()
119+
"Unable to parse PEM-encoded item from {}: {err}",
120+
path.display(),
130121
),
131122
}
132123
.into())
133124
}
134125
}
135126
};
136127

137-
ClientConfig::builder()
138-
.with_safe_defaults()
139-
.with_root_certificates(store)
128+
config_builder
140129
.with_client_auth_cert(certs, key)
141130
.map_err(|error| ErrorKind::InvalidTlsConfig {
142131
message: error.to_string(),
143132
})?
144133
} else {
145-
ClientConfig::builder()
146-
.with_safe_defaults()
147-
.with_root_certificates(store)
148-
.with_no_client_auth()
134+
config_builder.with_no_client_auth()
149135
};
150136

151137
if let Some(true) = cfg.allow_invalid_certificates {
152138
// nosemgrep: rustls-dangerous
153139
config // mongodb rating: No Fix Needed
154140
.dangerous()
155-
.set_certificate_verifier(Arc::new(NoCertVerifier {}));
141+
.set_certificate_verifier(Arc::new(danger::NoCertVerifier(
142+
provider::default_provider(),
143+
)));
156144
}
157145

158146
Ok(config)
159147
}
160148

161-
struct NoCertVerifier {}
162-
163-
impl ServerCertVerifier for NoCertVerifier {
164-
fn verify_server_cert(
165-
&self,
166-
_: &Certificate,
167-
_: &[Certificate],
168-
_: &ServerName,
169-
_: &mut dyn Iterator<Item = &[u8]>,
170-
_: &[u8],
171-
_: SystemTime,
172-
) -> std::result::Result<ServerCertVerified, TlsError> {
173-
Ok(ServerCertVerified::assertion())
149+
mod danger {
150+
use super::*;
151+
use rustls::{
152+
client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
153+
crypto::{verify_tls12_signature, verify_tls13_signature, CryptoProvider},
154+
pki_types::UnixTime,
155+
DigitallySignedStruct,
156+
SignatureScheme,
157+
};
158+
159+
#[derive(Debug)]
160+
pub(super) struct NoCertVerifier(pub(super) CryptoProvider);
161+
162+
impl ServerCertVerifier for NoCertVerifier {
163+
fn verify_server_cert(
164+
&self,
165+
_end_entity: &CertificateDer<'_>,
166+
_intermediates: &[CertificateDer<'_>],
167+
_server_name: &ServerName<'_>,
168+
_ocsp: &[u8],
169+
_now: UnixTime,
170+
) -> std::result::Result<ServerCertVerified, TlsError> {
171+
Ok(ServerCertVerified::assertion())
172+
}
173+
174+
fn verify_tls12_signature(
175+
&self,
176+
message: &[u8],
177+
cert: &CertificateDer<'_>,
178+
dss: &DigitallySignedStruct,
179+
) -> std::result::Result<HandshakeSignatureValid, TlsError> {
180+
verify_tls12_signature(
181+
message,
182+
cert,
183+
dss,
184+
&self.0.signature_verification_algorithms,
185+
)
186+
}
187+
188+
fn verify_tls13_signature(
189+
&self,
190+
message: &[u8],
191+
cert: &CertificateDer<'_>,
192+
dss: &DigitallySignedStruct,
193+
) -> std::result::Result<HandshakeSignatureValid, TlsError> {
194+
verify_tls13_signature(
195+
message,
196+
cert,
197+
dss,
198+
&self.0.signature_verification_algorithms,
199+
)
200+
}
201+
202+
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
203+
self.0.signature_verification_algorithms.supported_schemes()
204+
}
174205
}
175206
}

0 commit comments

Comments
 (0)