1use crate::connector::ConnectorOptions;
15use crate::tls;
16use rustls_webpki::types::{CertificateDer, PrivateKeyDer};
17use std::io::{self, BufReader, ErrorKind};
18use std::path::PathBuf;
19use tokio_rustls::rustls::{ClientConfig, RootCertStore};
20
21pub(crate) async fn load_certs(path: PathBuf) -> io::Result<Vec<CertificateDer<'static>>> {
26 tokio::task::spawn_blocking(move || {
27 let file = std::fs::File::open(path)?;
28 let mut reader = BufReader::new(file);
29 rustls_pemfile::certs(&mut reader).collect::<io::Result<Vec<_>>>()
30 })
31 .await?
32}
33
34pub(crate) async fn load_key(path: PathBuf) -> io::Result<PrivateKeyDer<'static>> {
37 tokio::task::spawn_blocking(move || {
38 let file = std::fs::File::open(path)?;
39 let mut reader = BufReader::new(file);
40 rustls_pemfile::private_key(&mut reader)?.ok_or_else(|| {
41 io::Error::new(ErrorKind::NotFound, "could not find client key in the path")
42 })
43 })
44 .await?
45}
46
47pub(crate) async fn config_tls(options: &ConnectorOptions) -> io::Result<ClientConfig> {
48 let mut root_store = RootCertStore::empty();
49 if options.tls_client_config.is_some() || options.certificates.is_empty() {
51 let certs_iter = rustls_native_certs::load_native_certs().map_err(|err| {
52 io::Error::new(
53 ErrorKind::Other,
54 format!("could not load platform certs: {err}"),
55 )
56 })?;
57 root_store.add_parsable_certificates(certs_iter);
58 }
59
60 let tls_config = {
62 if let Some(config) = &options.tls_client_config {
63 Ok(config.to_owned())
64 } else {
65 for cafile in &options.certificates {
67 let trust_anchors = load_certs(cafile.to_owned())
68 .await?
69 .into_iter()
70 .map(|cert| {
71 rustls_webpki::anchor_from_trusted_cert(&cert).map(|ta| ta.to_owned())
72 })
73 .collect::<Result<Vec<_>, rustls_webpki::Error>>()
74 .map_err(|err| {
75 io::Error::new(
76 ErrorKind::InvalidInput,
77 format!("could not load certs: {err}"),
78 )
79 })?;
80 root_store.extend(trust_anchors);
81 }
82 let builder = ClientConfig::builder().with_root_certificates(root_store);
83 if let Some(cert) = options.client_cert.clone() {
84 if let Some(key) = options.client_key.clone() {
85 let key = tls::load_key(key).await?;
86 let cert = tls::load_certs(cert).await?;
87 builder.with_client_auth_cert(cert, key).map_err(|_| {
88 io::Error::new(ErrorKind::Other, "could not add certificate or key")
89 })
90 } else {
91 Err(io::Error::new(
92 ErrorKind::Other,
93 "found certificate, but no key",
94 ))
95 }
96 } else {
97 Ok(builder.with_no_client_auth())
99 }
100 }
101 }?;
102 Ok(tls_config)
103}