Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ http-body-util = "0.1.0"
hyper = { version = "1.0", default-features = false, features = ["server", "http1"] }
hyper-util = { version = "0.1.1", features = ["tokio"] }
proptest = "1.1.0"
rustls-webpki = { version = "0.103.3" }
tokio-rustls = "0.26.4"
webpki-root-certs = "1"

[build-dependencies]
platforms = "3.4"
Expand Down
92 changes: 92 additions & 0 deletions src/anchors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// @generated by tests/static_roots.rs
use rustls::pki_types::CertificateDer;

pub(crate) const RUSTUP_TRUST_ANCHORS: &[CertificateDer<'static>] = &[
CertificateDer::from_slice(&[
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Since you already have the hostnames, maybe it could be useful to indicate which is which, say with a comment?

48, 130, 3, 95, 48, 130, 2, 71, 160, 3, 2, 1, 2, 2, 11, 4, 0, 0, 0, 0, 1, 33, 88, 83, 8,
162, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 76, 49, 32, 48, 30, 6, 3,
85, 4, 11, 19, 23, 71, 108, 111, 98, 97, 108, 83, 105, 103, 110, 32, 82, 111, 111, 116, 32,
67, 65, 32, 45, 32, 82, 51, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 71, 108, 111, 98, 97,
108, 83, 105, 103, 110, 49, 19, 48, 17, 6, 3, 85, 4, 3, 19, 10, 71, 108, 111, 98, 97, 108,
83, 105, 103, 110, 48, 30, 23, 13, 48, 57, 48, 51, 49, 56, 49, 48, 48, 48, 48, 48, 90, 23,
13, 50, 57, 48, 51, 49, 56, 49, 48, 48, 48, 48, 48, 90, 48, 76, 49, 32, 48, 30, 6, 3, 85,
4, 11, 19, 23, 71, 108, 111, 98, 97, 108, 83, 105, 103, 110, 32, 82, 111, 111, 116, 32, 67,
65, 32, 45, 32, 82, 51, 49, 19, 48, 17, 6, 3, 85, 4, 10, 19, 10, 71, 108, 111, 98, 97, 108,
83, 105, 103, 110, 49, 19, 48, 17, 6, 3, 85, 4, 3, 19, 10, 71, 108, 111, 98, 97, 108, 83,
105, 103, 110, 48, 130, 1, 34, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3,
130, 1, 15, 0, 48, 130, 1, 10, 2, 130, 1, 1, 0, 204, 37, 118, 144, 121, 6, 120, 34, 22,
245, 192, 131, 182, 132, 202, 40, 158, 253, 5, 118, 17, 197, 173, 136, 114, 252, 70, 2, 67,
199, 178, 138, 157, 4, 95, 36, 203, 46, 75, 225, 96, 130, 70, 225, 82, 171, 12, 129, 71,
112, 108, 221, 100, 209, 235, 245, 44, 163, 15, 130, 61, 12, 43, 174, 151, 215, 182, 20,
134, 16, 121, 187, 59, 19, 128, 119, 140, 8, 225, 73, 210, 106, 98, 47, 31, 94, 250, 150,
104, 223, 137, 39, 149, 56, 159, 6, 215, 62, 201, 203, 38, 89, 13, 115, 222, 176, 200, 233,
38, 14, 131, 21, 198, 239, 91, 139, 210, 4, 96, 202, 73, 166, 40, 246, 105, 59, 246, 203,
200, 40, 145, 229, 157, 138, 97, 87, 55, 172, 116, 20, 220, 116, 224, 58, 238, 114, 47, 46,
156, 251, 208, 187, 191, 245, 61, 0, 225, 6, 51, 232, 130, 43, 174, 83, 166, 58, 22, 115,
140, 221, 65, 14, 32, 58, 192, 180, 167, 161, 233, 178, 79, 144, 46, 50, 96, 233, 87, 203,
185, 4, 146, 104, 104, 229, 56, 38, 96, 117, 178, 159, 119, 255, 145, 20, 239, 174, 32, 73,
252, 173, 64, 21, 72, 209, 2, 49, 97, 25, 94, 184, 151, 239, 173, 119, 183, 100, 154, 122,
191, 95, 193, 19, 239, 155, 98, 251, 13, 108, 224, 84, 105, 22, 169, 3, 218, 110, 233, 131,
147, 113, 118, 198, 105, 133, 130, 23, 2, 3, 1, 0, 1, 163, 66, 48, 64, 48, 14, 6, 3, 85,
29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 6, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4, 5, 48, 3, 1,
1, 255, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 143, 240, 75, 127, 168, 46, 69, 36, 174,
77, 80, 250, 99, 154, 139, 222, 226, 221, 27, 188, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13,
1, 1, 11, 5, 0, 3, 130, 1, 1, 0, 75, 64, 219, 192, 80, 170, 254, 200, 12, 239, 247, 150,
84, 69, 73, 187, 150, 0, 9, 65, 172, 179, 19, 134, 134, 40, 7, 51, 202, 107, 230, 116, 185,
186, 0, 45, 174, 164, 10, 211, 245, 241, 241, 15, 138, 191, 115, 103, 74, 131, 199, 68,
123, 120, 224, 175, 110, 108, 111, 3, 41, 142, 51, 57, 69, 195, 142, 228, 185, 87, 108,
170, 252, 18, 150, 236, 83, 198, 45, 228, 36, 108, 185, 148, 99, 251, 220, 83, 104, 103,
86, 62, 131, 184, 207, 53, 33, 195, 201, 104, 254, 206, 218, 194, 83, 170, 204, 144, 138,
233, 240, 93, 70, 140, 149, 221, 122, 88, 40, 26, 47, 29, 222, 205, 0, 55, 65, 143, 237,
68, 109, 215, 83, 40, 151, 126, 243, 103, 4, 30, 21, 215, 138, 150, 180, 211, 222, 76, 39,
164, 76, 27, 115, 115, 118, 244, 23, 153, 194, 31, 122, 14, 227, 45, 8, 173, 10, 28, 44,
255, 60, 171, 85, 14, 15, 145, 126, 54, 235, 195, 87, 73, 190, 225, 46, 45, 124, 96, 139,
195, 65, 81, 19, 35, 157, 206, 247, 50, 107, 148, 1, 168, 153, 231, 44, 51, 31, 58, 59, 37,
210, 134, 64, 206, 59, 44, 134, 120, 201, 97, 47, 20, 186, 238, 219, 85, 111, 223, 132,
238, 5, 9, 77, 189, 40, 216, 114, 206, 211, 98, 80, 101, 30, 235, 146, 151, 131, 49, 217,
179, 181, 202, 71, 88, 63, 95,
]),
CertificateDer::from_slice(&[
48, 130, 3, 65, 48, 130, 2, 41, 160, 3, 2, 1, 2, 2, 19, 6, 108, 159, 207, 153, 191, 140,
10, 57, 226, 240, 120, 138, 67, 230, 150, 54, 91, 202, 48, 13, 6, 9, 42, 134, 72, 134, 247,
13, 1, 1, 11, 5, 0, 48, 57, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 15, 48, 13,
6, 3, 85, 4, 10, 19, 6, 65, 109, 97, 122, 111, 110, 49, 25, 48, 23, 6, 3, 85, 4, 3, 19, 16,
65, 109, 97, 122, 111, 110, 32, 82, 111, 111, 116, 32, 67, 65, 32, 49, 48, 30, 23, 13, 49,
53, 48, 53, 50, 54, 48, 48, 48, 48, 48, 48, 90, 23, 13, 51, 56, 48, 49, 49, 55, 48, 48, 48,
48, 48, 48, 90, 48, 57, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 15, 48, 13, 6, 3,
85, 4, 10, 19, 6, 65, 109, 97, 122, 111, 110, 49, 25, 48, 23, 6, 3, 85, 4, 3, 19, 16, 65,
109, 97, 122, 111, 110, 32, 82, 111, 111, 116, 32, 67, 65, 32, 49, 48, 130, 1, 34, 48, 13,
6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 130, 1, 15, 0, 48, 130, 1, 10, 2, 130,
1, 1, 0, 178, 120, 128, 113, 202, 120, 213, 227, 113, 175, 71, 128, 80, 116, 125, 110, 216,
215, 136, 118, 244, 153, 104, 247, 88, 33, 96, 249, 116, 132, 1, 47, 172, 2, 45, 134, 211,
160, 67, 122, 78, 178, 164, 208, 54, 186, 1, 190, 141, 219, 72, 200, 7, 23, 54, 76, 244,
238, 136, 35, 199, 62, 235, 55, 245, 181, 25, 248, 73, 104, 176, 222, 215, 185, 118, 56,
29, 97, 158, 164, 254, 130, 54, 165, 229, 74, 86, 228, 69, 225, 249, 253, 180, 22, 250,
116, 218, 156, 155, 53, 57, 47, 250, 176, 32, 80, 6, 108, 122, 208, 128, 178, 166, 249,
175, 236, 71, 25, 143, 80, 56, 7, 220, 162, 135, 57, 88, 248, 186, 213, 169, 249, 72, 103,
48, 150, 238, 148, 120, 94, 111, 137, 163, 81, 192, 48, 134, 102, 161, 69, 102, 186, 84,
235, 163, 195, 145, 249, 72, 220, 255, 209, 232, 48, 45, 125, 45, 116, 112, 53, 215, 136,
36, 247, 158, 196, 89, 110, 187, 115, 135, 23, 242, 50, 70, 40, 184, 67, 250, 183, 29, 170,
202, 180, 242, 159, 36, 14, 45, 75, 247, 113, 92, 94, 105, 255, 234, 149, 2, 203, 56, 138,
174, 80, 56, 111, 219, 251, 45, 98, 27, 197, 199, 30, 84, 225, 119, 224, 103, 200, 15, 156,
135, 35, 214, 63, 64, 32, 127, 32, 128, 196, 128, 76, 62, 59, 36, 38, 142, 4, 174, 108,
154, 200, 170, 13, 2, 3, 1, 0, 1, 163, 66, 48, 64, 48, 15, 6, 3, 85, 29, 19, 1, 1, 255, 4,
5, 48, 3, 1, 1, 255, 48, 14, 6, 3, 85, 29, 15, 1, 1, 255, 4, 4, 3, 2, 1, 134, 48, 29, 6, 3,
85, 29, 14, 4, 22, 4, 20, 132, 24, 204, 133, 52, 236, 188, 12, 148, 148, 46, 8, 89, 156,
199, 178, 16, 78, 10, 8, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 3, 130,
1, 1, 0, 152, 242, 55, 90, 65, 144, 161, 26, 197, 118, 81, 40, 32, 54, 35, 14, 174, 230,
40, 187, 170, 248, 148, 174, 72, 164, 48, 127, 27, 252, 36, 141, 75, 180, 200, 161, 151,
246, 182, 241, 122, 112, 200, 83, 147, 204, 8, 40, 227, 152, 37, 207, 35, 164, 249, 222,
33, 211, 124, 133, 9, 173, 78, 154, 117, 58, 194, 11, 106, 137, 120, 118, 68, 71, 24, 101,
108, 141, 65, 142, 59, 127, 154, 203, 244, 181, 167, 80, 215, 5, 44, 55, 232, 3, 75, 173,
233, 97, 160, 2, 110, 245, 242, 240, 197, 178, 237, 91, 183, 220, 250, 148, 92, 119, 158,
19, 165, 127, 82, 173, 149, 242, 248, 147, 59, 222, 139, 92, 91, 202, 90, 82, 91, 96, 175,
20, 247, 75, 239, 163, 251, 159, 64, 149, 109, 49, 84, 252, 66, 211, 199, 70, 31, 35, 173,
217, 15, 72, 112, 154, 217, 117, 120, 113, 209, 114, 67, 52, 117, 110, 87, 89, 194, 2, 92,
38, 96, 41, 207, 35, 25, 22, 142, 136, 67, 165, 212, 228, 203, 8, 251, 35, 17, 67, 232, 67,
41, 114, 98, 161, 169, 93, 94, 8, 212, 144, 174, 184, 216, 206, 20, 194, 208, 85, 242, 134,
246, 196, 147, 67, 119, 102, 97, 192, 185, 232, 65, 215, 151, 120, 96, 3, 110, 74, 114,
174, 165, 209, 125, 186, 16, 158, 134, 108, 27, 138, 185, 89, 51, 248, 235, 196, 144, 190,
241, 185,
]),
];
22 changes: 14 additions & 8 deletions src/download/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,12 +546,14 @@ mod reqwest_be {
use std::sync::{Arc, OnceLock};
use std::time::Duration;

#[cfg(feature = "reqwest-rustls-tls")]
use crate::anchors::RUSTUP_TRUST_ANCHORS;
use anyhow::{Context, anyhow};
use reqwest::{Client, ClientBuilder, Proxy, Response, header};
#[cfg(feature = "reqwest-rustls-tls")]
use rustls::crypto::aws_lc_rs;
#[cfg(feature = "reqwest-rustls-tls")]
use rustls_platform_verifier::BuilderVerifierExt;
use rustls_platform_verifier::Verifier;
use tokio_stream::StreamExt;
use url::Url;

Expand Down Expand Up @@ -607,15 +609,19 @@ mod reqwest_be {
return Ok(client);
}

let mut tls_config =
rustls::ClientConfig::builder_with_provider(Arc::new(aws_lc_rs::default_provider()))
.with_safe_default_protocol_versions()
.unwrap()
.with_platform_verifier()
let provider = Arc::new(aws_lc_rs::default_provider());
let verifier =
Verifier::new_with_extra_roots(RUSTUP_TRUST_ANCHORS.iter().cloned(), provider.clone())
.map_err(|err| {
DownloadError::Message(format!("failed to initialize platform verifier: {err}"))
})?
.with_no_client_auth();
})?;

