Better handle user ID's matched by --all.

- Change `sq pki link add`, `sq pki link authorize`, `sq pki link
    retract`, `sq pki vouch add`, and `sq pki vouch authorize` to
    better handle unusable user IDs matched by `--all`.  Specifically,
    if the user explicitly designates a user ID and we can't use it,
    then fail loudly, but if a user ID is selected by `--all` and it
    not usable, only emit a warning.
This commit is contained in:
Neal H. Walfield 2024-12-13 10:48:30 +01:00
parent 1dfaaeb644
commit 1a8dd3e467
No known key found for this signature in database
GPG Key ID: 6863C9AD5B4D22D3
5 changed files with 111 additions and 14 deletions

View File

@ -72,7 +72,7 @@ pub fn add(sq: Sq, c: link::AddCommand)
&trust_root,
&cert,
&userids[..],
true, // User-supplied user IDs.
! c.userids.all().unwrap_or(false), // User-supplied user IDs.
&templates,
0, // Trust depth.
&[][..], // Domain.
@ -105,7 +105,7 @@ pub fn authorize(sq: Sq, c: link::AuthorizeCommand)
&trust_root,
&cert,
&userids[..],
true, // User supplied user IDs.
! c.userids.all().unwrap_or(false), // User-supplied user IDs.
&[(c.amount, c.expiration.value())][..],
c.depth,
&c.domain[..],
@ -138,7 +138,7 @@ pub fn retract(sq: Sq, c: link::RetractCommand)
&trust_root,
&cert,
&userids[..],
true, // User supplied user IDs.
! c.userids.all().unwrap_or(false), // User-supplied user IDs.
&[(TrustAmount::None, Expiration::Never)],
0,
&[][..], &[][..], // Domain, regex.

View File

@ -34,7 +34,7 @@ pub fn add(sq: Sq, mut c: add::Command)
&certifier,
&cert,
&userids[..],
true, // User supplied user IDs.
! c.userids.all().unwrap_or(false), // User-supplied user IDs.
&[(c.amount, expiration)],
0,
&[][..], &[][..], // Domain, regex.

View File

@ -35,7 +35,7 @@ pub fn authorize(sq: Sq, mut c: authorize::Command)
&certifier,
&cert,
&userids[..],
true, // User supplied user IDs.
! c.userids.all().unwrap_or(false), // User-supplied user IDs.
&[(c.amount, expiration)],
c.depth,
&c.domain[..],

View File

@ -310,7 +310,14 @@ The certifier is the same as the certificate to certify."));
qprintln!("You never certified {:?} for {}, \
there is nothing to retract.",
userid_str(), cert.fingerprint());
return Ok(vec![ Packet::from(userid.userid().clone()) ]);
if user_supplied_userids {
return Err(anyhow::anyhow!(
"You never certified {:?} for {}, \
there is nothing to retract.",
userid_str(), cert.fingerprint()));
} else {
return Ok(vec![ Packet::from(userid.userid().clone()) ]);
}
}
} else {
if let RevocationStatus::Revoked(_)
@ -335,10 +342,17 @@ The certifier is the same as the certificate to certify."));
qprintln!("You never certified {:?} for {}, \
there is nothing to retract.",
userid_str(), cert.fingerprint());
// Return a signature packet to indicate that we
// processed something. But don't return a
// signature.
return Ok(vec![ Packet::from(userid.userid().clone()) ]);
if user_supplied_userids {
return Err(anyhow::anyhow!(
"You never certified {:?} for {}, \
there is nothing to retract.",
userid_str(), cert.fingerprint()));
} else {
// Return a signature packet to indicate that we
// processed something. But don't return a
// signature.
return Ok(vec![ Packet::from(userid.userid().clone()) ]);
}
} else {
return Err(anyhow::anyhow!(
"{:?} is NOT a self-signed user ID.",
@ -419,10 +433,16 @@ The certifier is the same as the certificate to certify."));
.collect::<Vec<Packet>>();
if certifications.is_empty() {
return Err(anyhow::anyhow!(
"Can't certify {}. The certificate has no self-signed \
user IDs and you didn't specify any user IDs to certify.",
cert.fingerprint()));
if retract {
return Err(anyhow::anyhow!(
"Can't retract links for {}. There is nothing to retract.",
cert.fingerprint()));
} else {
return Err(anyhow::anyhow!(
"Can't certify {}. The certificate has no self-signed \
user IDs and you didn't specify any user IDs to certify.",
cert.fingerprint()));
}
}
if certifications.iter().all(|p| matches!(p, Packet::UserID(_))) {

View File

@ -1019,3 +1019,80 @@ fn link_retract_userid_designators() {
assert!(sq.pki_authenticate(
&[], &fpr, UserIDArg::UserID("<alice@example.com>")).is_err());
}
#[test]
fn retract() {
let mut sq = Sq::new();
let (cert, cert_path, _rev_path) = sq.key_generate(
&[], &["Alice <alice@example.org>" ]);
sq.key_import(cert_path);
// If a user ID was never linked, retract fails.
// Check for a self-signed user ID.
sq.tick(1);
assert!(sq.pki_link_retract_maybe(
&[], cert.key_handle(),
&[ UserIDArg::UserID("Alice <alice@example.org>") ]).is_err());
assert!(sq.pki_link_retract_maybe(
&[], cert.key_handle(),
&[ UserIDArg::Email("alice@example.org") ]).is_err());
// Check for a user ID that is not self signed.
assert!(sq.pki_link_retract_maybe(
&[], cert.key_handle(),
&[ UserIDArg::UserID("Alice <alice@example.com>") ]).is_err());
assert!(sq.pki_link_retract_maybe(
&[], cert.key_handle(),
&[ UserIDArg::Email("alice@example.com") ]).is_err());
// --all doesn't care.
assert!(sq.pki_link_retract_maybe(
&["--all"], cert.key_handle(), NO_USERIDS).is_ok());
// Now create a link. If we retract the same link multiple times,
// we don't get an error, but the subsequent calls won't do
// anything except emit the message "Certification parameters are
// unchanged.")
sq.tick(1);
sq.pki_link_add(
&[], cert.key_handle(),
&[ UserIDArg::UserID("Alice <alice@example.org>") ]);
for _ in 1..4 {
sq.tick(1);
sq.pki_link_retract(
&[], cert.key_handle(),
&[ UserIDArg::UserID("Alice <alice@example.org>") ]);
sq.tick(1);
sq.pki_link_retract(
&[], cert.key_handle(),
&[ UserIDArg::Email("alice@example.org") ]);
}
sq.pki_link_add(
&[], cert.key_handle(),
&[ UserIDArg::AddUserID("Alice <alice@example.com>") ]);
for _ in 1..4 {
sq.tick(1);
sq.pki_link_retract(
&[], cert.key_handle(),
&[ UserIDArg::UserID("Alice <alice@example.com>") ]);
// We can't name "Alice <alice@example.com>" by email, because
// it is not self-signed.
sq.tick(1);
assert!(sq.pki_link_retract_maybe(
&[], cert.key_handle(),
&[ UserIDArg::Email("alice@example.com") ]).is_err());
}
// --all doesn't care.
assert!(sq.pki_link_retract_maybe(
&["--all"], cert.key_handle(), NO_USERIDS).is_ok());
}