mirror of
https://github.com/lldap/lldap.git
synced 2026-03-31 15:07:48 +01:00
Fix LDAP bind to not support email login - only allow email login for web UI
Co-authored-by: nitnelave <796633+nitnelave@users.noreply.github.com>
This commit is contained in:
@@ -78,40 +78,24 @@ impl SqlBackendHandler {
|
||||
|
||||
Ok(users.first().map(|user_and_groups| user_and_groups.user.user_id.clone()))
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl LoginHandler for SqlBackendHandler {
|
||||
#[instrument(skip_all, level = "debug", err)]
|
||||
async fn bind(&self, request: BindRequest) -> Result<()> {
|
||||
// First try to authenticate with the provided name as a user ID
|
||||
let mut actual_user_id = request.name.clone();
|
||||
let mut password_hash = self
|
||||
if let Some(password_hash) = self
|
||||
.get_password_file_for_user(request.name.clone())
|
||||
.await?;
|
||||
|
||||
// If no user found by user ID, try to find by email
|
||||
if password_hash.is_none() {
|
||||
debug!(r#"User "{}" not found by user ID, trying email lookup"#, &request.name);
|
||||
if let Some(user_id_by_email) = self
|
||||
.find_user_id_by_email(&request.name.as_str())
|
||||
.await?
|
||||
{
|
||||
debug!(r#"Found user by email: "{}""#, &user_id_by_email);
|
||||
actual_user_id = user_id_by_email;
|
||||
password_hash = self
|
||||
.get_password_file_for_user(actual_user_id.clone())
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(password_hash) = password_hash {
|
||||
info!(r#"Login attempt for "{}" (input: "{}")"#, &actual_user_id, &request.name);
|
||||
info!(r#"Login attempt for "{}""#, &request.name);
|
||||
if passwords_match(
|
||||
&password_hash,
|
||||
&request.password,
|
||||
&self.opaque_setup,
|
||||
&actual_user_id,
|
||||
&request.name,
|
||||
)
|
||||
.is_ok()
|
||||
{
|
||||
@@ -137,14 +121,33 @@ impl OpaqueHandler for SqlOpaqueHandler {
|
||||
&self,
|
||||
request: login::ClientLoginStartRequest,
|
||||
) -> Result<login::ServerLoginStartResponse> {
|
||||
let user_id = request.username;
|
||||
info!(r#"OPAQUE login attempt for "{}""#, &user_id);
|
||||
let maybe_password_file = self
|
||||
.get_password_file_for_user(user_id.clone())
|
||||
// First try to authenticate with the provided name as a user ID
|
||||
let mut actual_user_id = request.username.clone();
|
||||
let mut maybe_password_file = self
|
||||
.get_password_file_for_user(request.username.clone())
|
||||
.await?;
|
||||
|
||||
// If no user found by user ID, try to find by email for web UI login
|
||||
if maybe_password_file.is_none() {
|
||||
debug!(r#"User "{}" not found by user ID, trying email lookup for web login"#, &request.username);
|
||||
if let Some(user_id_by_email) = self
|
||||
.find_user_id_by_email(request.username.as_str())
|
||||
.await?
|
||||
{
|
||||
debug!(r#"Found user by email: "{}""#, &user_id_by_email);
|
||||
actual_user_id = user_id_by_email;
|
||||
maybe_password_file = self
|
||||
.get_password_file_for_user(actual_user_id.clone())
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
info!(r#"OPAQUE login attempt for "{}" (input: "{}")"#, &actual_user_id, &request.username);
|
||||
|
||||
let maybe_password_file = maybe_password_file
|
||||
.map(|bytes| {
|
||||
opaque::server::ServerRegistration::deserialize(&bytes).map_err(|_| {
|
||||
DomainError::InternalError(format!("Corrupted password file for {}", &user_id))
|
||||
DomainError::InternalError(format!("Corrupted password file for {}", &actual_user_id))
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
@@ -156,11 +159,11 @@ impl OpaqueHandler for SqlOpaqueHandler {
|
||||
&self.opaque_setup,
|
||||
maybe_password_file,
|
||||
request.login_start_request,
|
||||
&user_id,
|
||||
&actual_user_id,
|
||||
)?;
|
||||
let secret_key = self.get_orion_secret_key()?;
|
||||
let server_data = login::ServerData {
|
||||
username: user_id,
|
||||
username: actual_user_id,
|
||||
server_login: start_response.state,
|
||||
};
|
||||
let encrypted_state = orion::aead::seal(&secret_key, &bincode::serialize(&server_data)?)?;
|
||||
@@ -342,6 +345,7 @@ mod tests {
|
||||
let handler = SqlOpaqueHandler::new(generate_random_private_key(), sql_pool.clone());
|
||||
insert_user(&handler, "bob", "bob00").await;
|
||||
|
||||
// Test login with username (should work)
|
||||
handler
|
||||
.bind(BindRequest {
|
||||
name: UserId::new("bob"),
|
||||
@@ -349,6 +353,8 @@ mod tests {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Test login with non-existent user
|
||||
handler
|
||||
.bind(BindRequest {
|
||||
name: UserId::new("andrew"),
|
||||
@@ -356,6 +362,8 @@ mod tests {
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
||||
// Test login with wrong password
|
||||
handler
|
||||
.bind(BindRequest {
|
||||
name: UserId::new("bob"),
|
||||
@@ -363,47 +371,37 @@ mod tests {
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
||||
// Test that email login is NOT supported for LDAP bind
|
||||
handler
|
||||
.bind(BindRequest {
|
||||
name: UserId::new("bob@bob.bob"),
|
||||
password: "bob00".to_string(),
|
||||
})
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_bind_user_with_email() {
|
||||
async fn test_opaque_login_with_email() {
|
||||
let sql_pool = get_initialized_db().await;
|
||||
let handler = SqlOpaqueHandler::new(generate_random_private_key(), sql_pool.clone());
|
||||
insert_user(&handler, "bob", "bob00").await;
|
||||
crate::logging::init_for_tests();
|
||||
let backend_handler = SqlBackendHandler::new(generate_random_private_key(), sql_pool);
|
||||
insert_user(&backend_handler, "bob", "bob00").await;
|
||||
|
||||
// Test login with username (should work as before)
|
||||
handler
|
||||
.bind(BindRequest {
|
||||
name: UserId::new("bob"),
|
||||
password: "bob00".to_string(),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
// Test OPAQUE login with username (should work as before)
|
||||
attempt_login(&backend_handler, "bob", "bob00").await.unwrap();
|
||||
|
||||
// Test login with email (new functionality)
|
||||
handler
|
||||
.bind(BindRequest {
|
||||
name: UserId::new("bob@bob.bob"),
|
||||
password: "bob00".to_string(),
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
// Test OPAQUE login with email (new functionality)
|
||||
attempt_login(&backend_handler, "bob@bob.bob", "bob00").await.unwrap();
|
||||
|
||||
// Test login with non-existent email
|
||||
handler
|
||||
.bind(BindRequest {
|
||||
name: UserId::new("nonexistent@bob.bob"),
|
||||
password: "bob00".to_string(),
|
||||
})
|
||||
// Test OPAQUE login with non-existent email
|
||||
attempt_login(&backend_handler, "nonexistent@bob.bob", "bob00")
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
||||
// Test login with wrong password using email
|
||||
handler
|
||||
.bind(BindRequest {
|
||||
name: UserId::new("bob@bob.bob"),
|
||||
password: "wrong_password".to_string(),
|
||||
})
|
||||
// Test OPAQUE login with wrong password using email
|
||||
attempt_login(&backend_handler, "bob@bob.bob", "wrong_password")
|
||||
.await
|
||||
.unwrap_err();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user