From 22e29d22cc0d657138ec82d2e13f2c1462f45613 Mon Sep 17 00:00:00 2001 From: Maurus Decimus <11444311+mdecimus@users.noreply.github.com> Date: Sun, 10 May 2026 13:13:27 +0200 Subject: [PATCH] Fix LDAP: Impersonation fails when the user has not logged in before --- CHANGELOG.md | 4 +++- crates/common/src/auth/authentication.rs | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f00e901..b08b90a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,9 @@ If you are upgrading from v0.16.x, replace the binary (or run `docker pull`). If - JMAP: - Patching ids containing digits in JSON Pointers fails. - Patching nested objects with `null` values fails. -- SQL directory: Return `Failed` instead of `Error` when the query returns no results. +- External directories: + - SQL: Return `Failed` instead of `Error` when the query returns no results. + - LDAP: Impersonation fails when the user has not logged in before. - Network: Attempt binding to IPv4 when binding to IPv6 fails with `EAFNOSUPPORT` error. - Bootstrap: Timeout after 30 seconds when probing the data store. - HTTP: Use permissive CORS headers for `.well-known` endpoints. diff --git a/crates/common/src/auth/authentication.rs b/crates/common/src/auth/authentication.rs index 96c03e45..31227b68 100644 --- a/crates/common/src/auth/authentication.rs +++ b/crates/common/src/auth/authentication.rs @@ -14,7 +14,7 @@ use crate::{ }; use base64::{Engine, engine::general_purpose}; use directory::{ - Credentials, Directory, + Credentials, Directory, Recipient, core::secret::{SecretVerificationResult, verify_mfa_secret_hash, verify_secret_hash}, }; use registry::schema::{ @@ -264,8 +264,19 @@ impl Server { Permission::Authenticate, ])?; let address = username.account().address(); - let master_address = username.account().address(); - if let Some(account_id) = self.account_id_from_email(address, false).await? { + let master_address = auth_as_address; + let mut account_id = self.account_id_from_email(address, false).await?; + if account_id.is_none() + && let Some(impersonated_domain) = username.account().domain() + && let Some(impersonated_domain_cache) = + self.domain(impersonated_domain).await? + && let Some(directory) = + self.get_directory_for_cached_domain(&impersonated_domain_cache) + && let Recipient::Account(account) = directory.recipient(address).await? + { + account_id = Some(self.synchronize_account(account).await?.id); + } + if let Some(account_id) = account_id { trc::event!( Auth(trc::AuthEvent::Success), AccountName = address.to_string(),