diff --git a/tonic/Cargo.toml b/tonic/Cargo.toml index cefdafc57..50d8aa1fe 100644 --- a/tonic/Cargo.toml +++ b/tonic/Cargo.toml @@ -29,9 +29,8 @@ zstd = ["dep:zstd"] default = ["transport", "codegen", "prost"] prost = ["dep:prost"] tls = ["dep:rustls-pemfile", "dep:tokio-rustls", "dep:tokio", "tokio?/rt", "tokio?/macros"] -tls-roots = ["tls-roots-common", "dep:rustls-native-certs"] -tls-roots-common = ["tls", "channel"] -tls-webpki-roots = ["tls-roots-common", "dep:webpki-roots"] +tls-roots = ["tls", "channel", "dep:rustls-native-certs"] +tls-webpki-roots = ["tls", "channel", "dep:webpki-roots"] router = ["dep:axum"] server = [ "router", diff --git a/tonic/src/transport/channel/endpoint.rs b/tonic/src/transport/channel/endpoint.rs index 4961e03b6..03d7ebd7e 100644 --- a/tonic/src/transport/channel/endpoint.rs +++ b/tonic/src/transport/channel/endpoint.rs @@ -25,11 +25,6 @@ pub struct Endpoint { pub(crate) rate_limit: Option<(u64, Duration)>, #[cfg(feature = "tls")] pub(crate) tls: Option, - // Only applies if the tls config is not explicitly set. This allows users - // to connect to a server that doesn't support ALPN while using the - // tls-roots-common feature for setting up TLS. - #[cfg(feature = "tls-roots-common")] - pub(crate) tls_assume_http2: bool, pub(crate) buffer_size: Option, pub(crate) init_stream_window_size: Option, pub(crate) init_connection_window_size: Option, @@ -256,18 +251,6 @@ impl Endpoint { }) } - /// Configures TLS to assume that the server offers HTTP/2 even if it - /// doesn't perform ALPN negotiation. This only applies if a tls_config has - /// not been set. - #[cfg(feature = "tls-roots-common")] - #[cfg_attr(docsrs, doc(cfg(feature = "tls-roots-common")))] - pub fn tls_assume_http2(self, assume_http2: bool) -> Self { - Endpoint { - tls_assume_http2: assume_http2, - ..self - } - } - /// Set the value of `TCP_NODELAY` option for accepted connections. Enabled by default. pub fn tcp_nodelay(self, enabled: bool) -> Self { Endpoint { @@ -320,16 +303,11 @@ impl Endpoint { } pub(crate) fn connector(&self, c: C) -> service::Connector { - #[cfg(all(feature = "tls", not(feature = "tls-roots-common")))] - let connector = service::Connector::new(c, self.tls.clone()); - - #[cfg(all(feature = "tls", feature = "tls-roots-common"))] - let connector = service::Connector::new(c, self.tls.clone(), self.tls_assume_http2); - - #[cfg(not(feature = "tls"))] - let connector = service::Connector::new(c); - - connector + service::Connector::new( + c, + #[cfg(feature = "tls")] + self.tls.clone(), + ) } /// Create a channel from this config. @@ -435,8 +413,6 @@ impl From for Endpoint { timeout: None, #[cfg(feature = "tls")] tls: None, - #[cfg(feature = "tls-roots-common")] - tls_assume_http2: false, buffer_size: None, init_stream_window_size: None, init_connection_window_size: None, diff --git a/tonic/src/transport/channel/service/connector.rs b/tonic/src/transport/channel/service/connector.rs index 2e8291c04..146dc94ed 100644 --- a/tonic/src/transport/channel/service/connector.rs +++ b/tonic/src/transport/channel/service/connector.rs @@ -33,40 +33,16 @@ pub(crate) struct Connector { inner: C, #[cfg(feature = "tls")] tls: Option, - // When connecting to a URI with the https scheme, assume that the server - // is capable of speaking HTTP/2 even if it doesn't offer ALPN. - #[cfg(feature = "tls-roots-common")] - assume_http2: bool, } impl Connector { - pub(crate) fn new( - inner: C, - #[cfg(feature = "tls")] tls: Option, - #[cfg(feature = "tls-roots-common")] assume_http2: bool, - ) -> Self { + pub(crate) fn new(inner: C, #[cfg(feature = "tls")] tls: Option) -> Self { Self { inner, #[cfg(feature = "tls")] tls, - #[cfg(feature = "tls-roots-common")] - assume_http2, } } - - #[cfg(feature = "tls-roots-common")] - fn tls_or_default(&self, scheme: Option<&str>, host: Option<&str>) -> Option { - if self.tls.is_some() { - return self.tls.clone(); - } - - let host = match (scheme, host) { - (Some("https"), Some(host)) => host, - _ => return None, - }; - - TlsConnector::new(Vec::new(), None, host, self.assume_http2).ok() - } } impl Service for Connector @@ -87,12 +63,9 @@ where } fn call(&mut self, uri: Uri) -> Self::Future { - #[cfg(all(feature = "tls", not(feature = "tls-roots-common")))] + #[cfg(feature = "tls")] let tls = self.tls.clone(); - #[cfg(feature = "tls-roots-common")] - let tls = self.tls_or_default(uri.scheme_str(), uri.host()); - #[cfg(feature = "tls")] let is_https = uri.scheme_str() == Some("https"); let connect = self.inner.call(uri); diff --git a/tonic/src/transport/channel/service/tls.rs b/tonic/src/transport/channel/service/tls.rs index c63396a70..54abcbee3 100644 --- a/tonic/src/transport/channel/service/tls.rs +++ b/tonic/src/transport/channel/service/tls.rs @@ -26,15 +26,21 @@ impl TlsConnector { identity: Option, domain: &str, assume_http2: bool, + #[cfg(feature = "tls-roots")] with_native_roots: bool, + #[cfg(feature = "tls-webpki-roots")] with_webpki_roots: bool, ) -> Result { let builder = ClientConfig::builder(); let mut roots = RootCertStore::empty(); #[cfg(feature = "tls-roots")] - roots.add_parsable_certificates(rustls_native_certs::load_native_certs()?); + if with_native_roots { + roots.add_parsable_certificates(rustls_native_certs::load_native_certs()?); + } #[cfg(feature = "tls-webpki-roots")] - roots.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); + if with_webpki_roots { + roots.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); + } for cert in ca_certs { add_certs_from_pem(&mut Cursor::new(cert), &mut roots)?; diff --git a/tonic/src/transport/channel/tls.rs b/tonic/src/transport/channel/tls.rs index 31f5a7a46..1dabec306 100644 --- a/tonic/src/transport/channel/tls.rs +++ b/tonic/src/transport/channel/tls.rs @@ -13,6 +13,10 @@ pub struct ClientTlsConfig { certs: Vec, identity: Option, assume_http2: bool, + #[cfg(feature = "tls-roots")] + with_native_roots: bool, + #[cfg(feature = "tls-webpki-roots")] + with_webpki_roots: bool, } impl fmt::Debug for ClientTlsConfig { @@ -33,6 +37,10 @@ impl ClientTlsConfig { certs: Vec::new(), identity: None, assume_http2: false, + #[cfg(feature = "tls-roots")] + with_native_roots: false, + #[cfg(feature = "tls-webpki-roots")] + with_webpki_roots: false, } } @@ -75,6 +83,26 @@ impl ClientTlsConfig { } } + /// Enables the platform's trusted certs. + #[cfg(feature = "tls-roots")] + #[cfg_attr(docsrs, doc(cfg(feature = "tls-roots")))] + pub fn with_native_roots(self) -> Self { + ClientTlsConfig { + with_native_roots: true, + ..self + } + } + + /// Enables the webpki roots. + #[cfg(feature = "tls-webpki-roots")] + #[cfg_attr(docsrs, doc(cfg(feature = "tls-webpki-roots")))] + pub fn with_webpki_roots(self) -> Self { + ClientTlsConfig { + with_webpki_roots: true, + ..self + } + } + pub(crate) fn tls_connector(&self, uri: Uri) -> Result { let domain = match &self.domain { Some(domain) => domain, @@ -85,6 +113,10 @@ impl ClientTlsConfig { self.identity.clone(), domain, self.assume_http2, + #[cfg(feature = "tls-roots")] + self.with_native_roots, + #[cfg(feature = "tls-webpki-roots")] + self.with_webpki_roots, ) } }