Skip to content

Commit 5351caa

Browse files
committed
other: make webpki-roots optional for Linux.
This commit removes the Linux dependency on the `webpki-roots` crate. In its place a new `Verifier::with_extra_roots` constructor is provided. The new constructor allows the caller to provide a set of extra `OwnedTrustAnchors`s that will be loaded in addition to the platform provided trust anchors. Callers that expect to need to augment the platform roots can use this (with `webpki-roots` or otherwise) to achieve their goal. The wasm32 target continues to depend on `webpki-roots` since there is no platform provider for trust anchors.
1 parent 9e8ce31 commit 5351caa

File tree

2 files changed

+45
-33
lines changed

2 files changed

+45
-33
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ once_cell = { version = "1.9", optional = true } # Only used during doc generati
4646
[target.'cfg(target_os = "linux")'.dependencies]
4747
rustls-native-certs = "0.6"
4848
once_cell = "1.9"
49-
webpki-roots = "0.25" # Augmentation to `openssl-probe` due to inconsistencies on Linux distros.
5049
webpki = { package = "rustls-webpki", version = "0.101", features = ["alloc", "std"] }
5150

5251
[target.'cfg(target_os = "android")'.dependencies]

src/verification/others.rs

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ use super::log_server_cert;
22
use once_cell::sync::OnceCell;
33
use rustls::{
44
client::{ServerCertVerifier, WebPkiVerifier},
5-
CertificateError, Error as TlsError, RootCertStore,
5+
CertificateError, Error as TlsError,
66
};
7+
use std::sync::Mutex;
78

89
/// A TLS certificate verifier that uses the system's root store and WebPKI.
910
#[derive(Default)]
@@ -17,17 +18,34 @@ pub struct Verifier {
1718
// that might have been made since.
1819
inner: OnceCell<WebPkiVerifier>,
1920

21+
// Extra trust anchors to add to the verifier above and beyond those provided by the
22+
// platform via rustls-native-certs.
23+
extra_roots: Mutex<Vec<rustls::OwnedTrustAnchor>>,
24+
2025
/// Testing only: an additional root CA certificate to trust.
2126
#[cfg(any(test, feature = "ffi-testing", feature = "dbg"))]
2227
test_only_root_ca_override: Option<Vec<u8>>,
2328
}
2429

2530
impl Verifier {
2631
/// Creates a new verifier whose certificate validation is provided by
27-
/// WebPKI.
32+
/// WebPKI, using root certificates provided by the platform.
2833
pub fn new() -> Self {
2934
Self {
3035
inner: OnceCell::new(),
36+
extra_roots: Vec::new().into(),
37+
#[cfg(any(test, feature = "ffi-testing", feature = "dbg"))]
38+
test_only_root_ca_override: None,
39+
}
40+
}
41+
42+
/// Creates a new verifier whose certificate validation is provided by
43+
/// WebPKI, using root certificates provided by the platform and augmented by
44+
/// the provided extra root certificates.
45+
pub fn new_with_extra_roots(roots: impl IntoIterator<Item = rustls::OwnedTrustAnchor>) -> Self {
46+
Self {
47+
inner: OnceCell::new(),
48+
extra_roots: roots.into_iter().collect::<Vec<_>>().into(),
3149
#[cfg(any(test, feature = "ffi-testing", feature = "dbg"))]
3250
test_only_root_ca_override: None,
3351
}
@@ -38,6 +56,7 @@ impl Verifier {
3856
pub(crate) fn new_with_fake_root(root: &[u8]) -> Self {
3957
Self {
4058
inner: OnceCell::new(),
59+
extra_roots: Vec::new().into(),
4160
test_only_root_ca_override: Some(root.into()),
4261
}
4362
}
@@ -68,35 +87,42 @@ impl Verifier {
6887
log::warn!("Some CA root certificates were ignored due to errors");
6988
}
7089

71-
// While we load webpki-roots anyway, this can be helpful to know for troubleshooting.
7290
if root_store.is_empty() {
7391
log::error!("No CA certificates were loaded from the system");
92+
} else {
93+
log::debug!("Loaded {added} CA certificates from the system");
7494
}
7595

76-
// Finding TLS roots on Linux is not reliable enough to always depend on it
77-
// across various distributions. Instead, we always load the WebPKI roots in
78-
// addition so that a valid trust anchor is more likely to be available.
79-
load_webpki_roots(&mut root_store);
80-
81-
log::debug!(
82-
"Loaded WebPKI roots in addition to {} roots from the system",
83-
added
84-
);
96+
// Safety: There's no way for the mutex to be locked multiple times, so this is
97+
// an infallible operation.
98+
let mut extra_roots = self.extra_roots.try_lock().unwrap();
99+
if !extra_roots.is_empty() {
100+
let count = extra_roots.len();
101+
root_store.add_trust_anchors(&mut extra_roots.drain(..));
102+
log::debug!(
103+
"Loaded {count} extra CA certificates in addition to roots from the system",
104+
);
105+
}
85106
}
86107
Err(err) => {
87108
// This only contains a path to a system directory:
88-
// https://github.com/rustls/rustls-native-certs/blob/main/src/lib.rs#L71
89-
log::error!(
90-
"No CA certificates were loaded: {}. Falling back to WebPKI roots",
91-
err,
92-
);
93-
load_webpki_roots(&mut root_store);
109+
// https://github.com/rustls/rustls-native-certs/blob/bc13b9a6bfc2e1eec881597055ca49accddd972a/src/lib.rs#L91-L94
110+
return Err(rustls::Error::General(format!(
111+
"failed to load system root certificates: {}",
112+
err
113+
)));
94114
}
95115
};
96116

97117
#[cfg(target_arch = "wasm32")]
98118
{
99-
load_webpki_roots(&mut root_store);
119+
root_store.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|root| {
120+
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
121+
root.subject,
122+
root.spki,
123+
root.name_constraints,
124+
)
125+
}));
100126
};
101127

102128
Ok(WebPkiVerifier::new(root_store, None))
@@ -152,16 +178,3 @@ fn map_webpki_errors(err: TlsError) -> TlsError {
152178

153179
err
154180
}
155-
156-
/// Loads the static `webpki-roots` into the provided certificate store.
157-
fn load_webpki_roots(store: &mut RootCertStore) {
158-
use rustls::OwnedTrustAnchor;
159-
160-
store.add_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|root| {
161-
OwnedTrustAnchor::from_subject_spki_name_constraints(
162-
root.subject,
163-
root.spki,
164-
root.name_constraints,
165-
)
166-
}));
167-
}

0 commit comments

Comments
 (0)