c60a2d33fb
- Give Sequoia a little space to backdate the signatures. Note: It will not backdate them past the key creation time.
358 lines
13 KiB
Rust
358 lines
13 KiB
Rust
use std::ffi::OsStr;
|
|
use std::path::Path;
|
|
|
|
use super::common::{artifact, NO_USERIDS, Sq, STANDARD_POLICY, UserIDArg};
|
|
|
|
use sequoia_openpgp as openpgp;
|
|
use openpgp::{
|
|
Cert,
|
|
Result,
|
|
cert::amalgamation::ValidateAmalgamation,
|
|
parse::Parse,
|
|
};
|
|
|
|
#[test]
|
|
fn update_files() -> Result<()> {
|
|
// See https://gitlab.com/sequoia-pgp/sequoia/-/issues/1111
|
|
let now = std::time::SystemTime::now()
|
|
- std::time::Duration::new(60 * 60, 0);
|
|
|
|
let sq = Sq::at(now);
|
|
|
|
let alice_userid = "<alice@example.org>";
|
|
let (alice, alice_pgp, _alice_rev)
|
|
= sq.key_generate(&[], &["<alice@example.org>"]);
|
|
let (_bob, bob_pgp, _bob_rev)
|
|
= sq.key_generate(&[], &["<bob@example.org>"]);
|
|
|
|
// Attest the certifications.
|
|
//
|
|
// public is first merged into private.
|
|
let attest = |sq: &Sq, public: &Path| {
|
|
let priv_file = sq.scratch_file(
|
|
&*format!("{}-priv",
|
|
public.file_name()
|
|
.unwrap_or(OsStr::new(""))
|
|
.to_str().unwrap_or("")));
|
|
|
|
sq.keyring_merge(
|
|
&[ public, &alice_pgp ][..], None,
|
|
&*priv_file);
|
|
|
|
let approval_file = sq.scratch_file(
|
|
&*format!("{}-approval", public.display()));
|
|
|
|
let approval = sq.key_approvals_update(
|
|
&["--add-all"], &priv_file, NO_USERIDS, &*approval_file);
|
|
|
|
eprintln!("{}", sq.inspect(&approval_file));
|
|
|
|
assert_eq!(approval.bad_signatures().count(), 0);
|
|
|
|
let approval_ua = approval.userids().next().unwrap();
|
|
assert_eq!(approval_ua.attestations().count(), 1);
|
|
|
|
};
|
|
|
|
// Attest nothing.
|
|
attest(&sq, &alice_pgp);
|
|
|
|
// Have Bob certify Alice.
|
|
let alice2_pub_pgp = sq.scratch_file("alice2_pub");
|
|
let alice2 = sq.pki_vouch_add(&[],
|
|
&bob_pgp,
|
|
&alice_pgp,
|
|
&[alice_userid],
|
|
&*alice2_pub_pgp);
|
|
assert_eq!(alice2.fingerprint(), alice.fingerprint());
|
|
|
|
// Attest Bob's certification.
|
|
attest(&sq, &alice2_pub_pgp);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
const ALICE_USERID: &str = "<alice@example.org>";
|
|
const BOB_USERID: &str = "<bob@example.org>";
|
|
|
|
fn make_keys(sq: &mut Sq) -> Result<(Cert, Cert)> {
|
|
let (alice, alice_pgp, _alice_rev)
|
|
= sq.key_generate(&[], &[ALICE_USERID]);
|
|
let (bob, bob_pgp, _bob_rev)
|
|
= sq.key_generate(&[], &[BOB_USERID]);
|
|
|
|
sq.key_import(alice_pgp);
|
|
sq.key_import(bob_pgp);
|
|
|
|
// Give Sequoia a little space to backdate the signatures. Note:
|
|
// It will not backdate them past the key creation time.
|
|
sq.tick(10);
|
|
|
|
Ok((alice, bob))
|
|
}
|
|
|
|
|
|
#[test]
|
|
fn update_all() -> Result<()> {
|
|
// See https://gitlab.com/sequoia-pgp/sequoia/-/issues/1111
|
|
let now = std::time::SystemTime::now()
|
|
- std::time::Duration::new(60 * 60, 0);
|
|
|
|
let mut sq = Sq::at(now);
|
|
let (alice, bob) = make_keys(&mut sq)?;
|
|
|
|
// Attest the zero certifications.
|
|
let approval = sq.key_approvals_update(
|
|
&["--add-all"], alice.key_handle(), NO_USERIDS, None);
|
|
|
|
assert_eq!(approval.bad_signatures().count(), 0);
|
|
let approval_ua = approval.userids().next().unwrap();
|
|
assert_eq!(approval_ua.attestations().count(), 1);
|
|
assert_eq!(approval_ua.with_policy(STANDARD_POLICY, None).unwrap()
|
|
.attested_certifications().count(), 0);
|
|
|
|
// Have Bob certify Alice.
|
|
let alice2 = sq.pki_vouch_add(&[],
|
|
bob.key_handle(),
|
|
alice.key_handle(),
|
|
&[ALICE_USERID],
|
|
None);
|
|
assert_eq!(alice2.fingerprint(), alice.fingerprint());
|
|
|
|
// Attest Bob's certification.
|
|
let approval = sq.key_approvals_update(
|
|
&["--add-all"], &alice.key_handle(), NO_USERIDS, None);
|
|
|
|
assert_eq!(approval.bad_signatures().count(), 0);
|
|
let approval_ua = approval.userids().next().unwrap();
|
|
assert_eq!(approval_ua.attestations().count(), 2);
|
|
assert_eq!(approval_ua.with_policy(STANDARD_POLICY, None).unwrap()
|
|
.attested_certifications().count(), 1);
|
|
|
|
// Drop the approval of Bob's certification.
|
|
let approval = sq.key_approvals_update(
|
|
&["--remove-all"], &alice.key_handle(), NO_USERIDS, None);
|
|
|
|
assert_eq!(approval.bad_signatures().count(), 0);
|
|
let approval_ua = approval.userids().next().unwrap();
|
|
assert_eq!(approval_ua.attestations().count(), 3);
|
|
assert_eq!(approval_ua.with_policy(STANDARD_POLICY, None).unwrap()
|
|
.attested_certifications().count(), 0);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn update_by() -> Result<()> {
|
|
// See https://gitlab.com/sequoia-pgp/sequoia/-/issues/1111
|
|
let now = std::time::SystemTime::now()
|
|
- std::time::Duration::new(60 * 60, 0);
|
|
|
|
let mut sq = Sq::at(now);
|
|
let (alice, bob) = make_keys(&mut sq)?;
|
|
let bob_fp = bob.fingerprint().to_string();
|
|
|
|
// Attest the zero certifications.
|
|
let approval = sq.key_approvals_update(
|
|
&["--add-by", &bob_fp], alice.key_handle(), NO_USERIDS, None);
|
|
|
|
assert_eq!(approval.bad_signatures().count(), 0);
|
|
let approval_ua = approval.userids().next().unwrap();
|
|
assert_eq!(approval_ua.attestations().count(), 1);
|
|
assert_eq!(approval_ua.with_policy(STANDARD_POLICY, None).unwrap()
|
|
.attested_certifications().count(), 0);
|
|
|
|
// Have Bob certify Alice.
|
|
let alice2 = sq.pki_vouch_add(&[],
|
|
bob.key_handle(),
|
|
alice.key_handle(),
|
|
&[ALICE_USERID],
|
|
None);
|
|
assert_eq!(alice2.fingerprint(), alice.fingerprint());
|
|
|
|
// Attest Bob's certification.
|
|
let approval = sq.key_approvals_update(
|
|
&["--add-by", &bob_fp], &alice.key_handle(), NO_USERIDS, None);
|
|
|
|
assert_eq!(approval.bad_signatures().count(), 0);
|
|
let approval_ua = approval.userids().next().unwrap();
|
|
assert_eq!(approval_ua.attestations().count(), 2);
|
|
assert_eq!(approval_ua.with_policy(STANDARD_POLICY, None).unwrap()
|
|
.attested_certifications().count(), 1);
|
|
|
|
// Drop the approval of Bob's certification.
|
|
let approval = sq.key_approvals_update(
|
|
&["--remove-by", &bob_fp], &alice.key_handle(), NO_USERIDS, None);
|
|
|
|
assert_eq!(approval.bad_signatures().count(), 0);
|
|
let approval_ua = approval.userids().next().unwrap();
|
|
assert_eq!(approval_ua.attestations().count(), 3);
|
|
assert_eq!(approval_ua.with_policy(STANDARD_POLICY, None).unwrap()
|
|
.attested_certifications().count(), 0);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
|
|
#[test]
|
|
fn update_authenticated() -> Result<()> {
|
|
// See https://gitlab.com/sequoia-pgp/sequoia/-/issues/1111
|
|
let now = std::time::SystemTime::now()
|
|
- std::time::Duration::new(60 * 60, 0);
|
|
|
|
let mut sq = Sq::at(now);
|
|
let (alice, bob) = make_keys(&mut sq)?;
|
|
let bob_fp = bob.fingerprint().to_string();
|
|
|
|
// Have Bob certify Alice.
|
|
let alice2 = sq.pki_vouch_add(&[],
|
|
bob.key_handle(),
|
|
alice.key_handle(),
|
|
&[ALICE_USERID],
|
|
None);
|
|
assert_eq!(alice2.fingerprint(), alice.fingerprint());
|
|
|
|
// Attest the zero certifications.
|
|
let approval = sq.key_approvals_update(
|
|
&["--add-authenticated"], alice.key_handle(), NO_USERIDS, None);
|
|
|
|
assert_eq!(approval.bad_signatures().count(), 0);
|
|
let approval_ua = approval.userids().next().unwrap();
|
|
assert_eq!(approval_ua.attestations().count(), 1);
|
|
assert_eq!(approval_ua.with_policy(STANDARD_POLICY, None).unwrap()
|
|
.attested_certifications().count(), 0);
|
|
|
|
// Link Bob's cert to his user ID.
|
|
let mut link = sq.command();
|
|
link.args(&["pki", "link", "add",
|
|
"--cert", &bob_fp,
|
|
"--userid", BOB_USERID]);
|
|
sq.run(link, true);
|
|
|
|
// Attest Bob's certification.
|
|
let approval = sq.key_approvals_update(
|
|
&["--add-authenticated"], &alice.key_handle(), NO_USERIDS, None);
|
|
|
|
assert_eq!(approval.bad_signatures().count(), 0);
|
|
let approval_ua = approval.userids().next().unwrap();
|
|
assert_eq!(approval_ua.attestations().count(), 2);
|
|
assert_eq!(approval_ua.with_policy(STANDARD_POLICY, None).unwrap()
|
|
.attested_certifications().count(), 1);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn ignore_shadow_ca() {
|
|
// Check that update ignores certificates made by shadow CAs.
|
|
let now = std::time::SystemTime::now()
|
|
- std::time::Duration::new(60 * 60, 0);
|
|
|
|
let mut sq = Sq::at(now);
|
|
let (alice, bob) = make_keys(&mut sq).unwrap();
|
|
|
|
// Have Bob certify Alice.
|
|
let alice2 = sq.pki_vouch_add(&[],
|
|
bob.key_handle(),
|
|
alice.key_handle(),
|
|
&[ALICE_USERID],
|
|
None);
|
|
assert_eq!(alice2.fingerprint(), alice.fingerprint());
|
|
|
|
let shadow_ca = artifact("keys/_sequoia_ca_keys.openpgp.org.pgp");
|
|
sq.key_import(&shadow_ca);
|
|
let shadow_ca = Cert::from_file(&shadow_ca).unwrap();
|
|
|
|
// Have the shadow CA certify Alice.
|
|
let alice2 = sq.pki_vouch_add(&[],
|
|
&shadow_ca.key_handle(),
|
|
alice.key_handle(),
|
|
&[ALICE_USERID],
|
|
None);
|
|
assert_eq!(alice2.fingerprint(), alice.fingerprint());
|
|
|
|
// Attest to all certifications. This should ignore the shadow
|
|
// CA's certification.
|
|
let approval = sq.key_approvals_update(
|
|
&["--add-all"], &alice.key_handle(), NO_USERIDS, None);
|
|
|
|
assert_eq!(approval.bad_signatures().count(), 0);
|
|
let approval_ua = approval.userids().next().unwrap();
|
|
// We have an attestation key signature.
|
|
assert_eq!(approval_ua.attestations().count(), 1);
|
|
// With one attestation (not two!).
|
|
assert_eq!(approval_ua.with_policy(STANDARD_POLICY, None).unwrap()
|
|
.attested_certifications().count(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn ignore_unexportable_certifications() {
|
|
// Check that update ignores certificates that are not exportable.
|
|
let now = std::time::SystemTime::now()
|
|
- std::time::Duration::new(60 * 60, 0);
|
|
|
|
let mut sq = Sq::at(now);
|
|
let (alice, bob) = make_keys(&mut sq).unwrap();
|
|
|
|
// Have Bob create a non-exportable certification for Alice.
|
|
let alice2 = sq.pki_vouch_add(&["--local"],
|
|
bob.key_handle(),
|
|
alice.key_handle(),
|
|
&[ALICE_USERID],
|
|
None);
|
|
assert_eq!(alice2.fingerprint(), alice.fingerprint());
|
|
|
|
// Attest to all certifications. This should ignore
|
|
// non-exportable certifications.
|
|
let approval = sq.key_approvals_update(
|
|
&["--add-all"], &alice.key_handle(), NO_USERIDS, None);
|
|
|
|
assert_eq!(approval.bad_signatures().count(), 0);
|
|
let approval_ua = approval.userids().next().unwrap();
|
|
for attestation in approval_ua.attestations() {
|
|
eprintln!(" - {:?}", attestation);
|
|
}
|
|
// We have an attestation key signature.
|
|
assert_eq!(approval_ua.attestations().count(), 1);
|
|
// With zero attestations.
|
|
assert_eq!(approval_ua.with_policy(STANDARD_POLICY, None).unwrap()
|
|
.attested_certifications().count(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn userid_designators() {
|
|
let self_signed_email = "alice@example.org";
|
|
let self_signed_userid
|
|
= &format!("Alice <{}>", self_signed_email);
|
|
|
|
let other_email = "alice@other.org";
|
|
let other_userid = &format!("Alice <{}>", other_email);
|
|
|
|
let mut sq = Sq::new();
|
|
|
|
let (cert, cert_path, _rev_path)
|
|
= sq.key_generate(&[], &[ self_signed_userid ]);
|
|
sq.key_import(cert_path);
|
|
|
|
// Give Sequoia a little space to backdate the signatures. Note:
|
|
// It will not backdate them past the key creation time.
|
|
sq.tick(10);
|
|
|
|
// 1. --userid: use the specified self-signed user ID.
|
|
sq.key_approvals_update(
|
|
&["--add-all"], cert.key_handle(),
|
|
&[ UserIDArg::UserID(self_signed_userid) ], None);
|
|
assert!(sq.try_key_approvals_update(
|
|
&["--add-all"], cert.key_handle(),
|
|
&[ UserIDArg::UserID(other_userid) ], None).is_err());
|
|
|
|
// 2. --email: use the self-signed user ID with the specified
|
|
// email address.
|
|
sq.key_approvals_update(
|
|
&["--add-all"], cert.key_handle(),
|
|
&[ UserIDArg::Email(self_signed_email) ], None);
|
|
assert!(sq.try_key_approvals_update(
|
|
&["--add-all"], cert.key_handle(),
|
|
&[ UserIDArg::Email(other_email) ], None).is_err());
|
|
}
|