db: treat emails correctly during publication
This commit is contained in:
parent
c3d4b448a5
commit
30bb4b2993
|
@ -53,7 +53,7 @@ mod stateful_tokens;
|
||||||
pub use stateful_tokens::StatefulTokens;
|
pub use stateful_tokens::StatefulTokens;
|
||||||
|
|
||||||
mod openpgp_utils;
|
mod openpgp_utils;
|
||||||
use openpgp_utils::{tpk_filter_userids, tpk_to_string, tpk_clean, is_status_revoked, POLICY};
|
use openpgp_utils::{tpk_filter_userids, tpk_filter_alive_emails, tpk_to_string, tpk_clean, is_status_revoked, POLICY};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
|
@ -270,36 +270,11 @@ pub trait Database: Sync + Send {
|
||||||
return Ok(ImportResult::Unchanged(TpkStatus { is_revoked, email_status, unparsed_uids }));
|
return Ok(ImportResult::Unchanged(TpkStatus { is_revoked, email_status, unparsed_uids }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the key is revoked, consider all uids revoked
|
let published_tpk_new = if is_revoked {
|
||||||
let newly_revoked_uids: Vec<&UserID> = if is_revoked {
|
tpk_filter_alive_emails(&full_tpk_new, &[])
|
||||||
full_tpk_new.userids().bundles().map(|binding| binding.userid()).collect()
|
|
||||||
} else {
|
} else {
|
||||||
let revoked_uids: Vec<UserID> = full_tpk_new
|
tpk_filter_alive_emails(&full_tpk_new, &published_emails)
|
||||||
.userids()
|
}?;
|
||||||
.bundles()
|
|
||||||
.filter(|binding| is_status_revoked(binding.revoked(&*POLICY, None)))
|
|
||||||
.map(|binding| binding.userid().clone())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
published_tpk_old
|
|
||||||
.as_ref()
|
|
||||||
.map(|tpk| tpk
|
|
||||||
.userids()
|
|
||||||
.bundles()
|
|
||||||
.map(|binding| binding.userid())
|
|
||||||
.filter(|uid| revoked_uids.contains(uid))
|
|
||||||
.collect()
|
|
||||||
).unwrap_or_default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let published_tpk_new = tpk_filter_userids(
|
|
||||||
&full_tpk_new, |uid| {
|
|
||||||
if let Ok(email) = Email::try_from(uid) {
|
|
||||||
published_emails.contains(&email) && !newly_revoked_uids.contains(&uid)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let newly_revoked_emails: Vec<&Email> = published_emails
|
let newly_revoked_emails: Vec<&Email> = published_emails
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -470,12 +445,10 @@ pub trait Database: Sync + Send {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let published_tpk_new = {
|
let mut published_emails = published_emails_old.clone();
|
||||||
tpk_filter_userids(&full_tpk, |uid| {
|
published_emails.push(email_new.clone());
|
||||||
Email::try_from(uid).map(|email| email == *email_new)
|
|
||||||
.unwrap_or(false) || published_uids_old.contains(uid)
|
let published_tpk_new = tpk_filter_alive_emails(&full_tpk, &published_emails)?;
|
||||||
})?
|
|
||||||
};
|
|
||||||
|
|
||||||
if !published_tpk_new
|
if !published_tpk_new
|
||||||
.userids()
|
.userids()
|
||||||
|
@ -556,7 +529,7 @@ pub trait Database: Sync + Send {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let published_tpk_new = {
|
let published_tpk_new = {
|
||||||
tpk_filter_userids(&published_tpk_old, |uid| email_remove(uid))?
|
tpk_filter_userids(&published_tpk_old, |uid| email_remove(uid.userid()))?
|
||||||
};
|
};
|
||||||
|
|
||||||
let published_emails_new: Vec<Email> = published_tpk_new
|
let published_emails_new: Vec<Email> = published_tpk_new
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use failure::Fallible as Result;
|
use failure::Fallible as Result;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use openpgp::{
|
use openpgp::{
|
||||||
Cert,
|
Cert,
|
||||||
|
cert::components::ComponentBundle,
|
||||||
RevocationStatus,
|
RevocationStatus,
|
||||||
armor::{Writer, Kind},
|
armor::{Writer, Kind},
|
||||||
packet::UserID,
|
packet::UserID,
|
||||||
|
@ -9,6 +11,8 @@ use openpgp::{
|
||||||
policy::StandardPolicy,
|
policy::StandardPolicy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use Email;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref POLICY: StandardPolicy = StandardPolicy::new();
|
pub static ref POLICY: StandardPolicy = StandardPolicy::new();
|
||||||
}
|
}
|
||||||
|
@ -62,10 +66,23 @@ pub fn tpk_clean(tpk: &Cert) -> Result<Cert> {
|
||||||
Cert::from_packet_pile(acc.into())
|
Cert::from_packet_pile(acc.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Filters the Cert, keeping only UserIDs that aren't revoked, and whose emails match the given list
|
||||||
|
pub fn tpk_filter_alive_emails(tpk: &Cert, emails: &[Email]) -> Result<Cert> {
|
||||||
|
tpk_filter_userids(tpk, |uid| {
|
||||||
|
if is_status_revoked(uid.revoked(&*POLICY, None)) {
|
||||||
|
false
|
||||||
|
} else if let Ok(email) = Email::try_from(uid.userid()) {
|
||||||
|
emails.contains(&email)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Filters the Cert, keeping only those UserIDs that fulfill the
|
/// Filters the Cert, keeping only those UserIDs that fulfill the
|
||||||
/// predicate `filter`.
|
/// predicate `filter`.
|
||||||
pub fn tpk_filter_userids<F>(tpk: &Cert, filter: F) -> Result<Cert>
|
pub fn tpk_filter_userids<F>(tpk: &Cert, filter: F) -> Result<Cert>
|
||||||
where F: Fn(&UserID) -> bool
|
where F: Fn(&ComponentBundle<UserID>) -> bool
|
||||||
{
|
{
|
||||||
// Iterate over the Cert, pushing packets we want to merge
|
// Iterate over the Cert, pushing packets we want to merge
|
||||||
// into the accumulator.
|
// into the accumulator.
|
||||||
|
@ -91,7 +108,7 @@ pub fn tpk_filter_userids<F>(tpk: &Cert, filter: F) -> Result<Cert>
|
||||||
// Updates for UserIDs fulfilling `filter`.
|
// Updates for UserIDs fulfilling `filter`.
|
||||||
for uidb in tpk.userids().bundles() {
|
for uidb in tpk.userids().bundles() {
|
||||||
// Only include userids matching filter
|
// Only include userids matching filter
|
||||||
if filter(uidb.userid()) {
|
if filter(uidb) {
|
||||||
acc.push(uidb.userid().clone().into());
|
acc.push(uidb.userid().clone().into());
|
||||||
for s in uidb.self_signatures() { acc.push(s.clone().into()) }
|
for s in uidb.self_signatures() { acc.push(s.clone().into()) }
|
||||||
for s in uidb.certifications() { acc.push(s.clone().into()) }
|
for s in uidb.certifications() { acc.push(s.clone().into()) }
|
||||||
|
|
Loading…
Reference in New Issue