diff --git a/crates/directory/src/backend/ldap/config.rs b/crates/directory/src/backend/ldap/config.rs index e818138cc..209851891 100644 --- a/crates/directory/src/backend/ldap/config.rs +++ b/crates/directory/src/backend/ldap/config.rs @@ -72,6 +72,10 @@ impl LdapDirectory { .values((&prefix, "attributes.secret")) .map(|(_, v)| v.to_string()) .collect(), + attr_secret_changed: config + .values((&prefix, "attributes.secret-changed")) + .map(|(_, v)| v.to_string()) + .collect(), attr_email_address: config .values((&prefix, "attributes.email")) .map(|(_, v)| v.to_string()) diff --git a/crates/directory/src/backend/ldap/lookup.rs b/crates/directory/src/backend/ldap/lookup.rs index ad4707391..d54eff886 100644 --- a/crates/directory/src/backend/ldap/lookup.rs +++ b/crates/directory/src/backend/ldap/lookup.rs @@ -6,6 +6,7 @@ use ldap3::{Ldap, LdapConnAsync, ResultEntry, Scope, SearchEntry}; use mail_send::Credentials; +use store::xxhash_rust; use trc::AddContext; use crate::{ @@ -373,6 +374,15 @@ impl LdapMappings { for item in value { principal.append_str(PrincipalField::Secrets, item); } + } else if self.attr_secret_changed.contains(&attr) { + // Create a disabled AppPassword, used to indicate that the password has been changed + // but cannot be used for authentication. + for item in value { + principal.append_str( + PrincipalField::Secrets, + format!("$app${}$", xxhash_rust::xxh3::xxh3_64(item.as_bytes())), + ); + } } else if self.attr_email_address.contains(&attr) { for item in value { principal.prepend_str(PrincipalField::Emails, item.to_lowercase()); diff --git a/crates/directory/src/backend/ldap/mod.rs b/crates/directory/src/backend/ldap/mod.rs index a72e41480..f085d6cf2 100644 --- a/crates/directory/src/backend/ldap/mod.rs +++ b/crates/directory/src/backend/ldap/mod.rs @@ -29,6 +29,7 @@ pub struct LdapMappings { attr_groups: Vec, attr_description: Vec, attr_secret: Vec, + attr_secret_changed: Vec, attr_email_address: Vec, attr_email_alias: Vec, attr_quota: Vec, diff --git a/crates/directory/src/core/secret.rs b/crates/directory/src/core/secret.rs index b4945ea48..ed92772db 100644 --- a/crates/directory/src/core/secret.rs +++ b/crates/directory/src/core/secret.rs @@ -264,7 +264,9 @@ pub async fn verify_secret_hash(hashed_secret: &str, secret: &str) -> trc::Resul .into_err() .details(hashed_secret.to_string())) } - } else { + } else if !hashed_secret.is_empty() { Ok(hashed_secret == secret) + } else { + Ok(false) } } diff --git a/crates/store/src/lib.rs b/crates/store/src/lib.rs index 01b43629a..62bf9c3ed 100644 --- a/crates/store/src/lib.rs +++ b/crates/store/src/lib.rs @@ -22,6 +22,7 @@ pub use rand; pub use roaring; use utils::config::cron::SimpleCron; use write::{BitmapClass, ValueClass}; +pub use xxhash_rust; #[cfg(feature = "s3")] use backend::s3::S3Store;