1#![cfg(feature = "client")]
2use hickory_proto::rr::rdata::TLSA;
3use openssl::ssl::SslOptions;
4use std::sync::Arc;
5use tokio::time::{Duration, Instant};
6use tokio_rustls::rustls::client::danger::ServerCertVerifier;
7use tokio_rustls::rustls::crypto::{aws_lc_rs as provider, CryptoProvider};
8use tokio_rustls::rustls::{ClientConfig, SupportedCipherSuite};
9use tokio_rustls::TlsConnector;
10
11#[derive(Clone, Debug)]
12struct RustlsCacheKey {
13 insecure: bool,
14 rustls_cipher_suites: Vec<SupportedCipherSuite>,
15}
16
17impl std::cmp::PartialEq for RustlsCacheKey {
26 fn eq(&self, other: &RustlsCacheKey) -> bool {
27 if self.insecure != other.insecure {
28 return false;
29 }
30 self.rustls_cipher_suites
31 .iter()
32 .map(|s| s.suite())
33 .eq(other.rustls_cipher_suites.iter().map(|s| s.suite()))
34 }
35}
36
37impl std::cmp::Eq for RustlsCacheKey {}
38
39impl std::hash::Hash for RustlsCacheKey {
40 fn hash<H>(&self, hasher: &mut H)
41 where
42 H: std::hash::Hasher,
43 {
44 self.insecure.hash(hasher);
45 for suite in &self.rustls_cipher_suites {
46 suite.suite().as_str().hash(hasher);
47 }
48 }
49}
50
51lruttl::declare_cache! {
52static RUSTLS_CACHE: LruCacheWithTtl<RustlsCacheKey, Arc<ClientConfig>>::new("rfc5321_rustls_config", 32);
53}
54
55impl RustlsCacheKey {
56 fn get(&self) -> Option<Arc<ClientConfig>> {
57 RUSTLS_CACHE.get(self)
58 }
59
60 async fn set(self, value: Arc<ClientConfig>) {
61 RUSTLS_CACHE
62 .insert(
63 self,
64 value,
65 Instant::now() + Duration::from_secs(15 * 60),
70 )
71 .await;
72 }
73}
74
75#[derive(Debug, Clone, Default)]
76pub struct TlsOptions {
77 pub insecure: bool,
78 pub alt_name: Option<String>,
79 pub dane_tlsa: Vec<TLSA>,
80 pub prefer_openssl: bool,
81 pub openssl_cipher_list: Option<String>,
82 pub openssl_cipher_suites: Option<String>,
83 pub openssl_options: Option<SslOptions>,
84 pub rustls_cipher_suites: Vec<SupportedCipherSuite>,
85}
86
87impl TlsOptions {
88 pub async fn build_tls_connector(&self) -> TlsConnector {
95 let key = RustlsCacheKey {
96 insecure: self.insecure,
97 rustls_cipher_suites: self.rustls_cipher_suites.clone(),
98 };
99
100 if let Some(config) = key.get() {
101 return TlsConnector::from(config);
102 }
103 let cipher_suites = if self.rustls_cipher_suites.is_empty() {
104 provider::DEFAULT_CIPHER_SUITES
105 } else {
106 &self.rustls_cipher_suites
107 };
108
109 let provider = Arc::new(CryptoProvider {
110 cipher_suites: cipher_suites.to_vec(),
111 ..provider::default_provider()
112 });
113
114 let verifier: Arc<dyn ServerCertVerifier> = if self.insecure {
115 Arc::new(danger::NoCertificateVerification::new(provider.clone()))
116 } else {
117 Arc::new(rustls_platform_verifier::Verifier::new().with_provider(provider.clone()))
118 };
119
120 let config = Arc::new(
121 ClientConfig::builder_with_provider(provider)
122 .with_protocol_versions(tokio_rustls::rustls::DEFAULT_VERSIONS)
123 .expect("inconsistent cipher-suite/versions selected")
124 .dangerous()
125 .with_custom_certificate_verifier(verifier)
126 .with_no_client_auth(),
127 );
128 key.set(config.clone()).await;
129
130 TlsConnector::from(config)
131 }
132}
133
134mod danger {
135 use std::sync::Arc;
136 use tokio_rustls::rustls::client::danger::{
137 HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier,
138 };
139 use tokio_rustls::rustls::crypto::{
140 verify_tls12_signature, verify_tls13_signature, CryptoProvider,
141 };
142 use tokio_rustls::rustls::pki_types::{CertificateDer, ServerName, UnixTime};
143 use tokio_rustls::rustls::DigitallySignedStruct;
144
145 #[derive(Debug)]
146 pub struct NoCertificateVerification(Arc<CryptoProvider>);
147
148 impl NoCertificateVerification {
149 pub fn new(provider: Arc<CryptoProvider>) -> Self {
150 Self(provider)
151 }
152 }
153
154 impl ServerCertVerifier for NoCertificateVerification {
155 fn verify_server_cert(
156 &self,
157 _end_entity: &CertificateDer<'_>,
158 _intermediates: &[CertificateDer<'_>],
159 _server_name: &ServerName<'_>,
160 _ocsp: &[u8],
161 _now: UnixTime,
162 ) -> Result<ServerCertVerified, tokio_rustls::rustls::Error> {
163 Ok(ServerCertVerified::assertion())
164 }
165
166 fn verify_tls12_signature(
167 &self,
168 message: &[u8],
169 cert: &CertificateDer<'_>,
170 dss: &DigitallySignedStruct,
171 ) -> Result<HandshakeSignatureValid, tokio_rustls::rustls::Error> {
172 verify_tls12_signature(
173 message,
174 cert,
175 dss,
176 &self.0.signature_verification_algorithms,
177 )
178 }
179
180 fn verify_tls13_signature(
181 &self,
182 message: &[u8],
183 cert: &CertificateDer<'_>,
184 dss: &DigitallySignedStruct,
185 ) -> Result<HandshakeSignatureValid, tokio_rustls::rustls::Error> {
186 verify_tls13_signature(
187 message,
188 cert,
189 dss,
190 &self.0.signature_verification_algorithms,
191 )
192 }
193
194 fn supported_verify_schemes(&self) -> Vec<tokio_rustls::rustls::SignatureScheme> {
195 self.0.signature_verification_algorithms.supported_schemes()
196 }
197 }
198}