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

86
Cargo.lock generated
View file

@ -359,12 +359,6 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]] [[package]]
name = "bincode" name = "bincode"
version = "1.3.3" version = "1.3.3"
@ -844,12 +838,6 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.28" version = "0.3.28"
@ -965,12 +953,6 @@ dependencies = [
"slab", "slab",
] ]
[[package]]
name = "gcc"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.7" version = "0.14.7"
@ -1671,29 +1653,6 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "rand"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
dependencies = [
"libc",
"rand 0.4.6",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi",
]
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.7.3" version = "0.7.3"
@ -1738,21 +1697,6 @@ dependencies = [
"rand_core 0.6.4", "rand_core 0.6.4",
] ]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]] [[package]]
name = "rand_core" name = "rand_core"
version = "0.5.1" version = "0.5.1"
@ -1780,15 +1724,6 @@ dependencies = [
"rand_core 0.5.1", "rand_core 0.5.1",
] ]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.16" version = "0.2.16"
@ -1813,25 +1748,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e" checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e"
[[package]]
name = "rust-crypto"
version = "0.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
dependencies = [
"gcc",
"libc",
"rand 0.3.23",
"rustc-serialize",
"time 0.1.45",
]
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
[[package]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.2.3" version = "0.2.3"
@ -2049,10 +1965,8 @@ name = "skynet_ldap_server"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async-std", "async-std",
"base64 0.21.2",
"dotenv", "dotenv",
"ldap3", "ldap3",
"rust-crypto",
"serde", "serde",
"sqlx", "sqlx",
"surf", "surf",

View file

@ -8,9 +8,6 @@ edition = "2021"
[dependencies] [dependencies]
# for the ldap # for the ldap
ldap3="0.11.1" ldap3="0.11.1"
# to be able to upgrade user passwords
base64 = "0.21"
rust-crypto = "^0.2"
# to move some config into env # to move some config into env
dotenv = "0.15.0" dotenv = "0.15.0"

View file

@ -1,8 +1,7 @@
use ldap3::{LdapConn, Mod, Scope, SearchEntry}; use ldap3::{LdapConn, Mod, Scope, SearchEntry};
use std::collections::HashSet;
use base64::{engine::general_purpose, Engine as _}; use ldap3::exop::{PasswordModify, PasswordModifyResp};
use crypto::{digest::Digest, sha2::Sha512}; use std::collections::HashSet;
// for teh webserver // for teh webserver
use dotenv::dotenv; use dotenv::dotenv;
@ -69,21 +68,6 @@ fn get_config() -> 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)] #[derive(Debug, Deserialize)]
struct LdapUpdate { struct LdapUpdate {
user: String, 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()?; let (rs, _res) = ldap.search(&dn, Scope::Base, "(objectClass=*)", vec!["userPassword"])?.success()?;
if !rs.is_empty() { if !rs.is_empty() {
let tmp = SearchEntry::construct(rs[0].clone()); 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; pw_keep_same = true;
} }
} }
let mut mods = vec![];
// check if the password field itself is being updated // check if the password field itself is being updated
let pass_new = if &field != "userPassword" { let (pass_old, pass_new) = if &field != "userPassword" {
mods.push(Mod::Replace(field, HashSet::from([value]))); // if password is not being updated then just update the required field
// retain the older password let mods = vec![
pass Mod::Replace(field, HashSet::from([value]))
];
ldap.modify(&dn, mods)?.success()?;
// pass back the "old" and "new" passwords
(pass.clone(), pass.clone())
} else { } else {
// password is going to be updated, even if the old value is not starting with "{SSHA512}"
pw_keep_same = false; pw_keep_same = false;
value (pass.clone(), value.clone())
}; };
if !pw_keep_same { 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); ldap.extended(tmp)?.success()?;
// 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.modify(&dn, mods)?.success()?;
ldap.unbind()?; ldap.unbind()?;
Ok(json!({"result": "success"}).into()) Ok(json!({"result": "success"}).into())
} }
/** Create new account /* Create new account
1. Check if ID is available 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 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 update the groups
check if there are any pending signups check if there are any pending signups