pub mod vault {
pub mod lock;
pub mod genpwd;
}
use vault::lock::Lock;
use std::path::PathBuf;
use std::sync::OnceLock;
use std::process;
use std::io::ErrorKind;
use std::sync::Arc;
use libeipc::EIPC_Server;
use base64::{encode, decode};
use std::sync::Mutex;
use crate::config::Config;
static LOCK: OnceLock<Mutex<Lock>> = OnceLock::new();
pub struct SPMGD {
pub running: bool,
store: std::collections::HashMap<String, String>,
}
impl SPMGD {
pub fn new(config: Config) -> Self {
let cfg_rc = Arc::new(config);
std::fs::create_dir_all(&cfg_rc.spmg_path).unwrap();
let spmg_path = PathBuf::from(cfg_rc.spmg_path.clone());
if LOCK.set(Mutex::new(Lock::new(cfg_rc.clone(), spmg_path.join("pwds.lock")))).is_err() {
eprintln!("LOCK is already initialized!");
}
let socket_path = format!("{}/socket", cfg_rc.spmg_path);
let mut unix_socket_listener = EIPC_Server::new(&socket_path, cfg_rc.hkdf_salt.clone());
unix_socket_listener.set_handler("init", Box::new(|args: &str, ppid: u32| -> String {
println!("Creating a new lock!");
if let Some(lock) = LOCK.get() {
let mut lock = lock.lock().unwrap();
lock.init(ppid, args);
}
String::from("OK")
}));
unix_socket_listener.set_handler("get-cached", Box::new(|args: &str, ppid: u32| -> String {
if let Some(lock) = LOCK.get() {
let mut lock = lock.lock().unwrap();
if let Ok(key) = lock.get_cached_key(ppid) {
encode(key)
} else {
String::from("NONE")
}
} else {
String::from("NOLOCK")
}
}));
unix_socket_listener.set_handler("clear-cache", Box::new(|args: &str, ppid: u32| -> String {
if let Some(lock) = LOCK.get() {
let mut lock = lock.lock().unwrap();
match lock.clear_cache(ppid) {
Ok(result) => {
result
}
Err(err) => {
eprintln!("{}", err);
String::from("NOT-CACHED")
}
}
} else {
String::from("NOLOCK")
}
}));
unix_socket_listener.set_handler("cache-expiration", Box::new(|args: &str, ppid: u32| -> String {
if let Some(lock) = LOCK.get() {
let mut lock = lock.lock().unwrap();
if let Ok(cache_expiration) = lock.get_cache_expiration(ppid) {
cache_expiration.to_string()
} else {
String::from("NONE")
}
} else {
String::from("NOLOCK")
}
}));
unix_socket_listener.set_handler("add", Box::new(|arg_str: &str, ppid: u32| -> String {
let args: Vec<&str> = arg_str.split_whitespace().collect();
let mut pwd: Option<String> = None;
if let Some(lock) = LOCK.get() {
let mut lock = lock.lock().unwrap();
let add_result = lock.add(ppid, args[0], args[1], args[2]);
match add_result {
Ok(got_pwd) => {
String::from("OK")
},
Err(ref e) if e.kind() == ErrorKind::InvalidData => {
String::from("ERR UNAUTH")
},
Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {
String::from("ERR EXISTS")
},
Err(ref e) if e.kind() == ErrorKind::NotConnected => {
String::from("ERR NOLOCK")
},
Err(e) => {
String::from("ERR OR")
}
}
} else {
String::from("NOLOCK")
}
}));
unix_socket_listener.set_handler("new", Box::new(|args: &str, ppid: u32| -> String {
String::from("CREATED")
}));
unix_socket_listener.set_handler("get", Box::new(|arg_str: &str, ppid: u32| -> String {
let args: Vec<&str> = arg_str.split_whitespace().collect();
let mut pwd: Option<String> = None;
if let Some(lock) = LOCK.get() {
let mut lock = lock.lock().unwrap();
let get_result = lock.get(ppid, args[0], args[1]);
match get_result {
Ok(got_pwd) => {
got_pwd
},
Err(ref e) if e.kind() == ErrorKind::InvalidData => {
String::from("ERR UNAUTH")
},
Err(ref e) if e.kind() == ErrorKind::NotFound => {
String::from("ERR NOTFOUND")
},
Err(ref e) if e.kind() == ErrorKind::NotConnected => {
String::from("ERR NOLOCK")
},
Err(e) => {
String::from("ERR OR")
}
}
} else {
String::from("NOLOCK")
}
}));
unix_socket_listener.set_handler("kill", Box::new(|args: &str, ppid: u32| -> String {
process::exit(0);
}));
unix_socket_listener.open();
Self {
running: false,
store: std::collections::HashMap::new(),
}
}
}