1use crate::connector::ConnectorOptions;
15use crate::rustls::pki_types::{CertificateDer, PrivateKeyDer};
16use crate::tls;
17use rustls_pki_types::pem::PemObject;
18use std::io::{self, BufReader, ErrorKind};
19use std::path::PathBuf;
20use tokio_rustls::rustls::{ClientConfig, RootCertStore};
21
22pub(crate) async fn load_certs(path: PathBuf) -> io::Result<Vec<CertificateDer<'static>>> {
27 tokio::task::spawn_blocking(move || {
28 let file = std::fs::File::open(path)?;
29 let reader = BufReader::new(file);
30 CertificateDer::pem_reader_iter(reader)
31 .collect::<Result<Vec<_>, _>>()
32 .map_err(|e| {
33 io::Error::new(
34 ErrorKind::InvalidData,
35 format!("could not load certificates: {}", e),
36 )
37 })
38 })
39 .await?
40}
41
42pub(crate) async fn load_key(path: PathBuf) -> io::Result<PrivateKeyDer<'static>> {
45 tokio::task::spawn_blocking(move || {
46 let file = std::fs::File::open(path)?;
47 let mut reader = BufReader::new(file);
48 PrivateKeyDer::from_pem_reader(&mut reader).map_err(|e| {
49 io::Error::new(
50 ErrorKind::InvalidData,
51 format!("could not load private key: {}", e),
52 )
53 })
54 })
55 .await?
56}
57
58pub(crate) async fn config_tls(options: &ConnectorOptions) -> io::Result<ClientConfig> {
59 let mut root_store = RootCertStore::empty();
60 if options.tls_client_config.is_some() || options.certificates.is_empty() {
62 let certs_result = rustls_native_certs::load_native_certs();
63 if !certs_result.errors.is_empty() {
64 let errors = certs_result
65 .errors
66 .into_iter()
67 .map(|e| e.to_string())
68 .collect::<Vec<String>>()
69 .join("\n");
70 return Err(io::Error::other(format!(
71 "could not load platform certs: {errors}"
72 )));
73 }
74 root_store.add_parsable_certificates(certs_result.certs);
75 }
76
77 let tls_config = {
79 if let Some(config) = &options.tls_client_config {
80 Ok(config.to_owned())
81 } else {
82 for cafile in &options.certificates {
84 let trust_anchors = load_certs(cafile.to_owned())
85 .await?
86 .into_iter()
87 .map(|cert| {
88 rustls_webpki::anchor_from_trusted_cert(&cert).map(|ta| ta.to_owned())
89 })
90 .collect::<Result<Vec<_>, rustls_webpki::Error>>()
91 .map_err(|err| {
92 io::Error::new(
93 ErrorKind::InvalidInput,
94 format!("could not load certs: {err}"),
95 )
96 })?;
97 root_store.extend(trust_anchors);
98 }
99 let builder = ClientConfig::builder().with_root_certificates(root_store);
100 if let Some(cert) = options.client_cert.clone() {
101 if let Some(key) = options.client_key.clone() {
102 let key = tls::load_key(key).await?;
103 let cert = tls::load_certs(cert).await?;
104 builder
105 .with_client_auth_cert(cert, key)
106 .map_err(|_| io::Error::other("could not add certificate or key"))
107 } else {
108 Err(io::Error::other("found certificate, but no key"))
109 }
110 } else {
111 Ok(builder.with_no_client_auth())
113 }
114 }
115 }?;
116 Ok(tls_config)
117}