2023-06-04 11:17:16 +00:00
|
|
|
use crate::State;
|
|
|
|
use ldap3::exop::PasswordModify;
|
|
|
|
use ldap3::{LdapConn, Mod, Scope, SearchEntry};
|
|
|
|
use std::collections::HashSet;
|
|
|
|
use tide::prelude::{json, Deserialize};
|
|
|
|
use tide::Request;
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
pub struct LdapUpdate {
|
|
|
|
user: String,
|
|
|
|
pass: String,
|
|
|
|
field: String,
|
|
|
|
value: String,
|
|
|
|
}
|
2023-06-04 11:19:17 +00:00
|
|
|
|
|
|
|
/// Handles updating a single field with the users own password
|
2023-06-04 11:17:16 +00:00
|
|
|
pub async fn post_update_ldap(mut req: Request<State>) -> tide::Result {
|
|
|
|
let LdapUpdate {
|
|
|
|
user,
|
|
|
|
pass,
|
|
|
|
field,
|
|
|
|
value,
|
|
|
|
} = req.body_json().await?;
|
|
|
|
|
|
|
|
let config = &req.state().config;
|
|
|
|
|
|
|
|
// easier to give each request its own connection
|
|
|
|
let mut ldap = LdapConn::new(&config.ldap_host)?;
|
|
|
|
|
|
|
|
let dn = format!("uid={},ou=users,dc=skynet,dc=ie", user);
|
|
|
|
ldap.simple_bind(&dn, &pass)?.success()?;
|
|
|
|
|
|
|
|
// always assume insecure
|
|
|
|
let mut pw_keep_same = false;
|
2023-07-16 22:14:21 +00:00
|
|
|
let mut pw_secure = false;
|
2023-06-04 11:17:16 +00:00
|
|
|
|
|
|
|
// get the users current password hash
|
|
|
|
let (rs, _res) = ldap.search(&dn, Scope::Base, "(objectClass=*)", vec!["userPassword"])?.success()?;
|
|
|
|
if !rs.is_empty() {
|
|
|
|
let tmp = SearchEntry::construct(rs[0].clone());
|
|
|
|
if !tmp.attrs["userPassword"].is_empty() && tmp.attrs["userPassword"][0].starts_with("{SSHA512}") {
|
|
|
|
pw_keep_same = true;
|
2023-07-16 22:14:21 +00:00
|
|
|
pw_secure = true;
|
|
|
|
}
|
|
|
|
if !tmp.attrs["skSecure"].is_empty() && tmp.attrs["skSecure"][0] == "1" {
|
|
|
|
pw_secure = true;
|
2023-06-04 11:17:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if the password field itself is being updated
|
|
|
|
let (pass_old, pass_new) = if &field != "userPassword" {
|
|
|
|
// if password is not being updated then just update the required field
|
2023-07-16 22:14:21 +00:00
|
|
|
let mut mods = vec![
|
|
|
|
// main value we are updating
|
|
|
|
Mod::Replace(field, HashSet::from([value])),
|
|
|
|
];
|
2023-07-16 23:14:48 +00:00
|
|
|
|
2023-07-16 22:14:21 +00:00
|
|
|
// if teh password is changing then its inherentrly secure, same if its currently an empty field
|
|
|
|
if !pw_keep_same || !pw_secure {
|
|
|
|
mods.push(Mod::Replace(String::from("skSecure"), HashSet::from([String::from("1")])));
|
|
|
|
}
|
2023-07-16 23:14:48 +00:00
|
|
|
|
2023-06-04 11:17:16 +00:00
|
|
|
ldap.modify(&dn, mods)?.success()?;
|
|
|
|
|
|
|
|
// pass back the "old" and "new" passwords
|
|
|
|
(pass.clone(), pass.clone())
|
|
|
|
} else {
|
|
|
|
// password is going to be updated, even if the old value is not starting with "{SSHA512}"
|
|
|
|
|
|
|
|
pw_keep_same = false;
|
|
|
|
(pass.clone(), value)
|
|
|
|
};
|
|
|
|
|
|
|
|
if !pw_keep_same {
|
|
|
|
// really easy to update password once ye know how
|
|
|
|
|
|
|
|
let tmp = PasswordModify {
|
|
|
|
// none as we are staying on the same connection
|
|
|
|
user_id: None,
|
|
|
|
|
|
|
|
old_pass: Some(&pass_old),
|
|
|
|
new_pass: Some(&pass_new),
|
|
|
|
};
|
|
|
|
|
|
|
|
ldap.extended(tmp)?.success()?;
|
|
|
|
};
|
|
|
|
|
|
|
|
ldap.unbind()?;
|
|
|
|
|
|
|
|
Ok(json!({"result": "success"}).into())
|
|
|
|
}
|