1 | #[cfg (feature = "rustls-native-certs" )] |
2 | use std::io; |
3 | #[cfg (feature = "rustls-platform-verifier" )] |
4 | use std::sync::Arc; |
5 | |
6 | #[cfg (any( |
7 | feature = "rustls-platform-verifier" , |
8 | feature = "rustls-native-certs" , |
9 | feature = "webpki-roots" |
10 | ))] |
11 | use rustls::client::WantsClientCert; |
12 | use rustls::{ClientConfig, ConfigBuilder, WantsVerifier}; |
13 | #[cfg (feature = "rustls-native-certs" )] |
14 | use rustls_native_certs::CertificateResult; |
15 | |
16 | /// Methods for configuring roots |
17 | /// |
18 | /// This adds methods (gated by crate features) for easily configuring |
19 | /// TLS server roots a rustls ClientConfig will trust. |
20 | pub trait ConfigBuilderExt { |
21 | /// Use the platform's native verifier to verify server certificates. |
22 | /// |
23 | /// See the documentation for [rustls-platform-verifier] for more details. |
24 | /// |
25 | /// [rustls-platform-verifier]: https://docs.rs/rustls-platform-verifier |
26 | #[cfg (feature = "rustls-platform-verifier" )] |
27 | fn with_platform_verifier(self) -> ConfigBuilder<ClientConfig, WantsClientCert>; |
28 | |
29 | /// This configures the platform's trusted certs, as implemented by |
30 | /// rustls-native-certs |
31 | /// |
32 | /// This will return an error if no valid certs were found. In that case, |
33 | /// it's recommended to use `with_webpki_roots`. |
34 | #[cfg (feature = "rustls-native-certs" )] |
35 | fn with_native_roots(self) -> Result<ConfigBuilder<ClientConfig, WantsClientCert>, io::Error>; |
36 | |
37 | /// This configures the webpki roots, which are Mozilla's set of |
38 | /// trusted roots as packaged by webpki-roots. |
39 | #[cfg (feature = "webpki-roots" )] |
40 | fn with_webpki_roots(self) -> ConfigBuilder<ClientConfig, WantsClientCert>; |
41 | } |
42 | |
43 | impl ConfigBuilderExt for ConfigBuilder<ClientConfig, WantsVerifier> { |
44 | #[cfg (feature = "rustls-platform-verifier" )] |
45 | fn with_platform_verifier(self) -> ConfigBuilder<ClientConfig, WantsClientCert> { |
46 | let provider = self.crypto_provider().clone(); |
47 | self.dangerous() |
48 | .with_custom_certificate_verifier(Arc::new( |
49 | rustls_platform_verifier::Verifier::new().with_provider(provider), |
50 | )) |
51 | } |
52 | |
53 | #[cfg (feature = "rustls-native-certs" )] |
54 | #[cfg_attr (not(feature = "logging" ), allow(unused_variables))] |
55 | fn with_native_roots(self) -> Result<ConfigBuilder<ClientConfig, WantsClientCert>, io::Error> { |
56 | let mut roots = rustls::RootCertStore::empty(); |
57 | let mut valid_count = 0; |
58 | let mut invalid_count = 0; |
59 | |
60 | let CertificateResult { certs, errors, .. } = rustls_native_certs::load_native_certs(); |
61 | if !errors.is_empty() { |
62 | crate::log::warn!("native root CA certificate loading errors: {errors:?}" ); |
63 | } |
64 | |
65 | if certs.is_empty() { |
66 | return Err(io::Error::new( |
67 | io::ErrorKind::NotFound, |
68 | format!("no native root CA certificates found (errors: {errors:?})" ), |
69 | )); |
70 | } |
71 | |
72 | for cert in certs { |
73 | match roots.add(cert) { |
74 | Ok(_) => valid_count += 1, |
75 | Err(err) => { |
76 | crate::log::debug!("certificate parsing failed: {:?}" , err); |
77 | invalid_count += 1 |
78 | } |
79 | } |
80 | } |
81 | |
82 | crate::log::debug!( |
83 | "with_native_roots processed {} valid and {} invalid certs" , |
84 | valid_count, |
85 | invalid_count |
86 | ); |
87 | if roots.is_empty() { |
88 | crate::log::debug!("no valid native root CA certificates found" ); |
89 | Err(io::Error::new( |
90 | io::ErrorKind::NotFound, |
91 | format!("no valid native root CA certificates found ({invalid_count} invalid)" ), |
92 | ))? |
93 | } |
94 | |
95 | Ok(self.with_root_certificates(roots)) |
96 | } |
97 | |
98 | #[cfg (feature = "webpki-roots" )] |
99 | fn with_webpki_roots(self) -> ConfigBuilder<ClientConfig, WantsClientCert> { |
100 | let mut roots = rustls::RootCertStore::empty(); |
101 | roots.extend( |
102 | webpki_roots::TLS_SERVER_ROOTS |
103 | .iter() |
104 | .cloned(), |
105 | ); |
106 | self.with_root_certificates(roots) |
107 | } |
108 | } |
109 | |