Add certificates

- Refactor `Recipient` out of `MailContext`.
- Add lookup of authenticated certificates for recipients.
This commit is contained in:
Malte Meiboom
2025-12-11 16:03:34 +01:00
parent 23c698f445
commit dd71b89485
6 changed files with 92 additions and 24 deletions
+1
View File
@@ -19,6 +19,7 @@ log4rs = "1.3.0"
sequoia-cert-store = "0.7.1" sequoia-cert-store = "0.7.1"
sequoia-directories = "0.1.0" sequoia-directories = "0.1.0"
sequoia-openpgp = "2.1.0" sequoia-openpgp = "2.1.0"
sequoia-wot = "0.15.0"
serde = "1.0.228" serde = "1.0.228"
serde_derive = "1.0.228" serde_derive = "1.0.228"
thiserror = "2.0.17" thiserror = "2.0.17"
+38 -1
View File
@@ -4,12 +4,18 @@
// cryptographic functions // cryptographic functions
// //
use std::sync::Arc;
use anyhow; use anyhow;
use sequoia_openpgp::parse::Parse; use sequoia_openpgp::parse::Parse;
use sequoia_openpgp::{Fingerprint, Cert}; use sequoia_openpgp::{Fingerprint, Cert};
use sequoia_openpgp::cert::raw::RawCertParser; use sequoia_openpgp::cert::raw::RawCertParser;
use sequoia_cert_store::CertStore; use sequoia_cert_store::{Store, CertStore, LazyCert};
use sequoia_wot::{self as wot};
use wot::store::Store as _;
use crate::types::errors::HuskError; use crate::types::errors::HuskError;
use crate::types::husk_context::HuskContext;
pub fn get_local_trust_root(cert_store: &CertStore) -> anyhow::Result<Cert> { pub fn get_local_trust_root(cert_store: &CertStore) -> anyhow::Result<Cert> {
@@ -45,3 +51,34 @@ pub fn get_local_trust_root(cert_store: &CertStore) -> anyhow::Result<Cert> {
} }
} }
pub fn get_certificates<'hc>(context: &HuskContext<'hc>, email: &str)
-> Vec<Arc<LazyCert<'hc>>> {
let cert_store = &context.cert_store;
let trust_roots = vec![(context.local_trust_root.fingerprint(), wot::FULLY_TRUSTED)];
let wot_store = wot::store::CertStore::from_store(cert_store, &context.policy, None);
let nb = wot::NetworkBuilder::rooted(&wot_store, &*trust_roots);
let n = nb.build();
let bindings: Vec<_> = n.lookup_synopses_by_email(email)
.into_iter()
.map(|(fp, userid)| (fp, Some(userid)))
.collect();
let mut result = vec![];
for (fpr, some_userid) in bindings {
if let Some(userid) = some_userid {
let paths = n.authenticate(userid, &fpr, wot::FULLY_TRUSTED);
if paths.len() > 0 {
log::debug!("authenticated!!!");
for (path, _) in paths.iter() {
if let Ok(cert) = cert_store.lookup_by_cert_fpr(&path.target().fingerprint()) {
result.push(cert);
}
}
}
}
}
result
}
+4 -1
View File
@@ -51,7 +51,10 @@ impl<'hc> HuskContext<'hc> {
} }
pub fn add_recipient(&mut self, rcpt: String) -> anyhow::Result<()> { pub fn add_recipient(&mut self, rcpt: String) -> anyhow::Result<()> {
self.mail.add_recipient(rcpt)
let certs = crypto::get_certificates(&self, rcpt.as_str());
self.mail.add_recipient(rcpt, certs)
} }
} }
+9 -22
View File
@@ -4,34 +4,20 @@
// Mail Context // Mail Context
// //
use anyhow; use std::sync::Arc;
use sequoia_cert_store::LazyCert;
use sequoia_openpgp::cert::ValidCert; use crate::types::recipient::Recipient;
#[derive(Debug, Clone)] pub struct MailContext<'mc> {
pub struct Recipient<'r> {
pub email: String,
pub cert: Option<ValidCert<'r>>,
}
impl From<String> for Recipient<'_> {
fn from(email: String) -> Self {
Recipient {
email: email,
cert: None
}
}
}
pub struct MailContext<'c> {
pub sender: Option<String>, pub sender: Option<String>,
pub recipients: Vec<Recipient<'c>>, pub recipients: Vec<Recipient<'mc>>,
// header // header
// body // body
// body size // body size
} }
impl MailContext<'_> { impl<'mc> MailContext<'mc> {
pub fn new() -> Self { pub fn new() -> Self {
MailContext { MailContext {
@@ -44,8 +30,9 @@ impl MailContext<'_> {
self.sender = Some(sender); self.sender = Some(sender);
} }
pub fn add_recipient(&mut self, rcpt: String) -> anyhow::Result<()> { pub fn add_recipient(&mut self, rcpt: String, certs: Vec<Arc<LazyCert<'mc>>>) -> anyhow::Result<()> {
let recipient: Recipient = rcpt.into(); let mut recipient: Recipient = rcpt.into();
recipient.certs = certs;
self.recipients.push(recipient); self.recipients.push(recipient);
+1
View File
@@ -1,3 +1,4 @@
pub mod husk_context; pub mod husk_context;
pub mod mail_context; pub mod mail_context;
pub mod errors; pub mod errors;
pub mod recipient;
+39
View File
@@ -0,0 +1,39 @@
//
// Husk milter
//
// Recipient
//
use anyhow;
use std::sync::Arc;
use std::ffi::CString;
use sequoia_cert_store::LazyCert;
#[derive(Debug, Clone)]
pub struct Recipient<'r> {
pub email: String,
pub certs: Vec<Arc<LazyCert<'r>>>
}
impl From<String> for Recipient<'_> {
fn from(email: String) -> Self {
Recipient {
email: email,
certs: Vec::new()
}
}
}
impl TryFrom<CString> for Recipient<'_> {
type Error=anyhow::Error;
fn try_from(value: CString) -> Result<Self, Self::Error> {
match value.into_string() {
Ok(s) => Ok(s.into()),
Err(e) => Err(e.into()),
}
}
}