let mut tls_config = rustls::ClientConfig::builder_with_provider(provider)
.with_safe_default_protocol_versions()
.unwrap()
.dangerous() // We're using a rustls verifier, so it's okay
.with_custom_certificate_verifier(Arc::new(verifier))
.with_no_client_auth();
tls_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];

let client = client_generic()
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ fn component_for_bin(binary: &str) -> Option<&'static str> {

#[macro_use]
pub mod cli;
#[cfg(feature = "reqwest-rustls-tls")]
mod anchors;
mod command;
mod config;
mod diskio;
Expand Down
1 change: 1 addition & 0 deletions tests/suite/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ mod cli_v1;
mod cli_v2;
mod dist_install;
mod known_triples;
mod static_roots;
172 changes: 172 additions & 0 deletions tests/suite/static_roots.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
//! Connects to a known set of `HOSTS`, captures the root certificates for the
//! certificate chain presented, and writes them to `src/anchors.rs` in a way
//! that is easy to consume for use as `extra_roots` in rustls-platform-verifier.

use std::{
fs,
process::Command,
sync::{Arc, Mutex},
};

use rustls::{
DigitallySignedStruct, Error, RootCertStore, SignatureScheme,
client::{
WebPkiServerVerifier,
danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
},
crypto::{CryptoProvider, aws_lc_rs},
pki_types::{CertificateDer, ServerName, TrustAnchor, UnixTime},
};
use tempfile::NamedTempFile;
use tokio::net::TcpStream;
use tokio_rustls::TlsConnector;
use webpki::{EndEntityCert, anchor_from_trusted_cert};
use webpki_root_certs::TLS_SERVER_ROOT_CERTS;

