Skip to content

Commit 442fb50

Browse files
authored
Don't force users to unsafe. (#109)
Fixes #103
1 parent 03066d8 commit 442fb50

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

web-transport-quinn/examples/echo-client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ async fn main() -> anyhow::Result<()> {
3434
log::warn!("disabling TLS certificate verification; a MITM attack is possible");
3535

3636
// Accept any certificate.
37-
unsafe { client.with_no_certificate_verification()? }
37+
client.dangerous().with_no_certificate_verification()?
3838
} else if let Some(path) = &args.tls_cert {
3939
// Read the PEM certificate chain
4040
let chain = fs::File::open(path).context("failed to open cert file")?;

web-transport-quinn/src/client.rs

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -125,21 +125,13 @@ impl ClientBuilder {
125125
self.build(crypto)
126126
}
127127

128-
/// Ignore the server's provided certificate, always accepting it.
128+
/// Access dangerous configuration options.
129129
///
130-
/// # Safety
131-
/// This makes the connection vulnerable to man-in-the-middle attacks.
132-
/// Only use it in secure environments, such as in local development or over a VPN connection.
133-
pub unsafe fn with_no_certificate_verification(self) -> Result<Client, ClientError> {
134-
let noop = NoCertificateVerification(self.provider.clone());
135-
136-
let crypto = self
137-
.builder()
138-
.dangerous()
139-
.with_custom_certificate_verifier(Arc::new(noop))
140-
.with_no_client_auth();
141-
142-
self.build(crypto)
130+
/// This method returns a builder that provides access to potentially insecure
131+
/// TLS configurations. These options are opt-in and require explicit acknowledgment
132+
/// through the builder pattern, making the security implications clear at the call site.
133+
pub fn dangerous(self) -> DangerousClientBuilder {
134+
DangerousClientBuilder { inner: self }
143135
}
144136

145137
fn builder(&self) -> rustls::ConfigBuilder<rustls::ClientConfig, rustls::WantsVerifier> {
@@ -176,6 +168,39 @@ impl Default for ClientBuilder {
176168
}
177169
}
178170

171+
#[cfg(any(feature = "aws-lc-rs", feature = "ring"))]
172+
/// Builder for dangerous TLS configuration options.
173+
///
174+
/// This builder provides access to potentially insecure TLS configurations.
175+
/// These options should only be used when you understand the security implications,
176+
/// such as in local development or over a secure VPN connection.
177+
pub struct DangerousClientBuilder {
178+
inner: ClientBuilder,
179+
}
180+
181+
#[cfg(any(feature = "aws-lc-rs", feature = "ring"))]
182+
impl DangerousClientBuilder {
183+
/// Disable certificate verification entirely.
184+
///
185+
/// This makes the connection vulnerable to man-in-the-middle attacks.
186+
/// Only use this in secure environments, such as in local development or over a VPN connection.
187+
///
188+
/// This method is safe in the Rust sense (no memory unsafety), but dangerous in the
189+
/// security sense, hence the explicit `dangerous()` builder requirement.
190+
pub fn with_no_certificate_verification(self) -> Result<Client, ClientError> {
191+
let noop = NoCertificateVerification(self.inner.provider.clone());
192+
193+
let crypto = self
194+
.inner
195+
.builder()
196+
.dangerous()
197+
.with_custom_certificate_verifier(Arc::new(noop))
198+
.with_no_client_auth();
199+
200+
self.inner.build(crypto)
201+
}
202+
}
203+
179204
/// A client for connecting to a WebTransport server.
180205
#[derive(Clone, Debug)]
181206
pub struct Client {

0 commit comments

Comments
 (0)