use std::{fs::File, io::prelude::*, path::Path};
use rand::{RngExt, distr::Alphanumeric};
use crate::error::Error;
pub fn read_shared_secret(path: &Path) -> Result<Vec<u8>, Error> {
let mut file = File::open(path).map_err(|err| {
Error::IoPathError(
path.to_path_buf(),
"opening secret file. Did you start the daemon at least once?",
err,
)
})?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)
.map_err(|err| Error::IoPathError(path.to_path_buf(), "reading secret file", err))?;
Ok(buffer)
}
pub fn init_shared_secret(path: &Path) -> Result<(), Error> {
if path.exists() {
return Ok(());
}
const PASSWORD_LEN: usize = 512;
let mut rng = rand::rng();
let secret: String = std::iter::repeat(())
.map(|()| rng.sample(Alphanumeric))
.map(char::from)
.take(PASSWORD_LEN)
.collect();
let mut file = File::create(path)
.map_err(|err| Error::IoPathError(path.to_path_buf(), "creating shared secret", err))?;
file.write_all(&secret.into_bytes())
.map_err(|err| Error::IoPathError(path.to_path_buf(), "writing shared secret", err))?;
#[cfg(not(target_os = "windows"))]
{
use std::os::unix::fs::PermissionsExt;
let mut permissions = file
.metadata()
.map_err(|err| {
Error::IoPathError(path.to_path_buf(), "reading secret file metadata", err)
})?
.permissions();
permissions.set_mode(0o640);
std::fs::set_permissions(path, permissions).map_err(|err| {
Error::IoPathError(path.to_path_buf(), "setting secret file permissions", err)
})?;
}
Ok(())
}