use crate::pki::{EPFCertificate, EpfPkiSerializable, EpfPublicKey};
use crate::util::verifying_key;
use std::collections::HashMap;
use std::error::Error;
use std::ffi::OsStr;
use std::fmt::{Display, Formatter};
use std::fs;
pub struct EpfCaPool {
pub ca_lookup_table: HashMap<EpfPublicKey, EPFCertificate>,
}
pub trait EpfCaPoolOps {
fn new() -> Self;
fn get_ca(&self, public_key: &EpfPublicKey) -> Option<&EPFCertificate>;
fn insert(&mut self, cert: &EPFCertificate);
}
impl EpfCaPoolOps for EpfCaPool {
fn new() -> Self {
Self {
ca_lookup_table: HashMap::new(),
}
}
fn get_ca(&self, public_key: &EpfPublicKey) -> Option<&EPFCertificate> {
self.ca_lookup_table.get(public_key)
}
fn insert(&mut self, cert: &EPFCertificate) {
self.ca_lookup_table
.insert(verifying_key(&cert.details.public_key), cert.clone());
}
}
#[derive(Debug)]
pub enum EpfCaPoolLoaderError {
CertDirDoesNotExist(String),
}
impl Display for EpfCaPoolLoaderError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
EpfCaPoolLoaderError::CertDirDoesNotExist(d) => {
write!(f, "Certificate dir does not exist: {}", d)
}
}
}
}
impl Error for EpfCaPoolLoaderError {}
#[cfg(unix)]
#[cfg(not(tarpaulin))]
pub fn load_ca_pool() -> Result<EpfCaPool, Box<dyn Error>> {
let mut cert_strings = vec![];
for entry in fs::read_dir("/etc/e3pf/certs")? {
let entry = entry?;
if entry.path().extension() == Some(OsStr::new("pem")) {
cert_strings.push(fs::read_to_string(entry.path())?);
}
}
let mut ca_pool = EpfCaPool::new();
for cert in cert_strings {
ca_pool.insert(&EPFCertificate::from_pem(cert.as_bytes())?);
}
Ok(ca_pool)
}
#[cfg(test)]
mod tests {
use crate::ca_pool::EpfCaPoolLoaderError;
#[test]
pub fn ca_pool_error_display_test() {
println!(
"{}",
EpfCaPoolLoaderError::CertDirDoesNotExist("".to_string())
);
}
}