This commit is contained in:
aiden 2023-05-25 04:58:55 +01:00
parent 350ccae12a
commit 2a6f6a0413
Signed by: aiden
GPG Key ID: EFA9C74AEBF806E0
4 changed files with 24 additions and 83 deletions

View File

@ -3,12 +3,9 @@ name = "acmec"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version = "1.0.136", features = ["derive"] }
reqwest = { version = "*", features = ["blocking", "json"] }
openssl = "0.10.38"
serde_json = "1.0.79"
[features]
dropfile = { git = "https://github.com/bridgeloop/dropfile.git" }

View File

@ -1,55 +0,0 @@
use std::{fs::File, io::{Seek, Write}};
pub struct CleanFile {
path: String,
file: Option<File>,
created: bool,
written_to: bool,
}
impl CleanFile {
pub fn open(path: String, create: bool) -> Result<Self, &'static str> {
let mut file_options = File::options();
file_options.read(true).write(true).create_new(create);
let file = file_options.open(&(path)).map_err(|err| match err.kind() {
std::io::ErrorKind::AlreadyExists => "file already exists",
_ => "failed to open file"
})?;
return Ok(Self { path, file: Some(file), created: create, written_to: false, });
}
fn delete_file(&mut self) -> Result<(), &'static str> {
return if let Some(_) = self.file.take() {
std::fs::remove_file(&(self.path)).map_err(|_| "failed to delete file")
} else { Ok(()) };
}
pub fn delete(mut self) -> Result<(), &'static str> {
return self.delete_file();
}
pub fn write<T: AsRef<[u8]>>(&mut self, bytes: T) -> Result<(), &'static str> {
let file: &mut File = self.file.as_mut().ok_or("file deleted")?;
file.set_len(0).map_err(|_| "failed to truncate file")?;
file.seek(std::io::SeekFrom::Start(0)).map_err(|_| "failed to seek file")?;
file.write_all(bytes.as_ref()).map_err(|_| "failed to write to file")?;
self.written_to = true;
return Ok(());
}
pub fn file(&self) -> Result<&File, &'static str> {
return self.file.as_ref().ok_or("file deleted");
}
pub fn path(&self) -> &str {
return &(self.path);
}
}
impl Drop for CleanFile {
fn drop(&mut self) {
if self.created && !self.written_to {
self.delete_file().unwrap();
}
}
}

View File

@ -1,5 +1,6 @@
use std::ops::{Deref, DerefMut};
use crate::{clean_file::CleanFile, stringify_ser};
use std::{ops::{Deref, DerefMut}, path::Path};
use crate::stringify_ser;
use dropfile::DropFile;
mod acmec_config;
use acmec_config::AcmecConfig;
@ -22,20 +23,20 @@ pub struct OrderDetails {
}
pub struct ConfigFile {
clean_file: Option<CleanFile>,
file: Option<DropFile>,
config: AcmecConfig,
}
impl ConfigFile {
pub fn open(path: String, create: bool) -> Result<Self, &'static str> {
let clean_file = CleanFile::open(path, create)?;
let config: AcmecConfig = serde_json::from_reader(clean_file.file().unwrap()).unwrap_or_default();
return Ok(Self { clean_file: Some(clean_file), config, });
let mut file = DropFile::open(path, create)?;
let config: AcmecConfig = serde_json::from_reader(&mut(file)).unwrap_or_default();
return Ok(Self { file: Some(file), config, });
}
pub fn delete(mut self) -> Result<(), &'static str> {
return self.clean_file.take().unwrap().delete();
return self.file.take().unwrap().delete();
}
pub fn path(&self) -> &str {
return self.clean_file.as_ref().unwrap().path();
pub fn path(&self) -> &Path {
return self.file.as_ref().unwrap().path();
}
}
impl Deref for ConfigFile {
@ -51,12 +52,12 @@ impl DerefMut for ConfigFile {
}
impl Drop for ConfigFile {
fn drop(&mut self) {
let Some(mut clean_file) = self.clean_file.take() else {
let Some(mut file) = self.file.take() else {
return;
};
if self.changed() {
let json_config = stringify_ser(&(self.config)).unwrap();
clean_file.write(json_config).unwrap();
file.write_trunc(json_config.as_bytes()).unwrap();
}
}
}
}

View File

@ -38,13 +38,11 @@ use openssl::{
};
use reqwest::{self, header::HeaderValue, blocking::{Client as HttpClient, Response as HttpResponse}};
use {serde, serde_json};
use dropfile::DropFile;
mod acme;
use acme::*;
mod clean_file;
use clean_file::*;
mod config_file;
use config_file::*;
@ -303,7 +301,7 @@ fn main() -> Result<(), &'static str> {
let config_file = ConfigFile::open(config_path, false)?;
let mut context = AcmecContext::with_config_file(&(config_file), pem_passphrase)?;
println!("REALLY delete \"{}\"? this cannot be undone! [yes / any other line]", config_file.path());
println!("REALLY delete \"{}\"? this cannot be undone! [yes / any other line]", config_file.path().display());
let mut buf = String::new();
std::io::stdin().read_line(&mut(buf)).expect("failed to read line from stdin");
if buf != "yes\n" {
@ -381,8 +379,8 @@ fn main() -> Result<(), &'static str> {
let cert_path = args_iter.next().ok_or("expected path to cert file")?;
let pkey_path = args_iter.next().ok_or("expected path to pkey file")?;
let mut cert_file = CleanFile::open(cert_path, true)?;
let mut pkey_file = CleanFile::open(pkey_path, true)?;
let mut cert_file = DropFile::open(cert_path, true)?;
let mut pkey_file = DropFile::open(pkey_path, true)?;
for url in &(order.challenges) {
acme_post(&mut(context), &(url), "{}")?;
@ -449,11 +447,11 @@ fn main() -> Result<(), &'static str> {
.text()
.map_err(|_| "failed to read response")?;
if let Err(_) = cert_file.write(&(cert)) {
if let Err(_) = cert_file.write_trunc(cert.as_bytes()) {
eprintln!("failed to write certificate to file, printing to stdout instead");
println!("{}", cert);
}
if let Err(_) = pkey_file.write(&*(pkey_pem)) {
if let Err(_) = pkey_file.write_trunc(pkey_pem) {
eprintln!("failed to write private key to file, printing to stdout instead");
println!("{}", pkey_pem_view);
}
@ -488,14 +486,14 @@ fn main() -> Result<(), &'static str> {
builder.sign(&(kp), MessageDigest::sha256()).unwrap();
let cert_pem = builder.build().to_pem().map_err(|_| "failed to encode certificate as pem")?;
let mut cert_file = CleanFile::open(cert_path, true)?;
let mut priv_file = CleanFile::open(key_path, true)?;
let mut cert_file = DropFile::open(cert_path, true)?;
let mut priv_file = DropFile::open(key_path, true)?;
if let Err(_) = cert_file.write(&(cert_pem)) {
if let Err(_) = cert_file.write_trunc(&(cert_pem)) {
eprintln!("failed to write certificate! printing to stdout instead...");
println!("{}", from_utf8(&(cert_pem)).unwrap());
}
if let Err(_) = priv_file.write(&(priv_pem)) {
if let Err(_) = priv_file.write_trunc(&(priv_pem)) {
eprintln!("failed to write private key! printing to stdout instead...");
println!("{}", from_utf8(&(priv_pem)).unwrap());
}