diff --git a/Cargo.toml b/Cargo.toml index d7a6124..51b642a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,14 +22,13 @@ exclude = [ [features] # By default we use rustls for TLS default = ["rustls-tls"] -rustls-tls = ["ureq/tls"] +rustls-tls = ["ureq/tls", "rustls-pemfile", "rustls"] # If this feature is enabled we instead use the native TLS implementation for the # target platform native-tls = [ "ureq/native-tls", "native-tls-crate/vendored", "rustls-pemfile", - "rustls", ] [dependencies] diff --git a/src/ctx.rs b/src/ctx.rs index edb2185..b5cb262 100644 --- a/src/ctx.rs +++ b/src/ctx.rs @@ -62,6 +62,40 @@ impl Ctx { builder = builder.tls_connector(std::sync::Arc::new(tls_connector)); } + #[cfg(feature = "rustls-tls")] + 'custom: { + // "common"? env vars that people who use custom certs use? I guess + // this is easy to expand if it's not the case. /shrug + const CERT_ENVS: &[&str] = &["REQUESTS_CA_BUNDLE", "CURL_CA_BUNDLE", "SSL_CERT_FILE"]; + + let Some((env, cert_path)) = CERT_ENVS.iter().find_map(|env| { + std::env::var_os(env).map(|var| (env, std::path::PathBuf::from(var))) + }) else { + break 'custom; + }; + + fn build(cert_path: &std::path::Path) -> anyhow::Result { + let mut reader = std::io::BufReader::new(std::fs::File::open(cert_path)?); + let certs = rustls_pemfile::certs(&mut reader)?; + let mut root_certs = rustls::RootCertStore::empty(); + root_certs.add_parsable_certificates(&certs); + let client_config = rustls::ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(root_certs) + .with_no_client_auth(); + Ok(client_config) + } + + let client_config = build(&cert_path).with_context(|| { + format!( + "failed to add custom cert from path '{}' configured by env var '{env}'", + cert_path.display() + ) + })?; + + builder = builder.tls_config(std::sync::Arc::new(client_config)); + } + // Allow user to specify timeout values in the case of bad/slow proxies // or MS itself being terrible, but default to a minute, which is _far_ // more than it should take in normal situations, as by default ureq