rudo/src/cache.rs

94 lines
2.9 KiB
Rust

use std::{
fs::{DirBuilder, File, OpenOptions},
io::{Read, Write},
path::PathBuf,
time::{Duration, SystemTime},
};
use fork::{daemon, Fork};
use libc::kill;
const DEFAULT_AUTH_CACHE_DURATION: u64 = 5 * 60;
const AUTH_CACHE_PATH: &str = "/tmp/rudo/cache/auth/";
const SESSION_CACHE_PATH: &str = "/tmp/rudo/cache/session/";
pub fn clear_auth_cache(alias: &str, ppid: u32) -> Result<(), std::io::Error> {
let ppid_str = format!["{ppid}"];
let mut path = PathBuf::from(SESSION_CACHE_PATH);
path.push(&ppid_str);
if let Err(e) = std::fs::remove_file(&path) {
println!["Failed to remove session file: {e}"];
std::process::exit(1);
}
let mut path = PathBuf::from(AUTH_CACHE_PATH);
path.push(ppid_str);
path.push(alias);
if let Err(e) = std::fs::remove_dir_all(&path) {
println!["Failed to remove session dir: {e}"];
std::process::exit(1);
}
Ok(())
}
pub fn update_auth_cache(alias: &str, ppid: u32) -> Result<(), std::io::Error> {
let ppid_str = format!["{ppid}"];
let mut session_path = PathBuf::from(SESSION_CACHE_PATH);
DirBuilder::new().recursive(true).create(&session_path)?;
session_path.push(&ppid_str);
let mut timestamp_path = PathBuf::from(AUTH_CACHE_PATH);
timestamp_path.push(ppid_str);
DirBuilder::new().recursive(true).create(&timestamp_path)?;
timestamp_path.push(alias);
let mut opts = OpenOptions::new();
opts.write(true).create(true);
let mut timestamp_file = opts.open(&timestamp_path)?;
let time = SystemTime::now() + Duration::from_secs(DEFAULT_AUTH_CACHE_DURATION);
timestamp_file.write_all(&bincode::serialize(&time).unwrap_or_default())?;
match OpenOptions::new()
.create_new(true)
.write(true)
.open(&session_path)
{
Ok(_) => {
if let Ok(Fork::Child) = daemon(false, false) {
std::thread::sleep(Duration::from_secs(DEFAULT_AUTH_CACHE_DURATION));
if unsafe { kill(ppid as _, 0) } == -1 {
clear_auth_cache(alias, ppid)?;
}
}
}
Err(_) => (),
};
Ok(())
}
pub fn check_auth_cache(alias: &str, ppid: u32) -> bool {
let mut path = PathBuf::from(AUTH_CACHE_PATH);
path.push(format!["{ppid}"]);
path.push(alias);
let mut file = if let Ok(file) = File::open(&path) {
file
} else {
return false;
};
let mut buf = Vec::new();
if let Err(_) = file.read_to_end(&mut buf) {
return false;
};
match bincode::deserialize::<SystemTime>(&buf) {
Ok(old_time) => {
if old_time.elapsed().unwrap_or_default()
< Duration::from_secs(DEFAULT_AUTH_CACHE_DURATION as u64)
{
true
} else {
false
}
}
Err(e) => {
dbg!["{}", e];
false
}
}
}