Skip to content
Closed
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
6 changes: 4 additions & 2 deletions tonic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ transport = [
]
tls = ["transport", "tokio-rustls"]
tls-roots = ["tls", "rustls-native-certs"]
tls-dangerous = ["rustls", "webpki"]
Copy link
Member

Choose a reason for hiding this comment

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

This should only have to enable "rustls/dangerous_configuration" then we leave it out of the default. So this is an opt-in feature that will only enable that specific rustls feature if you opt in.

Copy link
Author

Choose a reason for hiding this comment

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

I didn't know feature flags were transitive, I'm looking into it.

Copy link
Author

Choose a reason for hiding this comment

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

After thinking about it, I don't understand what you want me to do

Copy link
Member

Choose a reason for hiding this comment

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

It should be possible to set tls-dangerous to be like:

tls-dangerous = ["rustls/dangerous-config", "webpki"]

Since, rustls is already included with tokio-rustls this feature set should work.

Let me know if that makes sense!


# [[bench]]
# name = "bench_main"
# harness = false

[dependencies]
bytes = "0.5"
futures-core = { version = "0.3", default-features = false }
futures-core = { version = "0.3", default-features = false }
futures-util = { version = "0.3", default-features = false }
tracing = "0.1"
http = "0.2"
Expand Down Expand Up @@ -74,6 +75,8 @@ tracing-futures = { version = "0.2", optional = true }
# rustls
tokio-rustls = { version = "0.12", optional = true }
rustls-native-certs = { version = "0.1", optional = true }
rustls = { version = "0.16", features = ["dangerous_configuration"], optional = true }
webpki = { version = "0.21", optional = true }

[dev-dependencies]
tokio = { version = "0.2", features = ["rt-core", "macros"] }
Expand All @@ -88,4 +91,3 @@ rustdoc-args = ["--cfg", "docsrs"]
[[bench]]
name = "decode"
harness = false

44 changes: 43 additions & 1 deletion tonic/src/transport/channel/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ pub struct ClientTlsConfig {
cert: Option<Certificate>,
identity: Option<Identity>,
rustls_raw: Option<tokio_rustls::rustls::ClientConfig>,
#[cfg(feature = "tls-dangerous")]
certs_validation: bool,
}

#[cfg(feature = "tls")]
Expand All @@ -37,6 +39,8 @@ impl ClientTlsConfig {
cert: None,
identity: None,
rustls_raw: None,
#[cfg(feature = "tls-dangerous")]
certs_validation: true,
}
}

Expand Down Expand Up @@ -80,14 +84,52 @@ impl ClientTlsConfig {
}
}

/// Disables certificate validation.
///
/// # Warning
///
/// You should think very carefully before using this method. If
/// invalid certificates are trusted, *any* certificate for *any* site
/// will be trusted for use. This includes expired certificates. This
/// introduces significant vulnerabilities, and should only be used
/// as a last resort.
///
/// # Optional
///
/// This requires the optional `tls` and `tls-dangerous` features to be enabled.
#[cfg(feature = "tls-dangerous")]
#[cfg_attr(docsrs, doc(cfg(feature = "tls-dangerous")))]
pub fn danger_accept_invalid_certs(self) -> Self {
ClientTlsConfig {
certs_validation: false,
..self
}
}

pub(crate) fn tls_connector(&self, uri: Uri) -> Result<TlsConnector, crate::Error> {
let domain = match &self.domain {
None => uri.host().ok_or(Error::new_invalid_uri())?.to_string(),
Some(domain) => domain.clone(),
};
match &self.rustls_raw {
None => {
TlsConnector::new_with_rustls_cert(self.cert.clone(), self.identity.clone(), domain)
let certs_validation = {
#[cfg(feature = "tls-dangerous")]
{
self.certs_validation
}
#[cfg(not(feature = "tls-dangerous"))]
{
true
}
};

TlsConnector::new_with_rustls_cert(
self.cert.clone(),
self.identity.clone(),
certs_validation,
domain,
)
}
Some(c) => TlsConnector::new_with_rustls_raw(c.clone(), domain),
}
Expand Down
25 changes: 25 additions & 0 deletions tonic/src/transport/service/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl TlsConnector {
pub(crate) fn new_with_rustls_cert(
ca_cert: Option<Certificate>,
identity: Option<Identity>,
_certs_validation: bool,
domain: String,
) -> Result<Self, crate::Error> {
let mut config = ClientConfig::new();
Expand All @@ -63,6 +64,14 @@ impl TlsConnector {
config.root_store.add_pem_file(&mut buf).unwrap();
}

#[cfg(feature = "tls-dangerous")]
{
if !_certs_validation {
config.dangerous()
.set_certificate_verifier(std::sync::Arc::new(NoCertsValidation));
}
}

Ok(Self {
config: Arc::new(config),
domain: Arc::new(domain),
Expand Down Expand Up @@ -245,3 +254,19 @@ mod rustls_keys {
Ok((cert, key))
}
}

#[cfg(feature = "tls-dangerous")]
struct NoCertsValidation;

#[cfg(feature = "tls-dangerous")]
impl rustls::ServerCertVerifier for NoCertsValidation {
fn verify_server_cert(
&self,
_roots: &rustls::RootCertStore,
_presented_certs: &[rustls::Certificate],
_dns_name: webpki::DNSNameRef<'_>,
_ocsp_response: &[u8],
) -> Result<rustls::ServerCertVerified, rustls::TLSError> {
Ok(rustls::ServerCertVerified::assertion())
}
}