#[tokio::test]
async fn store_static_roots() {
let provider = Arc::new(aws_lc_rs::default_provider());
let mut root_store = RootCertStore::empty();
let mut roots = Vec::with_capacity(TLS_SERVER_ROOT_CERTS.len());
for cert_der in TLS_SERVER_ROOT_CERTS {
let ta = anchor_from_trusted_cert(cert_der).unwrap();
roots.push((cert_der, ta.clone()));
root_store.roots.push(ta);
}

let root_store = Arc::new(root_store);
let inner = WebPkiServerVerifier::builder_with_provider(root_store.clone(), provider.clone())
.build()
.unwrap();

let verifier = Arc::new(TrackRootVerifier {
root: Mutex::default(),
roots: root_store,
inner,
provider: provider.clone(),
});

let config = Arc::new(
rustls::ClientConfig::builder_with_provider(provider)
.with_safe_default_protocol_versions()
.unwrap()
.dangerous()
.with_custom_certificate_verifier(verifier.clone())
.with_no_client_auth(),
);

let mut code = "// @generated by tests/static_roots.rs\n".to_string();
code.push_str("use rustls::pki_types::CertificateDer;\n\n");
code.push_str("pub(crate) const RUSTUP_TRUST_ANCHORS: &[CertificateDer<'static>] = &[\n");
let connector = TlsConnector::from(config);
for &host in HOSTS {
connector
.connect(
ServerName::try_from(host).unwrap(),
TcpStream::connect((host, 443)).await.unwrap(),
)
.await
.unwrap();

let root = verifier.root.lock().unwrap().take().unwrap();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: That's a lot of .unwrap() here. Maybe this test function return a result and the overall code can be shortened by quite a bit? Not 100% sure, but probably worth testing though (pun intended) :)

let root_cert = roots
.iter()
.find_map(|(cert_der, ta)| match ta == &root {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This might be a good place to put .then_some() since the match isn't really doing too much.

true => Some(cert_der),
false => None,
})
.unwrap();

code.push_str(&format!(
" CertificateDer::from_slice(&{:?}),\n",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt whether that will give the right formatting. How about disabling formatting and/or lints altogether and just maintaining an OK-ish style here?

root_cert.as_ref()
));
}
code.push_str("];\n");

let tmp = NamedTempFile::new().unwrap();
fs::write(&tmp, &code).unwrap();
Command::new("rustfmt").arg(tmp.path()).status().unwrap();
let new = fs::read_to_string(&tmp).unwrap();

let old = fs::read_to_string(PATH).unwrap();
if old != new {
fs::rename(tmp.path(), PATH).unwrap();
panic!("anchors.rs is outdated; updated it");
}
}

