mirror of
https://github.com/lldap/lldap.git
synced 2026-03-31 15:07:48 +01:00
refactor(server): migrate to rustls 0.23 and centralize TLS logic (#1389)
This commit upgrades the TLS stack to Rustls 0.23 Key changes: - Dependencies: Updated 'rustls' (v0.23), 'tokio-rustls' (v0.26), and 'actix-web' (v4.12.1). - Build Fix: Configured 'rustls' to use the 'ring' provider (disabling default 'aws-lc-rs') to ensure ARMv7 compatibility. - Refactor: Created 'server/src/tls.rs' to handle certificate loading (DRY). - LDAP: Updated 'ldap_server.rs' to use the new TLS module and Rustls APIs. - Healthcheck: Updated 'healthcheck.rs' to use Rustls 0.23 types.
This commit is contained in:
Generated
+65
-50
@@ -76,6 +76,7 @@ dependencies = [
|
||||
"actix-codec",
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-tls",
|
||||
"actix-utils",
|
||||
"base64 0.22.1",
|
||||
"bitflags 2.10.0",
|
||||
@@ -181,11 +182,11 @@ dependencies = [
|
||||
"futures-core",
|
||||
"impl-more",
|
||||
"pin-project-lite",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
"tokio-rustls 0.23.4",
|
||||
"tokio-rustls 0.26.4",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"webpki-roots 0.22.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -211,6 +212,7 @@ dependencies = [
|
||||
"actix-rt",
|
||||
"actix-server",
|
||||
"actix-service",
|
||||
"actix-tls",
|
||||
"actix-utils",
|
||||
"actix-web-codegen",
|
||||
"bytes",
|
||||
@@ -530,6 +532,28 @@ version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-rs"
|
||||
version = "1.15.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256"
|
||||
dependencies = [
|
||||
"aws-lc-sys",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-sys"
|
||||
version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c34dda4df7017c8db52132f0f8a2e0f8161649d15723ed63fc00c82d0f2081a"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cmake",
|
||||
"dunce",
|
||||
"fs_extra",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.76"
|
||||
@@ -788,6 +812,15 @@ version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.1.0"
|
||||
@@ -1284,6 +1317,12 @@ version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
|
||||
|
||||
[[package]]
|
||||
name = "dunce"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
@@ -1487,6 +1526,12 @@ version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619"
|
||||
|
||||
[[package]]
|
||||
name = "fs_extra"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
||||
|
||||
[[package]]
|
||||
name = "fslock"
|
||||
version = "0.2.1"
|
||||
@@ -2700,7 +2745,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"quoted_printable",
|
||||
"rustls 0.21.12",
|
||||
"rustls-pemfile",
|
||||
"rustls-pemfile 1.0.4",
|
||||
"serde",
|
||||
"socket2 0.4.10",
|
||||
"tokio",
|
||||
@@ -2814,8 +2859,9 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"rand_chacha 0.3.1",
|
||||
"reqwest 0.11.27",
|
||||
"rustls 0.20.9",
|
||||
"rustls-pemfile",
|
||||
"rustls 0.23.35",
|
||||
"rustls-pemfile 2.2.0",
|
||||
"rustls-pki-types",
|
||||
"sea-orm",
|
||||
"secstr",
|
||||
"serde",
|
||||
@@ -2826,7 +2872,7 @@ dependencies = [
|
||||
"thiserror 2.0.17",
|
||||
"time",
|
||||
"tokio",
|
||||
"tokio-rustls 0.23.4",
|
||||
"tokio-rustls 0.26.4",
|
||||
"tokio-stream",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
@@ -2838,7 +2884,7 @@ dependencies = [
|
||||
"url",
|
||||
"urlencoding",
|
||||
"uuid 1.19.0",
|
||||
"webpki-roots 0.22.6",
|
||||
"webpki-roots 0.26.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4066,7 +4112,7 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rustls 0.21.12",
|
||||
"rustls-pemfile",
|
||||
"rustls-pemfile 1.0.4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
@@ -4233,18 +4279,6 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.20.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring 0.16.20",
|
||||
"sct",
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.21.12"
|
||||
@@ -4263,6 +4297,7 @@ version = "0.23.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring 0.17.14",
|
||||
@@ -4293,6 +4328,15 @@ dependencies = [
|
||||
"base64 0.21.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "1.13.2"
|
||||
@@ -4329,6 +4373,7 @@ version = "0.103.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"ring 0.17.14",
|
||||
"rustls-pki-types",
|
||||
"untrusted 0.9.0",
|
||||
@@ -5297,17 +5342,6 @@ dependencies = [
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.23.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
|
||||
dependencies = [
|
||||
"rustls 0.20.9",
|
||||
"tokio",
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-rustls"
|
||||
version = "0.24.1"
|
||||
@@ -5880,25 +5914,6 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki"
|
||||
version = "0.22.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53"
|
||||
dependencies = [
|
||||
"ring 0.17.14",
|
||||
"untrusted 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
|
||||
dependencies = [
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.23.1"
|
||||
|
||||
+17
-9
@@ -18,7 +18,6 @@ actix-http = "3"
|
||||
actix-rt = "2"
|
||||
actix-server = "2"
|
||||
actix-service = "2"
|
||||
actix-web = "4.3"
|
||||
actix-web-httpauth = "0.8"
|
||||
anyhow = "*"
|
||||
async-trait = "0.1"
|
||||
@@ -35,12 +34,12 @@ jwt = "0.16"
|
||||
ldap3_proto = "0.6.0"
|
||||
log = "*"
|
||||
rand_chacha = "0.3"
|
||||
rustls-pemfile = "1"
|
||||
rustls-pemfile = "2"
|
||||
serde_json = "1"
|
||||
sha2 = "0.10"
|
||||
thiserror = "2"
|
||||
time = "0.3"
|
||||
tokio-rustls = "0.23"
|
||||
tokio-rustls = "0.26"
|
||||
tokio-stream = "*"
|
||||
tokio-util = "0.7"
|
||||
tracing = "*"
|
||||
@@ -48,7 +47,20 @@ tracing-actix-web = "0.7"
|
||||
tracing-attributes = "^0.1.21"
|
||||
tracing-log = "*"
|
||||
urlencoding = "2"
|
||||
webpki-roots = "0.22.2"
|
||||
webpki-roots = "0.26"
|
||||
|
||||
[dependencies.actix-web]
|
||||
features = ["rustls-0_23"]
|
||||
version = "4.12.1"
|
||||
|
||||
[dependencies.rustls]
|
||||
default-features = false
|
||||
features = ["ring", "logging", "std", "tls12"]
|
||||
version = "0.23"
|
||||
|
||||
[dependencies.rustls-pki-types]
|
||||
features = ["std"]
|
||||
version = "1"
|
||||
|
||||
[dependencies.chrono]
|
||||
features = ["serde"]
|
||||
@@ -145,7 +157,7 @@ features = ["smallvec", "chrono", "tokio"]
|
||||
version = "^0.1.6"
|
||||
|
||||
[dependencies.actix-tls]
|
||||
features = ["default", "rustls"]
|
||||
features = ["default", "rustls-0_23"]
|
||||
version = "3"
|
||||
|
||||
[dependencies.sea-orm]
|
||||
@@ -163,10 +175,6 @@ version = "0.11"
|
||||
default-features = false
|
||||
features = ["rustls-tls-webpki-roots"]
|
||||
|
||||
[dependencies.rustls]
|
||||
version = "0.20"
|
||||
features = ["dangerous_configuration"]
|
||||
|
||||
[dependencies.url]
|
||||
version = "2"
|
||||
features = ["serde"]
|
||||
|
||||
+79
-42
@@ -1,4 +1,4 @@
|
||||
use crate::{configuration::LdapsOptions, ldap_server::read_certificates};
|
||||
use crate::{configuration::LdapsOptions, tls};
|
||||
use anyhow::{Context, Result, anyhow, bail, ensure};
|
||||
use futures_util::SinkExt;
|
||||
use ldap3_proto::{
|
||||
@@ -8,6 +8,11 @@ use ldap3_proto::{
|
||||
LdapSearchScope,
|
||||
},
|
||||
};
|
||||
use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
|
||||
use rustls::crypto::{verify_tls12_signature, verify_tls13_signature};
|
||||
use rustls::pki_types::{CertificateDer, ServerName, UnixTime};
|
||||
use rustls::{DigitallySignedStruct, SignatureScheme};
|
||||
use std::sync::Arc;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_rustls::TlsConnector as RustlsTlsConnector;
|
||||
use tokio_util::codec::{FramedRead, FramedWrite};
|
||||
@@ -74,56 +79,81 @@ pub async fn check_ldap(host: &str, port: u16) -> Result<()> {
|
||||
check_ldap_endpoint(TcpStream::connect((host, port)).await?).await
|
||||
}
|
||||
|
||||
fn get_root_certificates() -> rustls::RootCertStore {
|
||||
let mut root_store = rustls::RootCertStore::empty();
|
||||
root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| {
|
||||
rustls::OwnedTrustAnchor::from_subject_spki_name_constraints(
|
||||
ta.subject,
|
||||
ta.spki,
|
||||
ta.name_constraints,
|
||||
)
|
||||
}));
|
||||
root_store
|
||||
}
|
||||
|
||||
fn get_tls_connector(ldaps_options: &LdapsOptions) -> Result<RustlsTlsConnector> {
|
||||
let mut client_config = rustls::ClientConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_root_certificates(get_root_certificates())
|
||||
.with_no_client_auth();
|
||||
let (certs, _private_key) = read_certificates(ldaps_options)?;
|
||||
// Check that the server cert is the one in the config file.
|
||||
let certs = tls::load_certificates(&ldaps_options.cert_file)?;
|
||||
let target_cert = certs.first().expect("empty certificate chain").clone();
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CertificateVerifier {
|
||||
certificate: rustls::Certificate,
|
||||
certificate_path: String,
|
||||
certificate: CertificateDer<'static>,
|
||||
}
|
||||
impl rustls::client::ServerCertVerifier for CertificateVerifier {
|
||||
|
||||
impl ServerCertVerifier for CertificateVerifier {
|
||||
fn verify_server_cert(
|
||||
&self,
|
||||
end_entity: &rustls::Certificate,
|
||||
_intermediates: &[rustls::Certificate],
|
||||
_server_name: &rustls::ServerName,
|
||||
_scts: &mut dyn Iterator<Item = &[u8]>,
|
||||
end_entity: &CertificateDer<'_>,
|
||||
_intermediates: &[CertificateDer<'_>],
|
||||
_server_name: &ServerName<'_>,
|
||||
_ocsp_response: &[u8],
|
||||
_now: std::time::SystemTime,
|
||||
) -> std::result::Result<rustls::client::ServerCertVerified, rustls::Error> {
|
||||
_now: UnixTime,
|
||||
) -> Result<ServerCertVerified, rustls::Error> {
|
||||
if end_entity != &self.certificate {
|
||||
return Err(rustls::Error::InvalidCertificateData(format!(
|
||||
"Server certificate doesn't match the one in the config file {}",
|
||||
&self.certificate_path
|
||||
)));
|
||||
return Err(rustls::Error::InvalidCertificate(
|
||||
rustls::CertificateError::NotValidForName,
|
||||
));
|
||||
}
|
||||
Ok(rustls::client::ServerCertVerified::assertion())
|
||||
Ok(ServerCertVerified::assertion())
|
||||
}
|
||||
|
||||
fn verify_tls12_signature(
|
||||
&self,
|
||||
message: &[u8],
|
||||
cert: &CertificateDer<'_>,
|
||||
dss: &DigitallySignedStruct,
|
||||
) -> Result<HandshakeSignatureValid, rustls::Error> {
|
||||
verify_tls12_signature(
|
||||
message,
|
||||
cert,
|
||||
dss,
|
||||
&rustls::crypto::ring::default_provider().signature_verification_algorithms,
|
||||
)
|
||||
}
|
||||
|
||||
fn verify_tls13_signature(
|
||||
&self,
|
||||
message: &[u8],
|
||||
cert: &CertificateDer<'_>,
|
||||
dss: &DigitallySignedStruct,
|
||||
) -> Result<HandshakeSignatureValid, rustls::Error> {
|
||||
verify_tls13_signature(
|
||||
message,
|
||||
cert,
|
||||
dss,
|
||||
&rustls::crypto::ring::default_provider().signature_verification_algorithms,
|
||||
)
|
||||
}
|
||||
|
||||
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
|
||||
rustls::crypto::ring::default_provider()
|
||||
.signature_verification_algorithms
|
||||
.supported_schemes()
|
||||
}
|
||||
}
|
||||
let mut dangerous_config = rustls::client::DangerousClientConfig {
|
||||
cfg: &mut client_config,
|
||||
};
|
||||
dangerous_config.set_certificate_verifier(std::sync::Arc::new(CertificateVerifier {
|
||||
certificate: certs.first().expect("empty certificate chain").clone(),
|
||||
certificate_path: ldaps_options.cert_file.clone(),
|
||||
}));
|
||||
Ok(std::sync::Arc::new(client_config).into())
|
||||
|
||||
let verifier = Arc::new(CertificateVerifier {
|
||||
certificate: target_cert,
|
||||
});
|
||||
|
||||
let client_config = rustls::ClientConfig::builder_with_provider(
|
||||
rustls::crypto::ring::default_provider().into(),
|
||||
)
|
||||
.with_safe_default_protocol_versions()
|
||||
.context("Failed to set default protocol versions")?
|
||||
.dangerous()
|
||||
.with_custom_certificate_verifier(verifier)
|
||||
.with_no_client_auth();
|
||||
|
||||
Ok(Arc::new(client_config).into())
|
||||
}
|
||||
|
||||
#[instrument(skip_all, level = "info", err, fields(host = %host, port = %ldaps_options.port))]
|
||||
@@ -134,10 +164,17 @@ pub async fn check_ldaps(host: &str, ldaps_options: &LdapsOptions) -> Result<()>
|
||||
};
|
||||
let tls_connector =
|
||||
get_tls_connector(ldaps_options).context("while preparing the tls connection")?;
|
||||
|
||||
let domain = match host.parse::<std::net::IpAddr>() {
|
||||
Ok(ip) => ServerName::IpAddress(ip.into()),
|
||||
Err(_) => ServerName::try_from(host.to_string())
|
||||
.map_err(|_| anyhow!("Invalid DNS name: {}", host))?,
|
||||
};
|
||||
|
||||
check_ldap_endpoint(
|
||||
tls_connector
|
||||
.connect(
|
||||
rustls::ServerName::try_from(host).context("while parsing the server name")?,
|
||||
domain,
|
||||
TcpStream::connect((host, ldaps_options.port))
|
||||
.await
|
||||
.context("while connecting TCP")?,
|
||||
|
||||
+12
-49
@@ -1,14 +1,14 @@
|
||||
use crate::configuration::{Configuration, LdapsOptions};
|
||||
use crate::tls;
|
||||
use actix_rt::net::TcpStream;
|
||||
use actix_server::ServerBuilder;
|
||||
use actix_service::{ServiceFactoryExt, fn_service};
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
use anyhow::{Context, Result};
|
||||
use ldap3_proto::{LdapCodec, control::LdapControl, proto::LdapMsg, proto::LdapOp};
|
||||
use lldap_access_control::AccessControlledBackendHandler;
|
||||
use lldap_domain_handlers::handler::{BackendHandler, LoginHandler};
|
||||
use lldap_ldap::{LdapHandler, LdapInfo};
|
||||
use lldap_opaque_handler::OpaqueHandler;
|
||||
use rustls::PrivateKey;
|
||||
use tokio_rustls::TlsAcceptor as RustlsTlsAcceptor;
|
||||
use tokio_util::codec::{FramedRead, FramedWrite};
|
||||
use tracing::{debug, error, info, instrument};
|
||||
@@ -102,55 +102,18 @@ where
|
||||
Ok(requests.into_inner().unsplit(resp.into_inner()))
|
||||
}
|
||||
|
||||
fn read_private_key(key_file: &str) -> Result<PrivateKey> {
|
||||
use rustls_pemfile::{ec_private_keys, pkcs8_private_keys, rsa_private_keys};
|
||||
use std::{fs::File, io::BufReader};
|
||||
pkcs8_private_keys(&mut BufReader::new(File::open(key_file)?))
|
||||
.map_err(anyhow::Error::from)
|
||||
.and_then(|keys| {
|
||||
keys.into_iter()
|
||||
.next()
|
||||
.ok_or_else(|| anyhow!("No PKCS8 key"))
|
||||
})
|
||||
.or_else(|_| {
|
||||
rsa_private_keys(&mut BufReader::new(File::open(key_file)?))
|
||||
.map_err(anyhow::Error::from)
|
||||
.and_then(|keys| {
|
||||
keys.into_iter()
|
||||
.next()
|
||||
.ok_or_else(|| anyhow!("No PKCS1 key"))
|
||||
})
|
||||
})
|
||||
.or_else(|_| {
|
||||
ec_private_keys(&mut BufReader::new(File::open(key_file)?))
|
||||
.map_err(anyhow::Error::from)
|
||||
.and_then(|keys| keys.into_iter().next().ok_or_else(|| anyhow!("No EC key")))
|
||||
})
|
||||
.with_context(|| {
|
||||
format!("Cannot read either PKCS1, PKCS8 or EC private key from {key_file}")
|
||||
})
|
||||
.map(rustls::PrivateKey)
|
||||
}
|
||||
|
||||
pub fn read_certificates(
|
||||
ldaps_options: &LdapsOptions,
|
||||
) -> Result<(Vec<rustls::Certificate>, rustls::PrivateKey)> {
|
||||
use std::{fs::File, io::BufReader};
|
||||
let certs = rustls_pemfile::certs(&mut BufReader::new(File::open(&ldaps_options.cert_file)?))?
|
||||
.into_iter()
|
||||
.map(rustls::Certificate)
|
||||
.collect::<Vec<_>>();
|
||||
let private_key = read_private_key(&ldaps_options.key_file)?;
|
||||
Ok((certs, private_key))
|
||||
}
|
||||
|
||||
fn get_tls_acceptor(ldaps_options: &LdapsOptions) -> Result<RustlsTlsAcceptor> {
|
||||
let (certs, private_key) = read_certificates(ldaps_options)?;
|
||||
let certs = tls::load_certificates(&ldaps_options.cert_file)?;
|
||||
let private_key = tls::load_private_key(&ldaps_options.key_file)?;
|
||||
|
||||
let server_config = std::sync::Arc::new(
|
||||
rustls::ServerConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(certs, private_key)?,
|
||||
rustls::ServerConfig::builder_with_provider(
|
||||
rustls::crypto::ring::default_provider().into(),
|
||||
)
|
||||
.with_safe_default_protocol_versions()
|
||||
.context("Failed to set default protocol versions")?
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(certs, private_key)?,
|
||||
);
|
||||
Ok(server_config.into())
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ mod mail;
|
||||
mod sql_tcp_backend_handler;
|
||||
mod tcp_backend_handler;
|
||||
mod tcp_server;
|
||||
mod tls;
|
||||
|
||||
use crate::{
|
||||
cli::{Command, RunOpts, TestEmailOpts},
|
||||
|
||||
@@ -12,3 +12,4 @@ pub mod mail;
|
||||
pub mod sql_tcp_backend_handler;
|
||||
pub mod tcp_backend_handler;
|
||||
pub mod tcp_server;
|
||||
pub mod tls;
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
use rustls::pki_types::{CertificateDer, PrivateKeyDer, pem::PemObject};
|
||||
|
||||
pub fn load_certificates(filename: &str) -> Result<Vec<CertificateDer<'static>>> {
|
||||
let certs = CertificateDer::pem_file_iter(filename)
|
||||
.with_context(|| format!("Unable to open or read certificate file: {}", filename))?
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.with_context(|| format!("Error parsing certificates in {}", filename))?;
|
||||
|
||||
if certs.is_empty() {
|
||||
return Err(anyhow!("No certificates found in {}", filename));
|
||||
}
|
||||
|
||||
Ok(certs)
|
||||
}
|
||||
|
||||
pub fn load_private_key(filename: &str) -> Result<PrivateKeyDer<'static>> {
|
||||
PrivateKeyDer::from_pem_file(filename)
|
||||
.with_context(|| format!("Unable to load private key from {}", filename))
|
||||
}
|
||||
Reference in New Issue
Block a user