1mod traits;
7
8pub use traits::*;
9
10use hickory_proto::rr::rdata::tlsa::{CertUsage, Matching, Selector};
11use hickory_proto::rr::rdata::TLSA;
12use openssl::pkey::PKey;
13use openssl::ssl::{DaneMatchType, DaneSelector, DaneUsage, SslOptions};
14use openssl::x509::X509;
15use rustls::pki_types::{CertificateDer, PrivateKeyDer};
16use rustls_pemfile::certs;
17use std::io::BufReader;
18use std::sync::Arc;
19use thiserror::Error;
20use tokio::time::{Duration, Instant};
21use tokio_rustls::rustls::client::danger::ServerCertVerifier;
22use tokio_rustls::rustls::crypto::{aws_lc_rs as provider, CryptoProvider};
23use tokio_rustls::rustls::{ClientConfig, SupportedCipherSuite};
24use tokio_rustls::TlsConnector;
25
26#[derive(Error, Debug, Clone)]
28pub enum OpensslConnectorError {
29 #[error("SSL Error: {0}")]
30 SslErrorStack(String),
31 #[error("No usable DANE TLSA records for {hostname}: {tlsa:?}")]
32 NoUsableDaneTlsa { hostname: String, tlsa: Vec<TLSA> },
33}
34
35impl From<openssl::error::ErrorStack> for OpensslConnectorError {
36 fn from(err: openssl::error::ErrorStack) -> Self {
37 OpensslConnectorError::SslErrorStack(err.to_string())
38 }
39}
40
41#[derive(Clone, Debug)]
42struct RustlsCacheKey {
43 insecure: bool,
44 certificate_from_pem: Option<Arc<Box<[u8]>>>,
45 private_key_from_pem: Option<Arc<Box<[u8]>>>,
46 rustls_cipher_suites: Vec<SupportedCipherSuite>,
47}
48
49impl std::cmp::PartialEq for RustlsCacheKey {
58 fn eq(&self, other: &RustlsCacheKey) -> bool {
59 if self.insecure != other.insecure {
60 return false;
61 }
62 self.rustls_cipher_suites
63 .iter()
64 .map(|s| s.suite())
65 .eq(other.rustls_cipher_suites.iter().map(|s| s.suite()))
66 }
67}
68
69impl std::cmp::Eq for RustlsCacheKey {}
70
71impl std::hash::Hash for RustlsCacheKey {
72 fn hash<H>(&self, hasher: &mut H)
73 where
74 H: std::hash::Hasher,
75 {
76 self.insecure.hash(hasher);
77 for suite in &self.rustls_cipher_suites {
78 suite.suite().as_str().hash(hasher);
79 }
80 if let Some(pem) = &self.certificate_from_pem {
81 pem.as_ref().clone().into_vec().hash(hasher);
82 }
83 if let Some(pem) = &self.private_key_from_pem {
84 pem.as_ref().clone().into_vec().hash(hasher);
85 }
86 }
87}
88
89lruttl::declare_cache! {
90static RUSTLS_CACHE: LruCacheWithTtl<RustlsCacheKey, Arc<ClientConfig>>::new("rustls_client_config", 32);
92}
93
94impl RustlsCacheKey {
95 fn get(&self) -> Option<Arc<ClientConfig>> {
96 RUSTLS_CACHE.get(self)
97 }
98
99 async fn set(self, value: Arc<ClientConfig>) {
100 RUSTLS_CACHE
101 .insert(
102 self,
103 value,
104 Instant::now() + Duration::from_secs(15 * 60),
109 )
110 .await;
111 }
112}
113
114#[derive(Debug, Clone, Default)]
115pub struct TlsOptions {
116 pub insecure: bool,
117 pub alt_name: Option<String>,
118 pub dane_tlsa: Vec<TLSA>,
119 pub prefer_openssl: bool,
120 pub certificate_from_pem: Option<Arc<Box<[u8]>>>,
121 pub private_key_from_pem: Option<Arc<Box<[u8]>>>,
122 pub openssl_cipher_list: Option<String>,
123 pub openssl_cipher_suites: Option<String>,
124 pub openssl_options: Option<SslOptions>,
125 pub rustls_cipher_suites: Vec<SupportedCipherSuite>,
126}
127
128impl TlsOptions {
129 pub async fn build_tls_connector(&self) -> anyhow::Result<TlsConnector> {
136 let key = RustlsCacheKey {
137 insecure: self.insecure,
138 rustls_cipher_suites: self.rustls_cipher_suites.clone(),
139 certificate_from_pem: self.certificate_from_pem.clone(),
140 private_key_from_pem: self.private_key_from_pem.clone(),
141 };
142 if let Some(config) = key.get() {
143 return Ok(TlsConnector::from(config));
144 }
145 let cipher_suites = if self.rustls_cipher_suites.is_empty() {
146 provider::DEFAULT_CIPHER_SUITES
147 } else {
148 &self.rustls_cipher_suites
149 };
150
151 let provider = Arc::new(CryptoProvider {
152 cipher_suites: cipher_suites.to_vec(),
153 ..provider::default_provider()
154 });
155
156 let verifier: Arc<dyn ServerCertVerifier> = if self.insecure {
157 Arc::new(danger::NoCertificateVerification::new(provider.clone()))
158 } else {
159 Arc::new(rustls_platform_verifier::Verifier::new().with_provider(provider.clone()))
160 };
161
162 let rustls_certificate = self.load_tls_cert().await?;
163 let rustls_private_key = self.load_private_key().await?;
164
165 let builder = ClientConfig::builder_with_provider(provider.clone())
166 .with_protocol_versions(tokio_rustls::rustls::DEFAULT_VERSIONS)
167 .expect("inconsistent cipher-suite/versions selected")
168 .dangerous()
169 .with_custom_certificate_verifier(verifier.clone());
170 let config = match (&rustls_certificate, &rustls_private_key) {
171 (Some(certs), Some(key)) => builder
172 .clone()
173 .with_client_auth_cert(certs.as_ref().clone(), key.as_ref().clone_key()),
174 _ => Ok(builder.with_no_client_auth()),
175 }?;
176
177 let config = Arc::new(config);
178 key.set(config.clone()).await;
179
180 Ok(TlsConnector::from(config))
181 }
182
183 async fn load_tls_cert(&self) -> std::io::Result<Option<Arc<Vec<CertificateDer<'static>>>>> {
184 match &self.certificate_from_pem {
185 Some(pem) => {
186 let data = pem.as_ref().clone().into_vec();
187 let mut reader = BufReader::new(data.as_slice());
188 let certs = certs(&mut reader)
189 .into_iter()
190 .map(|r| r.map(CertificateDer::into_owned))
191 .collect::<Result<Vec<CertificateDer<'static>>, std::io::Error>>()?;
192 Ok(Some(Arc::new(certs)))
193 }
194 None => return Ok(None),
195 }
196 }
197
198 async fn load_private_key(&self) -> std::io::Result<Option<Arc<PrivateKeyDer<'static>>>> {
199 match &self.private_key_from_pem {
200 Some(pem) => {
201 let data = pem.as_ref().clone().into_vec();
202
203 let pkcs8_keys: Vec<PrivateKeyDer<'static>> = {
205 let mut reader = BufReader::new(data.as_slice());
206 rustls_pemfile::pkcs8_private_keys(&mut reader)
207 .into_iter()
208 .map(|r| r.map(PrivateKeyDer::Pkcs8))
209 .collect::<Result<Vec<PrivateKeyDer<'static>>, std::io::Error>>()?
210 };
211
212 if !pkcs8_keys.is_empty() {
213 return Ok(pkcs8_keys.into_iter().next().map(Arc::new));
214 }
215
216 let rsa_keys: Vec<PrivateKeyDer<'static>> = {
218 let mut reader = BufReader::new(data.as_slice());
219 rustls_pemfile::rsa_private_keys(&mut reader)
220 .into_iter()
221 .map(|r| r.map(PrivateKeyDer::Pkcs1))
222 .collect::<Result<Vec<PrivateKeyDer<'static>>, std::io::Error>>()?
223 };
224
225 if !rsa_keys.is_empty() {
226 return Ok(rsa_keys.into_iter().next().map(Arc::new));
227 }
228
229 let ec_keys: Vec<PrivateKeyDer<'static>> = {
231 let mut reader = BufReader::new(data.as_slice());
232 rustls_pemfile::ec_private_keys(&mut reader)
233 .into_iter()
234 .map(|r| r.map(PrivateKeyDer::Sec1))
235 .collect::<Result<Vec<PrivateKeyDer<'static>>, std::io::Error>>()?
236 };
237
238 if !ec_keys.is_empty() {
239 return Ok(ec_keys.into_iter().next().map(Arc::new));
240 }
241
242 Err(std::io::Error::new(
243 std::io::ErrorKind::InvalidData,
244 "No private key found in PEM file",
245 ))
246 }
247 None => return Ok(None),
248 }
249 }
250
251 pub fn build_openssl_connector(
254 &self,
255 hostname: &str,
256 ) -> Result<openssl::ssl::ConnectConfiguration, OpensslConnectorError> {
257 tracing::trace!("build_openssl_connector for {hostname}");
258 let mut builder =
259 openssl::ssl::SslConnector::builder(openssl::ssl::SslMethod::tls_client())?;
260
261 if let (Some(cert_data), Some(key_data)) =
262 (&self.certificate_from_pem, &self.private_key_from_pem)
263 {
264 let cert = X509::from_pem(cert_data)?;
265 builder.set_certificate(&cert)?;
266
267 let key = PKey::private_key_from_pem(key_data)?;
268 builder.set_private_key(&key)?;
269
270 builder.check_private_key()?;
271 }
272
273 if let Some(list) = &self.openssl_cipher_list {
274 builder.set_cipher_list(list)?;
275 }
276
277 if let Some(suites) = &self.openssl_cipher_suites {
278 builder.set_ciphersuites(suites)?;
279 }
280
281 if let Some(options) = &self.openssl_options {
282 builder.clear_options(SslOptions::all());
283 builder.set_options(*options);
284 }
285
286 if self.insecure {
287 builder.set_verify(openssl::ssl::SslVerifyMode::NONE);
288 }
289
290 if !self.dane_tlsa.is_empty() {
291 builder.dane_enable()?;
292 builder.set_no_dane_ee_namechecks();
293 }
294
295 let connector = builder.build();
296
297 let mut config = connector.configure()?;
298
299 if !self.dane_tlsa.is_empty() {
300 config.dane_enable(hostname)?;
301 let mut any_usable = false;
302 for tlsa in &self.dane_tlsa {
303 let usable = config.dane_tlsa_add(
304 match tlsa.cert_usage() {
305 CertUsage::PkixTa => DaneUsage::PKIX_TA,
306 CertUsage::PkixEe => DaneUsage::PKIX_EE,
307 CertUsage::DaneTa => DaneUsage::DANE_TA,
308 CertUsage::DaneEe => DaneUsage::DANE_EE,
309 CertUsage::Unassigned(n) => DaneUsage::from_raw(n),
310 CertUsage::Private => DaneUsage::PRIV_CERT,
311 },
312 match tlsa.selector() {
313 Selector::Full => DaneSelector::CERT,
314 Selector::Spki => DaneSelector::SPKI,
315 Selector::Unassigned(n) => DaneSelector::from_raw(n),
316 Selector::Private => DaneSelector::PRIV_SEL,
317 },
318 match tlsa.matching() {
319 Matching::Raw => DaneMatchType::FULL,
320 Matching::Sha256 => DaneMatchType::SHA2_256,
321 Matching::Sha512 => DaneMatchType::SHA2_512,
322 Matching::Unassigned(n) => DaneMatchType::from_raw(n),
323 Matching::Private => DaneMatchType::PRIV_MATCH,
324 },
325 tlsa.cert_data(),
326 )?;
327
328 tracing::trace!("build_dane_connector usable={usable} {tlsa:?}");
329 if usable {
330 any_usable = true;
331 }
332 }
333
334 if !any_usable {
335 return Err(OpensslConnectorError::NoUsableDaneTlsa {
336 hostname: hostname.to_string(),
337 tlsa: self.dane_tlsa.clone(),
338 });
339 }
340 }
341
342 Ok(config)
343 }
344}
345
346mod danger {
347 use std::sync::Arc;
348 use tokio_rustls::rustls::client::danger::{
349 HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier,
350 };
351 use tokio_rustls::rustls::crypto::{
352 verify_tls12_signature, verify_tls13_signature, CryptoProvider,
353 };
354 use tokio_rustls::rustls::pki_types::{CertificateDer, ServerName, UnixTime};
355 use tokio_rustls::rustls::DigitallySignedStruct;
356
357 #[derive(Debug)]
358 pub struct NoCertificateVerification(Arc<CryptoProvider>);
359
360 impl NoCertificateVerification {
361 pub fn new(provider: Arc<CryptoProvider>) -> Self {
362 Self(provider)
363 }
364 }
365
366 impl ServerCertVerifier for NoCertificateVerification {
367 fn verify_server_cert(
368 &self,
369 _end_entity: &CertificateDer<'_>,
370 _intermediates: &[CertificateDer<'_>],
371 _server_name: &ServerName<'_>,
372 _ocsp: &[u8],
373 _now: UnixTime,
374 ) -> Result<ServerCertVerified, tokio_rustls::rustls::Error> {
375 Ok(ServerCertVerified::assertion())
376 }
377
378 fn verify_tls12_signature(
379 &self,
380 message: &[u8],
381 cert: &CertificateDer<'_>,
382 dss: &DigitallySignedStruct,
383 ) -> Result<HandshakeSignatureValid, tokio_rustls::rustls::Error> {
384 verify_tls12_signature(
385 message,
386 cert,
387 dss,
388 &self.0.signature_verification_algorithms,
389 )
390 }
391
392 fn verify_tls13_signature(
393 &self,
394 message: &[u8],
395 cert: &CertificateDer<'_>,
396 dss: &DigitallySignedStruct,
397 ) -> Result<HandshakeSignatureValid, tokio_rustls::rustls::Error> {
398 verify_tls13_signature(
399 message,
400 cert,
401 dss,
402 &self.0.signature_verification_algorithms,
403 )
404 }
405
406 fn supported_verify_schemes(&self) -> Vec<tokio_rustls::rustls::SignatureScheme> {
407 self.0.signature_verification_algorithms.supported_schemes()
408 }
409 }
410}