ldap_client/
tls_config.rs1use std::sync::Arc;
7
8use rustls::ClientConfig;
9use rustls_pki_types::{CertificateDer, PrivateKeyDer};
10
11pub enum TrustAnchors {
13 SystemPlusAdditional(Vec<CertificateDer<'static>>),
15 ExplicitOnly(Vec<CertificateDer<'static>>),
17}
18
19#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
21pub enum TlsVersion {
22 Tls12,
24 #[default]
26 Tls13,
27}
28
29pub struct TlsConfig {
32 pub trust_anchors: TrustAnchors,
33 pub client_cert: Option<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)>,
34 pub min_tls_version: TlsVersion,
35 #[cfg(feature = "danger-disable-verify")]
36 pub danger_disable_verification: bool,
37}
38
39impl Default for TlsConfig {
40 fn default() -> Self {
41 Self {
42 trust_anchors: TrustAnchors::SystemPlusAdditional(Vec::new()),
43 client_cert: None,
44 min_tls_version: TlsVersion::default(),
45 #[cfg(feature = "danger-disable-verify")]
46 danger_disable_verification: false,
47 }
48 }
49}
50
51impl TlsConfig {
52 pub fn build(self) -> Result<Arc<ClientConfig>, rustls::Error> {
54 #[cfg(feature = "danger-disable-verify")]
55 if self.danger_disable_verification {
56 let config = crate::conn::danger_no_verify_tls_config();
57 return Ok(Arc::new(config));
58 }
59
60 let root_store = match self.trust_anchors {
61 TrustAnchors::SystemPlusAdditional(extra) => {
62 let mut store = rustls::RootCertStore::from_iter(
63 webpki_roots::TLS_SERVER_ROOTS.iter().cloned(),
64 );
65 for cert in extra {
66 store.add(cert)?;
67 }
68 store
69 }
70 TrustAnchors::ExplicitOnly(certs) => {
71 let mut store = rustls::RootCertStore::empty();
72 for cert in certs {
73 store.add(cert)?;
74 }
75 store
76 }
77 };
78
79 let versions: &[&rustls::SupportedProtocolVersion] = match self.min_tls_version {
80 TlsVersion::Tls13 => &[&rustls::version::TLS13],
81 TlsVersion::Tls12 => &[&rustls::version::TLS12, &rustls::version::TLS13],
82 };
83
84 let builder = ClientConfig::builder_with_protocol_versions(versions)
85 .with_root_certificates(root_store);
86
87 let config = match self.client_cert {
88 Some((certs, key)) => builder.with_client_auth_cert(certs, key)?,
89 None => builder.with_no_client_auth(),
90 };
91
92 Ok(Arc::new(config))
93 }
94}