From 9a42893ddfcf6c867ed1d96202e57b14a1deae05 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Wed, 16 Feb 2022 12:18:19 +0100 Subject: sq: Implement sq keyring filter --handle. --- sq/src/commands/keyring.rs | 26 ++++++++++++++++++++++---- sq/src/sq-usage.rs | 3 +++ sq/src/sq_cli.rs | 8 ++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/sq/src/commands/keyring.rs b/sq/src/commands/keyring.rs index fc3d867a..0fc2f51a 100644 --- a/sq/src/commands/keyring.rs +++ b/sq/src/commands/keyring.rs @@ -16,6 +16,7 @@ use openpgp::{ CertParser, }, Fingerprint, + KeyHandle, packet::{ UserID, UserAttribute, @@ -80,8 +81,24 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { let any_ua_predicates = false; let ua_predicate = |_ua: &UserAttribute| false; - let any_key_predicates = false; - let key_predicate = |_key: &Key<_, _>| false; + let any_key_predicates = m.is_present("handle"); + let handles: Vec = + if let Some(handles) = m.values_of("handle") { + use std::str::FromStr; + handles.into_iter().map(KeyHandle::from_str) + .collect::>()? + } else { + Vec::with_capacity(0) + }; + let key_predicate = |key: &Key<_, _>| { + let mut keep = false; + + for handle in &handles { + keep |= handle.aliases(key.key_handle()); + } + + keep + }; let filter_fn = |c: Cert| -> Option { if ! (any_uid_predicates @@ -91,7 +108,7 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { Some(c) } else if ! (c.userids().any(|c| uid_predicate(&c)) || c.user_attributes().any(|c| ua_predicate(&c)) - || c.keys().subkeys().any(|c| key_predicate(&c))) { + || c.keys().any(|c| key_predicate(c.key()))) { None } else if m.is_present("prune-certs") { let c = c @@ -102,7 +119,8 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { ! any_ua_predicates || ua_predicate(&c) }) .retain_subkeys(|c| { - ! any_key_predicates || key_predicate(&c) + ! any_key_predicates + || key_predicate(c.key().role_as_unspecified()) }); if c.userids().count() == 0 && c.user_attributes().count() == 0 diff --git a/sq/src/sq-usage.rs b/sq/src/sq-usage.rs index 6ec1be5e..75dba89a 100644 --- a/sq/src/sq-usage.rs +++ b/sq/src/sq-usage.rs @@ -897,6 +897,9 @@ //! --email
... //! Parses user ids into name and email address and case-sensitively //! matches on the email address, requiring an exact match. +//! --handle ... +//! Matches on both primary keys and subkeys, including those +//! certificates that match the given fingerprint or key id. //! --name ... //! Parses user ids into name and email and case-sensitively matches on //! the name, requiring an exact match. diff --git a/sq/src/sq_cli.rs b/sq/src/sq_cli.rs index 0c3b23c9..7c66d7c8 100644 --- a/sq/src/sq_cli.rs +++ b/sq/src/sq_cli.rs @@ -872,6 +872,14 @@ $ sq keyring filter --domain example.org --prune-certs certs.pgp address and case-sensitively matches \ on the domain of the email address, \ requiring an exact match.")) + .arg(Arg::with_name("handle") + .long("handle").value_name("FINGERPRINT|KEYID") + .multiple(true).number_of_values(1) + .help("Matches on (sub)key fingerprints and key ids") + .long_help( + "Matches on both primary keys and subkeys, \ + including those certificates that match the \ + given fingerprint or key id.")) .arg(Arg::with_name("prune-certs") .short("P").long("prune-certs") .help("Removes certificate components not \ -- cgit v1.2.3