mirror of
https://github.com/nitnelave/lldap.git
synced 2023-04-12 14:25:13 +00:00
server: Allow readonly users to change non-admin passwords
This commit is contained in:
parent
786f571e86
commit
1a37e1ee04
@ -566,7 +566,22 @@ impl<Backend: BackendHandler + LoginHandler + OpaqueHandler> LdapHandler<Backend
|
|||||||
(Some(user), Some(password)) => {
|
(Some(user), Some(password)) => {
|
||||||
match get_user_id_from_distinguished_name(user, &self.base_dn, &self.base_dn_str) {
|
match get_user_id_from_distinguished_name(user, &self.base_dn, &self.base_dn_str) {
|
||||||
Ok(uid) => {
|
Ok(uid) => {
|
||||||
if *permission != Permission::Admin && user_id != &uid {
|
let user_is_admin = match self.backend_handler.get_user_groups(&uid).await {
|
||||||
|
Ok(groups) => groups.iter().any(|g| g.display_name == "lldap_admin"),
|
||||||
|
Err(e) => {
|
||||||
|
return vec![make_extended_response(
|
||||||
|
LdapResultCode::OperationsError,
|
||||||
|
format!(
|
||||||
|
"Internal error while requesting user's groups: {:#?}",
|
||||||
|
e
|
||||||
|
),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !(*permission == Permission::Admin
|
||||||
|
|| user_id == &uid
|
||||||
|
|| (*permission == Permission::Readonly && !user_is_admin))
|
||||||
|
{
|
||||||
return vec![make_extended_response(
|
return vec![make_extended_response(
|
||||||
LdapResultCode::InsufficentAccessRights,
|
LdapResultCode::InsufficentAccessRights,
|
||||||
format!(
|
format!(
|
||||||
@ -2258,6 +2273,9 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_password_change() {
|
async fn test_password_change() {
|
||||||
let mut mock = MockTestBackendHandler::new();
|
let mut mock = MockTestBackendHandler::new();
|
||||||
|
mock.expect_get_user_groups()
|
||||||
|
.with(eq(UserId::new("bob")))
|
||||||
|
.returning(|_| Ok(HashSet::new()));
|
||||||
use lldap_auth::*;
|
use lldap_auth::*;
|
||||||
let mut rng = rand::rngs::OsRng;
|
let mut rng = rand::rngs::OsRng;
|
||||||
let registration_start_request =
|
let registration_start_request =
|
||||||
@ -2299,9 +2317,60 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_password_change_readonly() {
|
||||||
|
let mut mock = MockTestBackendHandler::new();
|
||||||
|
mock.expect_get_user_groups()
|
||||||
|
.with(eq(UserId::new("bob")))
|
||||||
|
.returning(|_| Ok(HashSet::new()));
|
||||||
|
use lldap_auth::*;
|
||||||
|
let mut rng = rand::rngs::OsRng;
|
||||||
|
let registration_start_request =
|
||||||
|
opaque::client::registration::start_registration("password", &mut rng).unwrap();
|
||||||
|
let request = registration::ClientRegistrationStartRequest {
|
||||||
|
username: "bob".to_string(),
|
||||||
|
registration_start_request: registration_start_request.message,
|
||||||
|
};
|
||||||
|
let start_response = opaque::server::registration::start_registration(
|
||||||
|
&opaque::server::ServerSetup::new(&mut rng),
|
||||||
|
request.registration_start_request,
|
||||||
|
&request.username,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
mock.expect_registration_start().times(1).return_once(|_| {
|
||||||
|
Ok(registration::ServerRegistrationStartResponse {
|
||||||
|
server_data: "".to_string(),
|
||||||
|
registration_response: start_response.message,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
mock.expect_registration_finish()
|
||||||
|
.times(1)
|
||||||
|
.return_once(|_| Ok(()));
|
||||||
|
let mut ldap_handler = setup_bound_readonly_handler(mock).await;
|
||||||
|
let request = LdapOp::ExtendedRequest(
|
||||||
|
LdapPasswordModifyRequest {
|
||||||
|
user_identity: Some("uid=bob,ou=people,dc=example,dc=com".to_string()),
|
||||||
|
old_password: None,
|
||||||
|
new_password: Some("password".to_string()),
|
||||||
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
ldap_handler.handle_ldap_message(request).await,
|
||||||
|
Some(vec![make_extended_response(
|
||||||
|
LdapResultCode::Success,
|
||||||
|
"".to_string(),
|
||||||
|
)])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_password_change_errors() {
|
async fn test_password_change_errors() {
|
||||||
let mut ldap_handler = setup_bound_admin_handler(MockTestBackendHandler::new()).await;
|
let mut mock = MockTestBackendHandler::new();
|
||||||
|
mock.expect_get_user_groups()
|
||||||
|
.with(eq(UserId::new("bob")))
|
||||||
|
.returning(|_| Ok(HashSet::new()));
|
||||||
|
let mut ldap_handler = setup_bound_admin_handler(mock).await;
|
||||||
let request = LdapOp::ExtendedRequest(
|
let request = LdapOp::ExtendedRequest(
|
||||||
LdapPasswordModifyRequest {
|
LdapPasswordModifyRequest {
|
||||||
user_identity: None,
|
user_identity: None,
|
||||||
@ -2346,8 +2415,20 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_password_change_unauthorized() {
|
async fn test_password_change_unauthorized_readonly() {
|
||||||
let mut ldap_handler = setup_bound_readonly_handler(MockTestBackendHandler::new()).await;
|
let mut mock = MockTestBackendHandler::new();
|
||||||
|
let mut groups = HashSet::new();
|
||||||
|
groups.insert(GroupDetails {
|
||||||
|
group_id: GroupId(0),
|
||||||
|
display_name: "lldap_admin".to_string(),
|
||||||
|
creation_date: chrono::Utc.timestamp(42, 42),
|
||||||
|
uuid: uuid!("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"),
|
||||||
|
});
|
||||||
|
mock.expect_get_user_groups()
|
||||||
|
.with(eq(UserId::new("bob")))
|
||||||
|
.times(1)
|
||||||
|
.return_once(|_| Ok(groups));
|
||||||
|
let mut ldap_handler = setup_bound_readonly_handler(mock).await;
|
||||||
let request = LdapOp::ExtendedRequest(
|
let request = LdapOp::ExtendedRequest(
|
||||||
LdapPasswordModifyRequest {
|
LdapPasswordModifyRequest {
|
||||||
user_identity: Some("uid=bob,ou=people,dc=example,dc=com".to_string()),
|
user_identity: Some("uid=bob,ou=people,dc=example,dc=com".to_string()),
|
||||||
|
Loading…
Reference in New Issue
Block a user