You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
2.7 KiB
129 lines
2.7 KiB
//! Used for resolving autodetects
|
|
use super::*;
|
|
use std::{
|
|
path::{
|
|
Path,
|
|
},
|
|
error,
|
|
fmt,
|
|
io,
|
|
};
|
|
use tokio::{
|
|
prelude::*,
|
|
fs::{
|
|
OpenOptions,
|
|
File,
|
|
},
|
|
io::{
|
|
BufReader,
|
|
},
|
|
};
|
|
|
|
use config::op::KeyFormat;
|
|
|
|
/// Find the format (Binary, Text, PEM) of this key file.
|
|
///
|
|
/// # Note
|
|
/// This isn't an infallible test as it only parses parts of headers, if it detects a type it doesn't guarantee that the file *actually* is that type. It is just a hint or best-guess.
|
|
#[instrument(err, skip(path), fields(path = ?path.as_ref()))]
|
|
pub async fn find_key_format(path: impl AsRef<Path>, can_pem: bool) -> eyre::Result<KeyFormat>
|
|
{
|
|
async fn check_bin(file: &mut File) -> Result<bool, Error>
|
|
{
|
|
let mut buffer = [0u8; 4];
|
|
file.read_exact(&mut buffer[..]).await?;
|
|
Ok(&buffer[..] == format::RAE_HEADER_BIT)
|
|
}
|
|
async fn check_text(file: &mut File) -> Result<bool, Error>
|
|
{
|
|
let mut buffer = [0u8; 4];
|
|
file.read_exact(&mut buffer[..]).await?;
|
|
if &buffer[..] != b"--- " {
|
|
return Ok(false);
|
|
}
|
|
file.read_exact(&mut buffer[..]).await?;
|
|
Ok(&buffer[..] == format::RAE_HEADER_BIT)
|
|
}
|
|
async fn check_pem(file: &mut File) -> Result<bool, Error>
|
|
{
|
|
todo!("I don't remember the PEM format right now")
|
|
}
|
|
let mut file = {
|
|
let path = path.as_ref();
|
|
OpenOptions::new()
|
|
.read(true)
|
|
.open(path).await
|
|
.wrap_err(eyre::eyre!("Failed to open file to check"))
|
|
.with_section(|| format!("{:?}", path).header("Path was"))?
|
|
};
|
|
|
|
macro_rules! reset {
|
|
() => {
|
|
file.seek(std::io::SeekFrom::Start(0)).await?
|
|
}
|
|
}
|
|
|
|
if can_pem {
|
|
if check_pem(&mut file).await
|
|
.with_note(|| "With check for PEM")? {
|
|
return Ok(KeyFormat::PEM);
|
|
} else {
|
|
reset!();
|
|
}
|
|
}
|
|
if check_bin(&mut file).await
|
|
.with_note(|| "With check for binary")? {
|
|
return Ok(KeyFormat::Bin);
|
|
} else {
|
|
reset!();
|
|
}
|
|
if check_text(&mut file).await
|
|
.with_note(|| "With check for text")? {
|
|
return Ok(KeyFormat::Text);
|
|
}
|
|
|
|
return Err(Error::UnknownFormat)?;
|
|
}
|
|
|
|
pub async fn find_file_mode<P: AsRef<Path>>(path: P) -> Result<config::op::Mode, Error>
|
|
{
|
|
//TODO: we need to calculate mode here
|
|
|
|
todo!()
|
|
}
|
|
|
|
pub async fn find_key_mode<P: AsRef<Path>>(path: P) -> Result<config::KeyKind, Error>
|
|
{
|
|
//TODO: we need to calculate mode here
|
|
|
|
todo!()
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
#[non_exhaustive]
|
|
pub enum Error
|
|
{
|
|
UnknownFormat,
|
|
IO(io::Error),
|
|
Unknown,
|
|
}
|
|
|
|
impl error::Error for Error{}
|
|
impl fmt::Display for Error
|
|
{
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
|
{
|
|
match self {
|
|
_ => write!(f, "unknown error"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<io::Error> for Error
|
|
{
|
|
#[inline] fn from(from: io::Error) -> Self
|
|
{
|
|
Self::IO(from)
|
|
}
|
|
}
|