ldap_backend/src/main.rs

137 lines
3.3 KiB
Rust
Raw Normal View History

2023-05-25 21:02:42 +00:00
use std::collections::HashSet;
use ldap3::result::Result;
use ldap3::{LdapConn, Scope, SearchEntry, Mod};
use base64::{Engine as _, engine::general_purpose};
use crypto::{sha2::Sha512, digest::Digest};
2023-05-25 23:02:12 +00:00
// for teh webserver
use sqlx::{Pool, Sqlite};
use std::env;
use dotenv::dotenv;
use tide::prelude::*;
use tide::{Request, Response};
use skynet_ldap_server::db_init;
#[derive(Clone)]
struct State {
db: Pool<Sqlite>,
config: Config,
}
#[async_std::main]
async fn main() -> tide::Result<()> {
let config = get_config();
let db = db_init(&config.database).await?;
let host_port = config.host_port.clone();
tide::log::start();
let state = State {
db,
config,
};
let mut app = tide::with_state(state);
//app.at("/steam_ost/:username").get(results_get);
app.listen(host_port).await?;
Ok(())
}
#[derive(Debug, Clone)]
struct Config {
ldap_host: String,
database: String,
host_port: String,
}
fn get_config() -> Config {
dotenv().ok();
// reasonable defaults
let mut config = Config {
ldap_host: "".to_string(),
database: "database.db".to_string(),
host_port: "127.0.0.1:8087".to_string(),
};
if let Ok(x) = env::var("LDAP_HOST") {
config.key = x.trim().to_string();
}
if let Ok(x) = env::var("DATABASE") {
config.database = x.trim().to_string();
}
if let Ok(x) = env::var("HOST_PORT") {
config.host_port = x.trim().to_string();
}
config
}
2023-05-25 21:02:42 +00:00
//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
}
2023-05-25 23:02:12 +00:00
async fn post_update_ldap(mut req: Request<State>) -> tide::Result {
2023-05-25 21:02:42 +00:00
let mut ldap = LdapConn::new("ldaps://sso.skynet.ie")?;
2023-05-25 23:02:12 +00:00
2023-05-25 21:02:42 +00:00
let user = "silver";
let pass = "";
let field = "sshPublicKey";
let value = "em232323232323";
2023-05-25 23:02:12 +00:00
2023-05-25 21:02:42 +00:00
let dn = format!("uid={},ou=users,dc=skynet,dc=ie", user);
ldap.simple_bind(&dn, pass)?.success()?;
// always assume insecure
let mut secure = false;
2023-05-25 23:02:12 +00:00
2023-05-25 21:02:42 +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("{SHA512}") {
secure = true;
}
}
let mut mods = vec![
Mod::Replace(field, HashSet::from([value]))
];
let mut pw_hashset = HashSet::new();
let pass_tmp;
if !secure {
let mut hasher = Sha512::new();
hasher.input_str(pass);
// get it as hex string
let hex = hasher.result_str();
2023-05-25 23:02:12 +00:00
2023-05-25 21:02:42 +00:00
// convert it to b64
pass_tmp = format!("{{SHA512}}{}", hex_to_base64(&hex));
pw_hashset.insert(pass_tmp.as_str());
mods.push(Mod::Replace("userPassword", pw_hashset));
};
2023-05-25 23:02:12 +00:00
ldap.unbind()?;
Ok(format!("Hello, {}! I've put in an order for {} shoes", "name", "legs").into())
2023-05-25 16:01:50 +00:00
}