sequoia-sq/tests/integration/sq_pki_vouch_authorize.rs
Justus Winter 3b1bd79195
Align user ID designators in sq pki {link,vouch} {add,authorize}.
- Align user ID designators across these four commands.  Previously,
    `--all` was implied for the authorize commands if no user ID
    designator was given.

  - However, this is problematic for the following reasons:

    - First, it is inconsistent across the commands.

    - Second, while CAs can add any name to their cert because they
      are CAs, those certifications are subject to constraints, such
      as domain constraints, or the amount.  But, the link we add
      fully authenticates the current user IDs, which may not be what
      the user wants, so it should require explicit consent.

    - Third, making this implicit again is easier than going from
      implicit to explicit, which breaks existing users.

  - Fixes #442.
2024-11-27 13:33:30 +01:00

338 lines
11 KiB
Rust

use super::common::NO_USERIDS;
use super::common::Sq;
#[test]
fn sq_pki_vouch_authorize_then_authenticate() {
let mut sq = Sq::new();
let otto_somewhere_com = "<otto@somewhere.com>";
let (otto, otto_pgp, _otto_rev)
= sq.key_generate(&[], &[otto_somewhere_com]);
sq.key_import(&otto_pgp);
let ca_example_org = "<ca@example.org>";
let (ca, ca_pgp, _ca_rev)
= sq.key_generate(&[], &[ca_example_org]);
sq.key_import(&ca_pgp);
let alice_example_org = "<alice@example.org>";
let (alice, alice_pgp, _alice_rev)
= sq.key_generate(&[], &[alice_example_org]);
sq.key_import(&alice_pgp);
let bob_example_org = "<bob@example.org>";
let bob_other_org = "<bob@other.org>";
let (bob, bob_pgp, _bob_rev)
= sq.key_generate(&[], &[bob_example_org, bob_other_org]);
sq.key_import(&bob_pgp);
sq.tick(1);
// The ca certifies alice's and bob's certificates for each of
// their user IDs.
let certification = sq.scratch_file(None);
sq.pki_vouch_add(
&[],
ca.key_handle(), alice.key_handle(),
&[ alice_example_org ],
certification.as_path());
sq.cert_import(&certification);
let certification = sq.scratch_file(None);
sq.pki_vouch_add(
&[],
ca.key_handle(), bob.key_handle(),
&[ bob_example_org, bob_other_org ],
certification.as_path());
sq.cert_import(certification);
// Check whether we can authenticate alice's and bob's
// certificates for their user ID using otto as the trust root.
let check = |sq: &Sq,
can_authenticate_alice,
can_authenticate_bob1,
can_authenticate_bob2|
{
for (cert, userid, can_authenticate) in &[
(&alice, alice_example_org, can_authenticate_alice),
(&bob, bob_example_org, can_authenticate_bob1),
(&bob, bob_other_org, can_authenticate_bob2),
]
{
let r = sq.pki_authenticate(
&["--trust-root", &otto.fingerprint().to_string() ],
&cert.fingerprint().to_string(),
userid);
match (can_authenticate, r.is_ok()) {
(true, false) => {
panic!("Expected to authenticated {}, but didn't.",
userid);
}
(false, true) => {
panic!("Expected to NOT authenticated {}, but did.",
userid);
}
_ => (),
}
}
};
// No delegation yet.
println!("CA: not authorized");
check(
&sq,
false, // Alice.
false, // bob@example.org
false);// bob@other.org
// Otto authorizes completely to the CA.
let certification = sq.scratch_file(None);
sq.tick(1);
sq.pki_vouch_authorize(&["--unconstrained", "--all"],
otto.key_handle(), ca.key_handle(),
NO_USERIDS,
certification.as_path());
sq.cert_import(certification);
println!("CA: authorized, and unconstrained");
check(
&sq,
true, // alice@example.org
true, // bob@example.org
true);// bob@other.org
// Otto authorizes to the CA with the regex contraint "example".
let certification = sq.scratch_file(None);
sq.tick(1);
sq.pki_vouch_authorize(&["--regex", "example", "--all"],
otto.key_handle(), ca.key_handle(),
NO_USERIDS,
certification.as_path());
sq.cert_import(certification);
println!("CA: authorized for \"example\"");
check(
&sq,
true, // alice@example.org
true, // bob@example.org
false);// bob@other.org
// Otto authorizes to the CA with the domain contraint "example.org".
let certification = sq.scratch_file(None);
sq.tick(1);
sq.pki_vouch_authorize(&["--domain", "example.org", "--all"],
otto.key_handle(), ca.key_handle(),
NO_USERIDS,
certification.as_path());
sq.cert_import(certification);
println!("CA: authorized for \"example.org\"");
check(
&sq,
true, // alice@example.org
true, // bob@example.org
false);// bob@other.org
// Otto authorizes to the CA with the regex contraint "other".
let certification = sq.scratch_file(None);
sq.tick(1);
sq.pki_vouch_authorize(&["--regex", "other", "--all"],
otto.key_handle(), ca.key_handle(),
NO_USERIDS,
certification.as_path());
sq.cert_import(certification);
println!("CA: authorized for \"other\"");
check(
&sq,
false, // alice@example.org
false, // bob@example.org
true); // bob@other.org
// Otto authorizes to the CA with the regex contraint "bob".
let certification = sq.scratch_file(None);
sq.tick(1);
sq.pki_vouch_authorize(&["--regex", "bob", "--all"],
otto.key_handle(), ca.key_handle(),
NO_USERIDS,
certification.as_path());
sq.cert_import(certification);
println!("CA: authorized for \"bob\"");
check(
&sq,
false, // alice@example.org
true, // bob@example.org
true); // bob@other.org
// Otto authorizes to the CA with the regex contraint "bob" or "alice".
let certification = sq.scratch_file(None);
sq.tick(1);
sq.pki_vouch_authorize(&["--regex", "bob", "--regex", "alice", "--all"],
otto.key_handle(), ca.key_handle(),
NO_USERIDS,
certification.as_path());
sq.cert_import(certification);
println!("CA: authorized for \"bob\" or \"alice\"");
check(
&sq,
true, // alice@example.org
true, // bob@example.org
true);// bob@other.org
// Otto authorizes to the CA for the domains example.org and other.org.
let certification = sq.scratch_file(None);
sq.tick(1);
sq.pki_vouch_authorize(
&["--domain", "example.org", "--domain", "other.org", "--all"],
otto.key_handle(), ca.key_handle(),
NO_USERIDS,
certification.as_path());
sq.cert_import(certification);
println!("CA: authorized for the domains example.org and other.org");
check(
&sq,
true, // alice@example.org
true, // bob@example.org
true);// bob@other.org
// Otto authorizes to the CA for the domain example.com and the regex alice.
let certification = sq.scratch_file(None);
sq.tick(1);
sq.pki_vouch_authorize(
&["--domain", "other.org", "--regex", "alice", "--all"],
otto.key_handle(), ca.key_handle(),
NO_USERIDS,
certification.as_path());
sq.cert_import(certification);
println!("CA: authorized for the domains example.org and other.org");
check(
&sq,
true, // alice@example.org
false, // bob@example.org
true); // bob@other.org
// Otto authorizes to the CA with the regex contraint "zoo".
let certification = sq.scratch_file(None);
sq.tick(1);
sq.pki_vouch_authorize(&["--regex", "zoo", "--all"],
otto.key_handle(), ca.key_handle(),
NO_USERIDS,
certification.as_path());
sq.cert_import(certification);
println!("CA: authorized for \"zoo\"");
check(
&sq,
false, // alice@example.org
false, // bob@example.org
false);// bob@other.org
// Otto authorizes to the CA with the domain contraint "example".
let certification = sq.scratch_file(None);
sq.tick(1);
sq.pki_vouch_authorize(&["--domain", "example", "--all"],
otto.key_handle(), ca.key_handle(),
NO_USERIDS,
certification.as_path());
sq.cert_import(certification);
println!("CA: authorized for \"zoo\"");
check(
&sq,
false, // alice@example.org
false, // bob@example.org
false);// bob@other.org
}
#[test]
fn sq_pki_vouch_authorize_all_revoked() {
// When we don't provide any user IDs, `sq pki vouch authorize`
// certifies all of the self signed user IDs. Make sure this
// works in the presence of a revoked user ID, which should be
// ignored.
let mut sq = Sq::new();
let otto_somewhere_com = "<otto@somewhere.com>";
let (otto, otto_pgp, _otto_rev)
= sq.key_generate(&[], &[otto_somewhere_com]);
sq.key_import(&otto_pgp);
let ca_example_org = "<ca@example.org>";
let ca_example_com = "<ca@example.com>";
let (ca, ca_pgp, _ca_rev)
= sq.key_generate(&[], &[ca_example_org, ca_example_com]);
sq.key_import(&ca_pgp);
// Revoke ca@example.com.
sq.tick(1);
let revocation = sq.scratch_file("revocation");
sq.key_userid_revoke(&[], ca.fingerprint(), ca_example_com,
"retired", "bye", Some(revocation.as_path()));
sq.cert_import(&revocation);
let alice_example_org = "<alice@example.org>";
let (alice, alice_pgp, _alice_rev)
= sq.key_generate(&[], &[alice_example_org]);
sq.key_import(&alice_pgp);
sq.tick(1);
// The ca certifies alice's certificate.
let certification = sq.scratch_file(None);
sq.pki_vouch_add(
&[],
ca.key_handle(), alice.key_handle(),
&[ alice_example_org ],
certification.as_path());
sq.cert_import(&certification);
// Check whether we can authenticate alice's and bob's
// certificates for their user ID using otto as the trust root.
let check = |sq: &Sq, can_authenticate|
{
let r = sq.pki_authenticate(
&["--trust-root", &otto.fingerprint().to_string() ],
&alice.fingerprint().to_string(),
alice_example_org);
match (can_authenticate, r.is_ok()) {
(true, false) => {
panic!("Expected to authenticated {}, but didn't.",
alice_example_org);
}
(false, true) => {
panic!("Expected to NOT authenticated {}, but did.",
alice_example_org);
}
_ => (),
}
};
// No delegation yet.
println!("CA: not authorized");
check(&sq, false);
// Otto completely authorizes the CA. Note: we don't specify any
// user IDs so only valid self-signed user IDs should be used.
// That means the revoked user ID should be skipped.
let certification = sq.scratch_file(None);
sq.tick(1);
sq.pki_vouch_authorize(&["--unconstrained", "--all"],
otto.key_handle(), ca.key_handle(),
NO_USERIDS,
certification.as_path());
sq.cert_import(certification);
println!("CA: authorized, and unconstrained");
check(&sq, true);
}