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-codec",
|
||||||
"actix-rt",
|
"actix-rt",
|
||||||
"actix-service",
|
"actix-service",
|
||||||
|
"actix-tls",
|
||||||
"actix-utils",
|
"actix-utils",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"bitflags 2.10.0",
|
"bitflags 2.10.0",
|
||||||
@@ -181,11 +182,11 @@ dependencies = [
|
|||||||
"futures-core",
|
"futures-core",
|
||||||
"impl-more",
|
"impl-more",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"rustls-pki-types",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls 0.23.4",
|
"tokio-rustls 0.26.4",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tracing",
|
"tracing",
|
||||||
"webpki-roots 0.22.6",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -211,6 +212,7 @@ dependencies = [
|
|||||||
"actix-rt",
|
"actix-rt",
|
||||||
"actix-server",
|
"actix-server",
|
||||||
"actix-service",
|
"actix-service",
|
||||||
|
"actix-tls",
|
||||||
"actix-utils",
|
"actix-utils",
|
||||||
"actix-web-codegen",
|
"actix-web-codegen",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -530,6 +532,28 @@ version = "1.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
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]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.76"
|
version = "0.3.76"
|
||||||
@@ -788,6 +812,15 @@ version = "0.7.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cmake"
|
||||||
|
version = "0.1.57"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color_quant"
|
name = "color_quant"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -1284,6 +1317,12 @@ version = "0.11.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
|
checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dunce"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
@@ -1487,6 +1526,12 @@ version = "2.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619"
|
checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fs_extra"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fslock"
|
name = "fslock"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -2700,7 +2745,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"quoted_printable",
|
"quoted_printable",
|
||||||
"rustls 0.21.12",
|
"rustls 0.21.12",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile 1.0.4",
|
||||||
"serde",
|
"serde",
|
||||||
"socket2 0.4.10",
|
"socket2 0.4.10",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -2814,8 +2859,9 @@ dependencies = [
|
|||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"rand_chacha 0.3.1",
|
"rand_chacha 0.3.1",
|
||||||
"reqwest 0.11.27",
|
"reqwest 0.11.27",
|
||||||
"rustls 0.20.9",
|
"rustls 0.23.35",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile 2.2.0",
|
||||||
|
"rustls-pki-types",
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
"secstr",
|
"secstr",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -2826,7 +2872,7 @@ dependencies = [
|
|||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
"time",
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls 0.23.4",
|
"tokio-rustls 0.26.4",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -2838,7 +2884,7 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
"urlencoding",
|
"urlencoding",
|
||||||
"uuid 1.19.0",
|
"uuid 1.19.0",
|
||||||
"webpki-roots 0.22.6",
|
"webpki-roots 0.26.11",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4066,7 +4112,7 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rustls 0.21.12",
|
"rustls 0.21.12",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile 1.0.4",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
@@ -4233,18 +4279,6 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"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]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.21.12"
|
version = "0.21.12"
|
||||||
@@ -4263,6 +4297,7 @@ version = "0.23.35"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f"
|
checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aws-lc-rs",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ring 0.17.14",
|
"ring 0.17.14",
|
||||||
@@ -4293,6 +4328,15 @@ dependencies = [
|
|||||||
"base64 0.21.7",
|
"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]]
|
[[package]]
|
||||||
name = "rustls-pki-types"
|
name = "rustls-pki-types"
|
||||||
version = "1.13.2"
|
version = "1.13.2"
|
||||||
@@ -4329,6 +4373,7 @@ version = "0.103.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52"
|
checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aws-lc-rs",
|
||||||
"ring 0.17.14",
|
"ring 0.17.14",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"untrusted 0.9.0",
|
"untrusted 0.9.0",
|
||||||
@@ -5297,17 +5342,6 @@ dependencies = [
|
|||||||
"syn 2.0.111",
|
"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]]
|
[[package]]
|
||||||
name = "tokio-rustls"
|
name = "tokio-rustls"
|
||||||
version = "0.24.1"
|
version = "0.24.1"
|
||||||
@@ -5880,25 +5914,6 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"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]]
|
[[package]]
|
||||||
name = "webpki-roots"
|
name = "webpki-roots"
|
||||||
version = "0.23.1"
|
version = "0.23.1"
|
||||||
|
|||||||
+17
-9
@@ -18,7 +18,6 @@ actix-http = "3"
|
|||||||
actix-rt = "2"
|
actix-rt = "2"
|
||||||
actix-server = "2"
|
actix-server = "2"
|
||||||
actix-service = "2"
|
actix-service = "2"
|
||||||
actix-web = "4.3"
|
|
||||||
actix-web-httpauth = "0.8"
|
actix-web-httpauth = "0.8"
|
||||||
anyhow = "*"
|
anyhow = "*"
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
@@ -35,12 +34,12 @@ jwt = "0.16"
|
|||||||
ldap3_proto = "0.6.0"
|
ldap3_proto = "0.6.0"
|
||||||
log = "*"
|
log = "*"
|
||||||
rand_chacha = "0.3"
|
rand_chacha = "0.3"
|
||||||
rustls-pemfile = "1"
|
rustls-pemfile = "2"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
sha2 = "0.10"
|
sha2 = "0.10"
|
||||||
thiserror = "2"
|
thiserror = "2"
|
||||||
time = "0.3"
|
time = "0.3"
|
||||||
tokio-rustls = "0.23"
|
tokio-rustls = "0.26"
|
||||||
tokio-stream = "*"
|
tokio-stream = "*"
|
||||||
tokio-util = "0.7"
|
tokio-util = "0.7"
|
||||||
tracing = "*"
|
tracing = "*"
|
||||||
@@ -48,7 +47,20 @@ tracing-actix-web = "0.7"
|
|||||||
tracing-attributes = "^0.1.21"
|
tracing-attributes = "^0.1.21"
|
||||||
tracing-log = "*"
|
tracing-log = "*"
|
||||||
urlencoding = "2"
|
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]
|
[dependencies.chrono]
|
||||||
features = ["serde"]
|
features = ["serde"]
|
||||||
@@ -145,7 +157,7 @@ features = ["smallvec", "chrono", "tokio"]
|
|||||||
version = "^0.1.6"
|
version = "^0.1.6"
|
||||||
|
|
||||||
[dependencies.actix-tls]
|
[dependencies.actix-tls]
|
||||||
features = ["default", "rustls"]
|
features = ["default", "rustls-0_23"]
|
||||||
version = "3"
|
version = "3"
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
@@ -163,10 +175,6 @@ version = "0.11"
|
|||||||
default-features = false
|
default-features = false
|
||||||
features = ["rustls-tls-webpki-roots"]
|
features = ["rustls-tls-webpki-roots"]
|
||||||
|
|
||||||
[dependencies.rustls]
|
|
||||||
version = "0.20"
|
|
||||||
features = ["dangerous_configuration"]
|
|
||||||
|
|
||||||
[dependencies.url]
|
[dependencies.url]
|
||||||
version = "2"
|
version = "2"
|
||||||
features = ["serde"]
|
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 anyhow::{Context, Result, anyhow, bail, ensure};
|
||||||
use futures_util::SinkExt;
|
use futures_util::SinkExt;
|
||||||
use ldap3_proto::{
|
use ldap3_proto::{
|
||||||
@@ -8,6 +8,11 @@ use ldap3_proto::{
|
|||||||
LdapSearchScope,
|
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::net::TcpStream;
|
||||||
use tokio_rustls::TlsConnector as RustlsTlsConnector;
|
use tokio_rustls::TlsConnector as RustlsTlsConnector;
|
||||||
use tokio_util::codec::{FramedRead, FramedWrite};
|
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
|
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> {
|
fn get_tls_connector(ldaps_options: &LdapsOptions) -> Result<RustlsTlsConnector> {
|
||||||
let mut client_config = rustls::ClientConfig::builder()
|
let certs = tls::load_certificates(&ldaps_options.cert_file)?;
|
||||||
.with_safe_defaults()
|
let target_cert = certs.first().expect("empty certificate chain").clone();
|
||||||
.with_root_certificates(get_root_certificates())
|
|
||||||
.with_no_client_auth();
|
#[derive(Debug)]
|
||||||
let (certs, _private_key) = read_certificates(ldaps_options)?;
|
|
||||||
// Check that the server cert is the one in the config file.
|
|
||||||
struct CertificateVerifier {
|
struct CertificateVerifier {
|
||||||
certificate: rustls::Certificate,
|
certificate: CertificateDer<'static>,
|
||||||
certificate_path: String,
|
|
||||||
}
|
}
|
||||||
impl rustls::client::ServerCertVerifier for CertificateVerifier {
|
|
||||||
|
impl ServerCertVerifier for CertificateVerifier {
|
||||||
fn verify_server_cert(
|
fn verify_server_cert(
|
||||||
&self,
|
&self,
|
||||||
end_entity: &rustls::Certificate,
|
end_entity: &CertificateDer<'_>,
|
||||||
_intermediates: &[rustls::Certificate],
|
_intermediates: &[CertificateDer<'_>],
|
||||||
_server_name: &rustls::ServerName,
|
_server_name: &ServerName<'_>,
|
||||||
_scts: &mut dyn Iterator<Item = &[u8]>,
|
|
||||||
_ocsp_response: &[u8],
|
_ocsp_response: &[u8],
|
||||||
_now: std::time::SystemTime,
|
_now: UnixTime,
|
||||||
) -> std::result::Result<rustls::client::ServerCertVerified, rustls::Error> {
|
) -> Result<ServerCertVerified, rustls::Error> {
|
||||||
if end_entity != &self.certificate {
|
if end_entity != &self.certificate {
|
||||||
return Err(rustls::Error::InvalidCertificateData(format!(
|
return Err(rustls::Error::InvalidCertificate(
|
||||||
"Server certificate doesn't match the one in the config file {}",
|
rustls::CertificateError::NotValidForName,
|
||||||
&self.certificate_path
|
));
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
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,
|
let verifier = Arc::new(CertificateVerifier {
|
||||||
};
|
certificate: target_cert,
|
||||||
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(),
|
let client_config = rustls::ClientConfig::builder_with_provider(
|
||||||
}));
|
rustls::crypto::ring::default_provider().into(),
|
||||||
Ok(std::sync::Arc::new(client_config).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))]
|
#[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 =
|
let tls_connector =
|
||||||
get_tls_connector(ldaps_options).context("while preparing the tls connection")?;
|
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(
|
check_ldap_endpoint(
|
||||||
tls_connector
|
tls_connector
|
||||||
.connect(
|
.connect(
|
||||||
rustls::ServerName::try_from(host).context("while parsing the server name")?,
|
domain,
|
||||||
TcpStream::connect((host, ldaps_options.port))
|
TcpStream::connect((host, ldaps_options.port))
|
||||||
.await
|
.await
|
||||||
.context("while connecting TCP")?,
|
.context("while connecting TCP")?,
|
||||||
|
|||||||
+12
-49
@@ -1,14 +1,14 @@
|
|||||||
use crate::configuration::{Configuration, LdapsOptions};
|
use crate::configuration::{Configuration, LdapsOptions};
|
||||||
|
use crate::tls;
|
||||||
use actix_rt::net::TcpStream;
|
use actix_rt::net::TcpStream;
|
||||||
use actix_server::ServerBuilder;
|
use actix_server::ServerBuilder;
|
||||||
use actix_service::{ServiceFactoryExt, fn_service};
|
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 ldap3_proto::{LdapCodec, control::LdapControl, proto::LdapMsg, proto::LdapOp};
|
||||||
use lldap_access_control::AccessControlledBackendHandler;
|
use lldap_access_control::AccessControlledBackendHandler;
|
||||||
use lldap_domain_handlers::handler::{BackendHandler, LoginHandler};
|
use lldap_domain_handlers::handler::{BackendHandler, LoginHandler};
|
||||||
use lldap_ldap::{LdapHandler, LdapInfo};
|
use lldap_ldap::{LdapHandler, LdapInfo};
|
||||||
use lldap_opaque_handler::OpaqueHandler;
|
use lldap_opaque_handler::OpaqueHandler;
|
||||||
use rustls::PrivateKey;
|
|
||||||
use tokio_rustls::TlsAcceptor as RustlsTlsAcceptor;
|
use tokio_rustls::TlsAcceptor as RustlsTlsAcceptor;
|
||||||
use tokio_util::codec::{FramedRead, FramedWrite};
|
use tokio_util::codec::{FramedRead, FramedWrite};
|
||||||
use tracing::{debug, error, info, instrument};
|
use tracing::{debug, error, info, instrument};
|
||||||
@@ -102,55 +102,18 @@ where
|
|||||||
Ok(requests.into_inner().unsplit(resp.into_inner()))
|
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> {
|
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(
|
let server_config = std::sync::Arc::new(
|
||||||
rustls::ServerConfig::builder()
|
rustls::ServerConfig::builder_with_provider(
|
||||||
.with_safe_defaults()
|
rustls::crypto::ring::default_provider().into(),
|
||||||
.with_no_client_auth()
|
)
|
||||||
.with_single_cert(certs, private_key)?,
|
.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())
|
Ok(server_config.into())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ mod mail;
|
|||||||
mod sql_tcp_backend_handler;
|
mod sql_tcp_backend_handler;
|
||||||
mod tcp_backend_handler;
|
mod tcp_backend_handler;
|
||||||
mod tcp_server;
|
mod tcp_server;
|
||||||
|
mod tls;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cli::{Command, RunOpts, TestEmailOpts},
|
cli::{Command, RunOpts, TestEmailOpts},
|
||||||
|
|||||||
@@ -12,3 +12,4 @@ pub mod mail;
|
|||||||
pub mod sql_tcp_backend_handler;
|
pub mod sql_tcp_backend_handler;
|
||||||
pub mod tcp_backend_handler;
|
pub mod tcp_backend_handler;
|
||||||
pub mod tcp_server;
|
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