diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-15 16:37:08 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-17 16:30:22 -0600 |
| commit | 45df4d0d9b577fecee798d672695fe24ff57fb1b (patch) | |
| tree | 1b99bf645035b58e0d6db08c7a83521f41f7a75b /vendor/hyper-rustls/src | |
| parent | f94f79608393d4ab127db63cc41668445ef6b243 (diff) | |
feat: migrate from Cedar to SpiceDB authorization system
This is a major architectural change that replaces the Cedar policy-based
authorization system with SpiceDB's relation-based authorization.
Key changes:
- Migrate from Rust to Go implementation
- Replace Cedar policies with SpiceDB schema and relationships
- Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks
- Update build system and dependencies for Go ecosystem
- Maintain Envoy integration for external authorization
This change enables more flexible permission modeling through SpiceDB's
Google Zanzibar inspired relation-based system, supporting complex
hierarchical permissions that were difficult to express in Cedar.
Breaking change: Existing Cedar policies and Rust-based configuration
will no longer work and need to be migrated to SpiceDB schema.
Diffstat (limited to 'vendor/hyper-rustls/src')
| -rw-r--r-- | vendor/hyper-rustls/src/config.rs | 136 | ||||
| -rw-r--r-- | vendor/hyper-rustls/src/connector.rs | 296 | ||||
| -rw-r--r-- | vendor/hyper-rustls/src/connector/builder.rs | 500 | ||||
| -rw-r--r-- | vendor/hyper-rustls/src/lib.rs | 76 | ||||
| -rw-r--r-- | vendor/hyper-rustls/src/stream.rs | 121 |
5 files changed, 0 insertions, 1129 deletions
diff --git a/vendor/hyper-rustls/src/config.rs b/vendor/hyper-rustls/src/config.rs deleted file mode 100644 index 38382617..00000000 --- a/vendor/hyper-rustls/src/config.rs +++ /dev/null @@ -1,136 +0,0 @@ -#[cfg(feature = "rustls-native-certs")] -use std::io; - -#[cfg(any( - feature = "rustls-platform-verifier", - feature = "rustls-native-certs", - feature = "webpki-roots" -))] -use rustls::client::WantsClientCert; -use rustls::{ClientConfig, ConfigBuilder, WantsVerifier}; -#[cfg(feature = "rustls-native-certs")] -use rustls_native_certs::CertificateResult; -#[cfg(feature = "rustls-platform-verifier")] -use rustls_platform_verifier::BuilderVerifierExt; - -/// Methods for configuring roots -/// -/// This adds methods (gated by crate features) for easily configuring -/// TLS server roots a rustls ClientConfig will trust. -pub trait ConfigBuilderExt: sealed::Sealed { - /// Use the platform's native verifier to verify server certificates. - /// - /// See the documentation for [rustls-platform-verifier] for more details. - /// - /// # Panics - /// - /// Since 0.27.7, this method will panic if the platform verifier cannot be initialized. - /// Use `try_with_platform_verifier()` instead to handle errors gracefully. - /// - /// [rustls-platform-verifier]: https://docs.rs/rustls-platform-verifier - #[deprecated(since = "0.27.7", note = "use `try_with_platform_verifier` instead")] - #[cfg(feature = "rustls-platform-verifier")] - fn with_platform_verifier(self) -> ConfigBuilder<ClientConfig, WantsClientCert>; - - /// Use the platform's native verifier to verify server certificates. - /// - /// See the documentation for [rustls-platform-verifier] for more details. - /// - /// [rustls-platform-verifier]: https://docs.rs/rustls-platform-verifier - #[cfg(feature = "rustls-platform-verifier")] - fn try_with_platform_verifier( - self, - ) -> Result<ConfigBuilder<ClientConfig, WantsClientCert>, rustls::Error>; - - /// This configures the platform's trusted certs, as implemented by - /// rustls-native-certs - /// - /// This will return an error if no valid certs were found. In that case, - /// it's recommended to use `with_webpki_roots`. - #[cfg(feature = "rustls-native-certs")] - fn with_native_roots(self) -> Result<ConfigBuilder<ClientConfig, WantsClientCert>, io::Error>; - - /// This configures the webpki roots, which are Mozilla's set of - /// trusted roots as packaged by webpki-roots. - #[cfg(feature = "webpki-roots")] - fn with_webpki_roots(self) -> ConfigBuilder<ClientConfig, WantsClientCert>; -} - -impl ConfigBuilderExt for ConfigBuilder<ClientConfig, WantsVerifier> { - #[cfg(feature = "rustls-platform-verifier")] - fn with_platform_verifier(self) -> ConfigBuilder<ClientConfig, WantsClientCert> { - self.try_with_platform_verifier() - .expect("failure to initialize platform verifier") - } - - #[cfg(feature = "rustls-platform-verifier")] - fn try_with_platform_verifier( - self, - ) -> Result<ConfigBuilder<ClientConfig, WantsClientCert>, rustls::Error> { - BuilderVerifierExt::with_platform_verifier(self) - } - - #[cfg(feature = "rustls-native-certs")] - #[cfg_attr(not(feature = "logging"), allow(unused_variables))] - fn with_native_roots(self) -> Result<ConfigBuilder<ClientConfig, WantsClientCert>, io::Error> { - let mut roots = rustls::RootCertStore::empty(); - let mut valid_count = 0; - let mut invalid_count = 0; - - let CertificateResult { certs, errors, .. } = rustls_native_certs::load_native_certs(); - if !errors.is_empty() { - crate::log::warn!("native root CA certificate loading errors: {errors:?}"); - } - - if certs.is_empty() { - return Err(io::Error::new( - io::ErrorKind::NotFound, - format!("no native root CA certificates found (errors: {errors:?})"), - )); - } - - for cert in certs { - match roots.add(cert) { - Ok(_) => valid_count += 1, - Err(err) => { - crate::log::debug!("certificate parsing failed: {:?}", err); - invalid_count += 1 - } - } - } - - crate::log::debug!( - "with_native_roots processed {} valid and {} invalid certs", - valid_count, - invalid_count - ); - if roots.is_empty() { - crate::log::debug!("no valid native root CA certificates found"); - Err(io::Error::new( - io::ErrorKind::NotFound, - format!("no valid native root CA certificates found ({invalid_count} invalid)"), - ))? - } - - Ok(self.with_root_certificates(roots)) - } - - #[cfg(feature = "webpki-roots")] - fn with_webpki_roots(self) -> ConfigBuilder<ClientConfig, WantsClientCert> { - let mut roots = rustls::RootCertStore::empty(); - roots.extend( - webpki_roots::TLS_SERVER_ROOTS - .iter() - .cloned(), - ); - self.with_root_certificates(roots) - } -} - -mod sealed { - use super::*; - - pub trait Sealed {} - - impl Sealed for ConfigBuilder<ClientConfig, WantsVerifier> {} -} diff --git a/vendor/hyper-rustls/src/connector.rs b/vendor/hyper-rustls/src/connector.rs deleted file mode 100644 index f8abe457..00000000 --- a/vendor/hyper-rustls/src/connector.rs +++ /dev/null @@ -1,296 +0,0 @@ -use std::future::Future; -use std::pin::Pin; -use std::sync::Arc; -use std::task::{Context, Poll}; -use std::{fmt, io}; - -use http::Uri; -use hyper::rt; -use hyper_util::client::legacy::connect::Connection; -use hyper_util::rt::TokioIo; -use pki_types::ServerName; -use tokio_rustls::TlsConnector; -use tower_service::Service; - -use crate::stream::MaybeHttpsStream; - -pub(crate) mod builder; - -type BoxError = Box<dyn std::error::Error + Send + Sync>; - -/// A Connector for the `https` scheme. -#[derive(Clone)] -pub struct HttpsConnector<T> { - force_https: bool, - http: T, - tls_config: Arc<rustls::ClientConfig>, - server_name_resolver: Arc<dyn ResolveServerName + Sync + Send>, -} - -impl<T> HttpsConnector<T> { - /// Creates a [`crate::HttpsConnectorBuilder`] to configure a `HttpsConnector`. - /// - /// This is the same as [`crate::HttpsConnectorBuilder::new()`]. - pub fn builder() -> builder::ConnectorBuilder<builder::WantsTlsConfig> { - builder::ConnectorBuilder::new() - } - - /// Force the use of HTTPS when connecting. - /// - /// If a URL is not `https` when connecting, an error is returned. - pub fn enforce_https(&mut self) { - self.force_https = true; - } -} - -impl<T> Service<Uri> for HttpsConnector<T> -where - T: Service<Uri>, - T::Response: Connection + rt::Read + rt::Write + Send + Unpin + 'static, - T::Future: Send + 'static, - T::Error: Into<BoxError>, -{ - type Response = MaybeHttpsStream<T::Response>; - type Error = BoxError; - - #[allow(clippy::type_complexity)] - type Future = - Pin<Box<dyn Future<Output = Result<MaybeHttpsStream<T::Response>, BoxError>> + Send>>; - - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { - match self.http.poll_ready(cx) { - Poll::Ready(Ok(())) => Poll::Ready(Ok(())), - Poll::Ready(Err(e)) => Poll::Ready(Err(e.into())), - Poll::Pending => Poll::Pending, - } - } - - fn call(&mut self, dst: Uri) -> Self::Future { - // dst.scheme() would need to derive Eq to be matchable; - // use an if cascade instead - match dst.scheme() { - Some(scheme) if scheme == &http::uri::Scheme::HTTP && !self.force_https => { - let future = self.http.call(dst); - return Box::pin(async move { - Ok(MaybeHttpsStream::Http(future.await.map_err(Into::into)?)) - }); - } - Some(scheme) if scheme != &http::uri::Scheme::HTTPS => { - let message = format!("unsupported scheme {scheme}"); - return Box::pin(async move { - Err(io::Error::new(io::ErrorKind::Other, message).into()) - }); - } - Some(_) => {} - None => { - return Box::pin(async move { - Err(io::Error::new(io::ErrorKind::Other, "missing scheme").into()) - }) - } - }; - - let cfg = self.tls_config.clone(); - let hostname = match self.server_name_resolver.resolve(&dst) { - Ok(hostname) => hostname, - Err(e) => { - return Box::pin(async move { Err(e) }); - } - }; - - let connecting_future = self.http.call(dst); - Box::pin(async move { - let tcp = connecting_future - .await - .map_err(Into::into)?; - Ok(MaybeHttpsStream::Https(TokioIo::new( - TlsConnector::from(cfg) - .connect(hostname, TokioIo::new(tcp)) - .await - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?, - ))) - }) - } -} - -impl<H, C> From<(H, C)> for HttpsConnector<H> -where - C: Into<Arc<rustls::ClientConfig>>, -{ - fn from((http, cfg): (H, C)) -> Self { - Self { - force_https: false, - http, - tls_config: cfg.into(), - server_name_resolver: Arc::new(DefaultServerNameResolver::default()), - } - } -} - -impl<T> fmt::Debug for HttpsConnector<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("HttpsConnector") - .field("force_https", &self.force_https) - .finish() - } -} - -/// The default server name resolver, which uses the hostname in the URI. -#[derive(Default)] -pub struct DefaultServerNameResolver(()); - -impl ResolveServerName for DefaultServerNameResolver { - fn resolve( - &self, - uri: &Uri, - ) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>> { - let mut hostname = uri.host().unwrap_or_default(); - - // Remove square brackets around IPv6 address. - if let Some(trimmed) = hostname - .strip_prefix('[') - .and_then(|h| h.strip_suffix(']')) - { - hostname = trimmed; - } - - ServerName::try_from(hostname.to_string()).map_err(|e| Box::new(e) as _) - } -} - -/// A server name resolver which always returns the same fixed name. -pub struct FixedServerNameResolver { - name: ServerName<'static>, -} - -impl FixedServerNameResolver { - /// Creates a new resolver returning the specified name. - pub fn new(name: ServerName<'static>) -> Self { - Self { name } - } -} - -impl ResolveServerName for FixedServerNameResolver { - fn resolve( - &self, - _: &Uri, - ) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>> { - Ok(self.name.clone()) - } -} - -impl<F, E> ResolveServerName for F -where - F: Fn(&Uri) -> Result<ServerName<'static>, E>, - E: Into<Box<dyn std::error::Error + Sync + Send>>, -{ - fn resolve( - &self, - uri: &Uri, - ) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>> { - self(uri).map_err(Into::into) - } -} - -/// A trait implemented by types that can resolve a [`ServerName`] for a request. -pub trait ResolveServerName { - /// Maps a [`Uri`] into a [`ServerName`]. - fn resolve( - &self, - uri: &Uri, - ) -> Result<ServerName<'static>, Box<dyn std::error::Error + Sync + Send>>; -} - -#[cfg(all( - test, - any(feature = "ring", feature = "aws-lc-rs"), - any( - feature = "rustls-native-certs", - feature = "webpki-roots", - feature = "rustls-platform-verifier", - ) -))] -mod tests { - use std::future::poll_fn; - - use http::Uri; - use hyper_util::rt::TokioIo; - use tokio::net::TcpStream; - use tower_service::Service; - - use super::*; - use crate::{ConfigBuilderExt, HttpsConnectorBuilder, MaybeHttpsStream}; - - #[tokio::test] - async fn connects_https() { - connect(Allow::Any, Scheme::Https) - .await - .unwrap(); - } - - #[tokio::test] - async fn connects_http() { - connect(Allow::Any, Scheme::Http) - .await - .unwrap(); - } - - #[tokio::test] - async fn connects_https_only() { - connect(Allow::Https, Scheme::Https) - .await - .unwrap(); - } - - #[tokio::test] - async fn enforces_https_only() { - let message = connect(Allow::Https, Scheme::Http) - .await - .unwrap_err() - .to_string(); - - assert_eq!(message, "unsupported scheme http"); - } - - async fn connect( - allow: Allow, - scheme: Scheme, - ) -> Result<MaybeHttpsStream<TokioIo<TcpStream>>, BoxError> { - let config_builder = rustls::ClientConfig::builder(); - cfg_if::cfg_if! { - if #[cfg(feature = "rustls-platform-verifier")] { - let config_builder = config_builder.try_with_platform_verifier()?; - } else if #[cfg(feature = "rustls-native-certs")] { - let config_builder = config_builder.with_native_roots().unwrap(); - } else if #[cfg(feature = "webpki-roots")] { - let config_builder = config_builder.with_webpki_roots(); - } - } - let config = config_builder.with_no_client_auth(); - - let builder = HttpsConnectorBuilder::new().with_tls_config(config); - let mut service = match allow { - Allow::Https => builder.https_only(), - Allow::Any => builder.https_or_http(), - } - .enable_http1() - .build(); - - poll_fn(|cx| service.poll_ready(cx)).await?; - service - .call(Uri::from_static(match scheme { - Scheme::Https => "https://google.com", - Scheme::Http => "http://google.com", - })) - .await - } - - enum Allow { - Https, - Any, - } - - enum Scheme { - Https, - Http, - } -} diff --git a/vendor/hyper-rustls/src/connector/builder.rs b/vendor/hyper-rustls/src/connector/builder.rs deleted file mode 100644 index 417d1303..00000000 --- a/vendor/hyper-rustls/src/connector/builder.rs +++ /dev/null @@ -1,500 +0,0 @@ -use std::sync::Arc; - -use hyper_util::client::legacy::connect::HttpConnector; -#[cfg(any( - feature = "rustls-native-certs", - feature = "rustls-platform-verifier", - feature = "webpki-roots" -))] -use rustls::crypto::CryptoProvider; -use rustls::ClientConfig; - -use super::{DefaultServerNameResolver, HttpsConnector, ResolveServerName}; -#[cfg(any( - feature = "rustls-native-certs", - feature = "webpki-roots", - feature = "rustls-platform-verifier" -))] -use crate::config::ConfigBuilderExt; -use pki_types::ServerName; - -/// A builder for an [`HttpsConnector`] -/// -/// This makes configuration flexible and explicit and ensures connector -/// features match crate features -/// -/// # Examples -/// -/// ``` -/// use hyper_rustls::HttpsConnectorBuilder; -/// -/// # #[cfg(all(feature = "webpki-roots", feature = "http1", feature="aws-lc-rs"))] -/// # { -/// # let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); -/// let https = HttpsConnectorBuilder::new() -/// .with_webpki_roots() -/// .https_only() -/// .enable_http1() -/// .build(); -/// # } -/// ``` -pub struct ConnectorBuilder<State>(State); - -/// State of a builder that needs a TLS client config next -pub struct WantsTlsConfig(()); - -impl ConnectorBuilder<WantsTlsConfig> { - /// Creates a new [`ConnectorBuilder`] - pub fn new() -> Self { - Self(WantsTlsConfig(())) - } - - /// Passes a rustls [`ClientConfig`] to configure the TLS connection - /// - /// The [`alpn_protocols`](ClientConfig::alpn_protocols) field is - /// required to be empty (or the function will panic) and will be - /// rewritten to match the enabled schemes (see - /// [`enable_http1`](ConnectorBuilder::enable_http1), - /// [`enable_http2`](ConnectorBuilder::enable_http2)) before the - /// connector is built. - pub fn with_tls_config(self, config: ClientConfig) -> ConnectorBuilder<WantsSchemes> { - assert!( - config.alpn_protocols.is_empty(), - "ALPN protocols should not be pre-defined" - ); - ConnectorBuilder(WantsSchemes { tls_config: config }) - } - - /// Shorthand for using rustls' default crypto provider and other defaults, and - /// the platform verifier. - /// - /// See [`ConfigBuilderExt::with_platform_verifier()`]. - #[cfg(all( - any(feature = "ring", feature = "aws-lc-rs"), - feature = "rustls-platform-verifier" - ))] - pub fn with_platform_verifier(self) -> ConnectorBuilder<WantsSchemes> { - self.try_with_platform_verifier() - .expect("failure to initialize platform verifier") - } - - /// Shorthand for using rustls' default crypto provider and other defaults, and - /// the platform verifier. - /// - /// See [`ConfigBuilderExt::with_platform_verifier()`]. - #[cfg(all( - any(feature = "ring", feature = "aws-lc-rs"), - feature = "rustls-platform-verifier" - ))] - pub fn try_with_platform_verifier( - self, - ) -> Result<ConnectorBuilder<WantsSchemes>, rustls::Error> { - Ok(self.with_tls_config( - ClientConfig::builder() - .try_with_platform_verifier()? - .with_no_client_auth(), - )) - } - - /// Shorthand for using a custom [`CryptoProvider`] and the platform verifier. - /// - /// See [`ConfigBuilderExt::with_platform_verifier()`]. - #[cfg(feature = "rustls-platform-verifier")] - pub fn with_provider_and_platform_verifier( - self, - provider: impl Into<Arc<CryptoProvider>>, - ) -> std::io::Result<ConnectorBuilder<WantsSchemes>> { - Ok(self.with_tls_config( - ClientConfig::builder_with_provider(provider.into()) - .with_safe_default_protocol_versions() - .and_then(|builder| builder.try_with_platform_verifier()) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))? - .with_no_client_auth(), - )) - } - - /// Shorthand for using rustls' default crypto provider and safe defaults, with - /// native roots. - /// - /// See [`ConfigBuilderExt::with_native_roots`] - #[cfg(all( - any(feature = "ring", feature = "aws-lc-rs"), - feature = "rustls-native-certs" - ))] - pub fn with_native_roots(self) -> std::io::Result<ConnectorBuilder<WantsSchemes>> { - Ok(self.with_tls_config( - ClientConfig::builder() - .with_native_roots()? - .with_no_client_auth(), - )) - } - - /// Shorthand for using a custom [`CryptoProvider`] and native roots - /// - /// See [`ConfigBuilderExt::with_native_roots`] - #[cfg(feature = "rustls-native-certs")] - pub fn with_provider_and_native_roots( - self, - provider: impl Into<Arc<CryptoProvider>>, - ) -> std::io::Result<ConnectorBuilder<WantsSchemes>> { - Ok(self.with_tls_config( - ClientConfig::builder_with_provider(provider.into()) - .with_safe_default_protocol_versions() - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))? - .with_native_roots()? - .with_no_client_auth(), - )) - } - - /// Shorthand for using rustls' default crypto provider and its - /// safe defaults. - /// - /// See [`ConfigBuilderExt::with_webpki_roots`] - #[cfg(all(any(feature = "ring", feature = "aws-lc-rs"), feature = "webpki-roots"))] - pub fn with_webpki_roots(self) -> ConnectorBuilder<WantsSchemes> { - self.with_tls_config( - ClientConfig::builder() - .with_webpki_roots() - .with_no_client_auth(), - ) - } - - /// Shorthand for using a custom [`CryptoProvider`], Rustls' safe default - /// protocol versions and Mozilla roots - /// - /// See [`ConfigBuilderExt::with_webpki_roots`] - #[cfg(feature = "webpki-roots")] - pub fn with_provider_and_webpki_roots( - self, - provider: impl Into<Arc<CryptoProvider>>, - ) -> Result<ConnectorBuilder<WantsSchemes>, rustls::Error> { - Ok(self.with_tls_config( - ClientConfig::builder_with_provider(provider.into()) - .with_safe_default_protocol_versions()? - .with_webpki_roots() - .with_no_client_auth(), - )) - } -} - -impl Default for ConnectorBuilder<WantsTlsConfig> { - fn default() -> Self { - Self::new() - } -} - -/// State of a builder that needs schemes (https:// and http://) to be -/// configured next -pub struct WantsSchemes { - tls_config: ClientConfig, -} - -impl ConnectorBuilder<WantsSchemes> { - /// Enforce the use of HTTPS when connecting - /// - /// Only URLs using the HTTPS scheme will be connectable. - pub fn https_only(self) -> ConnectorBuilder<WantsProtocols1> { - ConnectorBuilder(WantsProtocols1 { - tls_config: self.0.tls_config, - https_only: true, - server_name_resolver: None, - }) - } - - /// Allow both HTTPS and HTTP when connecting - /// - /// HTTPS URLs will be handled through rustls, - /// HTTP URLs will be handled by the lower-level connector. - pub fn https_or_http(self) -> ConnectorBuilder<WantsProtocols1> { - ConnectorBuilder(WantsProtocols1 { - tls_config: self.0.tls_config, - https_only: false, - server_name_resolver: None, - }) - } -} - -/// State of a builder that needs to have some protocols (HTTP1 or later) -/// enabled next -/// -/// No protocol has been enabled at this point. -pub struct WantsProtocols1 { - tls_config: ClientConfig, - https_only: bool, - server_name_resolver: Option<Arc<dyn ResolveServerName + Sync + Send>>, -} - -impl WantsProtocols1 { - fn wrap_connector<H>(self, conn: H) -> HttpsConnector<H> { - HttpsConnector { - force_https: self.https_only, - http: conn, - tls_config: std::sync::Arc::new(self.tls_config), - server_name_resolver: self - .server_name_resolver - .unwrap_or_else(|| Arc::new(DefaultServerNameResolver::default())), - } - } - - fn build(self) -> HttpsConnector<HttpConnector> { - let mut http = HttpConnector::new(); - // HttpConnector won't enforce scheme, but HttpsConnector will - http.enforce_http(false); - self.wrap_connector(http) - } -} - -impl ConnectorBuilder<WantsProtocols1> { - /// Enable HTTP1 - /// - /// This needs to be called explicitly, no protocol is enabled by default - #[cfg(feature = "http1")] - pub fn enable_http1(self) -> ConnectorBuilder<WantsProtocols2> { - ConnectorBuilder(WantsProtocols2 { inner: self.0 }) - } - - /// Enable HTTP2 - /// - /// This needs to be called explicitly, no protocol is enabled by default - #[cfg(feature = "http2")] - pub fn enable_http2(mut self) -> ConnectorBuilder<WantsProtocols3> { - self.0.tls_config.alpn_protocols = vec![b"h2".to_vec()]; - ConnectorBuilder(WantsProtocols3 { - inner: self.0, - enable_http1: false, - }) - } - - /// Enable all HTTP versions built into this library (enabled with Cargo features) - /// - /// For now, this could enable both HTTP 1 and 2, depending on active features. - /// In the future, other supported versions will be enabled as well. - #[cfg(feature = "http2")] - pub fn enable_all_versions(mut self) -> ConnectorBuilder<WantsProtocols3> { - #[cfg(feature = "http1")] - let alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; - #[cfg(not(feature = "http1"))] - let alpn_protocols = vec![b"h2".to_vec()]; - - self.0.tls_config.alpn_protocols = alpn_protocols; - ConnectorBuilder(WantsProtocols3 { - inner: self.0, - enable_http1: cfg!(feature = "http1"), - }) - } - - /// Override server name for the TLS stack - /// - /// By default, for each connection hyper-rustls will extract host portion - /// of the destination URL and verify that server certificate contains - /// this value. - /// - /// If this method is called, hyper-rustls will instead use this resolver - /// to compute the value used to verify the server certificate. - pub fn with_server_name_resolver( - mut self, - resolver: impl ResolveServerName + 'static + Sync + Send, - ) -> Self { - self.0.server_name_resolver = Some(Arc::new(resolver)); - self - } - - /// Override server name for the TLS stack - /// - /// By default, for each connection hyper-rustls will extract host portion - /// of the destination URL and verify that server certificate contains - /// this value. - /// - /// If this method is called, hyper-rustls will instead verify that server - /// certificate contains `override_server_name`. Domain name included in - /// the URL will not affect certificate validation. - #[deprecated( - since = "0.27.1", - note = "use Self::with_server_name_resolver with FixedServerNameResolver instead" - )] - pub fn with_server_name(self, mut override_server_name: String) -> Self { - // remove square brackets around IPv6 address. - if let Some(trimmed) = override_server_name - .strip_prefix('[') - .and_then(|s| s.strip_suffix(']')) - { - override_server_name = trimmed.to_string(); - } - - self.with_server_name_resolver(move |_: &_| { - ServerName::try_from(override_server_name.clone()) - }) - } -} - -/// State of a builder with HTTP1 enabled, that may have some other -/// protocols (HTTP2 or later) enabled next -/// -/// At this point a connector can be built, see -/// [`build`](ConnectorBuilder<WantsProtocols2>::build) and -/// [`wrap_connector`](ConnectorBuilder<WantsProtocols2>::wrap_connector). -pub struct WantsProtocols2 { - inner: WantsProtocols1, -} - -impl ConnectorBuilder<WantsProtocols2> { - /// Enable HTTP2 - /// - /// This needs to be called explicitly, no protocol is enabled by default - #[cfg(feature = "http2")] - pub fn enable_http2(mut self) -> ConnectorBuilder<WantsProtocols3> { - self.0.inner.tls_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()]; - ConnectorBuilder(WantsProtocols3 { - inner: self.0.inner, - enable_http1: true, - }) - } - - /// This builds an [`HttpsConnector`] built on hyper's default [`HttpConnector`] - pub fn build(self) -> HttpsConnector<HttpConnector> { - self.0.inner.build() - } - - /// This wraps an arbitrary low-level connector into an [`HttpsConnector`] - pub fn wrap_connector<H>(self, conn: H) -> HttpsConnector<H> { - // HTTP1-only, alpn_protocols stays empty - // HttpConnector doesn't have a way to say http1-only; - // its connection pool may still support HTTP2 - // though it won't be used - self.0.inner.wrap_connector(conn) - } -} - -/// State of a builder with HTTP2 (and possibly HTTP1) enabled -/// -/// At this point a connector can be built, see -/// [`build`](ConnectorBuilder<WantsProtocols3>::build) and -/// [`wrap_connector`](ConnectorBuilder<WantsProtocols3>::wrap_connector). -#[cfg(feature = "http2")] -pub struct WantsProtocols3 { - inner: WantsProtocols1, - // ALPN is built piecemeal without the need to read back this field - #[allow(dead_code)] - enable_http1: bool, -} - -#[cfg(feature = "http2")] -impl ConnectorBuilder<WantsProtocols3> { - /// This builds an [`HttpsConnector`] built on hyper's default [`HttpConnector`] - pub fn build(self) -> HttpsConnector<HttpConnector> { - self.0.inner.build() - } - - /// This wraps an arbitrary low-level connector into an [`HttpsConnector`] - pub fn wrap_connector<H>(self, conn: H) -> HttpsConnector<H> { - // If HTTP1 is disabled, we can set http2_only - // on the Client (a higher-level object that uses the connector) - // client.http2_only(!self.0.enable_http1); - self.0.inner.wrap_connector(conn) - } -} - -#[cfg(test)] -mod tests { - // Typical usage - #[test] - #[cfg(all(feature = "webpki-roots", feature = "http1"))] - fn test_builder() { - ensure_global_state(); - let _connector = super::ConnectorBuilder::new() - .with_webpki_roots() - .https_only() - .enable_http1() - .build(); - } - - #[test] - #[cfg(feature = "http1")] - #[should_panic(expected = "ALPN protocols should not be pre-defined")] - fn test_reject_predefined_alpn() { - ensure_global_state(); - let roots = rustls::RootCertStore::empty(); - let mut config_with_alpn = rustls::ClientConfig::builder() - .with_root_certificates(roots) - .with_no_client_auth(); - config_with_alpn.alpn_protocols = vec![b"fancyprotocol".to_vec()]; - let _connector = super::ConnectorBuilder::new() - .with_tls_config(config_with_alpn) - .https_only() - .enable_http1() - .build(); - } - - #[test] - #[cfg(all(feature = "http1", feature = "http2"))] - fn test_alpn() { - ensure_global_state(); - let roots = rustls::RootCertStore::empty(); - let tls_config = rustls::ClientConfig::builder() - .with_root_certificates(roots) - .with_no_client_auth(); - let connector = super::ConnectorBuilder::new() - .with_tls_config(tls_config.clone()) - .https_only() - .enable_http1() - .build(); - assert!(connector - .tls_config - .alpn_protocols - .is_empty()); - let connector = super::ConnectorBuilder::new() - .with_tls_config(tls_config.clone()) - .https_only() - .enable_http2() - .build(); - assert_eq!(&connector.tls_config.alpn_protocols, &[b"h2".to_vec()]); - let connector = super::ConnectorBuilder::new() - .with_tls_config(tls_config.clone()) - .https_only() - .enable_http1() - .enable_http2() - .build(); - assert_eq!( - &connector.tls_config.alpn_protocols, - &[b"h2".to_vec(), b"http/1.1".to_vec()] - ); - let connector = super::ConnectorBuilder::new() - .with_tls_config(tls_config) - .https_only() - .enable_all_versions() - .build(); - assert_eq!( - &connector.tls_config.alpn_protocols, - &[b"h2".to_vec(), b"http/1.1".to_vec()] - ); - } - - #[test] - #[cfg(all(not(feature = "http1"), feature = "http2"))] - fn test_alpn_http2() { - let roots = rustls::RootCertStore::empty(); - let tls_config = rustls::ClientConfig::builder() - .with_safe_defaults() - .with_root_certificates(roots) - .with_no_client_auth(); - let connector = super::ConnectorBuilder::new() - .with_tls_config(tls_config.clone()) - .https_only() - .enable_http2() - .build(); - assert_eq!(&connector.tls_config.alpn_protocols, &[b"h2".to_vec()]); - let connector = super::ConnectorBuilder::new() - .with_tls_config(tls_config) - .https_only() - .enable_all_versions() - .build(); - assert_eq!(&connector.tls_config.alpn_protocols, &[b"h2".to_vec()]); - } - - fn ensure_global_state() { - #[cfg(feature = "ring")] - let _ = rustls::crypto::ring::default_provider().install_default(); - #[cfg(feature = "aws-lc-rs")] - let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); - } -} diff --git a/vendor/hyper-rustls/src/lib.rs b/vendor/hyper-rustls/src/lib.rs deleted file mode 100644 index 89e355ae..00000000 --- a/vendor/hyper-rustls/src/lib.rs +++ /dev/null @@ -1,76 +0,0 @@ -//! # hyper-rustls -//! -//! A pure-Rust HTTPS connector for [hyper](https://hyper.rs), based on -//! [Rustls](https://github.com/rustls/rustls). -//! -//! ## Example client -//! -//! ```no_run -//! # #[cfg(all(feature = "rustls-native-certs", feature = "http1"))] -//! # fn main() { -//! use http::StatusCode; -//! use http_body_util::Empty; -//! use hyper::body::Bytes; -//! use hyper_util::client::legacy::Client; -//! use hyper_util::rt::TokioExecutor; -//! -//! let mut rt = tokio::runtime::Runtime::new().unwrap(); -//! let url = ("https://hyper.rs").parse().unwrap(); -//! let https = hyper_rustls::HttpsConnectorBuilder::new() -//! .with_native_roots() -//! .expect("no native root CA certificates found") -//! .https_only() -//! .enable_http1() -//! .build(); -//! -//! let client: Client<_, Empty<Bytes>> = Client::builder(TokioExecutor::new()).build(https); -//! -//! let res = rt.block_on(client.get(url)).unwrap(); -//! assert_eq!(res.status(), StatusCode::OK); -//! # } -//! # #[cfg(not(all(feature = "rustls-native-certs", feature = "http1")))] -//! # fn main() {} -//! ``` - -#![warn(missing_docs, unreachable_pub, clippy::use_self)] -#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] - -mod config; -mod connector; -mod stream; - -#[cfg(feature = "logging")] -mod log { - #[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))] - pub(crate) use log::debug; - #[cfg(feature = "rustls-native-certs")] - pub(crate) use log::warn; -} - -#[cfg(not(feature = "logging"))] -mod log { - #[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))] - macro_rules! debug ( ($($tt:tt)*) => {{}} ); - #[cfg(any(feature = "rustls-native-certs", feature = "webpki-roots"))] - pub(crate) use debug; - #[cfg(feature = "rustls-native-certs")] - macro_rules! warn_ ( ($($tt:tt)*) => {{}} ); - #[cfg(feature = "rustls-native-certs")] - pub(crate) use warn_ as warn; -} - -pub use crate::config::ConfigBuilderExt; -pub use crate::connector::builder::ConnectorBuilder as HttpsConnectorBuilder; -pub use crate::connector::{ - DefaultServerNameResolver, FixedServerNameResolver, HttpsConnector, ResolveServerName, -}; -pub use crate::stream::MaybeHttpsStream; - -/// The various states of the [`HttpsConnectorBuilder`] -pub mod builderstates { - #[cfg(feature = "http2")] - pub use crate::connector::builder::WantsProtocols3; - pub use crate::connector::builder::{ - WantsProtocols1, WantsProtocols2, WantsSchemes, WantsTlsConfig, - }; -} diff --git a/vendor/hyper-rustls/src/stream.rs b/vendor/hyper-rustls/src/stream.rs deleted file mode 100644 index f08e7b1b..00000000 --- a/vendor/hyper-rustls/src/stream.rs +++ /dev/null @@ -1,121 +0,0 @@ -// Copied from hyperium/hyper-tls#62e3376/src/stream.rs -use std::fmt; -use std::io; -use std::pin::Pin; -use std::task::{Context, Poll}; - -use hyper::rt; -use hyper_util::client::legacy::connect::{Connected, Connection}; - -use hyper_util::rt::TokioIo; -use tokio_rustls::client::TlsStream; - -/// A stream that might be protected with TLS. -#[allow(clippy::large_enum_variant)] -pub enum MaybeHttpsStream<T> { - /// A stream over plain text. - Http(T), - /// A stream protected with TLS. - Https(TokioIo<TlsStream<TokioIo<T>>>), -} - -impl<T: rt::Read + rt::Write + Connection + Unpin> Connection for MaybeHttpsStream<T> { - fn connected(&self) -> Connected { - match self { - Self::Http(s) => s.connected(), - Self::Https(s) => { - let (tcp, tls) = s.inner().get_ref(); - if tls.alpn_protocol() == Some(b"h2") { - tcp.inner().connected().negotiated_h2() - } else { - tcp.inner().connected() - } - } - } - } -} - -impl<T: fmt::Debug> fmt::Debug for MaybeHttpsStream<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Self::Http(..) => f.pad("Http(..)"), - Self::Https(..) => f.pad("Https(..)"), - } - } -} - -impl<T> From<T> for MaybeHttpsStream<T> { - fn from(inner: T) -> Self { - Self::Http(inner) - } -} - -impl<T> From<TlsStream<TokioIo<T>>> for MaybeHttpsStream<T> { - fn from(inner: TlsStream<TokioIo<T>>) -> Self { - Self::Https(TokioIo::new(inner)) - } -} - -impl<T: rt::Read + rt::Write + Unpin> rt::Read for MaybeHttpsStream<T> { - #[inline] - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context, - buf: rt::ReadBufCursor<'_>, - ) -> Poll<Result<(), io::Error>> { - match Pin::get_mut(self) { - Self::Http(s) => Pin::new(s).poll_read(cx, buf), - Self::Https(s) => Pin::new(s).poll_read(cx, buf), - } - } -} - -impl<T: rt::Write + rt::Read + Unpin> rt::Write for MaybeHttpsStream<T> { - #[inline] - fn poll_write( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll<Result<usize, io::Error>> { - match Pin::get_mut(self) { - Self::Http(s) => Pin::new(s).poll_write(cx, buf), - Self::Https(s) => Pin::new(s).poll_write(cx, buf), - } - } - - #[inline] - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { - match Pin::get_mut(self) { - Self::Http(s) => Pin::new(s).poll_flush(cx), - Self::Https(s) => Pin::new(s).poll_flush(cx), - } - } - - #[inline] - fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { - match Pin::get_mut(self) { - Self::Http(s) => Pin::new(s).poll_shutdown(cx), - Self::Https(s) => Pin::new(s).poll_shutdown(cx), - } - } - - #[inline] - fn is_write_vectored(&self) -> bool { - match self { - Self::Http(s) => s.is_write_vectored(), - Self::Https(s) => s.is_write_vectored(), - } - } - - #[inline] - fn poll_write_vectored( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - bufs: &[io::IoSlice<'_>], - ) -> Poll<Result<usize, io::Error>> { - match Pin::get_mut(self) { - Self::Http(s) => Pin::new(s).poll_write_vectored(cx, bufs), - Self::Https(s) => Pin::new(s).poll_write_vectored(cx, bufs), - } - } -} |
