parent
8f2f1b36ff
commit
c503e52204
|
@ -366,4 +366,12 @@ mod tests {
|
|||
|
||||
test::test_kid_lookup(&mut db);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uid_revocation() {
|
||||
let tmpdir = TempDir::new().unwrap();
|
||||
let mut db = Filesystem::new(tmpdir.path()).unwrap();
|
||||
|
||||
test::test_uid_revocation(&mut db);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,4 +170,11 @@ mod tests {
|
|||
|
||||
test::test_kid_lookup(&mut db);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uid_revocation() {
|
||||
let mut db = Memory::default();
|
||||
|
||||
test::test_uid_revocation(&mut db);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,29 +143,35 @@ pub trait Database: Sync + Send {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn unlink_userids(&self, fpr: &Fingerprint, userids: Vec<Email>) {
|
||||
for uid in userids {
|
||||
self.unlink_email(&uid, fpr);
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_or_publish(&self, mut tpk: TPK) -> Result<Vec<(Email, String)>> {
|
||||
use sequoia_openpgp::RevocationStatus;
|
||||
|
||||
let fpr = Fingerprint::try_from(tpk.primary().fingerprint())?;
|
||||
let mut ret = Vec::default();
|
||||
let mut active_uids = Vec::default();
|
||||
let mut revoked_uids = Vec::default();
|
||||
|
||||
// update verify tokens
|
||||
for uid in tpk.userids() {
|
||||
let email = Email::try_from(uid.userid().clone())?;
|
||||
|
||||
match uid.revoked() {
|
||||
RevocationStatus::Revoked(_) => { /* skip */ }
|
||||
RevocationStatus::CouldBe(_) |
|
||||
RevocationStatus::NotAsFarAsWeKnow => {
|
||||
let email = Email::try_from(uid.userid().clone())?;
|
||||
|
||||
if self.by_email(&email).is_none() {
|
||||
let payload = Verify::new(
|
||||
uid.userid(),
|
||||
&uid.selfsigs().collect::<Vec<_>>(),
|
||||
fpr.clone())?;
|
||||
|
||||
ret.push((email, self.new_verify_token(payload)?));
|
||||
}
|
||||
RevocationStatus::CouldBe(_) | RevocationStatus::Revoked(_) => {
|
||||
revoked_uids.push(email);
|
||||
}
|
||||
RevocationStatus::NotAsFarAsWeKnow if self.by_email(&email).is_none() => {
|
||||
let payload = Verify::new(
|
||||
uid.userid(),
|
||||
&uid.selfsigs().collect::<Vec<_>>(),
|
||||
fpr.clone())?;
|
||||
active_uids.push((email, self.new_verify_token(payload)?));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,7 +189,8 @@ pub trait Database: Sync + Send {
|
|||
|
||||
if self.compare_and_swap(&fpr, Some(&old), Some(&new))? {
|
||||
self.link_subkeys(&fpr, subkeys)?;
|
||||
return Ok(ret);
|
||||
self.unlink_userids(&fpr, revoked_uids);
|
||||
return Ok(active_uids);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +199,8 @@ pub trait Database: Sync + Send {
|
|||
|
||||
if self.compare_and_swap(&fpr, None, Some(&fresh))? {
|
||||
self.link_subkeys(&fpr, subkeys)?;
|
||||
return Ok(ret);
|
||||
self.unlink_userids(&fpr, revoked_uids);
|
||||
return Ok(active_uids);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ use std::str::FromStr;
|
|||
|
||||
use database::Database;
|
||||
use sequoia_openpgp::tpk::{TPKBuilder, UserIDBinding};
|
||||
use sequoia_openpgp::{Packet, packet::UserID, TPK, PacketPile, parse::Parse};
|
||||
use sequoia_openpgp::{Packet, packet::UserID, TPK, PacketPile, parse::Parse, RevocationStatus, constants::ReasonForRevocation, constants::SignatureType};
|
||||
use types::{KeyID, Email, Fingerprint};
|
||||
|
||||
pub fn test_uid_verification<D: Database>(db: &mut D) {
|
||||
|
@ -317,3 +317,56 @@ pub fn test_kid_lookup<D: Database>(db: &mut D) {
|
|||
assert_eq!(raw1, raw2);
|
||||
assert_eq!(raw1, raw3);
|
||||
}
|
||||
|
||||
pub fn test_uid_revocation<D: Database>(db: &mut D) {
|
||||
use std::{thread, time};
|
||||
|
||||
let str_uid1 = "Test A <test_a@example.com>";
|
||||
let str_uid2 = "Test B <test_b@example.com>";
|
||||
let tpk = TPKBuilder::default()
|
||||
.add_userid(str_uid1)
|
||||
.add_userid(str_uid2)
|
||||
.generate().unwrap().0;
|
||||
let mut uid1 = UserID::new();
|
||||
let mut uid2 = UserID::new();
|
||||
|
||||
uid1.set_userid_from_bytes(str_uid1.as_bytes());
|
||||
uid2.set_userid_from_bytes(str_uid2.as_bytes());
|
||||
|
||||
let email1 = Email::from_str(str_uid1).unwrap();
|
||||
let email2 = Email::from_str(str_uid2).unwrap();
|
||||
|
||||
// upload key
|
||||
let tokens = db.merge_or_publish(tpk.clone()).unwrap();
|
||||
let fpr = Fingerprint::try_from(tpk.fingerprint()).unwrap();
|
||||
|
||||
// verify uid
|
||||
assert_eq!(tokens.len(), 2);
|
||||
assert!(db.verify_token(&tokens[0].1).unwrap().is_some());
|
||||
assert!(db.verify_token(&tokens[1].1).unwrap().is_some());
|
||||
|
||||
// fetch both uids
|
||||
assert!(db.by_email(&email1).is_some());
|
||||
assert!(db.by_email(&email2).is_some());
|
||||
|
||||
thread::sleep(time::Duration::from_secs(2));
|
||||
|
||||
// revoke one uid
|
||||
let sig = {
|
||||
let uid = tpk.userids().find(|b| *b.userid() == uid2).unwrap();
|
||||
assert_eq!(RevocationStatus::NotAsFarAsWeKnow, uid.revoked());
|
||||
|
||||
let mut keypair = tpk.primary().clone().into_keypair().unwrap();
|
||||
uid.revoke(&mut keypair,
|
||||
ReasonForRevocation::UIDRetired,
|
||||
b"It was the maid :/").unwrap()
|
||||
};
|
||||
assert_eq!(sig.sigtype(), SignatureType::CertificateRevocation);
|
||||
let tpk = tpk.merge_packets(vec![sig.to_packet()]).unwrap();
|
||||
let tokens = db.merge_or_publish(tpk.clone()).unwrap();
|
||||
assert_eq!(tokens.len(), 0);
|
||||
|
||||
// fail to fetch by one uid, fail by another
|
||||
assert!(db.by_email(&email1).is_some());
|
||||
assert!(db.by_email(&email2).is_none());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue