Separate default-tls and native-tls features (#749)
To allow for the default-tls to change to a different backend by default, this adds a new `native-tls` optional feature. Any TLS feature that was only available using native-tls now requires the `native-tls` feature to be enabled.
This commit is contained in:
		
							
								
								
									
										3
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -55,6 +55,7 @@ jobs: | ||||
|           - windows / stable-i686-gnu | ||||
|           - "feat.: default-tls disabled" | ||||
|           - "feat.: rustls-tls" | ||||
|           - "feat.: native-tls" | ||||
|           - "feat.: default-tls and rustls-tls" | ||||
|           - "feat.: cookies" | ||||
|           - "feat.: blocking" | ||||
| @@ -100,6 +101,8 @@ jobs: | ||||
|             features: "--no-default-features" | ||||
|           - name: "feat.: rustls-tls" | ||||
|             features: "--no-default-features --features rustls-tls" | ||||
|           - name: "feat.: native-tls" | ||||
|             features: "--features native-tls" | ||||
|           - name: "feat.: default-tls and rustls-tls" | ||||
|             features: "--features rustls-tls" | ||||
|           - name: "feat.: cookies" | ||||
|   | ||||
							
								
								
									
										16
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Cargo.toml
									
									
									
									
									
								
							| @@ -18,12 +18,15 @@ all-features = true | ||||
| [features] | ||||
| default = ["default-tls"] | ||||
|  | ||||
| tls = [] | ||||
| # Note: this doesn't enable the 'native-tls' feature, which adds specific | ||||
| # functionality for it. | ||||
| default-tls = ["hyper-tls", "native-tls-crate", "__tls", "tokio-tls"] | ||||
|  | ||||
| default-tls = ["hyper-tls", "native-tls", "tls", "tokio-tls"] | ||||
| default-tls-vendored = ["default-tls", "native-tls/vendored"] | ||||
| # Enables native-tls specific functionality not available by default. | ||||
| native-tls = ["default-tls"] | ||||
| native-tls-vendored = ["native-tls", "native-tls-crate/vendored"] | ||||
|  | ||||
| rustls-tls = ["hyper-rustls", "tokio-rustls", "webpki-roots", "rustls", "tls"] | ||||
| rustls-tls = ["hyper-rustls", "tokio-rustls", "webpki-roots", "rustls", "__tls"] | ||||
|  | ||||
| blocking = ["futures-channel", "futures-util/io", "tokio/rt-threaded", "tokio/rt-core"] | ||||
|  | ||||
| @@ -40,6 +43,9 @@ stream = [] | ||||
| # Internal (PRIVATE!) features used to aid testing. | ||||
| # Don't rely on these whatsoever. They may disappear at anytime. | ||||
|  | ||||
| # Enables common types used for TLS. Useless on its own. | ||||
| __tls = [] | ||||
|  | ||||
| # When enabled, disable using the cached SYS_PROXIES. | ||||
| __internal_proxy_sys_no_cache = [] | ||||
|  | ||||
| @@ -74,7 +80,7 @@ serde_urlencoded = "0.6.1" | ||||
|  | ||||
| ## default-tls | ||||
| hyper-tls = { version = "0.4", optional = true } | ||||
| native-tls = { version = "0.2", optional = true } | ||||
| native-tls-crate = { version = "0.2", optional = true, package = "native-tls" } | ||||
| tokio-tls = { version = "0.3.0", optional = true } | ||||
|  | ||||
| # rustls-tls | ||||
|   | ||||
| @@ -13,8 +13,8 @@ use http::header::{ | ||||
| use http::Uri; | ||||
| use http::uri::Scheme; | ||||
| use hyper::client::ResponseFuture; | ||||
| #[cfg(feature = "default-tls")] | ||||
| use native_tls::TlsConnector; | ||||
| #[cfg(feature = "native-tls-crate")] | ||||
| use native_tls_crate::TlsConnector; | ||||
| use std::future::Future; | ||||
| use std::pin::Pin; | ||||
| use std::task::{Context, Poll}; | ||||
| @@ -30,9 +30,9 @@ use crate::connect::Connector; | ||||
| use crate::cookie; | ||||
| use crate::into_url::{expect_uri, try_uri}; | ||||
| use crate::redirect::{self, remove_sensitive_headers}; | ||||
| #[cfg(feature = "tls")] | ||||
| #[cfg(feature = "__tls")] | ||||
| use crate::tls::TlsBackend; | ||||
| #[cfg(feature = "tls")] | ||||
| #[cfg(feature = "__tls")] | ||||
| use crate::{Certificate, Identity}; | ||||
| use crate::{IntoUrl, Method, Proxy, StatusCode, Url}; | ||||
|  | ||||
| @@ -60,22 +60,22 @@ struct Config { | ||||
|     // NOTE: When adding a new field, update `fmt::Debug for ClientBuilder` | ||||
|     gzip: bool, | ||||
|     headers: HeaderMap, | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     #[cfg(feature = "native-tls")] | ||||
|     hostname_verification: bool, | ||||
|     #[cfg(feature = "tls")] | ||||
|     #[cfg(feature = "__tls")] | ||||
|     certs_verification: bool, | ||||
|     connect_timeout: Option<Duration>, | ||||
|     max_idle_per_host: usize, | ||||
|     #[cfg(feature = "tls")] | ||||
|     #[cfg(feature = "__tls")] | ||||
|     identity: Option<Identity>, | ||||
|     proxies: Vec<Proxy>, | ||||
|     auto_sys_proxy: bool, | ||||
|     redirect_policy: redirect::Policy, | ||||
|     referer: bool, | ||||
|     timeout: Option<Duration>, | ||||
|     #[cfg(feature = "tls")] | ||||
|     #[cfg(feature = "__tls")] | ||||
|     root_certs: Vec<Certificate>, | ||||
|     #[cfg(feature = "tls")] | ||||
|     #[cfg(feature = "__tls")] | ||||
|     tls: TlsBackend, | ||||
|     http2_only: bool, | ||||
|     http1_title_case_headers: bool, | ||||
| @@ -106,9 +106,9 @@ impl ClientBuilder { | ||||
|             config: Config { | ||||
|                 gzip: cfg!(feature = "gzip"), | ||||
|                 headers, | ||||
|                 #[cfg(feature = "default-tls")] | ||||
|                 #[cfg(feature = "native-tls")] | ||||
|                 hostname_verification: true, | ||||
|                 #[cfg(feature = "tls")] | ||||
|                 #[cfg(feature = "__tls")] | ||||
|                 certs_verification: true, | ||||
|                 connect_timeout: None, | ||||
|                 max_idle_per_host: std::usize::MAX, | ||||
| @@ -117,11 +117,11 @@ impl ClientBuilder { | ||||
|                 redirect_policy: redirect::Policy::default(), | ||||
|                 referer: true, | ||||
|                 timeout: None, | ||||
|                 #[cfg(feature = "tls")] | ||||
|                 #[cfg(feature = "__tls")] | ||||
|                 root_certs: Vec::new(), | ||||
|                 #[cfg(feature = "tls")] | ||||
|                 #[cfg(feature = "__tls")] | ||||
|                 identity: None, | ||||
|                 #[cfg(feature = "tls")] | ||||
|                 #[cfg(feature = "__tls")] | ||||
|                 tls: TlsBackend::default(), | ||||
|                 http2_only: false, | ||||
|                 http1_title_case_headers: false, | ||||
| @@ -150,25 +150,34 @@ impl ClientBuilder { | ||||
|         let proxies = Arc::new(proxies); | ||||
|  | ||||
|         let mut connector = { | ||||
|             #[cfg(feature = "tls")] | ||||
|             #[cfg(feature = "__tls")] | ||||
|             fn user_agent(headers: &HeaderMap) -> HeaderValue { | ||||
|                 headers[USER_AGENT].clone() | ||||
|             } | ||||
|  | ||||
|             #[cfg(feature = "tls")] | ||||
|             #[cfg(feature = "__tls")] | ||||
|             match config.tls { | ||||
|                 #[cfg(feature = "default-tls")] | ||||
|                 TlsBackend::Default => { | ||||
|                     let mut tls = TlsConnector::builder(); | ||||
|                     tls.danger_accept_invalid_hostnames(!config.hostname_verification); | ||||
|  | ||||
|                     #[cfg(feature = "native-tls")] | ||||
|                     { | ||||
|                         tls.danger_accept_invalid_hostnames(!config.hostname_verification); | ||||
|                     } | ||||
|  | ||||
|                     tls.danger_accept_invalid_certs(!config.certs_verification); | ||||
|  | ||||
|                     for cert in config.root_certs { | ||||
|                         cert.add_to_native_tls(&mut tls); | ||||
|                     } | ||||
|  | ||||
|                     if let Some(id) = config.identity { | ||||
|                         id.add_to_native_tls(&mut tls)?; | ||||
|  | ||||
|                     #[cfg(feature = "native-tls")] | ||||
|                     { | ||||
|                         if let Some(id) = config.identity { | ||||
|                             id.add_to_native_tls(&mut tls)?; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     Connector::new_default_tls( | ||||
| @@ -215,7 +224,7 @@ impl ClientBuilder { | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             #[cfg(not(feature = "tls"))] | ||||
|             #[cfg(not(feature = "__tls"))] | ||||
|             Connector::new(proxies.clone(), config.local_address, config.nodelay)? | ||||
|         }; | ||||
|  | ||||
| @@ -511,9 +520,9 @@ impl ClientBuilder { | ||||
|     /// | ||||
|     /// # Optional | ||||
|     /// | ||||
|     /// This requires the optional `default-tls` or `rustls-tls` feature to be | ||||
|     /// enabled. | ||||
|     #[cfg(feature = "tls")] | ||||
|     /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls` | ||||
|     /// feature to be enabled. | ||||
|     #[cfg(feature = "__tls")] | ||||
|     pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder { | ||||
|         self.config.root_certs.push(cert); | ||||
|         self | ||||
| @@ -523,9 +532,9 @@ impl ClientBuilder { | ||||
|     /// | ||||
|     /// # Optional | ||||
|     /// | ||||
|     /// This requires the optional `default-tls` or `rustls-tls` feature to be | ||||
|     /// This requires the optional `native-tls` or `rustls-tls` feature to be | ||||
|     /// enabled. | ||||
|     #[cfg(feature = "tls")] | ||||
|     #[cfg(feature = "__tls")] | ||||
|     pub fn identity(mut self, identity: Identity) -> ClientBuilder { | ||||
|         self.config.identity = Some(identity); | ||||
|         self | ||||
| @@ -544,8 +553,8 @@ impl ClientBuilder { | ||||
|     /// | ||||
|     /// # Optional | ||||
|     /// | ||||
|     /// This requires the optional `default-tls` feature to be enabled. | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     /// This requires the optional `native-tls` feature to be enabled. | ||||
|     #[cfg(feature = "native-tls")] | ||||
|     pub fn danger_accept_invalid_hostnames( | ||||
|         mut self, | ||||
|         accept_invalid_hostname: bool, | ||||
| @@ -568,9 +577,9 @@ impl ClientBuilder { | ||||
|     /// | ||||
|     /// # Optional | ||||
|     /// | ||||
|     /// This requires the optional `default-tls` or `rustls-tls` feature to be | ||||
|     /// enabled. | ||||
|     #[cfg(feature = "tls")] | ||||
|     /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls` | ||||
|     /// feature to be enabled. | ||||
|     #[cfg(feature = "__tls")] | ||||
|     pub fn danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder { | ||||
|         self.config.certs_verification = !accept_invalid_certs; | ||||
|         self | ||||
| @@ -583,9 +592,9 @@ impl ClientBuilder { | ||||
|     /// | ||||
|     /// # Optional | ||||
|     /// | ||||
|     /// This requires the optional `default-tls` feature to be enabled. | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     pub fn use_default_tls(mut self) -> ClientBuilder { | ||||
|     /// This requires the optional `native-tls` feature to be enabled. | ||||
|     #[cfg(feature = "native-tls")] | ||||
|     pub fn use_native_tls(mut self) -> ClientBuilder { | ||||
|         self.config.tls = TlsBackend::Default; | ||||
|         self | ||||
|     } | ||||
| @@ -888,21 +897,21 @@ impl Config { | ||||
|             f.field("tcp_nodelay", &true); | ||||
|         } | ||||
|  | ||||
|         #[cfg(feature = "default-tls")] | ||||
|         #[cfg(feature = "native-tls")] | ||||
|         { | ||||
|             if !self.hostname_verification { | ||||
|                 f.field("danger_accept_invalid_hostnames", &true); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #[cfg(feature = "tls")] | ||||
|         #[cfg(feature = "__tls")] | ||||
|         { | ||||
|             if !self.certs_verification { | ||||
|                 f.field("danger_accept_invalid_certs", &true); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         #[cfg(all(feature = "default-tls", feature = "rustls-tls"))] | ||||
|         #[cfg(all(feature = "native-tls-crate", feature = "rustls-tls"))] | ||||
|         { | ||||
|             f.field("tls_backend", &self.tls); | ||||
|         } | ||||
|   | ||||
| @@ -14,7 +14,7 @@ use super::request::{Request, RequestBuilder}; | ||||
| use super::response::Response; | ||||
| use super::wait; | ||||
| use crate::{async_impl, header, IntoUrl, Method, Proxy, redirect}; | ||||
| #[cfg(feature = "tls")] | ||||
| #[cfg(feature = "__tls")] | ||||
| use crate::{Certificate, Identity}; | ||||
|  | ||||
| /// A `Client` to make Requests with. | ||||
| @@ -331,45 +331,15 @@ impl ClientBuilder { | ||||
|     /// | ||||
|     /// # Optional | ||||
|     /// | ||||
|     /// This requires the optional `default-tls` or `rustls-tls` feature to be | ||||
|     /// enabled. | ||||
|     #[cfg(feature = "tls")] | ||||
|     /// This requires the optional `default-tls`, `native-tls`, or `rustls-tls` | ||||
|     /// feature to be enabled. | ||||
|     #[cfg(feature = "__tls")] | ||||
|     pub fn add_root_certificate(self, cert: Certificate) -> ClientBuilder { | ||||
|         self.with_inner(move |inner| inner.add_root_certificate(cert)) | ||||
|     } | ||||
|  | ||||
|     /// Sets the identity to be used for client certificate authentication. | ||||
|     /// | ||||
|     /// # Example | ||||
|     /// | ||||
|     /// ``` | ||||
|     /// # use std::fs::File; | ||||
|     /// # use std::io::Read; | ||||
|     /// # fn build_client() -> Result<(), Box<std::error::Error>> { | ||||
|     /// // read a local PKCS12 bundle | ||||
|     /// let mut buf = Vec::new(); | ||||
|     /// | ||||
|     /// #[cfg(feature = "default-tls")] | ||||
|     /// File::open("my-ident.pfx")?.read_to_end(&mut buf)?; | ||||
|     /// #[cfg(feature = "rustls-tls")] | ||||
|     /// File::open("my-ident.pem")?.read_to_end(&mut buf)?; | ||||
|     /// | ||||
|     /// #[cfg(feature = "default-tls")] | ||||
|     /// // create an Identity from the PKCS#12 archive | ||||
|     /// let pkcs12 = reqwest::Identity::from_pkcs12_der(&buf, "my-privkey-password")?; | ||||
|     /// #[cfg(feature = "rustls-tls")] | ||||
|     /// // create an Identity from the PEM file | ||||
|     /// let pkcs12 = reqwest::Identity::from_pem(&buf)?; | ||||
|     /// | ||||
|     /// // get a client builder | ||||
|     /// let client = reqwest::blocking::Client::builder() | ||||
|     ///     .identity(pkcs12) | ||||
|     ///     .build()?; | ||||
|     /// # drop(client); | ||||
|     /// # Ok(()) | ||||
|     /// # } | ||||
|     /// ``` | ||||
|     #[cfg(feature = "tls")] | ||||
|     #[cfg(feature = "__tls")] | ||||
|     pub fn identity(self, identity: Identity) -> ClientBuilder { | ||||
|         self.with_inner(move |inner| inner.identity(identity)) | ||||
|     } | ||||
| @@ -384,7 +354,11 @@ impl ClientBuilder { | ||||
|     /// hostname verification is not used, any valid certificate for any | ||||
|     /// site will be trusted for use from any other. This introduces a | ||||
|     /// significant vulnerability to man-in-the-middle attacks. | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     /// | ||||
|     /// # Optional | ||||
|     /// | ||||
|     /// This requires the optional `native-tls` feature to be enabled. | ||||
|     #[cfg(feature = "native-tls")] | ||||
|     pub fn danger_accept_invalid_hostnames(self, accept_invalid_hostname: bool) -> ClientBuilder { | ||||
|         self.with_inner(|inner| inner.danger_accept_invalid_hostnames(accept_invalid_hostname)) | ||||
|     } | ||||
| @@ -400,7 +374,7 @@ impl ClientBuilder { | ||||
|     /// will be trusted for use. This includes expired certificates. This | ||||
|     /// introduces significant vulnerabilities, and should only be used | ||||
|     /// as a last resort. | ||||
|     #[cfg(feature = "tls")] | ||||
|     #[cfg(feature = "__tls")] | ||||
|     pub fn danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder { | ||||
|         self.with_inner(|inner| inner.danger_accept_invalid_certs(accept_invalid_certs)) | ||||
|     } | ||||
| @@ -412,10 +386,10 @@ impl ClientBuilder { | ||||
|     /// | ||||
|     /// # Optional | ||||
|     /// | ||||
|     /// This requires the optional `default-tls` feature to be enabled. | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     pub fn use_default_tls(self) -> ClientBuilder { | ||||
|         self.with_inner(move |inner| inner.use_default_tls()) | ||||
|     /// This requires the optional `native-tls` feature to be enabled. | ||||
|     #[cfg(feature = "native-tls")] | ||||
|     pub fn use_native_tls(self) -> ClientBuilder { | ||||
|         self.with_inner(move |inner| inner.use_native_tls()) | ||||
|     } | ||||
|  | ||||
|     /// Force using the Rustls TLS backend. | ||||
|   | ||||
| @@ -3,9 +3,9 @@ use http::uri::{Scheme, Authority}; | ||||
| use http::Uri; | ||||
| use hyper::client::connect::{Connected, Connection}; | ||||
| use tokio::io::{AsyncRead, AsyncWrite}; | ||||
| #[cfg(feature = "default-tls")] | ||||
| use native_tls::{TlsConnector, TlsConnectorBuilder}; | ||||
| #[cfg(feature = "tls")] | ||||
| #[cfg(feature = "native-tls-crate")] | ||||
| use native_tls_crate::{TlsConnector, TlsConnectorBuilder}; | ||||
| #[cfg(feature = "__tls")] | ||||
| use http::header::HeaderValue; | ||||
| use bytes::{Buf, BufMut}; | ||||
|  | ||||
| @@ -38,15 +38,15 @@ pub(crate) struct Connector { | ||||
|     inner: Inner, | ||||
|     proxies: Arc<Vec<Proxy>>, | ||||
|     timeout: Option<Duration>, | ||||
|     #[cfg(feature = "tls")] | ||||
|     #[cfg(feature = "__tls")] | ||||
|     nodelay: bool, | ||||
|     #[cfg(feature = "tls")] | ||||
|     #[cfg(feature = "__tls")] | ||||
|     user_agent: HeaderValue, | ||||
| } | ||||
|  | ||||
| #[derive(Clone)] | ||||
| enum Inner { | ||||
|     #[cfg(not(feature = "tls"))] | ||||
|     #[cfg(not(feature = "__tls"))] | ||||
|     Http(HttpConnector), | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     DefaultTls(HttpConnector, TlsConnector), | ||||
| @@ -59,7 +59,7 @@ enum Inner { | ||||
| } | ||||
|  | ||||
| impl Connector { | ||||
|     #[cfg(not(feature = "tls"))] | ||||
|     #[cfg(not(feature = "__tls"))] | ||||
|     pub(crate) fn new<T>( | ||||
|         proxies: Arc<Vec<Proxy>>, | ||||
|         local_addr: T, | ||||
| @@ -199,7 +199,7 @@ impl Connector { | ||||
|                     Ok((Box::new(io) as Conn, connected)) | ||||
|                 } | ||||
|             } | ||||
|             #[cfg(not(feature = "tls"))] | ||||
|             #[cfg(not(feature = "__tls"))] | ||||
|             Inner::Http(_) => socks::connect(proxy, dst, dns), | ||||
|         } | ||||
|     } | ||||
| @@ -210,7 +210,7 @@ impl Connector { | ||||
|         is_proxy: bool, | ||||
|     ) -> Result<Conn, BoxError> { | ||||
|         match self.inner { | ||||
|             #[cfg(not(feature = "tls"))] | ||||
|             #[cfg(not(feature = "__tls"))] | ||||
|             Inner::Http(mut http) => { | ||||
|                 let io = http.call(dst).await?; | ||||
|                 Ok(Conn { | ||||
| @@ -281,7 +281,7 @@ impl Connector { | ||||
|         }; | ||||
|  | ||||
|  | ||||
|         #[cfg(feature = "tls")] | ||||
|         #[cfg(feature = "__tls")] | ||||
|         let auth = _auth; | ||||
|  | ||||
|         match &self.inner { | ||||
| @@ -352,7 +352,7 @@ impl Connector { | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|             #[cfg(not(feature = "tls"))] | ||||
|             #[cfg(not(feature = "__tls"))] | ||||
|             Inner::Http(_) => (), | ||||
|         } | ||||
|  | ||||
| @@ -510,7 +510,7 @@ impl AsyncWrite for Conn { | ||||
| pub(crate) type Connecting = | ||||
|     Pin<Box<dyn Future<Output = Result<Conn, BoxError>> + Send>>; | ||||
|  | ||||
| #[cfg(feature = "tls")] | ||||
| #[cfg(feature = "__tls")] | ||||
| async fn tunnel<T>( | ||||
|     mut conn: T, | ||||
|     host: String, | ||||
| @@ -586,7 +586,7 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "tls")] | ||||
| #[cfg(feature = "__tls")] | ||||
| fn tunnel_eof() -> io::Error { | ||||
|     io::Error::new( | ||||
|         io::ErrorKind::UnexpectedEof, | ||||
| @@ -834,7 +834,7 @@ mod socks { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "tls")] | ||||
| #[cfg(feature = "__tls")] | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use super::tunnel; | ||||
|   | ||||
							
								
								
									
										13
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/lib.rs
									
									
									
									
									
								
							| @@ -159,9 +159,11 @@ | ||||
| //! The following are a list of [Cargo features][cargo-features] that can be | ||||
| //! enabled or disabled: | ||||
| //! | ||||
| //! - **default-tls** *(enabled by default)*: Provides TLS support via the | ||||
| //!   `native-tls` library to connect over HTTPS. | ||||
| //! - **default-tls-vendored**: Enables the `vendored` feature of `native-tls`. | ||||
| //! - **default-tls** *(enabled by default)*: Provides TLS support to connect | ||||
| //!   over HTTPS. | ||||
| //! - **native-tls**: Enables TLS functionality provided by `native-tls`. | ||||
| //! - **native-tls-vendored**: Enables the `vendored` feature of `native-tls`. | ||||
| //! - **rustls-tls**: Enables TLS functionality provided by `rustls`. | ||||
| //! - **blocking**: Provides the [blocking][] client API. | ||||
| //! - **cookies**: Provides cookie session support. | ||||
| //! - **gzip**: Provides response body gzip decompression. | ||||
| @@ -179,7 +181,6 @@ | ||||
| //! [Proxy]: ./struct.Proxy.html | ||||
| //! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section | ||||
|  | ||||
| ////! - **rustls-tls**: Provides TLS support via the `rustls` library. | ||||
| ////! - **socks**: Provides SOCKS5 proxy support. | ||||
| ////! - **trust-dns**: Enables a trust-dns async resolver instead of default | ||||
| ////!   threadpool using `getaddrinfo`. | ||||
| @@ -278,7 +279,7 @@ if_hyper! { | ||||
|         multipart, Body, Client, ClientBuilder, Request, RequestBuilder, Response, ResponseBuilderExt, | ||||
|     }; | ||||
|     pub use self::proxy::Proxy; | ||||
|     #[cfg(feature = "tls")] | ||||
|     #[cfg(feature = "__tls")] | ||||
|     pub use self::tls::{Certificate, Identity}; | ||||
|  | ||||
|  | ||||
| @@ -292,7 +293,7 @@ if_hyper! { | ||||
|     //mod dns; | ||||
|     mod proxy; | ||||
|     pub mod redirect; | ||||
|     #[cfg(feature = "tls")] | ||||
|     #[cfg(feature = "__tls")] | ||||
|     mod tls; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										48
									
								
								src/tls.rs
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								src/tls.rs
									
									
									
									
									
								
							| @@ -4,11 +4,11 @@ use std::fmt; | ||||
| #[cfg(feature = "rustls-tls")] | ||||
| use tokio_rustls::webpki::DNSNameRef; | ||||
|  | ||||
| /// Represent a server X509 certificate. | ||||
| /// Represents a server X509 certificate. | ||||
| #[derive(Clone)] | ||||
| pub struct Certificate { | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     native: native_tls::Certificate, | ||||
|     #[cfg(feature = "native-tls-crate")] | ||||
|     native: native_tls_crate::Certificate, | ||||
|     #[cfg(feature = "rustls-tls")] | ||||
|     original: Cert, | ||||
| } | ||||
| @@ -20,14 +20,18 @@ enum Cert { | ||||
|     Pem(Vec<u8>), | ||||
| } | ||||
|  | ||||
| /// Represent a private key and X509 cert as a client certificate. | ||||
| /// Represents a private key and X509 cert as a client certificate. | ||||
| pub struct Identity { | ||||
|     #[cfg_attr( | ||||
|         not(any(feature = "native-tls", feature = "rustls-tls")), | ||||
|         allow(unused) | ||||
|     )] | ||||
|     inner: ClientCert, | ||||
| } | ||||
|  | ||||
| enum ClientCert { | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     Pkcs12(native_tls::Identity), | ||||
|     #[cfg(feature = "native-tls")] | ||||
|     Pkcs12(native_tls_crate::Identity), | ||||
|     #[cfg(feature = "rustls-tls")] | ||||
|     Pem { | ||||
|         key: rustls::PrivateKey, | ||||
| @@ -54,8 +58,8 @@ impl Certificate { | ||||
|     /// ``` | ||||
|     pub fn from_der(der: &[u8]) -> crate::Result<Certificate> { | ||||
|         Ok(Certificate { | ||||
|             #[cfg(feature = "default-tls")] | ||||
|             native: native_tls::Certificate::from_der(der).map_err(crate::error::builder)?, | ||||
|             #[cfg(feature = "native-tls-crate")] | ||||
|             native: native_tls_crate::Certificate::from_der(der).map_err(crate::error::builder)?, | ||||
|             #[cfg(feature = "rustls-tls")] | ||||
|             original: Cert::Der(der.to_owned()), | ||||
|         }) | ||||
| @@ -79,15 +83,15 @@ impl Certificate { | ||||
|     /// ``` | ||||
|     pub fn from_pem(pem: &[u8]) -> crate::Result<Certificate> { | ||||
|         Ok(Certificate { | ||||
|             #[cfg(feature = "default-tls")] | ||||
|             native: native_tls::Certificate::from_pem(pem).map_err(crate::error::builder)?, | ||||
|             #[cfg(feature = "native-tls-crate")] | ||||
|             native: native_tls_crate::Certificate::from_pem(pem).map_err(crate::error::builder)?, | ||||
|             #[cfg(feature = "rustls-tls")] | ||||
|             original: Cert::Pem(pem.to_owned()), | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     pub(crate) fn add_to_native_tls(self, tls: &mut native_tls::TlsConnectorBuilder) { | ||||
|     #[cfg(feature = "native-tls-crate")] | ||||
|     pub(crate) fn add_to_native_tls(self, tls: &mut native_tls_crate::TlsConnectorBuilder) { | ||||
|         tls.add_root_certificate(self.native); | ||||
|     } | ||||
|  | ||||
| @@ -147,11 +151,15 @@ impl Identity { | ||||
|     /// # Ok(()) | ||||
|     /// # } | ||||
|     /// ``` | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     /// | ||||
|     /// # Optional | ||||
|     /// | ||||
|     /// This requires the `native-tls` Cargo feature enabled. | ||||
|     #[cfg(feature = "native-tls")] | ||||
|     pub fn from_pkcs12_der(der: &[u8], password: &str) -> crate::Result<Identity> { | ||||
|         Ok(Identity { | ||||
|             inner: ClientCert::Pkcs12( | ||||
|                 native_tls::Identity::from_pkcs12(der, password).map_err(crate::error::builder)?, | ||||
|                 native_tls_crate::Identity::from_pkcs12(der, password).map_err(crate::error::builder)?, | ||||
|             ), | ||||
|         }) | ||||
|     } | ||||
| @@ -175,6 +183,10 @@ impl Identity { | ||||
|     /// # Ok(()) | ||||
|     /// # } | ||||
|     /// ``` | ||||
|     /// | ||||
|     /// # Optional | ||||
|     /// | ||||
|     /// This requires the `rustls-tls` Cargo feature enabled. | ||||
|     #[cfg(feature = "rustls-tls")] | ||||
|     pub fn from_pem(buf: &[u8]) -> crate::Result<Identity> { | ||||
|         use rustls::internal::pemfile; | ||||
| @@ -214,10 +226,10 @@ impl Identity { | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     #[cfg(feature = "native-tls")] | ||||
|     pub(crate) fn add_to_native_tls( | ||||
|         self, | ||||
|         tls: &mut native_tls::TlsConnectorBuilder, | ||||
|         tls: &mut native_tls_crate::TlsConnectorBuilder, | ||||
|     ) -> crate::Result<()> { | ||||
|         match self.inner { | ||||
|             ClientCert::Pkcs12(id) => { | ||||
| @@ -236,7 +248,7 @@ impl Identity { | ||||
|                 tls.set_single_client_cert(certs, key); | ||||
|                 Ok(()) | ||||
|             } | ||||
|             #[cfg(feature = "default-tls")] | ||||
|             #[cfg(feature = "native-tls")] | ||||
|             ClientCert::Pkcs12(..) => Err(crate::error::builder("incompatible TLS identity type")), | ||||
|         } | ||||
|     } | ||||
| @@ -308,7 +320,7 @@ mod tests { | ||||
|         Certificate::from_pem(b"not pem").unwrap_err(); | ||||
|     } | ||||
|  | ||||
|     #[cfg(feature = "default-tls")] | ||||
|     #[cfg(feature = "native-tls")] | ||||
|     #[test] | ||||
|     fn identity_from_pkcs12_der_invalid() { | ||||
|         Identity::from_pkcs12_der(b"not der", "nope").unwrap_err(); | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| #[cfg(feature = "tls")] | ||||
| #[cfg(feature = "__tls")] | ||||
| #[tokio::test] | ||||
| async fn test_badssl_modern() { | ||||
|     let text = reqwest::get("https://mozilla-modern.badssl.com/") | ||||
| @@ -29,7 +29,7 @@ async fn test_rustls_badssl_modern() { | ||||
|     assert!(text.contains("<title>mozilla-modern.badssl.com</title>")); | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "tls")] | ||||
| #[cfg(feature = "__tls")] | ||||
| #[tokio::test] | ||||
| async fn test_badssl_self_signed() { | ||||
|     let text = reqwest::Client::builder() | ||||
| @@ -47,7 +47,7 @@ async fn test_badssl_self_signed() { | ||||
|     assert!(text.contains("<title>self-signed.badssl.com</title>")); | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "default-tls")] | ||||
| #[cfg(feature = "native-tls")] | ||||
| #[tokio::test] | ||||
| async fn test_badssl_wrong_host() { | ||||
|     let text = reqwest::Client::builder() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user