Patch-Source: https://github.com/ducaale/xh/pull/281 -- From 36d7d7d2f98e367ff0c5b3d86dbea62b690d29b8 Mon Sep 17 00:00:00 2001 From: Jakub Jirutka Date: Mon, 26 Sep 2022 00:37:43 +0200 Subject: [PATCH] allow to build with native-tls only Bundling (static linking) TLS library is a very bad idea from the security perspective and Linux distributions try to avoid it. This will allow to build xh with native-tls (i.e. dynamically linked system-provided TLS library) only, without rustls. --- Cargo.toml | 5 +++-- build.rs | 15 +++++++++++---- src/cli.rs | 6 +++++- src/main.rs | 53 +++++++++++++++++++++++++++++++--------------------- tests/cli.rs | 3 ++- 5 files changed, 53 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b0ebbb3f..1d8662ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ url = "2.2.2" [dependencies.reqwest] version = "0.11.10" default-features = false -features = ["rustls-tls", "rustls-tls-webpki-roots", "rustls-tls-native-roots", "json", "multipart", "blocking", "socks", "cookies"] +features = ["json", "multipart", "blocking", "socks", "cookies"] [dependencies.syntect] version = "4.4" @@ -69,9 +69,10 @@ tempfile = "3.2.0" syntect = { version = "4.4", default-features = false } [features] -default = ["online-tests"] +default = ["online-tests", "rustls"] online-tests = [] native-tls = ["reqwest/native-tls", "reqwest/native-tls-alpn"] +rustls = ["reqwest/rustls-tls", "reqwest/rustls-tls-webpki-roots", "reqwest/rustls-tls-native-roots"] [package.metadata.deb] features = [] diff --git a/build.rs b/build.rs index b58bfc9e..daf2151e 100644 --- a/build.rs +++ b/build.rs @@ -14,13 +14,16 @@ fn build_syntax(dir: &str, out: &str) { dump_to_file(&ss, Path::new(&out_dir).join(out)).unwrap(); } -fn feature_status(feature: &str) -> String { - if env::var_os(format!( +fn feature_enabled(feature: &str) -> bool { + env::var_os(format!( "CARGO_FEATURE_{}", feature.to_uppercase().replace('-', "_") )) .is_some() - { +} + +fn feature_status(feature: &str) -> String { + if feature_enabled(feature) { format!("+{}", feature) } else { format!("-{}", feature) @@ -28,10 +31,14 @@ fn feature_status(feature: &str) -> String { } fn features() -> String { - feature_status("native-tls") + format!("{} {}", &feature_status("native-tls"), &feature_status("rustls")) } fn main() { + if !feature_enabled("native-tls") && !feature_enabled("rustls") { + panic!("Either native-tls or rustls feature must be enabled!"); + } + for dir in &["assets", "assets/basic", "assets/large"] { println!("cargo:rerun-if-changed={}", dir); for entry in read_dir(dir).unwrap() { diff --git a/src/cli.rs b/src/cli.rs index d897fab7..29986328 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -250,7 +250,7 @@ pub struct Cli { pub ssl: Option>, /// Use the system TLS library instead of rustls (if enabled at compile time). - #[clap(long)] + #[clap(long, hide = cfg!(not(all(feature = "native-tls", feature = "rustls"))))] pub native_tls: bool, /// The default scheme to use if not specified in the URL. @@ -454,6 +454,10 @@ impl Cli { ) })?; + if cfg!(not(feature = "rustls")) { + cli.native_tls = true; + } + Ok(cli) } diff --git a/src/main.rs b/src/main.rs index 3b93ab15..2885234c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -158,7 +158,6 @@ fn run(args: Cli) -> Result { let mut client = Client::builder() .http1_title_case_headers() - .use_rustls_tls() .http2_adaptive_window(true) .redirect(reqwest::redirect::Policy::none()) .timeout(timeout) @@ -166,6 +165,11 @@ fn run(args: Cli) -> Result { .no_deflate() .no_brotli(); + #[cfg(feature = "rustls")] + if !args.native_tls { + client = client.use_rustls_tls(); + } + if let Some(Some(tls_version)) = args.ssl { client = client .min_tls_version(tls_version) @@ -249,30 +253,37 @@ fn run(args: Cli) -> Result { if args.native_tls { // Unlike the --verify case this is advertised to not work, so it's // not an outright bug, but it's still imaginable that it'll start working - warn("Client certificates are not supported for native-tls"); + if cfg!(feature = "rustls") { + warn("Client certificates are not supported for native-tls"); + } else { + warn("Client certificates are not supported for native-tls and this binary was built without rustls support"); + } } - let mut buffer = Vec::new(); - let mut file = File::open(&cert) - .with_context(|| format!("Failed to open the cert file: {}", cert.display()))?; - file.read_to_end(&mut buffer) - .with_context(|| format!("Failed to read the cert file: {}", cert.display()))?; - - if let Some(cert_key) = args.cert_key { - buffer.push(b'\n'); + #[cfg(feature = "rustls")] + { + let mut buffer = Vec::new(); + let mut file = File::open(&cert) + .with_context(|| format!("Failed to open the cert file: {}", cert.display()))?; + file.read_to_end(&mut buffer) + .with_context(|| format!("Failed to read the cert file: {}", cert.display()))?; + + if let Some(cert_key) = args.cert_key { + buffer.push(b'\n'); + + let mut file = File::open(&cert_key).with_context(|| { + format!("Failed to open the cert key file: {}", cert_key.display()) + })?; + file.read_to_end(&mut buffer).with_context(|| { + format!("Failed to read the cert key file: {}", cert_key.display()) + })?; + } - let mut file = File::open(&cert_key).with_context(|| { - format!("Failed to open the cert key file: {}", cert_key.display()) - })?; - file.read_to_end(&mut buffer).with_context(|| { - format!("Failed to read the cert key file: {}", cert_key.display()) - })?; + // We may fail here if we can't parse it but also if we don't have the key + let identity = reqwest::Identity::from_pem(&buffer) + .context("Failed to load the cert/cert key files")?; + client = client.identity(identity); } - - // We may fail here if we can't parse it but also if we don't have the key - let identity = reqwest::Identity::from_pem(&buffer) - .context("Failed to load the cert/cert key files")?; - client = client.identity(identity); }; } diff --git a/tests/cli.rs b/tests/cli.rs index 24d80dae..30ffe761 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -1136,7 +1136,7 @@ fn improved_https_ip_error_with_support() { .stderr(contains("using the --native-tls flag")); } -#[cfg(feature = "native-tls")] +#[cfg(all(feature = "native-tls", feature = "rustls"))] #[test] fn auto_nativetls() { get_command() @@ -1200,6 +1200,7 @@ fn unsupported_tls_version_nativetls() { .stderr(contains("running without the --native-tls")); } +#[cfg(feature = "rustls")] #[test] fn unsupported_tls_version_rustls() { #[cfg(feature = "native-tls")]