summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2021-03-12 16:23:04 +0100
committerJustus Winter <justus@sequoia-pgp.org>2021-03-12 16:32:15 +0100
commit3c9351ade65fa888a13018765ba058363314d677 (patch)
tree817b3a554e0578e79356d2486566bf08ba0d7a52
parentefcf130fb2635848a609fb7d897aa0258bfaa9a2 (diff)
sq: Improve keyring list.
- Try hard to list the most relevant (i.e. primary) user id. - Add a flag --all-userids to list all userids.
-rw-r--r--sq/src/commands/keyring.rs71
-rw-r--r--sq/src/sq-usage.rs9
-rw-r--r--sq/src/sq_cli.rs11
3 files changed, 75 insertions, 16 deletions
diff --git a/sq/src/commands/keyring.rs b/sq/src/commands/keyring.rs
index bb561c8e..be8fae21 100644
--- a/sq/src/commands/keyring.rs
+++ b/sq/src/commands/keyring.rs
@@ -156,7 +156,7 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> {
},
("list", Some(m)) => {
let mut input = open_or_stdin(m.value_of("input"))?;
- list(&mut input)
+ list(config, &mut input, m.is_present("all-userids"))
},
("split", Some(m)) => {
let mut input = open_or_stdin(m.value_of("input"))?;
@@ -217,19 +217,68 @@ fn filter<F>(inputs: Option<clap::Values>, output: &mut dyn io::Write,
}
/// Lists certs in a keyring.
-fn list(input: &mut (dyn io::Read + Sync + Send))
- -> Result<()> {
+fn list(config: Config,
+ input: &mut (dyn io::Read + Sync + Send),
+ list_all_uids: bool)
+ -> Result<()>
+{
for (i, cert) in CertParser::from_reader(input)?.enumerate() {
let cert = cert.context("Malformed certificate in keyring")?;
- print!("{}. {:X}", i, cert.fingerprint());
- // Try to be more helpful by including the first userid in the
- // listing.
- if let Some(email) = cert.userids().nth(0)
- .and_then(|uid| uid.email().unwrap_or(None))
- {
- print!(" {}", email);
+ let line = format!("{}. {:X}", i, cert.fingerprint());
+ let indent = line.chars().map(|_| ' ').collect::<String>();
+ print!("{}", line);
+
+ // Try to be more helpful by including a User ID in the
+ // listing. We'd like it to be the primary one. Use
+ // decreasingly strict policies.
+ let mut primary_uid = None;
+
+ // First, apply our policy.
+ if let Ok(vcert) = cert.with_policy(&config.policy, None) {
+ if let Ok(primary) = vcert.primary_userid() {
+ println!(" {}", String::from_utf8_lossy(primary.value()));
+ primary_uid = Some(primary.value().to_vec());
+ }
+ }
+
+ // Second, apply the null policy.
+ if primary_uid.is_none() {
+ let null = openpgp::policy::NullPolicy::new();
+ if let Ok(vcert) = cert.with_policy(&null, None) {
+ if let Ok(primary) = vcert.primary_userid() {
+ println!(" {}", String::from_utf8_lossy(primary.value()));
+ primary_uid = Some(primary.value().to_vec());
+ }
+ }
+ }
+
+ // As a last resort, pick the first user id.
+ if primary_uid.is_none() {
+ if let Some(primary) = cert.userids().nth(0) {
+ println!(" {}", String::from_utf8_lossy(primary.value()));
+ primary_uid = Some(primary.value().to_vec());
+ }
+ }
+
+ if primary_uid.is_none() {
+ // No dice.
+ println!();
+ }
+
+ if list_all_uids {
+ // List all user ids independently of their validity.
+ for u in cert.userids() {
+ if primary_uid.as_ref()
+ .map(|p| &p[..] == u.value()).unwrap_or(false)
+ {
+ // Skip the user id we already printed.
+ continue;
+ }
+
+ println!("{} {}", indent,
+ String::from_utf8_lossy(u.value()));
+ }
}
- println!();
}
Ok(())
}
diff --git a/sq/src/sq-usage.rs b/sq/src/sq-usage.rs
index bd7acefb..94938f4e 100644
--- a/sq/src/sq-usage.rs
+++ b/sq/src/sq-usage.rs
@@ -621,13 +621,16 @@
//! ```text
//! Lists keys in a keyring
//!
-//! Prints the fingerprint as well one userid for every certificate
-//! encountered in the keyring.
+//! Prints the fingerprint as well as the primary userid for every
+//! certificate encountered in the keyring.
//!
//! USAGE:
-//! sq keyring list [FILE]
+//! sq keyring list [FLAGS] [FILE]
//!
//! FLAGS:
+//! --all-userids
+//! Lists all user ids, even those that are expired, revoked, or not
+//! valid under the standard policy.
//! -h, --help
//! Prints help information
//!
diff --git a/sq/src/sq_cli.rs b/sq/src/sq_cli.rs
index c76758ba..0948363c 100644
--- a/sq/src/sq_cli.rs
+++ b/sq/src/sq_cli.rs
@@ -889,8 +889,8 @@ $ sq keyring merge certs.pgp romeo-updates.pgp
.long_about(
"Lists keys in a keyring
-Prints the fingerprint as well one userid for every certificate
-encountered in the keyring.
+Prints the fingerprint as well as the primary userid for every
+certificate encountered in the keyring.
")
.after_help(
"EXAMPLES:
@@ -904,6 +904,13 @@ $ sq keyring filter --domain example.org certs.pgp | sq keyring list
.arg(Arg::with_name("input")
.value_name("FILE")
.help("Reads from FILE or stdin if omitted"))
+ .arg(Arg::with_name("all-userids")
+ .long("--all-userids")
+ .help("Lists all user ids")
+ .long_help(
+ "Lists all user ids, even those that are \
+ expired, revoked, or not valid under the \
+ standard policy."))
)
.subcommand(
SubCommand::with_name("split")