From 980bd475b6add727590915056abfc7b4049df074 Mon Sep 17 00:00:00 2001 From: Getz Mikalsen Date: Thu, 23 Apr 2026 17:39:25 +0000 Subject: [PATCH] feat: Add TLS options for LDAP (#1389) Optional StartTLS for LDAP and add option to skip TLS verification. Co-authored-by: Jade Ellis Reviewed-on: https://forgejo.ellis.link/continuwuation/continuwuity/pulls/1389 Reviewed-by: Jade Ellis --- changelog.d/1389.feature.md | 1 + conduwuit-example.toml | 8 ++++++++ src/core/config/mod.rs | 12 ++++++++++++ src/service/users/mod.rs | 26 ++++++++++++++++++++++---- 4 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 changelog.d/1389.feature.md diff --git a/changelog.d/1389.feature.md b/changelog.d/1389.feature.md new file mode 100644 index 000000000..365cec9d3 --- /dev/null +++ b/changelog.d/1389.feature.md @@ -0,0 +1 @@ +LDAP can now optionally be connected to using StartTLS, and you may unsafely skip verification. Contributed by @getz diff --git a/conduwuit-example.toml b/conduwuit-example.toml index 87a6b8df0..b4ea8da11 100644 --- a/conduwuit-example.toml +++ b/conduwuit-example.toml @@ -1966,6 +1966,14 @@ # #uri = "" +# StartTLS for LDAP connections. +# +#use_starttls = false + +# Skip TLS certificate verification, possibly dangerous. +# +#disable_tls_verification = false + # Root of the searches. # # example: "ou=users,dc=example,dc=org" diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index a099dd7c4..e0858d1d9 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -2324,6 +2324,18 @@ pub struct LdapConfig { #[serde(default)] pub uri: Option, + /// StartTLS for LDAP connections. + /// + /// default: false + #[serde(default)] + pub use_starttls: bool, + + /// Skip TLS certificate verification, possibly dangerous. + /// + /// default: false + #[serde(default)] + pub disable_tls_verification: bool, + /// Root of the searches. /// /// example: "ou=users,dc=example,dc=org" diff --git a/src/service/users/mod.rs b/src/service/users/mod.rs index 5f2787850..160964761 100644 --- a/src/service/users/mod.rs +++ b/src/service/users/mod.rs @@ -15,7 +15,7 @@ use conduwuit_core::{debug, error}; use database::{Deserialized, Ignore, Interfix, Json, Map}; use futures::{Stream, StreamExt, TryFutureExt}; #[cfg(feature = "ldap")] -use ldap3::{LdapConnAsync, Scope, SearchEntry}; +use ldap3::{LdapConnAsync, LdapConnSettings, Scope, SearchEntry}; use ruma::{ DeviceId, KeyId, MilliSecondsSinceUnixEpoch, OneTimeKeyAlgorithm, OneTimeKeyId, OneTimeKeyName, OwnedDeviceId, OwnedKeyId, OwnedMxcUri, OwnedUserId, RoomId, UInt, UserId, @@ -1285,6 +1285,24 @@ impl Service { } } + #[cfg(feature = "ldap")] + async fn create_ldap_connection( + config: &conduwuit_core::config::LdapConfig, + uri: &str, + ) -> Result<(LdapConnAsync, ldap3::Ldap), ldap3::LdapError> { + let mut settings = LdapConnSettings::new(); + + if config.use_starttls { + settings = settings.set_starttls(true); + } + + if config.disable_tls_verification { + settings = settings.set_no_tls_verify(true); + } + + LdapConnAsync::with_settings(settings, uri).await + } + #[cfg(not(feature = "ldap"))] pub async fn search_ldap(&self, _user_id: &UserId) -> Result)>> { Err!(FeatureDisabled("ldap")) @@ -1302,7 +1320,7 @@ impl Service { .ok_or_else(|| err!(Ldap(error!("LDAP URI is not configured."))))?; debug!(?uri, "LDAP creating connection..."); - let (conn, mut ldap) = LdapConnAsync::new(uri.as_str()) + let (conn, mut ldap) = Self::create_ldap_connection(config, uri.as_str()) .await .map_err(|e| err!(Ldap(error!(%user_id, "LDAP connection setup error: {e}"))))?; @@ -1411,9 +1429,9 @@ impl Service { .ok_or_else(|| err!(Ldap(error!("LDAP URI is not configured."))))?; debug!(?uri, "LDAP creating connection..."); - let (conn, mut ldap) = LdapConnAsync::new(uri.as_str()) + let (conn, mut ldap) = Self::create_ldap_connection(config, uri.as_str()) .await - .map_err(|e| err!(Ldap(error!(?user_dn, "LDAP connection setup error: {e}"))))?; + .map_err(|e| err!(Ldap(error!(%user_dn, "LDAP connection setup error: {e}"))))?; let driver = self.services.server.runtime().spawn(async move { match conn.drive().await {