1use crate::pki::{EPFCertificate, EpfPkiSerializable, EpfPublicKey};
2use crate::util::verifying_key;
3
4use std::collections::HashMap;
5use std::error::Error;
6use std::ffi::OsStr;
7use std::fmt::{Display, Formatter};
8use std::fs;
9
10pub struct EpfCaPool {
11 pub ca_lookup_table: HashMap<EpfPublicKey, EPFCertificate>,
12}
13
14pub trait EpfCaPoolOps {
15 fn new() -> Self;
16 fn get_ca(&self, public_key: &EpfPublicKey) -> Option<&EPFCertificate>;
17 fn insert(&mut self, cert: &EPFCertificate);
18}
19
20impl EpfCaPoolOps for EpfCaPool {
21 fn new() -> Self {
22 Self {
23 ca_lookup_table: HashMap::new(),
24 }
25 }
26
27 fn get_ca(&self, public_key: &EpfPublicKey) -> Option<&EPFCertificate> {
28 self.ca_lookup_table.get(public_key)
29 }
30
31 fn insert(&mut self, cert: &EPFCertificate) {
32 self.ca_lookup_table
33 .insert(verifying_key(&cert.details.public_key), cert.clone());
34 }
35}
36
37#[derive(Debug)]
38pub enum EpfCaPoolLoaderError {
39 CertDirDoesNotExist(String),
40}
41impl Display for EpfCaPoolLoaderError {
42 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
43 match self {
44 EpfCaPoolLoaderError::CertDirDoesNotExist(d) => {
45 write!(f, "Certificate dir does not exist: {}", d)
46 }
47 }
48 }
49}
50impl Error for EpfCaPoolLoaderError {}
51
52#[cfg(unix)]
53#[cfg(not(tarpaulin))]
54pub fn load_ca_pool() -> Result<EpfCaPool, Box<dyn Error>> {
55 let mut cert_strings = vec![];
56
57 for entry in fs::read_dir("/etc/e3pf/certs")? {
58 let entry = entry?;
59 if entry.path().extension() == Some(OsStr::new("pem")) {
60 cert_strings.push(fs::read_to_string(entry.path())?);
61 }
62 }
63
64 let mut ca_pool = EpfCaPool::new();
65
66 for cert in cert_strings {
67 ca_pool.insert(&EPFCertificate::from_pem(cert.as_bytes())?);
68 }
69
70 Ok(ca_pool)
71}
72
73#[cfg(test)]
74mod tests {
75 use crate::ca_pool::EpfCaPoolLoaderError;
76
77 #[test]
78 pub fn ca_pool_error_display_test() {
79 println!(
80 "{}",
81 EpfCaPoolLoaderError::CertDirDoesNotExist("".to_string())
82 );
83 }
84}