carry over verified UIDs on key update

This commit is contained in:
Kai Michaelis 2019-02-07 21:01:59 +01:00
parent 53719c2166
commit 563aaa8736
3 changed files with 128 additions and 14 deletions

View File

@ -429,4 +429,20 @@ mod tests {
test::test_uid_revocation(&mut db);
}
#[test]
fn key_reupload() {
let tmpdir = TempDir::new().unwrap();
let mut db = Filesystem::new(tmpdir.path()).unwrap();
test::test_reupload(&mut db);
}
#[test]
fn uid_replacement() {
let tmpdir = TempDir::new().unwrap();
let mut db = Filesystem::new(tmpdir.path()).unwrap();
test::test_uid_replacement(&mut db);
}
}

View File

@ -172,8 +172,9 @@ pub trait Database: Sync + Send {
use sequoia_openpgp::RevocationStatus;
let fpr = Fingerprint::try_from(tpk.primary().fingerprint())?;
let mut all_uids = Vec::default();
let mut active_uids = Vec::default();
let mut revoked_uids = Vec::default();
let mut verified_uids = Vec::default();
// update verify tokens
for uid in tpk.userids() {
@ -181,19 +182,51 @@ pub trait Database: Sync + Send {
match uid.revoked(None) {
RevocationStatus::CouldBe(_) | RevocationStatus::Revoked(_) => {
revoked_uids.push(email);
match self.by_email(&email) {
None => {}
Some(other_tpk) => {
match TPK::from_bytes(&other_tpk) {
Ok(other_tpk) => {
all_uids
.push((email, other_tpk.fingerprint()));
}
Err(_) => {}
}
}
};
}
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)?));
RevocationStatus::NotAsFarAsWeKnow => {
let add_to_verified = match self.by_email(&email) {
None => false,
Some(other_tpk) => {
match TPK::from_bytes(&other_tpk) {
Ok(other_tpk) => {
all_uids.push((
email.clone(),
other_tpk.fingerprint(),
));
other_tpk.fingerprint() == tpk.fingerprint()
}
Err(_) => false,
}
}
};
if add_to_verified {
verified_uids.push(email.clone());
} else {
let payload = Verify::new(
uid.userid(),
&uid.selfsigs().collect::<Vec<_>>(),
fpr.clone(),
)?;
active_uids.push((
email.clone(),
self.new_verify_token(payload)?,
));
}
}
_ => {}
}
}
@ -202,6 +235,10 @@ pub trait Database: Sync + Send {
tpk = Self::strip_userids(tpk)?;
for (email, fpr) in all_uids {
self.unlink_email(&email, &Fingerprint::try_from(fpr).unwrap());
}
for _ in 0..100
/* while cas failed */
{
@ -214,7 +251,10 @@ pub trait Database: Sync + Send {
if self.compare_and_swap(&fpr, Some(&old), Some(&new))? {
self.link_subkeys(&fpr, subkeys)?;
self.unlink_userids(&fpr, revoked_uids);
for email in verified_uids {
self.link_email(&email, &fpr);
}
return Ok(active_uids);
}
}
@ -224,7 +264,7 @@ pub trait Database: Sync + Send {
if self.compare_and_swap(&fpr, None, Some(&fresh))? {
self.link_subkeys(&fpr, subkeys)?;
self.unlink_userids(&fpr, revoked_uids);
return Ok(active_uids);
}
}

View File

@ -238,6 +238,64 @@ pub fn test_uid_verification<D: Database>(db: &mut D) {
}
}
pub fn test_reupload<D: Database>(db: &mut D) {
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();
// verify 1st uid
assert!(db.verify_token(&tokens[0].1).unwrap().is_some());
assert!(db.by_email(&email2).is_none() ^ db.by_email(&email1).is_none());
// reupload
let tokens = db.merge_or_publish(tpk.clone()).unwrap();
assert_eq!(tokens.len(), 1);
assert!(db.by_email(&email2).is_none() ^ db.by_email(&email1).is_none());
}
pub fn test_uid_replacement<D: Database>(db: &mut D) {
let str_uid = "Test A <test_a@example.com>";
let tpk1 = TPKBuilder::default()
.add_userid(str_uid)
.generate().unwrap().0;
let tpk2 = TPKBuilder::default()
.add_userid(str_uid)
.generate().unwrap().0;
let email = Email::from_str(str_uid).unwrap();
let fpr1 = tpk1.fingerprint();
let fpr2 = tpk2.fingerprint();
// upload key
let tokens = db.merge_or_publish(tpk1.clone()).unwrap();
// verify 1st uid
assert!(db.verify_token(&tokens[0].1).unwrap().is_some());
assert_eq!(TPK::from_bytes(&db.by_email(&email).unwrap()).unwrap().fingerprint(), fpr1);
// replace
let tokens = db.merge_or_publish(tpk2.clone()).unwrap();
assert!(db.by_email(&email).is_none());
assert!(db.verify_token(&tokens[0].1).unwrap().is_some());
assert_eq!(TPK::from_bytes(&db.by_email(&email).unwrap()).unwrap().fingerprint(), fpr2);
}
pub fn test_uid_deletion<D: Database>(db: &mut D) {
let str_uid1 = "Test A <test_a@example.com>";
let str_uid2 = "Test B <test_b@example.com>";