summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2022-02-16 12:18:19 +0100
committerJustus Winter <justus@sequoia-pgp.org>2022-02-16 12:56:20 +0100
commit9a42893ddfcf6c867ed1d96202e57b14a1deae05 (patch)
treeb904a2b054b71b9c02463d4e1e422abc4b7a02e9
parent72c829e39f3628f6bc8400b67045230f4449e8dc (diff)
sq: Implement sq keyring filter --handle.
-rw-r--r--sq/src/commands/keyring.rs26
-rw-r--r--sq/src/sq-usage.rs3
-rw-r--r--sq/src/sq_cli.rs8
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<KeyHandle> =
+ if let Some(handles) = m.values_of("handle") {
+ use std::str::FromStr;
+ handles.into_iter().map(KeyHandle::from_str)
+ .collect::<Result<_>>()?
+ } 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<Cert> {
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 <ADDRESS>...
//! Parses user ids into name and email address and case-sensitively
//! matches on the email address, requiring an exact match.
+//! --handle <FINGERPRINT|KEYID>...
+//! Matches on both primary keys and subkeys, including those
+//! certificates that match the given fingerprint or key id.
//! --name <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 \