Add introducers
- add the `Introducer` types - get introducers from the certificate store (and log them)
This commit is contained in:
+44
-1
@@ -8,14 +8,17 @@ use std::sync::Arc;
|
||||
|
||||
use anyhow;
|
||||
use sequoia_openpgp::parse::Parse;
|
||||
use sequoia_openpgp::policy::StandardPolicy;
|
||||
use sequoia_openpgp::{Fingerprint, Cert};
|
||||
use sequoia_openpgp::cert::raw::RawCertParser;
|
||||
use sequoia_cert_store::{Store, CertStore, LazyCert};
|
||||
use sequoia_wot::{self as wot};
|
||||
use wot::store::Store as _;
|
||||
use wot::{Depth, Path};
|
||||
|
||||
use crate::types::errors::HuskError;
|
||||
use crate::types::husk_context::HuskContext;
|
||||
use crate::types::introducer::Introducer;
|
||||
|
||||
pub fn get_local_trust_root(cert_store: &CertStore) -> anyhow::Result<Cert> {
|
||||
|
||||
@@ -71,7 +74,7 @@ pub fn get_certificates<'hc>(context: &HuskContext<'hc>, email: &str)
|
||||
if let Some(userid) = some_userid {
|
||||
let paths = n.authenticate(userid, &fpr, wot::FULLY_TRUSTED);
|
||||
if paths.len() > 0 {
|
||||
log::debug!("authenticated!!!");
|
||||
log::debug!("{} authenticated!!!", email);
|
||||
for (path, _) in paths.iter() {
|
||||
if let Ok(cert) = cert_store.lookup_by_cert_fpr(&path.target().fingerprint()) {
|
||||
result.push(cert);
|
||||
@@ -82,3 +85,43 @@ pub fn get_certificates<'hc>(context: &HuskContext<'hc>, email: &str)
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn get_introducers<'c>(cert_store: &CertStore<'c>, policy: &StandardPolicy, local_trust_root: Fingerprint) -> Vec<Introducer> {
|
||||
|
||||
let mut result = Vec::new();
|
||||
|
||||
let trust_roots = vec![(local_trust_root, wot::FULLY_TRUSTED)];
|
||||
let wot_store = wot::store::CertStore::from_store(cert_store, policy, None);
|
||||
let n = wot::NetworkBuilder::rooted(&wot_store, &*trust_roots)
|
||||
.build();
|
||||
|
||||
n.certified_userids().iter().for_each(|(fpr, user_id)| {
|
||||
let paths = n.authenticate(user_id, fpr, wot::FULLY_TRUSTED);
|
||||
|
||||
// find the longest path (highest trust depth)
|
||||
let mut depth = Depth::Limit(0);
|
||||
let mut target: Option<&Path> = None;
|
||||
paths.iter().for_each(|(path, amount)| {
|
||||
if *amount == wot::FULLY_TRUSTED {
|
||||
let d = path.residual_depth();
|
||||
if d > depth {
|
||||
depth = d;
|
||||
target = Some(path);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if depth > Depth::Limit(0) {
|
||||
if let Some(p) = target {
|
||||
if let Some(c) = p.certifications().last() {
|
||||
result.push( Introducer {
|
||||
cert: p.target().clone(),
|
||||
certification: c.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
+11
-2
@@ -93,6 +93,7 @@ impl Daemon {
|
||||
// setup Context
|
||||
match HuskContext::new(&config) {
|
||||
Ok(context) => {
|
||||
log::debug!("found introducers: {:?}", context.introducers);
|
||||
cx.data = Some(context).take();
|
||||
Status::Continue
|
||||
},
|
||||
@@ -149,10 +150,18 @@ impl Daemon {
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_data(_cx: &mut Context<HuskContext<'_>>) -> Status {
|
||||
async fn handle_data(cx: &mut Context<HuskContext<'_>>) -> Status {
|
||||
log::debug!("DATA");
|
||||
|
||||
Status::Continue
|
||||
if let Some(ref mut context) = cx.data {
|
||||
// XXX: check for early accepting
|
||||
// if there are no recipients with authenticated certificates
|
||||
// tell the MTA that this milter is done and the mail can be further
|
||||
// processed.
|
||||
Status::Continue
|
||||
} else {
|
||||
Status::Tempfail
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_header(_cx: &mut Context<HuskContext<'_>>, name: CString, value: CString) -> Status {
|
||||
|
||||
@@ -14,10 +14,13 @@ use sequoia_directories::Home;
|
||||
use crate::{config::HuskConfig, crypto};
|
||||
use crate::types::mail_context::MailContext;
|
||||
|
||||
use crate::types::introducer::Introducer;
|
||||
|
||||
pub struct HuskContext<'hc> {
|
||||
pub policy: StandardPolicy<'hc>,
|
||||
pub cert_store: CertStore<'hc>,
|
||||
pub local_trust_root: Cert,
|
||||
pub introducers: Vec<Introducer>,
|
||||
pub mail: MailContext<'hc>,
|
||||
}
|
||||
|
||||
@@ -33,11 +36,13 @@ impl<'hc> HuskContext<'hc> {
|
||||
let policy = StandardPolicy::new();
|
||||
|
||||
let local_trust_root = crypto::get_local_trust_root(&cert_store)?;
|
||||
let introducers = crypto::get_introducers(&cert_store, &policy, local_trust_root.fingerprint());
|
||||
|
||||
Ok(HuskContext {
|
||||
policy,
|
||||
cert_store,
|
||||
local_trust_root,
|
||||
introducers,
|
||||
mail: MailContext::new(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// husk-milter
|
||||
//
|
||||
// introducers
|
||||
//
|
||||
|
||||
use sequoia_wot as wot;
|
||||
use wot::{CertSynopsis, Certification};
|
||||
use sequoia_openpgp::{policy::StandardPolicy, Cert, KeyID};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Introducer {
|
||||
pub cert: CertSynopsis,
|
||||
pub certification: Certification,
|
||||
}
|
||||
|
||||
impl Introducer {
|
||||
|
||||
pub fn can_introduce(&self, email: &str) -> bool {
|
||||
if let Some(regexset) = self.certification.regular_expressions() {
|
||||
if regexset.matches_everything() {
|
||||
// return false, because unlimited certifications are
|
||||
// ignored.
|
||||
false
|
||||
} else {
|
||||
regexset.is_match(email)
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,3 +2,4 @@ pub mod husk_context;
|
||||
pub mod mail_context;
|
||||
pub mod errors;
|
||||
pub mod recipient;
|
||||
pub mod introducer;
|
||||
|
||||
Reference in New Issue
Block a user