Port sq pki {authenticate,identify} to the cert designator framework.
- Port `sq pki authenticate` and `sq pki identify` to the cert designator framework. See #207. - This changes the certificate parameter from a positional parameter to a named parameter. See #318.
This commit is contained in:
parent
d561fad1a6
commit
2e17dec9ad
6
NEWS
6
NEWS
@ -68,6 +68,12 @@
|
||||
- The argument `sq encrypt --set-metadata-time` has been removed.
|
||||
- The argument `sq encrypt --set-metadata-filename` now takes a
|
||||
string that specifies the file name to be set.
|
||||
- `sq pki authenticate`'s positional argument for specifying the
|
||||
certificate to authenticate must now be specified using a named
|
||||
argument, `--cert`.
|
||||
- `sq pki identify`'s positional argument for specifying the
|
||||
certificate to identify must now be specified using a named
|
||||
argument, `--cert`.
|
||||
|
||||
* Changes in 0.39.0
|
||||
** Notable changes
|
||||
|
@ -5,7 +5,6 @@ use std::ops::Deref;
|
||||
use clap::Parser;
|
||||
|
||||
use sequoia_openpgp as openpgp;
|
||||
use openpgp::KeyHandle;
|
||||
use openpgp::packet::UserID;
|
||||
|
||||
use crate::cli::types::TrustAmount;
|
||||
@ -57,21 +56,6 @@ pub enum Subcommands {
|
||||
Path(path::Command),
|
||||
}
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
pub struct CertArg {
|
||||
/// The fingerprint or Key ID of the certificate to authenticate.
|
||||
#[arg(value_name="FINGERPRINT|KEYID")]
|
||||
cert: KeyHandle
|
||||
}
|
||||
|
||||
impl Deref for CertArg {
|
||||
type Target = KeyHandle;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.cert
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(clap::Args, Debug)]
|
||||
pub struct UserIDArg {
|
||||
/// The User ID to authenticate.
|
||||
|
@ -8,7 +8,9 @@ use examples::Actions;
|
||||
use examples::Example;
|
||||
use examples::Setup;
|
||||
|
||||
use super::CertArg;
|
||||
use crate::cli::types::cert_designator;
|
||||
use crate::cli::types::CertDesignators;
|
||||
|
||||
use super::CertificationNetworkArg;
|
||||
use super::EmailArg;
|
||||
use super::GossipArg;
|
||||
@ -37,6 +39,18 @@ use super::UserIDArg;
|
||||
after_help = EXAMPLES,
|
||||
)]
|
||||
pub struct Command {
|
||||
// Note: don't add --cert-file: the certificate needs to be merged
|
||||
// into the certificate store, and --cert-file doesn't do that.
|
||||
// Instead, the user should use --keyring FILE and --cert FPR.
|
||||
#[command(flatten)]
|
||||
pub cert: CertDesignators<
|
||||
cert_designator::CertArg,
|
||||
cert_designator::CertPrefix,
|
||||
cert_designator::OneValue>,
|
||||
|
||||
#[command(flatten)]
|
||||
pub userid: UserIDArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub show_paths: ShowPathsArg,
|
||||
|
||||
@ -51,12 +65,6 @@ pub struct Command {
|
||||
|
||||
#[command(flatten)]
|
||||
pub trust_amount: RequiredTrustAmountArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cert: CertArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub userid: UserIDArg,
|
||||
}
|
||||
|
||||
const EXAMPLES: Actions = Actions {
|
||||
@ -74,7 +82,7 @@ const EXAMPLES: Actions = Actions {
|
||||
Authenticate a specific binding.",
|
||||
command: &[
|
||||
"sq", "pki", "authenticate",
|
||||
"EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"Alice <alice@example.org>",
|
||||
]
|
||||
}),
|
||||
@ -84,7 +92,7 @@ Check whether we can authenticate any user ID with the specified email \
|
||||
address for the given certificate.",
|
||||
command: &[
|
||||
"sq", "pki", "authenticate",
|
||||
"EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--email", "alice@example.org",
|
||||
],
|
||||
}),
|
||||
|
@ -8,7 +8,9 @@ use examples::Actions;
|
||||
use examples::Example;
|
||||
use examples::Setup;
|
||||
|
||||
use super::CertArg;
|
||||
use crate::cli::types::cert_designator;
|
||||
use crate::cli::types::CertDesignators;
|
||||
|
||||
use super::CertificationNetworkArg;
|
||||
use super::GossipArg;
|
||||
use super::RequiredTrustAmountArg;
|
||||
@ -32,6 +34,15 @@ use super::ShowPathsArg;
|
||||
after_help = EXAMPLES,
|
||||
)]
|
||||
pub struct Command {
|
||||
// Note: don't add --cert-file: the certificate needs to be merged
|
||||
// into the certificate store, and --cert-file doesn't do that.
|
||||
// Instead, the user should use --keyring FILE and --cert FPR.
|
||||
#[command(flatten)]
|
||||
pub cert: CertDesignators<
|
||||
cert_designator::CertArg,
|
||||
cert_designator::CertPrefix,
|
||||
cert_designator::OneValue>,
|
||||
|
||||
#[command(flatten)]
|
||||
pub show_paths: ShowPathsArg,
|
||||
|
||||
@ -43,9 +54,6 @@ pub struct Command {
|
||||
|
||||
#[command(flatten)]
|
||||
pub trust_amount: RequiredTrustAmountArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cert: CertArg,
|
||||
}
|
||||
|
||||
const EXAMPLES: Actions = Actions {
|
||||
@ -63,7 +71,7 @@ const EXAMPLES: Actions = Actions {
|
||||
Identify the user IDs that can be authenticated for the certificate.",
|
||||
command: &[
|
||||
"sq", "pki", "identify",
|
||||
"EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
],
|
||||
}),
|
||||
Action::Example(Example {
|
||||
@ -71,7 +79,7 @@ Identify the user IDs that can be authenticated for the certificate.",
|
||||
List all user IDs that have that have been certified by anyone.",
|
||||
command: &[
|
||||
"sq", "pki", "identify", "--gossip",
|
||||
"511257EBBF077B7AEDAE5D093F68CB84CE537C9A",
|
||||
"--cert", "511257EBBF077B7AEDAE5D093F68CB84CE537C9A",
|
||||
],
|
||||
}),
|
||||
]
|
||||
|
@ -402,7 +402,7 @@ pub fn dispatch(sq: Sq, c: download::Command)
|
||||
false, // certification network
|
||||
Some(TrustAmount::Full), // trust amount
|
||||
None, // user ID
|
||||
Some(&cert.key_handle()),
|
||||
Some(&cert),
|
||||
true, // show paths
|
||||
).is_ok();
|
||||
|
||||
|
@ -1,15 +1,13 @@
|
||||
use anyhow::Context;
|
||||
|
||||
use sequoia_openpgp as openpgp;
|
||||
use openpgp::Cert;
|
||||
use openpgp::KeyID;
|
||||
use openpgp::Fingerprint;
|
||||
use openpgp::KeyHandle;
|
||||
use openpgp::Result;
|
||||
use openpgp::packet::UserID;
|
||||
|
||||
use sequoia_cert_store as cert_store;
|
||||
use cert_store::store::StoreError;
|
||||
|
||||
use sequoia_wot as wot;
|
||||
use wot::store::Backend;
|
||||
use wot::store::Store;
|
||||
@ -85,7 +83,7 @@ pub fn authenticate<'store, 'rstore>(
|
||||
certification_network: bool,
|
||||
trust_amount: Option<TrustAmount<usize>>,
|
||||
userid: Option<&UserID>,
|
||||
certificate: Option<&KeyHandle>,
|
||||
certificate: Option<&Cert>,
|
||||
show_paths: bool,
|
||||
) -> Result<()>
|
||||
where 'store: 'rstore,
|
||||
@ -114,57 +112,7 @@ pub fn authenticate<'store, 'rstore>(
|
||||
let required_amount =
|
||||
required_trust_amount(trust_amount, certification_network)?;
|
||||
|
||||
let mut certificate_dealiased = None;
|
||||
let fingerprint: Option<Fingerprint> = if let Some(kh) = certificate {
|
||||
match sq.lookup(std::iter::once(kh), None, true, true) {
|
||||
Ok(certs) => {
|
||||
assert!(certs.len() >= 1);
|
||||
|
||||
if certs.len() > 1 {
|
||||
return Err(anyhow::anyhow!(
|
||||
"The key ID {} is ambiguous. \
|
||||
It could refer to any of the following \
|
||||
certificates: {}.",
|
||||
kh,
|
||||
certs.into_iter()
|
||||
.map(|c| c.fingerprint().to_hex())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ")));
|
||||
}
|
||||
|
||||
let fpr = certs[0].fingerprint();
|
||||
if ! KeyHandle::from(&fpr).aliases(kh) {
|
||||
// XXX: If the subkey does not have a backsig,
|
||||
// then it doesn't authenticate the primary key,
|
||||
// and thus the authentication confidence must be
|
||||
// 0, and the certificate should only be shown
|
||||
// when `--gossip` is passed.
|
||||
wprintln!("Certificate {} contains the subkey {}.",
|
||||
fpr, kh);
|
||||
}
|
||||
certificate_dealiased = Some(KeyHandle::from(&fpr));
|
||||
Some(fpr)
|
||||
}
|
||||
Err(err) => {
|
||||
if let Some(StoreError::NotFound(_)) = err.downcast_ref() {
|
||||
wprintln!("There are no certificates with the \
|
||||
specified {}. \
|
||||
Run `sq network fetch {}` to look for \
|
||||
matching certificates on public \
|
||||
directories.",
|
||||
if let KeyHandle::Fingerprint(_) = kh {
|
||||
"fingerprint"
|
||||
} else {
|
||||
"key ID"
|
||||
},
|
||||
kh);
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let fingerprint: Option<Fingerprint> = certificate.map(|c| c.fingerprint());
|
||||
|
||||
let mut bindings = Vec::new();
|
||||
if matches!(userid, Some(_)) && email {
|
||||
@ -216,9 +164,9 @@ pub fn authenticate<'store, 'rstore>(
|
||||
None
|
||||
}
|
||||
}).collect();
|
||||
} else if let Some(fingerprint) = fingerprint {
|
||||
} else if let Some(fingerprint) = fingerprint.as_ref() {
|
||||
if let Some(userid) = userid {
|
||||
bindings.push((fingerprint, userid.clone()));
|
||||
bindings.push((fingerprint.clone(), userid.clone()));
|
||||
} else {
|
||||
// Fingerprint, no User ID.
|
||||
bindings = n.certified_userids_of(&fingerprint)
|
||||
@ -316,7 +264,7 @@ pub fn authenticate<'store, 'rstore>(
|
||||
// We didn't show anything. Try to figure out what was wrong.
|
||||
if lint_input {
|
||||
// See if the target certificate exists.
|
||||
if let Some(kh) = certificate_dealiased {
|
||||
if let Some(kh) = fingerprint.as_ref().map(|fpr| KeyHandle::from(fpr)) {
|
||||
match n.lookup_synopses(&kh) {
|
||||
Err(err) => {
|
||||
wprintln!("Looking up target certificate ({}): {}",
|
||||
@ -512,11 +460,15 @@ pub fn dispatch(sq: Sq, cli: cli::pki::Command) -> Result<()> {
|
||||
Subcommands::Authenticate(authenticate::Command {
|
||||
email, gossip, certification_network, trust_amount,
|
||||
cert, userid, show_paths,
|
||||
}) => authenticate(
|
||||
&sq, false, None,
|
||||
*email, *gossip, *certification_network, *trust_amount,
|
||||
Some(&userid), Some(&cert), *show_paths,
|
||||
)?,
|
||||
}) => {
|
||||
let cert = sq.resolve_cert(&cert, 0)?.0;
|
||||
|
||||
authenticate(
|
||||
&sq, false, None,
|
||||
*email, *gossip, *certification_network, *trust_amount,
|
||||
Some(&userid), Some(&cert), *show_paths,
|
||||
)?
|
||||
}
|
||||
|
||||
// Find all authenticated bindings for a given User ID, list
|
||||
// the certificates.
|
||||
@ -533,10 +485,14 @@ pub fn dispatch(sq: Sq, cli: cli::pki::Command) -> Result<()> {
|
||||
Subcommands::Identify(identify::Command {
|
||||
gossip, certification_network, trust_amount,
|
||||
cert, show_paths,
|
||||
}) => authenticate(
|
||||
&sq, false, None,
|
||||
false, *gossip, *certification_network, *trust_amount,
|
||||
None, Some(&cert), *show_paths)?,
|
||||
}) => {
|
||||
let cert = sq.resolve_cert(&cert, 0)?.0;
|
||||
|
||||
authenticate(
|
||||
&sq, false, None,
|
||||
false, *gossip, *certification_network, *trust_amount,
|
||||
None, Some(&cert), *show_paths)?;
|
||||
}
|
||||
|
||||
// Authenticates a given path.
|
||||
Subcommands::Path(command) =>
|
||||
|
@ -1780,7 +1780,7 @@ impl Sq {
|
||||
for arg in extra_args {
|
||||
cmd.arg(arg);
|
||||
}
|
||||
cmd.arg(cert);
|
||||
cmd.arg("--cert").arg(cert);
|
||||
cmd.arg(userid);
|
||||
|
||||
let output = self.run(cmd, None);
|
||||
|
@ -40,7 +40,7 @@ fn sq_autocrypt_import() -> Result<()>
|
||||
let mut cmd = sq.command();
|
||||
cmd.arg("pki").arg("authenticate")
|
||||
.arg("--amount=40")
|
||||
.arg("A614C91D0392D83EE6B1C4A4DD4147FEF78AD630")
|
||||
.arg("--cert").arg("A614C91D0392D83EE6B1C4A4DD4147FEF78AD630")
|
||||
.arg("--email").arg("pink@probier.email");
|
||||
eprintln!("Running: {:?}", cmd);
|
||||
eprintln!("pre: {}", time_as_string(std::time::SystemTime::now().into()));
|
||||
@ -58,14 +58,14 @@ fn sq_autocrypt_import() -> Result<()>
|
||||
let mut cmd = sq.command();
|
||||
cmd.arg("pki").arg("authenticate")
|
||||
.arg("--gossip")
|
||||
.arg("CBCD8F030588653EEDD7E2659B7DD433F254904A")
|
||||
.arg("--cert").arg("CBCD8F030588653EEDD7E2659B7DD433F254904A")
|
||||
.arg("--email").arg("justus@sequoia-pgp.org");
|
||||
sq.run(cmd, true);
|
||||
|
||||
let mut cmd = sq.command();
|
||||
cmd.arg("pki").arg("authenticate")
|
||||
.arg("--gossip")
|
||||
.arg("BB6B7E5F8343B2BE990EB7A7F3AF066F267892C1")
|
||||
.arg("--cert").arg("BB6B7E5F8343B2BE990EB7A7F3AF066F267892C1")
|
||||
.arg("--email").arg("hilal-maria@probier.email");
|
||||
sq.run(cmd, true);
|
||||
|
||||
|
@ -113,6 +113,9 @@ where
|
||||
cmd.arg("--show-paths");
|
||||
}
|
||||
if let Some(target) = target {
|
||||
if ["authenticate", "identify"].contains(&command) {
|
||||
cmd.arg("--cert");
|
||||
}
|
||||
cmd.arg(&target.to_string());
|
||||
}
|
||||
if let Some(userid) = userid {
|
||||
|
Loading…
Reference in New Issue
Block a user