const PATH: &str = "src/anchors.rs";

#[derive(Debug)]
struct TrackRootVerifier {
root: Mutex<Option<TrustAnchor<'static>>>,
inner: Arc<WebPkiServerVerifier>,
roots: Arc<RootCertStore>,
provider: Arc<CryptoProvider>,
}

impl ServerCertVerifier for TrackRootVerifier {
fn verify_server_cert(
&self,
end_entity: &CertificateDer<'_>,
intermediates: &[CertificateDer<'_>],
server_name: &ServerName<'_>,
ocsp_response: &[u8],
now: UnixTime,
) -> Result<ServerCertVerified, Error> {
let verified = self.inner.verify_server_cert(
end_entity,
intermediates,
server_name,
ocsp_response,
now,
)?;

let cert = EndEntityCert::try_from(end_entity)
.map_err(|e| Error::General(format!("invalid end entity certificate: {e}")))?;

let path = cert
.verify_for_usage(
&self.provider.signature_verification_algorithms.all,
&self.roots.roots,
intermediates,
now,
webpki::KeyUsage::server_auth(),
None,
None,
)
.unwrap();

let mut root = self.root.lock().unwrap();
*root = Some(path.anchor().to_owned());
Ok(verified)
}

fn verify_tls12_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
self.inner.verify_tls12_signature(message, cert, dss)
}

fn verify_tls13_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, Error> {
self.inner.verify_tls13_signature(message, cert, dss)
}

fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
self.inner.supported_verify_schemes()
}
}

const HOSTS: &[&str] = &[
"fastly-static.rust-lang.org",
"cloudfront-static.rust-lang.org",
];
Loading