Support to rustls 0.20 (#1388)
This commit is contained in:
		| @@ -17,8 +17,6 @@ use hyper::client::ResponseFuture; | ||||
| #[cfg(feature = "native-tls-crate")] | ||||
| use native_tls_crate::TlsConnector; | ||||
| use pin_project_lite::pin_project; | ||||
| #[cfg(feature = "rustls-tls-native-roots")] | ||||
| use rustls::RootCertStore; | ||||
| use std::future::Future; | ||||
| use std::pin::Pin; | ||||
| use std::task::{Context, Poll}; | ||||
| @@ -322,68 +320,94 @@ impl ClientBuilder { | ||||
|                 TlsBackend::Rustls => { | ||||
|                     use crate::tls::NoVerifier; | ||||
|  | ||||
|                     let mut tls = rustls::ClientConfig::new(); | ||||
|                     match config.http_version_pref { | ||||
|                         HttpVersionPref::Http1 => { | ||||
|                             tls.set_protocols(&["http/1.1".into()]); | ||||
|                         } | ||||
|                         HttpVersionPref::Http2 => { | ||||
|                             tls.set_protocols(&["h2".into()]); | ||||
|                         } | ||||
|                         HttpVersionPref::All => { | ||||
|                             tls.set_protocols(&["h2".into(), "http/1.1".into()]); | ||||
|                         } | ||||
|                     } | ||||
|                     #[cfg(feature = "rustls-tls-webpki-roots")] | ||||
|                     if config.tls_built_in_root_certs { | ||||
|                         tls.root_store | ||||
|                             .add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS); | ||||
|                     } | ||||
|                     #[cfg(feature = "rustls-tls-native-roots")] | ||||
|                     if config.tls_built_in_root_certs { | ||||
|                         let roots_slice = NATIVE_ROOTS.as_ref().unwrap().roots.as_slice(); | ||||
|                         tls.root_store.roots.extend_from_slice(roots_slice); | ||||
|                     // Set root certificates. | ||||
|                     let mut root_cert_store = rustls::RootCertStore::empty(); | ||||
|                     for cert in config.root_certs { | ||||
|                         cert.add_to_rustls(&mut root_cert_store)?; | ||||
|                     } | ||||
|  | ||||
|                     #[cfg(feature = "rustls-tls-webpki-roots")] | ||||
|                     if config.tls_built_in_root_certs { | ||||
|                         use rustls::OwnedTrustAnchor; | ||||
|  | ||||
|                         let trust_anchors = | ||||
|                             webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|trust_anchor| { | ||||
|                                 OwnedTrustAnchor::from_subject_spki_name_constraints( | ||||
|                                     trust_anchor.subject, | ||||
|                                     trust_anchor.spki, | ||||
|                                     trust_anchor.name_constraints, | ||||
|                                 ) | ||||
|                             }); | ||||
|  | ||||
|                         root_cert_store.add_server_trust_anchors(trust_anchors); | ||||
|                     } | ||||
|  | ||||
|                     #[cfg(feature = "rustls-tls-native-roots")] | ||||
|                     if config.tls_built_in_root_certs { | ||||
|                         for cert in rustls_native_certs::load_native_certs() | ||||
|                             .map_err(crate::error::builder)? | ||||
|                         { | ||||
|                             root_cert_store | ||||
|                                 .add(&rustls::Certificate(cert.0)) | ||||
|                                 .map_err(crate::error::builder)? | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     // Set TLS versions. | ||||
|                     let mut versions = rustls::ALL_VERSIONS.to_vec(); | ||||
|  | ||||
|                     if let Some(min_tls_version) = config.min_tls_version { | ||||
|                         versions.retain(|&supported_version| { | ||||
|                             match tls::Version::from_rustls(supported_version.version) { | ||||
|                                 Some(version) => version >= min_tls_version, | ||||
|                                 // Assume it's so new we don't know about it, allow it | ||||
|                                 // (as of writing this is unreachable) | ||||
|                                 None => true, | ||||
|                             } | ||||
|                         }); | ||||
|                     } | ||||
|  | ||||
|                     if let Some(max_tls_version) = config.max_tls_version { | ||||
|                         versions.retain(|&supported_version| { | ||||
|                             match tls::Version::from_rustls(supported_version.version) { | ||||
|                                 Some(version) => version <= max_tls_version, | ||||
|                                 None => false, | ||||
|                             } | ||||
|                         }); | ||||
|                     } | ||||
|  | ||||
|                     // Build TLS config | ||||
|                     let config_builder = rustls::ClientConfig::builder() | ||||
|                         .with_safe_default_cipher_suites() | ||||
|                         .with_safe_default_kx_groups() | ||||
|                         .with_protocol_versions(&versions) | ||||
|                         .map_err(crate::error::builder)? | ||||
|                         .with_root_certificates(root_cert_store); | ||||
|  | ||||
|                     // Finalize TLS config | ||||
|                     let mut tls = if let Some(id) = config.identity { | ||||
|                         id.add_to_rustls(config_builder)? | ||||
|                     } else { | ||||
|                         config_builder.with_no_client_auth() | ||||
|                     }; | ||||
|  | ||||
|                     // Certificate verifier | ||||
|                     if !config.certs_verification { | ||||
|                         tls.dangerous() | ||||
|                             .set_certificate_verifier(Arc::new(NoVerifier)); | ||||
|                     } | ||||
|  | ||||
|                     for cert in config.root_certs { | ||||
|                         cert.add_to_rustls(&mut tls)?; | ||||
|                     } | ||||
|  | ||||
|                     if let Some(id) = config.identity { | ||||
|                         id.add_to_rustls(&mut tls)?; | ||||
|                     } | ||||
|  | ||||
|                     // rustls does not support TLS versions <1.2 and this is unlikely to change. | ||||
|                     // https://github.com/rustls/rustls/issues/33 | ||||
|  | ||||
|                     // As of writing, TLS 1.2 and 1.3 are the only implemented versions and are both | ||||
|                     // enabled by default. | ||||
|                     // rustls 0.20 will add ALL_VERSIONS and DEFAULT_VERSIONS. That will enable a more | ||||
|                     // sophisticated approach. | ||||
|                     // For now we assume the default tls.versions matches the future ALL_VERSIONS and | ||||
|                     // act based on that. | ||||
|  | ||||
|                     if let Some(min_tls_version) = config.min_tls_version { | ||||
|                         tls.versions | ||||
|                             .retain(|&version| match tls::Version::from_rustls(version) { | ||||
|                                 Some(version) => version >= min_tls_version, | ||||
|                                 // Assume it's so new we don't know about it, allow it | ||||
|                                 // (as of writing this is unreachable) | ||||
|                                 None => true, | ||||
|                             }); | ||||
|                     } | ||||
|  | ||||
|                     if let Some(max_tls_version) = config.max_tls_version { | ||||
|                         tls.versions | ||||
|                             .retain(|&version| match tls::Version::from_rustls(version) { | ||||
|                                 Some(version) => version <= max_tls_version, | ||||
|                                 None => false, | ||||
|                             }); | ||||
|                     // ALPN protocol | ||||
|                     match config.http_version_pref { | ||||
|                         HttpVersionPref::Http1 => { | ||||
|                             tls.alpn_protocols = vec!["http/1.1".into()]; | ||||
|                         } | ||||
|                         HttpVersionPref::Http2 => { | ||||
|                             tls.alpn_protocols = vec!["h2".into()]; | ||||
|                         } | ||||
|                         HttpVersionPref::All => { | ||||
|                             tls.alpn_protocols = vec!["h2".into(), "http/1.1".into()]; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     Connector::new_rustls_tls( | ||||
| @@ -1848,12 +1872,6 @@ fn add_cookie_header(headers: &mut HeaderMap, cookie_store: &dyn cookie::CookieS | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature = "rustls-tls-native-roots")] | ||||
| lazy_static! { | ||||
|     static ref NATIVE_ROOTS: std::io::Result<RootCertStore> = | ||||
|         rustls_native_certs::load_native_certs().map_err(|e| e.1); | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     #[tokio::test] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user