Partially implement ClientCertificateStore
for Filesystem
This commit is contained in:
parent
b957138048
commit
e1239fea58
2 changed files with 111 additions and 15 deletions
|
@ -5,6 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
digest = "0.10"
|
||||
rustls-pemfile = "1.0"
|
||||
sha2 = "0.10"
|
||||
time = "0.3"
|
||||
x509-parser = "0.15"
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
use std::io::BufReader;
|
||||
|
||||
use crate::prelude::Certificate;
|
||||
|
||||
use {
|
||||
super::*,
|
||||
crate::{message::Parser as MessageParser, prelude::ParseMailboxError},
|
||||
crate::{
|
||||
message::Parser as MessageParser,
|
||||
prelude::{ClientCertificateStore, ParseMailboxError},
|
||||
},
|
||||
rustls_pemfile::{read_one, Item},
|
||||
std::{
|
||||
ffi::OsString,
|
||||
fs::{self, File},
|
||||
io::{self, BufWriter, Write},
|
||||
iter,
|
||||
os::unix::fs::DirBuilderExt,
|
||||
path::{Path, PathBuf},
|
||||
},
|
||||
|
@ -141,11 +150,8 @@ impl MailStore for Filesystem {
|
|||
}
|
||||
|
||||
fn get_message(&self, user: &str, folder: &str, id: &str) -> Option<Message> {
|
||||
self.get_folder(user, folder).and_then(|f| {
|
||||
f.messages
|
||||
.get(id)
|
||||
.cloned()
|
||||
})
|
||||
self.get_folder(user, folder)
|
||||
.and_then(|f| f.messages.get(id).cloned())
|
||||
}
|
||||
|
||||
fn add_message(
|
||||
|
@ -288,6 +294,77 @@ impl MultiDomain for Filesystem {
|
|||
}
|
||||
}
|
||||
|
||||
impl ClientCertificateStore for Filesystem {
|
||||
fn get_certificate(&self, user: &Mailuser) -> Option<Certificate> {
|
||||
let mut path = self.path.clone();
|
||||
path.push(&user.host.to_string());
|
||||
path.push(&user.username);
|
||||
path.push("certificate.pem");
|
||||
if path.exists() {
|
||||
let Ok(fd) = File::open(&path) else {
|
||||
return None;
|
||||
};
|
||||
let mut reader = BufReader::new(fd);
|
||||
let mut certificate = Certificate {
|
||||
der: vec![],
|
||||
key: vec![],
|
||||
};
|
||||
for item in iter::from_fn(|| read_one(&mut reader).transpose()) {
|
||||
match item {
|
||||
Ok(Item::X509Certificate(cert)) => {
|
||||
if certificate.der.is_empty() {
|
||||
certificate.der = cert;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Ok(Item::RSAKey(key)) => {
|
||||
if certificate.key.is_empty() {
|
||||
certificate.key = key;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Ok(Item::PKCS8Key(key)) => {
|
||||
if certificate.key.is_empty() {
|
||||
certificate.key = key;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Ok(Item::ECKey(key)) => {
|
||||
if certificate.key.is_empty() {
|
||||
certificate.key = key;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if certificate.der.is_empty() || certificate.key.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(certificate)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_certificate(
|
||||
&mut self,
|
||||
user: &Mailuser,
|
||||
certificate: Certificate,
|
||||
) -> Option<Certificate> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn contains_certificate(&self, user: &Mailuser) -> bool {
|
||||
self.get_certificate(user).is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -299,10 +376,18 @@ mod tests {
|
|||
#[test]
|
||||
fn users() {
|
||||
let users = store().users();
|
||||
assert!(users.iter().any(|u| u.host.to_string() == "mail.gmi.org" && u.username == "jane" ));
|
||||
assert!(users.iter().any(|u| u.host.to_string() == "mail.gmi.org" && u.username == "dick" ));
|
||||
assert!(users.iter().any(|u| u.host.to_string() == "misfin.example.org" && u.username == "jane" ));
|
||||
assert!(users.iter().any(|u| u.host.to_string() == "misfin.example.org" && u.username == "dick" ));
|
||||
assert!(users
|
||||
.iter()
|
||||
.any(|u| u.host.to_string() == "mail.gmi.org" && u.username == "jane"));
|
||||
assert!(users
|
||||
.iter()
|
||||
.any(|u| u.host.to_string() == "mail.gmi.org" && u.username == "dick"));
|
||||
assert!(users
|
||||
.iter()
|
||||
.any(|u| u.host.to_string() == "misfin.example.org" && u.username == "jane"));
|
||||
assert!(users
|
||||
.iter()
|
||||
.any(|u| u.host.to_string() == "misfin.example.org" && u.username == "dick"));
|
||||
assert!(users.len() >= 4 && users.len() < 6);
|
||||
}
|
||||
|
||||
|
@ -336,7 +421,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn get_message() {
|
||||
let msg = store().get_message("jane@mail.gmi.org", "Inbox", "867017").unwrap();
|
||||
let msg = store()
|
||||
.get_message("jane@mail.gmi.org", "Inbox", "867017")
|
||||
.unwrap();
|
||||
assert_eq!(msg.from.username, "april");
|
||||
assert_eq!(msg.from.host.subdomain.unwrap(), "we.wear");
|
||||
}
|
||||
|
@ -352,18 +439,26 @@ mod tests {
|
|||
title: Some(String::from("Get a look at 'is 'orse")),
|
||||
body: String::from("Gorgeous, innit?"),
|
||||
};
|
||||
store().add_message("dick@mail.gmi.org", "Inbox", msg).unwrap();
|
||||
store()
|
||||
.add_message("dick@mail.gmi.org", "Inbox", msg)
|
||||
.unwrap();
|
||||
assert!(PathBuf::from("test/mailstore/mail.gmi.org/dick/Inbox/1687407844.gmi").exists());
|
||||
store().move_message("dick@mail.gmi.org", "1687407844", "Inbox", "Lists").unwrap();
|
||||
store()
|
||||
.move_message("dick@mail.gmi.org", "1687407844", "Inbox", "Lists")
|
||||
.unwrap();
|
||||
assert!(!PathBuf::from("test/mailstore/mail.gmi.org/dick/Inbox/1687407844.gmi").exists());
|
||||
assert!(PathBuf::from("test/mailstore/mail.gmi.org/dick/Lists/1687407844.gmi").exists());
|
||||
store().delete_message("dick@mail.gmi.org", "Lists", "1687407844").unwrap();
|
||||
store()
|
||||
.delete_message("dick@mail.gmi.org", "Lists", "1687407844")
|
||||
.unwrap();
|
||||
assert!(!PathBuf::from("test/mailstore/mail.gmi.org/dick/Lists/1687407844.gmi").exists());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn add_remove_user() {
|
||||
store().add_user("rob@misfin.example.org Rob Zombie").unwrap();
|
||||
store()
|
||||
.add_user("rob@misfin.example.org Rob Zombie")
|
||||
.unwrap();
|
||||
assert!(store().has_mailuser("rob@misfin.example.org"));
|
||||
assert!(store().remove_user("rob@misfin.example.org"));
|
||||
assert!(!store().has_mailuser("rob@misfin.example.org"));
|
||||
|
|
Loading…
Add table
Reference in a new issue