feat: turns out there is an extended ldap3 operation called password modify

This commit is contained in:
silver 2023-05-26 10:37:50 +01:00
parent f8089113f5
commit aa196ba33b
3 changed files with 30 additions and 131 deletions

View file

@ -1,8 +1,7 @@
use ldap3::{LdapConn, Mod, Scope, SearchEntry};
use std::collections::HashSet;
use base64::{engine::general_purpose, Engine as _};
use crypto::{digest::Digest, sha2::Sha512};
use ldap3::exop::{PasswordModify, PasswordModifyResp};
use std::collections::HashSet;
// for teh webserver
use dotenv::dotenv;
@ -69,21 +68,6 @@ fn get_config() -> Config {
config
}
//https://stackoverflow.com/a/44532957
pub fn hex_to_base64(hex: &str) -> String {
// Make vector of bytes from octets
let mut bytes = Vec::new();
for i in 0..(hex.len() / 2) {
let res = u8::from_str_radix(&hex[2 * i..2 * i + 2], 16);
match res {
Ok(v) => bytes.push(v),
Err(e) => println!("Problem with hex: {}", e),
};
}
general_purpose::STANDARD.encode(&bytes) // now convert from Vec<u8> to b64-encoded String
}
#[derive(Debug, Deserialize)]
struct LdapUpdate {
user: String,
@ -114,46 +98,50 @@ async fn post_update_ldap(mut req: Request<State>) -> tide::Result {
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("{SHA512}") {
if !tmp.attrs["userPassword"].is_empty() && tmp.attrs["userPassword"][0].starts_with("{SSHA512}") {
pw_keep_same = true;
}
}
let mut mods = vec![];
// check if the password field itself is being updated
let pass_new = if &field != "userPassword" {
mods.push(Mod::Replace(field, HashSet::from([value])));
// retain the older password
pass
let (pass_old, pass_new) = if &field != "userPassword" {
// if password is not being updated then just update the required field
let mods = vec![
Mod::Replace(field, HashSet::from([value]))
];
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;
value
(pass.clone(), value.clone())
};
if !pw_keep_same {
let mut hasher = Sha512::new();
// 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),
};
hasher.input_str(&pass_new);
// get it as hex string
let hex = hasher.result_str();
// convert it to b64
let pass_tmp = format!("{{SHA512}}{}", hex_to_base64(&hex));
mods.push(Mod::Replace(String::from("userPassword"), HashSet::from([pass_tmp])));
ldap.extended(tmp)?.success()?;
};
ldap.modify(&dn, mods)?.success()?;
ldap.unbind()?;
Ok(json!({"result": "success"}).into())
}
/** Create new account
/* Create new account
1. Check if ID is available
@ -170,16 +158,16 @@ async fn post_update_ldap(mut req: Request<State>) -> tide::Result {
*/
/** Join existing account to wolves
/* Join existing account to wolves
related to above
*/
/** Password reset via email
/* Password reset via email
*/
/** script to pull in all active members from wolves
/* script to pull in all active members from wolves
update the groups
check if there are any pending signups