Fix sq cert list for fingerprints and key IDs.

- The implementation of `sq cert list` tried to parse the
    pattern.  To do so, it relied on type inference to determine how
    to parse it.  The type was inferred from the type of the `cert`
    parameter to `authenticate`.  In
    2e17dec9ad, the type of the `cert`
    parameter changed from `KeyHandle` to `Cert`.  `Cert` has a
    `Parse` implementation so the type system didn't detect anything
    wrong.  However, we were now trying to parse the pattern as a
    `Cert` instead of a `KeyHandle`, which would fail for key handles.

  - Fix it, and add some tests for `sq cert list`.
This commit is contained in:
Neal H. Walfield 2024-11-16 21:12:50 +01:00
parent ebea7371db
commit 84b1bf99c6
No known key found for this signature in database
GPG Key ID: 6863C9AD5B4D22D3
4 changed files with 69 additions and 5 deletions

View File

@ -1,5 +1,8 @@
//! Operations on certs.
use sequoia_openpgp as openpgp;
use openpgp::KeyHandle;
use crate::{
Sq,
Result,
@ -27,15 +30,14 @@ pub fn dispatch(sq: Sq, command: Command) -> Result<()>
}) => {
let userid = userid.designators.into_iter().next();
if let Some(handle) = pattern.as_ref()
.and_then(|p| p.parse().ok())
if let Some(kh) = pattern.as_ref()
.and_then(|p| p.parse::<KeyHandle>().ok())
{
// A key handle was given as pattern and --email was not
// given. Act like `sq pki identify`.
let cert = sq.resolve_cert(&kh.into(), 0)?.0;
authenticate(
&sq, false, None,
*gossip, *certification_network, *trust_amount,
userid.as_ref(), Some(&handle), *show_paths)
userid.as_ref(), Some(&cert), *show_paths)
} else {
authenticate(
&sq, pattern.is_none(), pattern,

View File

@ -4,6 +4,7 @@ mod integration {
mod sq_cert_export;
mod sq_cert_import;
mod sq_cert_lint;
mod sq_cert_list;
mod sq_cli_version;
mod sq_decrypt;
mod sq_encrypt;

View File

@ -1475,6 +1475,26 @@ impl Sq {
Ok(out_key)
}
/// Runs `sq cert list` with the supplied arguments.
pub fn cert_list_maybe(&self, args: &[&str]) -> Result<Vec<u8>> {
let mut cmd = self.command();
cmd.arg("cert").arg("list");
for arg in args {
cmd.arg(arg);
}
let output = self.run(cmd, None);
if output.status.success() {
Ok(output.stdout)
} else {
Err(anyhow::anyhow!("sq cert list returned an error"))
}
}
/// Runs `sq cert list` with the supplied arguments.
pub fn cert_list(&self, args: &[&str]) -> Vec<u8> {
self.cert_list_maybe(args).expect("success")
}
/// Imports the specified certificate into the keystore.
pub fn cert_import_maybe<P>(&self, path: P) -> Result<()>
where P: AsRef<Path>

View File

@ -0,0 +1,41 @@
use super::common::Sq;
#[test]
fn list() {
let sq = Sq::new();
let email = "alice@example.org";
let name = "Alice Lovelace";
let userid = &format!("{} <{}>", name, email);
let (cert, cert_path, _rev_path)
= sq.key_generate(&[], &[ userid ]);
sq.key_import(&cert_path);
sq.pki_link_add(&[], cert.key_handle(), &[ userid ]);
// By fingerprint.
sq.cert_list(&[&cert.fingerprint().to_string()]);
// By user ID.
sq.cert_list(&[userid]);
sq.cert_list(&["--userid", userid]);
// By email.
sq.cert_list(&[email]);
sq.cert_list(&["--email", email]);
// By name.
sq.cert_list(&[name]);
// By substring.
sq.cert_list(&["lice"]);
sq.cert_list(&["LICE"]);
sq.cert_list(&["example.or"]);
sq.cert_list(&["ExAmPlE.Or"]);
// When we use --userid, then we don't do substring matching.
assert!(sq.cert_list_maybe(&["--userid", &userid[1..]]).is_err());
// When we use --email, then we don't do substring matching.
assert!(sq.cert_list_maybe(&["--email", &email[1..]]).is_err());
}