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
1 change: 1 addition & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion crates/yaak-http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ zstd = "0.13"
hyper-util = { version = "0.1.17", default-features = false, features = ["client-legacy"] }
log = { workspace = true }
mime_guess = "2.0.5"
native-tls = "0.2"
regex = "1.11.1"
reqwest = { workspace = true, features = ["rustls-tls-manual-roots-no-provider", "socks", "http2", "stream"] }
reqwest = { workspace = true, features = ["rustls-tls-manual-roots-no-provider", "native-tls", "socks", "http2", "stream"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
thiserror = { workspace = true }
Expand Down
65 changes: 61 additions & 4 deletions crates/yaak-http/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,56 @@ use std::sync::Arc;
use yaak_models::models::DnsOverride;
use yaak_tls::{ClientCertificateConfig, get_tls_config};

/// Build a native-tls connector for maximum compatibility when certificate
/// validation is disabled. Unlike rustls, native-tls uses the OS TLS stack
/// (Secure Transport on macOS, SChannel on Windows, OpenSSL on Linux) which
/// supports TLS 1.0+ for legacy servers.
fn build_native_tls_connector(
client_cert: Option<ClientCertificateConfig>,
) -> Result<native_tls::TlsConnector> {
let mut builder = native_tls::TlsConnector::builder();
builder.danger_accept_invalid_certs(true);
builder.danger_accept_invalid_hostnames(true);
builder.min_protocol_version(Some(native_tls::Protocol::Tlsv10));

if let Some(identity) = build_native_tls_identity(client_cert)? {
builder.identity(identity);
}

Ok(builder.build()?)
}

fn build_native_tls_identity(
client_cert: Option<ClientCertificateConfig>,
) -> Result<Option<native_tls::Identity>> {
let config = match client_cert {
None => return Ok(None),
Some(c) => c,
};

// Try PFX/PKCS12 first
if let Some(pfx_path) = &config.pfx_file {
if !pfx_path.is_empty() {
let pfx_data = std::fs::read(pfx_path)?;
let password = config.passphrase.as_deref().unwrap_or("");
let identity = native_tls::Identity::from_pkcs12(&pfx_data, password)?;
return Ok(Some(identity));
}
}

// Try CRT + KEY files
if let (Some(crt_path), Some(key_path)) = (&config.crt_file, &config.key_file) {
if !crt_path.is_empty() && !key_path.is_empty() {
let crt_data = std::fs::read(crt_path)?;
let key_data = std::fs::read(key_path)?;
let identity = native_tls::Identity::from_pkcs8(&crt_data, &key_data)?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep PKCS#1 client keys working in native TLS path

The new validate_certificates == false flow loads CRT+KEY identities with native_tls::Identity::from_pkcs8, which only accepts PKCS#8 keys and rejects common BEGIN RSA PRIVATE KEY (PKCS#1) files; before this change, the same path went through yaak_tls::load_private_key and accepted PKCS#1/PKCS#8/EC keys. This introduces a regression where mTLS requests now fail for users who disable certificate validation and provide an RSA PEM key that previously worked.

Useful? React with 👍 / 👎.

return Ok(Some(identity));
}
}

Ok(None)
}

#[derive(Clone)]
pub struct HttpConnectionProxySettingAuth {
pub user: String,
Expand Down Expand Up @@ -51,10 +101,17 @@ impl HttpConnectionOptions {
// This is needed so we can emit DNS timing events for each request
.pool_max_idle_per_host(0);

// Configure TLS with optional client certificate
let config =
get_tls_config(self.validate_certificates, true, self.client_certificate.clone())?;
client = client.use_preconfigured_tls(config);
// Configure TLS
if self.validate_certificates {
// Use rustls with platform certificate verification (TLS 1.2+ only)
let config = get_tls_config(true, true, self.client_certificate.clone())?;
client = client.use_preconfigured_tls(config);
} else {
// Use native TLS for maximum compatibility (supports TLS 1.0+)
let connector =
build_native_tls_connector(self.client_certificate.clone())?;
client = client.use_preconfigured_tls(connector);
}

// Configure DNS resolver - keep a reference to configure per-request
let resolver = LocalhostResolver::new(self.dns_overrides.clone());
Expand Down
6 changes: 6 additions & 0 deletions crates/yaak-http/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ pub enum Error {
#[error(transparent)]
TlsError(#[from] yaak_tls::error::Error),

#[error("Native TLS error: {0}")]
NativeTlsError(#[from] native_tls::Error),

#[error("IO error: {0}")]
IoError(#[from] std::io::Error),

#[error("Request failed with {0:?}")]
RequestError(String),

Expand Down
Loading