feat: turns out there is an extended ldap3 operation called password modify
This commit is contained in:
parent
f8089113f5
commit
aa196ba33b
3 changed files with 30 additions and 131 deletions
86
Cargo.lock
generated
86
Cargo.lock
generated
|
@ -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",
|
||||||
|
|
|
@ -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"
|
||||||
|
|
72
src/main.rs
72
src/main.rs
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue