parent
9cfc2e9a16
commit
e2d5bc1de4
@ -494,7 +494,7 @@ _Requirement: We must be able to generate a key with a User ID, and then strip t
|
||||
~~~scenario
|
||||
given an installed sq
|
||||
when I run sq --no-cert-store --no-key-store key generate --without-password --userid "<juliet@example.org>" --output key.pgp
|
||||
when I run sq --no-cert-store --no-key-store key userid strip --cert-file key.pgp --userid "<juliet@example.org>" --output new.pgp
|
||||
when I run sq --no-cert-store --no-key-store toolbox strip-userid --cert-file key.pgp --userid "<juliet@example.org>" --output new.pgp
|
||||
when I run sq --no-cert-store --no-key-store inspect new.pgp
|
||||
then stdout doesn't contain "UserID:"
|
||||
~~~
|
||||
@ -1103,11 +1103,11 @@ when I run sq --no-cert-store --no-key-store toolbox extract-cert bob.pgp --outp
|
||||
|
||||
when I run sq --no-cert-store --no-key-store pki certify --certifier-file alice.pgp bob-cert.pgp --email bob@example.org --output cert.pgp
|
||||
|
||||
when I run sq --no-cert-store --no-key-store key userid strip --cert-file cert.pgp --userid "<bob@example.org>" --output cert.0.pgp
|
||||
when I run sq --no-cert-store --no-key-store toolbox strip-userid --cert-file cert.pgp --userid "<bob@example.org>" --output cert.0.pgp
|
||||
when I run sq --no-cert-store --no-key-store inspect cert.0.pgp
|
||||
then stdout contains "Certifications: 1,"
|
||||
|
||||
when I run sq --no-cert-store --no-key-store key userid strip --cert-file cert.pgp --userid "Bob <bob@example.org>" --output cert.1.pgp
|
||||
when I run sq --no-cert-store --no-key-store toolbox strip-userid --cert-file cert.pgp --userid "Bob <bob@example.org>" --output cert.1.pgp
|
||||
when I run sq --no-cert-store --no-key-store inspect cert.1.pgp
|
||||
then stdout contains "Certifications: 1,"
|
||||
~~~
|
||||
|
@ -31,7 +31,6 @@ Add User IDs to a key, or revoke them.
|
||||
pub enum Command {
|
||||
Add(AddCommand),
|
||||
Revoke(RevokeCommand),
|
||||
Strip(StripCommand),
|
||||
}
|
||||
|
||||
const USERID_ADD_EXAMPLES: Actions = Actions {
|
||||
@ -372,120 +371,3 @@ impl From<UserIDReasonForRevocation> for ReasonForRevocation {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const USERID_STRIP_EXAMPLES: Actions = Actions {
|
||||
actions: &[
|
||||
Action::Example(Example {
|
||||
comment: "Strip a User ID from a cert in the cert store.",
|
||||
command: &[
|
||||
"sq", "key", "userid", "strip",
|
||||
"--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--userid", "Alice <alice@example.org>",
|
||||
],
|
||||
}),
|
||||
]
|
||||
};
|
||||
test_examples!(sq_key_userid_strip, USERID_STRIP_EXAMPLES);
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(
|
||||
about = "Strip a user ID",
|
||||
long_about =
|
||||
"Strip a user ID.
|
||||
|
||||
Note that this operation does not reliably remove User IDs from a \
|
||||
certificate that has already been disseminated! (OpenPGP software \
|
||||
typically appends new information it receives about a certificate to \
|
||||
its local copy of that certificate. Systems that have obtained a copy \
|
||||
of your certificate with the User ID that you are trying to strip will \
|
||||
not drop that User ID from their copy.)
|
||||
|
||||
In most cases, you will want to use the 'sq key userid revoke' operation \
|
||||
instead. That issues a revocation for a User ID, which can be used to mark \
|
||||
the User ID as invalidated.
|
||||
|
||||
However, this operation can be useful in very specific cases, in particular: \
|
||||
to remove a mistakenly added User ID before it has been uploaded to key \
|
||||
servers or otherwise shared.
|
||||
|
||||
Stripping a User ID may change how a certificate is interpreted. This \
|
||||
is because information about the certificate like algorithm preferences, \
|
||||
the primary key's key flags, etc. is stored in the User ID's binding \
|
||||
signature.
|
||||
",
|
||||
after_help = USERID_STRIP_EXAMPLES,
|
||||
)]
|
||||
#[clap(group(ArgGroup::new("cert_input").args(&["cert_file", "cert"]).required(true)))]
|
||||
#[clap(group(ArgGroup::new("cert-userid").args(&["names", "emails", "userid"]).required(true).multiple(true)))]
|
||||
pub struct StripCommand {
|
||||
#[clap(
|
||||
long,
|
||||
value_name = "FINGERPRINT|KEYID",
|
||||
help = "Strip the user ID on the specified certificate",
|
||||
)]
|
||||
pub cert: Option<KeyHandle>,
|
||||
#[clap(
|
||||
long,
|
||||
help = FileOrStdin::HELP_OPTIONAL,
|
||||
value_name = "CERT_FILE",
|
||||
conflicts_with = "cert",
|
||||
help = "Strip the user ID on the specified certificate",
|
||||
long_help = "\
|
||||
Strip the user ID on the specified certificate.
|
||||
|
||||
Read the certificate whose user ID should be stripped from FILE or \
|
||||
stdin, if `-`. It is an error for the file to contain more than one \
|
||||
certificate.",
|
||||
)]
|
||||
pub cert_file: Option<FileOrStdin>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
value_name = FileOrCertStore::VALUE_NAME,
|
||||
help = "Write to the specified FILE",
|
||||
long_help = "\
|
||||
Write to the specified FILE.
|
||||
|
||||
If not specified, and the certificate was read from the certificate
|
||||
store, imports the modified certificate into the cert store. If not
|
||||
specified, and the certificate was read from a file, writes the
|
||||
modified certificate to stdout.",
|
||||
)]
|
||||
pub output: Option<FileOrStdout>,
|
||||
|
||||
#[clap(
|
||||
long = "name",
|
||||
value_name = "NAME",
|
||||
help = "Strip the given name user ID",
|
||||
long_help = "\
|
||||
Strip the given name user ID. Must match a user ID exactly. To strip
|
||||
a user ID that contains more than just a name, use `--userid`.",
|
||||
)]
|
||||
pub names: Vec<String>,
|
||||
|
||||
#[clap(
|
||||
long = "email",
|
||||
value_name = "ADDRESS",
|
||||
help = "Strip the given email address user ID",
|
||||
long_help = "\
|
||||
Strip the given email address user ID. Must match a user ID exactly.
|
||||
To strip a user ID that contains more than just an email address name,
|
||||
use `--userid`.",
|
||||
)]
|
||||
pub emails: Vec<String>,
|
||||
|
||||
#[clap(
|
||||
value_name = "USERID",
|
||||
long,
|
||||
help = "Strip the given user IDs",
|
||||
long_help = "\
|
||||
Strip the given user IDs from the key. Must match a user ID exactly.",
|
||||
)]
|
||||
pub userid: Vec<UserID>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "Emit binary data",
|
||||
)]
|
||||
pub binary: bool,
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ pub mod dearmor;
|
||||
pub mod extract_cert;
|
||||
pub mod keyring;
|
||||
pub mod packet;
|
||||
pub mod strip_userid;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(
|
||||
@ -30,6 +31,7 @@ pub struct Command {
|
||||
pub enum Subcommands {
|
||||
Keyring(keyring::Command),
|
||||
ExtractCert(extract_cert::Command),
|
||||
StripUserid(strip_userid::Command),
|
||||
Packet(packet::Command),
|
||||
Armor(armor::Command),
|
||||
Dearmor(dearmor::Command),
|
||||
|
129
src/cli/toolbox/strip_userid.rs
Normal file
129
src/cli/toolbox/strip_userid.rs
Normal file
@ -0,0 +1,129 @@
|
||||
use clap::{ArgGroup, Args};
|
||||
|
||||
use sequoia_openpgp as openpgp;
|
||||
use openpgp::KeyHandle;
|
||||
use openpgp::packet::UserID;
|
||||
|
||||
use crate::cli::types::ClapData;
|
||||
use crate::cli::types::FileOrCertStore;
|
||||
use crate::cli::types::FileOrStdin;
|
||||
use crate::cli::types::FileOrStdout;
|
||||
|
||||
use crate::cli::examples::*;
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
#[clap(
|
||||
about = "Strip a user ID",
|
||||
long_about =
|
||||
"Strip a user ID.
|
||||
|
||||
Note that this operation does not reliably remove User IDs from a \
|
||||
certificate that has already been disseminated! (OpenPGP software \
|
||||
typically appends new information it receives about a certificate to \
|
||||
its local copy of that certificate. Systems that have obtained a copy \
|
||||
of your certificate with the User ID that you are trying to strip will \
|
||||
not drop that User ID from their copy.)
|
||||
|
||||
In most cases, you will want to use the 'sq key userid revoke' operation \
|
||||
instead. That issues a revocation for a User ID, which can be used to mark \
|
||||
the User ID as invalidated.
|
||||
|
||||
However, this operation can be useful in very specific cases, in particular: \
|
||||
to remove a mistakenly added User ID before it has been uploaded to key \
|
||||
servers or otherwise shared.
|
||||
|
||||
Stripping a User ID may change how a certificate is interpreted. This \
|
||||
is because information about the certificate like algorithm preferences, \
|
||||
the primary key's key flags, etc. is stored in the User ID's binding \
|
||||
signature.
|
||||
",
|
||||
after_help = USERID_STRIP_EXAMPLES,
|
||||
)]
|
||||
#[clap(group(ArgGroup::new("cert_input").args(&["cert_file", "cert"]).required(true)))]
|
||||
#[clap(group(ArgGroup::new("cert-userid").args(&["names", "emails", "userid"]).required(true).multiple(true)))]
|
||||
pub struct Command {
|
||||
#[clap(
|
||||
long,
|
||||
value_name = "FINGERPRINT|KEYID",
|
||||
help = "Strip the user ID on the specified certificate",
|
||||
)]
|
||||
pub cert: Option<KeyHandle>,
|
||||
#[clap(
|
||||
long,
|
||||
help = FileOrStdin::HELP_OPTIONAL,
|
||||
value_name = "CERT_FILE",
|
||||
conflicts_with = "cert",
|
||||
help = "Strip the user ID on the specified certificate",
|
||||
long_help = "\
|
||||
Strip the user ID on the specified certificate.
|
||||
|
||||
Read the certificate whose user ID should be stripped from FILE or \
|
||||
stdin, if `-`. It is an error for the file to contain more than one \
|
||||
certificate.",
|
||||
)]
|
||||
pub cert_file: Option<FileOrStdin>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
value_name = FileOrCertStore::VALUE_NAME,
|
||||
help = "Write to the specified FILE",
|
||||
long_help = "\
|
||||
Write to the specified FILE.
|
||||
|
||||
If not specified, and the certificate was read from the certificate
|
||||
store, imports the modified certificate into the cert store. If not
|
||||
specified, and the certificate was read from a file, writes the
|
||||
modified certificate to stdout.",
|
||||
)]
|
||||
pub output: Option<FileOrStdout>,
|
||||
|
||||
#[clap(
|
||||
long = "name",
|
||||
value_name = "NAME",
|
||||
help = "Strip the given name user ID",
|
||||
long_help = "\
|
||||
Strip the given name user ID. Must match a user ID exactly. To strip
|
||||
a user ID that contains more than just a name, use `--userid`.",
|
||||
)]
|
||||
pub names: Vec<String>,
|
||||
|
||||
#[clap(
|
||||
long = "email",
|
||||
value_name = "ADDRESS",
|
||||
help = "Strip the given email address user ID",
|
||||
long_help = "\
|
||||
Strip the given email address user ID. Must match a user ID exactly.
|
||||
To strip a user ID that contains more than just an email address name,
|
||||
use `--userid`.",
|
||||
)]
|
||||
pub emails: Vec<String>,
|
||||
|
||||
#[clap(
|
||||
value_name = "USERID",
|
||||
long,
|
||||
help = "Strip the given user IDs",
|
||||
long_help = "\
|
||||
Strip the given user IDs from the key. Must match a user ID exactly.",
|
||||
)]
|
||||
pub userid: Vec<UserID>,
|
||||
|
||||
#[clap(
|
||||
long,
|
||||
help = "Emit binary data",
|
||||
)]
|
||||
pub binary: bool,
|
||||
}
|
||||
|
||||
const USERID_STRIP_EXAMPLES: Actions = Actions {
|
||||
actions: &[
|
||||
Action::Example(Example {
|
||||
comment: "Strip a User ID from a cert in the cert store.",
|
||||
command: &[
|
||||
"sq", "toolbox", "strip-userid",
|
||||
"--cert", "EB28F26E2739A4870ECC47726F0073F60FD0CBF0",
|
||||
"--userid", "Alice <alice@example.org>",
|
||||
],
|
||||
}),
|
||||
]
|
||||
};
|
||||
test_examples!(sq_key_userid_strip, USERID_STRIP_EXAMPLES);
|
@ -20,7 +20,7 @@ mod password;
|
||||
mod revoke;
|
||||
use revoke::certificate_revoke;
|
||||
mod subkey;
|
||||
mod userid;
|
||||
pub mod userid;
|
||||
|
||||
pub fn dispatch(sq: Sq, command: cli::key::Command) -> Result<()>
|
||||
{
|
||||
|
@ -168,7 +168,6 @@ pub fn dispatch(
|
||||
match command {
|
||||
cli::key::userid::Command::Add(c) => userid_add(sq, c)?,
|
||||
cli::key::userid::Command::Revoke(c) => userid_revoke(sq, c)?,
|
||||
cli::key::userid::Command::Strip(c) => userid_strip(sq, c)?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -356,9 +355,9 @@ fn cert_checksum(cert: &Cert) -> Result<Vec<u8>> {
|
||||
sum.into_digest()
|
||||
}
|
||||
|
||||
fn userid_strip(
|
||||
pub fn userid_strip(
|
||||
sq: Sq,
|
||||
mut command: cli::key::userid::StripCommand,
|
||||
mut command: cli::toolbox::strip_userid::Command,
|
||||
) -> Result<()> {
|
||||
let cert = if let Some(file) = &command.cert_file {
|
||||
if command.output.is_none() {
|
||||
@ -390,7 +389,7 @@ fn userid_strip(
|
||||
|
||||
fn userid_strip_internal(
|
||||
sq: Sq,
|
||||
command: cli::key::userid::StripCommand,
|
||||
command: cli::toolbox::strip_userid::Command,
|
||||
key: Cert,
|
||||
tries: usize,
|
||||
) -> Result<()> {
|
||||
|
@ -25,5 +25,7 @@ pub fn dispatch(sq: Sq, command: Command) -> Result<()>
|
||||
armor::dispatch(sq, command),
|
||||
Subcommands::Dearmor(command) =>
|
||||
dearmor::dispatch(sq, command),
|
||||
Subcommands::StripUserid(command) =>
|
||||
crate::commands::key::userid::userid_strip(sq, command),
|
||||
}
|
||||
}
|
||||
|
@ -945,9 +945,9 @@ impl Sq {
|
||||
}
|
||||
|
||||
/// Strips user IDs to the given key.
|
||||
pub fn key_userid_strip(&self, key: Cert, args: &[&str]) -> Result<Cert> {
|
||||
pub fn toolbox_strip_userid(&self, key: Cert, args: &[&str]) -> Result<Cert> {
|
||||
let mut cmd = self.command();
|
||||
cmd.args(["key", "userid", "strip"]);
|
||||
cmd.args(["toolbox", "strip-userid"]);
|
||||
for arg in args {
|
||||
cmd.arg(arg);
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ fn sq_key_userid_strip() -> Result<()> {
|
||||
assert_eq!(key.userids().count(), 3);
|
||||
|
||||
// Whoops, that's a secret.
|
||||
let key = sq.key_userid_strip(key, &[
|
||||
let key = sq.toolbox_strip_userid(key, &[
|
||||
"--userid", "<joan@hut8.bletchley.park>",
|
||||
])?;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user