Implement 'introducer remove'
- Implement the subcommand `remove` for `introducer`. - Remove the introducer by adding a certification with trust level 1 and trust depth 0. - Move `crypt.rs` into `common/` and add a generic authenticaton function to be used by `introducer add` and `... remove`.
This commit is contained in:
+10
-84
@@ -1,22 +1,15 @@
|
||||
//! introducers
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use sequoia_cert_store::StoreUpdate;
|
||||
use sequoia_cert_store::store::MergePublicCollectStats;
|
||||
use sequoia_openpgp::packet::prelude::SignatureBuilder;
|
||||
use sequoia_wot as wot;
|
||||
use wot::{CertSynopsis, Certification};
|
||||
use sequoia_openpgp::{cert::ValidCert, policy::StandardPolicy};
|
||||
use sequoia_openpgp::Cert;
|
||||
use sequoia_openpgp::Fingerprint;
|
||||
use sequoia_openpgp::types::SignatureType;
|
||||
|
||||
use crate::mail;
|
||||
use crate::types::husk_context::HuskContext;
|
||||
use crate::common::escape;
|
||||
use crate::common::crypto;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum IntroducerError {
|
||||
@@ -87,86 +80,19 @@ impl Introducer {
|
||||
return Err(IntroducerError::UnsuitableCertificate.into());
|
||||
}
|
||||
|
||||
let policy = &context.policy;
|
||||
let root_signing_key = match context.local_trust_root.with_policy(policy, None)?
|
||||
.keys()
|
||||
.supported()
|
||||
.alive()
|
||||
.revoked(false)
|
||||
.for_certification()
|
||||
.next() {
|
||||
Some(k) => k.key(),
|
||||
None => {
|
||||
return Err(IntroducerError::RootDamaged.into());
|
||||
}
|
||||
};
|
||||
let mut root_signer = root_signing_key
|
||||
.clone()
|
||||
.parts_into_secret()?
|
||||
.into_keypair()?;
|
||||
crypto::authenticate(context, cert, true, Some(domains))
|
||||
}
|
||||
|
||||
pub fn remove(context: &HuskContext, cert: &ValidCert, _demote: bool)
|
||||
-> Result<()> {
|
||||
|
||||
// Check if domain list is not empty.
|
||||
// An empty list would create an unlimited introducer.
|
||||
if domains.is_empty() {
|
||||
return Err(IntroducerError::UnlimitedIntroducer.into());
|
||||
// Check if the local trust root certificate should be made an
|
||||
// introducer, which would be an error.
|
||||
if cert.fingerprint() == context.local_trust_root.fingerprint() {
|
||||
return Err(IntroducerError::UnsuitableCertificate.into());
|
||||
}
|
||||
|
||||
// Create the SignatureBuilder with a default preconfiguration.
|
||||
let mut builder =
|
||||
SignatureBuilder::new(SignatureType::GenericCertification)
|
||||
.set_signature_creation_time(std::time::SystemTime::now())?
|
||||
.set_trust_signature(1, 120)?
|
||||
.set_exportable_certification(false)?
|
||||
.set_revocable(true)?;
|
||||
// set no expiration date
|
||||
|
||||
// Add domains
|
||||
for domain in domains {
|
||||
if !mail::is_domain(domain.as_str()) {
|
||||
return Err(IntroducerError::InvalidDomainName(domain).into());
|
||||
}
|
||||
|
||||
builder = builder.add_regular_expression(format!("<[^>]+[@.]{}>$",
|
||||
escape::regex_ctrl_escape(domain.as_str())?
|
||||
))?;
|
||||
}
|
||||
|
||||
// For a certification, user ids are needed. Build a list of
|
||||
// valid (non self revoked) user ids.
|
||||
let user_ids: Vec<_> = cert.userids()
|
||||
.filter(|u| {
|
||||
u.self_revocations().count() == 0
|
||||
})
|
||||
.collect();
|
||||
|
||||
if user_ids.is_empty() {
|
||||
return Err(IntroducerError::NoUserIDs(cert.fingerprint()).into());
|
||||
}
|
||||
|
||||
// now certify
|
||||
let signatures: Vec<_> = user_ids.into_iter()
|
||||
.filter_map(|u| {
|
||||
let b = builder.clone();
|
||||
|
||||
b.sign_userid_binding(
|
||||
&mut root_signer,
|
||||
cert.primary_key().key(),
|
||||
u.userid()).ok()
|
||||
})
|
||||
.collect();
|
||||
let (new_cert, _) = cert.cert().clone().insert_packets(signatures)?;
|
||||
|
||||
// and (re)import
|
||||
let new_cert = Arc::new(new_cert.into());
|
||||
let stats = MergePublicCollectStats::new();
|
||||
let cert_store = &context.cert_store;
|
||||
cert_store.update_by(new_cert, &stats)?;
|
||||
|
||||
log::debug!("{:?}", stats);
|
||||
|
||||
// XXX: do something with the created stats
|
||||
Ok(())
|
||||
crypto::authenticate(context, cert, false, None)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user