|
|
@@ -1,13 +1,18 @@
|
|
|
+use std::collections::HashSet;
|
|
|
+use base64::{engine::general_purpose::STANDARD, Engine as _};
|
|
|
use deadpool::managed::Pool;
|
|
|
use ldap3::SearchEntry;
|
|
|
use regex::Regex;
|
|
|
+use ring::rand::{self, SecureRandom};
|
|
|
+use sha2::{Sha512, Digest};
|
|
|
|
|
|
pub mod pool;
|
|
|
|
|
|
use pool::{get_ldap_pool, LdapConfig, LdapManager};
|
|
|
|
|
|
pub enum Error {
|
|
|
- Authfailed(String)
|
|
|
+ Authfailed(String),
|
|
|
+ LdapServerError(String)
|
|
|
}
|
|
|
#[derive(Clone)]
|
|
|
pub struct LdapWrapper {
|
|
|
@@ -38,11 +43,11 @@ impl LdapWrapper {
|
|
|
let (result_entry, _ldap_res) = search_res.success().map_err(|_| {Error::Authfailed(format!("Wrong username or password"))})?;
|
|
|
|
|
|
if result_entry.is_empty() {
|
|
|
- return Err(Error::Authfailed((format!("No record found"))));
|
|
|
+ return Err(Error::Authfailed(format!("No record found")));
|
|
|
}
|
|
|
|
|
|
if result_entry.len() > 1 {
|
|
|
- return Err(Error::Authfailed((format!("Multiple records found"))));
|
|
|
+ return Err(Error::Authfailed(format!("Multiple records found")));
|
|
|
}
|
|
|
|
|
|
let records = SearchEntry::construct(result_entry.first().unwrap().to_owned());
|
|
|
@@ -61,6 +66,58 @@ impl LdapWrapper {
|
|
|
Error::Authfailed(format!("Wrong username or password"))
|
|
|
})
|
|
|
})
|
|
|
- .and(Ok(User{uid: uid, groups: vec!("coucou".to_string())}))
|
|
|
+ .and(Ok(User{uid: uid, groups: vec!("coucou".to_string())})) //TODO: add groups
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn change_password(&self, username: String, password: String, new_password: String) -> Result<(), Error> {
|
|
|
+ let mut salt = [0u8; 4];
|
|
|
+ let salt_generator = rand::SystemRandom::new();
|
|
|
+ let _ = salt_generator.fill(&mut salt);
|
|
|
+
|
|
|
+ let mut password_bytes = new_password.into_bytes();
|
|
|
+ //adding salt to the end of the password
|
|
|
+ salt.map(|elem| {
|
|
|
+ password_bytes.push(elem);
|
|
|
+ });
|
|
|
+
|
|
|
+ //Getting sha512 sum
|
|
|
+ let mut hasher = Sha512::new();
|
|
|
+ hasher.update(password_bytes);
|
|
|
+ let mut hash = hasher.finalize().as_slice().to_vec();
|
|
|
+
|
|
|
+ //Adding salt to the end of hash
|
|
|
+ salt.map(|elem| {
|
|
|
+ hash.push(elem);
|
|
|
+ });
|
|
|
+
|
|
|
+ let b64_new_password = format!("{{SSHA512}}{}", STANDARD.encode(hash));
|
|
|
+
|
|
|
+ let mut ldap = self.ldap_pool.get().await.unwrap();
|
|
|
+
|
|
|
+ let _ = ldap.simple_bind(format!("uid={},{}", username, self.config.basedn).as_str(), &password)
|
|
|
+ .await
|
|
|
+ .map_err(|_| {
|
|
|
+ Error::Authfailed(format!("Wrong current password"))
|
|
|
+ }).and_then(|r| {
|
|
|
+ r.success().map_err(|_| {
|
|
|
+ Error::Authfailed(format!("Wrong current password"))
|
|
|
+ })
|
|
|
+ });
|
|
|
+
|
|
|
+ let hashset= HashSet::from([b64_new_password.as_str()]);
|
|
|
+
|
|
|
+ let data = vec![ldap3::Mod::Replace("userPassword", hashset)];
|
|
|
+
|
|
|
+ ldap.modify(format!("uid={},{}", username, self.config.basedn).as_str(), data)
|
|
|
+ .await
|
|
|
+ .map_err(|e| {
|
|
|
+ Error::LdapServerError(format!("An error occured, contact admins: {}", e))
|
|
|
+ })
|
|
|
+ .and_then(|r| {
|
|
|
+ r.success().map_err(|e| {
|
|
|
+ Error::LdapServerError(format!("An error occured, contact admins: {}", e))
|
|
|
+ })
|
|
|
+ })
|
|
|
+ .and(Ok(()))
|
|
|
}
|
|
|
}
|