diff options
Diffstat (limited to 'sq')
-rw-r--r-- | sq/Cargo.toml | 5 | ||||
-rw-r--r-- | sq/build.rs | 13 | ||||
-rw-r--r-- | sq/src/commands/autocrypt.rs | 4 | ||||
-rw-r--r-- | sq/src/commands/key.rs | 10 | ||||
-rw-r--r-- | sq/src/commands/keyring.rs | 10 | ||||
-rw-r--r-- | sq/src/commands/net.rs | 10 | ||||
-rw-r--r-- | sq/src/commands/revoke.rs | 6 | ||||
-rw-r--r-- | sq/src/sq-usage.rs | 1154 | ||||
-rw-r--r-- | sq/src/sq.rs | 38 | ||||
-rw-r--r-- | sq/src/sq_cli.rs | 678 |
10 files changed, 936 insertions, 992 deletions
diff --git a/sq/Cargo.toml b/sq/Cargo.toml index 2007616d..47f121ea 100644 --- a/sq/Cargo.toml +++ b/sq/Cargo.toml @@ -32,7 +32,7 @@ sequoia-autocrypt = { path = "../autocrypt", version = "0.24", default-features sequoia-net = { path = "../net", version = "0.24", default-features = false } anyhow = "1.0.18" chrono = "0.4.10" -clap = { version = "2.33", features = ["wrap_help"] } +clap = { version = "3", features = ["derive", "wrap_help"] } itertools = "0.10" tempfile = "3.1" term_size = "0.3" @@ -40,7 +40,8 @@ tokio = { version = "1.13.1" } rpassword = "5.0" [build-dependencies] -clap = "2.33" +clap = "3" +clap_complete = "3" sequoia-openpgp = { path = "../openpgp", version = "1.0.0", default-features = false } subplot-build = "0.4.0" diff --git a/sq/build.rs b/sq/build.rs index 71399d46..efc13f8d 100644 --- a/sq/build.rs +++ b/sq/build.rs @@ -2,7 +2,7 @@ use std::env; use std::fs; use std::io::{self, Write}; use std::path::Path; -use clap::Shell; +use clap_complete::Shell; mod sq_cli { include!("src/sq_cli.rs"); @@ -18,7 +18,7 @@ fn main() { .expect("failed to generate code with Subplot"); let mut sq = sq_cli::configure( - clap::App::new("sq").set_term_width(80), + clap::Command::new("sq").term_width(80), cfg!(feature = "autocrypt"), ); let mut main = fs::File::create("src/sq-usage.rs").unwrap(); @@ -38,14 +38,15 @@ fn main() { }; fs::create_dir_all(&outdir).unwrap(); let mut sq = sq_cli::build(); + for shell in &[Shell::Bash, Shell::Fish, Shell::Zsh, Shell::PowerShell, Shell::Elvish] { - sq.gen_completions("sq", *shell, &outdir); - } + clap_complete::generate_to(*shell, &mut sq, "sq", &outdir).unwrap(); + }; } fn dump_help(sink: &mut dyn io::Write, - sq: &mut clap::App, + sq: &mut clap::Command, cmd: Vec<String>, heading: &str) -> io::Result<()> @@ -67,7 +68,7 @@ fn dump_help(sink: &mut dyn io::Write, .chain(std::iter::once("--help")) .collect::<Vec<_>>(); - let help = sq.get_matches_from_safe_borrow(&args) + let help = sq.try_get_matches_from_mut(&args) .unwrap_err().to_string(); writeln!(sink, "//! ```text")?; diff --git a/sq/src/commands/autocrypt.rs b/sq/src/commands/autocrypt.rs index ac852958..8ca018bf 100644 --- a/sq/src/commands/autocrypt.rs +++ b/sq/src/commands/autocrypt.rs @@ -15,7 +15,7 @@ use crate::{ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { match m.subcommand() { - ("decode", Some(m)) => { + Some(("decode", m)) => { let input = open_or_stdin(m.value_of("input"))?; let mut output = config.create_or_stdout_pgp(m.value_of("output"), @@ -29,7 +29,7 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { } output.finalize()?; }, - ("encode-sender", Some(m)) => { + Some(("encode-sender", m)) => { let input = open_or_stdin(m.value_of("input"))?; let mut output = config.create_or_stdout_safe(m.value_of("output"))?; diff --git a/sq/src/commands/key.rs b/sq/src/commands/key.rs index aa03f2e1..99e849d9 100644 --- a/sq/src/commands/key.rs +++ b/sq/src/commands/key.rs @@ -26,11 +26,11 @@ use crate::decrypt_key; pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { match m.subcommand() { - ("generate", Some(m)) => generate(config, m)?, - ("password", Some(m)) => password(config, m)?, - ("extract-cert", Some(m)) => extract_cert(config, m)?, - ("adopt", Some(m)) => adopt(config, m)?, - ("attest-certifications", Some(m)) => + Some(("generate", m)) => generate(config, m)?, + Some(("password", m)) => password(config, m)?, + Some(("extract-cert", m)) => extract_cert(config, m)?, + Some(("adopt", m)) => adopt(config, m)?, + Some(("attest-certifications", m)) => attest_certifications(config, m)?, _ => unreachable!(), } diff --git a/sq/src/commands/keyring.rs b/sq/src/commands/keyring.rs index 0fc2f51a..994c5fab 100644 --- a/sq/src/commands/keyring.rs +++ b/sq/src/commands/keyring.rs @@ -33,7 +33,7 @@ use crate::{ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { match m.subcommand() { - ("filter", Some(m)) => { + Some(("filter", m)) => { let any_uid_predicates = m.is_present("userid") || m.is_present("name") @@ -151,7 +151,7 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { to_certificate)?; output.finalize() }, - ("join", Some(m)) => { + Some(("join", m)) => { // XXX: Armor type selection is a bit problematic. If any // of the certificates contain a secret key, it would be // better to use Kind::SecretKey here. However, this @@ -164,7 +164,7 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { filter(m.values_of("input"), &mut output, Some, false)?; output.finalize() }, - ("merge", Some(m)) => { + Some(("merge", m)) => { let mut output = config.create_or_stdout_pgp(m.value_of("output"), m.is_present("binary"), @@ -172,11 +172,11 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { merge(m.values_of("input"), &mut output)?; output.finalize() }, - ("list", Some(m)) => { + Some(("list", m)) => { let mut input = open_or_stdin(m.value_of("input"))?; list(config, &mut input, m.is_present("all-userids")) }, - ("split", Some(m)) => { + Some(("split", m)) => { let mut input = open_or_stdin(m.value_of("input"))?; let prefix = // The prefix is either specified explicitly... diff --git a/sq/src/commands/net.rs b/sq/src/commands/net.rs index 44046ee8..dbd33227 100644 --- a/sq/src/commands/net.rs +++ b/sq/src/commands/net.rs @@ -53,7 +53,7 @@ pub fn dispatch_keyserver(config: Config, m: &clap::ArgMatches) -> Result<()> { .build()?; match m.subcommand() { - ("get", Some(m)) => { + Some(("get", m)) => { let query = m.value_of("query").unwrap(); let handle = query.parse::<KeyHandle>(); @@ -83,7 +83,7 @@ pub fn dispatch_keyserver(config: Config, m: &clap::ArgMatches) -> Result<()> { or an email address: {:?}", query)); } }, - ("send", Some(m)) => { + Some(("send", m)) => { let mut input = open_or_stdin(m.value_of("input"))?; let cert = Cert::from_reader(&mut input). context("Malformed key")?; @@ -106,7 +106,7 @@ pub fn dispatch_wkd(config: Config, m: &clap::ArgMatches) -> Result<()> { .build()?; match m.subcommand() { - ("url", Some(m)) => { + Some(("url", m)) => { let email_address = m.value_of("input").unwrap(); let wkd_url = wkd::Url::from(email_address)?; // XXX: Add other subcomand to specify whether it should be @@ -114,7 +114,7 @@ pub fn dispatch_wkd(config: Config, m: &clap::ArgMatches) -> Result<()> { let url = wkd_url.to_url(None)?; println!("{}", url); }, - ("get", Some(m)) => { + Some(("get", m)) => { // Check that the policy allows https. network_policy.assert(net::Policy::Encrypted)?; @@ -137,7 +137,7 @@ pub fn dispatch_wkd(config: Config, m: &clap::ArgMatches) -> Result<()> { serialize_keyring(&mut output, &certs, m.is_present("binary"))?; }, - ("generate", Some(m)) => { + Some(("generate", m)) => { let domain = m.value_of("domain").unwrap(); let skip = m.is_present("skip"); let f = open_or_stdin(m.value_of("input"))?; diff --git a/sq/src/commands/revoke.rs b/sq/src/commands/revoke.rs index b863f245..3e020ea0 100644 --- a/sq/src/commands/revoke.rs +++ b/sq/src/commands/revoke.rs @@ -47,8 +47,8 @@ impl Subcommand { pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { let (subcommand, m) = match m.subcommand() { - ("certificate", Some(m)) => (Subcommand::Certificate, m), - ("subkey", Some(m)) => { + Some(("certificate", m)) => (Subcommand::Certificate, m), + Some(("subkey", m)) => { let subkey = m.value_of("subkey").expect("required"); let kh: KeyHandle = subkey .parse() @@ -58,7 +58,7 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { (Subcommand::Subkey(kh), m) } - ("userid", Some(m)) => { + Some(("userid", m)) => { let userid = m.value_of("userid").expect("required"); (Subcommand::UserID(userid.into()), m) diff --git a/sq/src/sq-usage.rs b/sq/src/sq-usage.rs index c588c213..66ba9d38 100644 --- a/sq/src/sq-usage.rs +++ b/sq/src/sq-usage.rs @@ -18,42 +18,56 @@ //! to refer to OpenPGP keys that do contain secrets. //! //! USAGE: -//! sq [FLAGS] [OPTIONS] <SUBCOMMAND> +//! sq [OPTIONS] <SUBCOMMAND> //! -//! FLAGS: +//! OPTIONS: //! -f, --force //! Overwrites existing files //! //! -h, --help -//! Prints help information -//! -//! -V, --version -//! Prints version information +//! Print help information //! -//! -//! OPTIONS: -//! --known-notation <NOTATION>... +//! --known-notation <NOTATION> //! Adds NOTATION to the list of known notations. This is used when //! validating signatures. Signatures that have unknown notations with //! the critical bit set are considered invalid. //! +//! -V, --version +//! Print version information +//! //! SUBCOMMANDS: -//! encrypt Encrypts a message -//! decrypt Decrypts a message -//! sign Signs messages or data files -//! verify Verifies signed messages or detached signatures -//! key Manages keys -//! keyring Manages collections of keys or certs -//! certify Certifies a User ID for a Certificate -//! autocrypt Communicates certificates using Autocrypt -//! keyserver Interacts with keyservers -//! wkd Interacts with Web Key Directories -//! armor Converts binary to ASCII -//! dearmor Converts ASCII to binary -//! inspect Inspects data, like file(1) -//! packet Low-level packet manipulation -//! revoke Generates revocation certificates -//! help Prints this message or the help of the given subcommand(s) +//! encrypt +//! Encrypts a message +//! decrypt +//! Decrypts a message +//! sign +//! Signs messages or data files +//! verify +//! Verifies signed messages or detached signatures +//! key +//! Manages keys +//! keyring +//! Manages collections of keys or certs +//! certify +//! Certifies a User ID for a Certificate +//! autocrypt +//! Communicates certificates using Autocrypt +//! keyserver +//! Interacts with keyservers +//! wkd +//! Interacts with Web Key Directories +//! armor +//! Converts binary to ASCII +//! dearmor +//! Converts ASCII to binary +//! inspect +//! Inspects data, like file(1) +//! packet +//! Low-level packet manipulation +//! revoke +//! Generates revocation certificates +//! help +//! Print this message or the help of the given subcommand(s) //! ``` //! //! ## Subcommand encrypt @@ -67,52 +81,57 @@ //! The converse operation is "sq decrypt". //! //! USAGE: -//! sq encrypt [FLAGS] [OPTIONS] [--] [FILE] +//! sq encrypt [OPTIONS] [FILE] +//! +//! ARGS: +//! <FILE> +//! Reads from FILE or stdin if omitted //! -//! FLAGS: +//! OPTIONS: //! -B, --binary //! Emits binary data //! -//! -h, --help -//! Prints help information +//! --compression <KIND> +//! Selects compression scheme to use +//! +//! [default: pad] +//! [possible values: none, pad, zip, zlib, bzip2] //! -//! -s, --symmetric -//! Adds a password to encrypt with. The message can be decrypted with -//! either one of the recipient's keys, or any password. -//! --use-expired-subkey -//! If a certificate has only expired encryption-capable subkeys, falls -//! back to using the one that expired last +//! -h, --help +//! Print help information //! -//! OPTIONS: -//! --compression <KIND> -//! Selects compression scheme to use [default: pad] [possible values: -//! none, pad, zip, zlib, bzip2] //! --mode <MODE> //! Selects what kind of keys are considered for encryption. Transport //! select subkeys marked as suitable for transport encryption, rest //! selects those for encrypting data at rest, and all selects all -//! encryption-capable subkeys. [default: all] [possible values: -//! transport, rest, all] +//! encryption-capable subkeys. +//! +//! [default: all] +//! [possible values: transport, rest, all] +//! //! -o, --output <FILE> //! Writes to FILE or stdout if omitted //! //! --private-key-store <KEY_STORE> //! Provides parameters for private key store //! -//! --recipient-cert <CERT-RING>... +//! --recipient-cert <CERT-RING> //! Encrypts for all recipients in CERT-RING //! -//! --signer-key <KEY>... +//! -s, --symmetric +//! Adds a password to encrypt with. The message can be decrypted with +//! either one of the recipient's keys, or any password. +//! +//! --signer-key <KEY> //! Signs the message with KEY //! //! -t, --time <TIME> //! Chooses keys valid at the specified time and sets the signature's //! creation time //! -//! ARGS: -//! <FILE> -//! Reads from FILE or stdin if omitted -//! +//! --use-expired-subkey +//! If a certificate has only expired encryption-capable subkeys, falls +//! back to using the one that expired last //! //! EXAMPLES: //! @@ -150,9 +169,13 @@ //! The converse operation is "sq encrypt". //! //! USAGE: -//! sq decrypt [FLAGS] [OPTIONS] [--] [FILE] +//! sq decrypt [OPTIONS] [FILE] +//! +//! ARGS: +//! <FILE> +//! Reads from FILE or stdin if omitted //! -//! FLAGS: +//! OPTIONS: //! --dump //! Prints a packet dump to stderr //! @@ -160,34 +183,27 @@ //! Prints the session key to stderr //! //! -h, --help -//! Prints help information -//! -//! -x, --hex -//! Prints a hexdump (implies --dump) +//! Print help information //! +//! -n, --signatures <N> +//! Sets the threshold of valid signatures to N. The message will only +//! be considered verified if this threshold is reached. [default: 1 if +//! at least one signer cert file is given, 0 otherwise] //! -//! OPTIONS: //! -o, --output <FILE> //! Writes to FILE or stdout if omitted //! //! --private-key-store <KEY_STORE> //! Provides parameters for private key store //! -//! --recipient-key <KEY>... +//! --recipient-key <KEY> //! Decrypts with KEY //! -//! --signer-cert <CERT>... +//! --signer-cert <CERT> //! Verifies signatures with CERT //! -//! -n, --signatures <N> -//! Sets the threshold of valid signatures to N. The message will only -//! be considered verified if this threshold is reached. [default: 1 if -//! at least one signer cert file is given, 0 otherwise] -//! -//! ARGS: -//! <FILE> -//! Reads from FILE or stdin if omitted -//! +//! -x, --hex +//! Prints a hexdump (implies --dump) //! //! EXAMPLES: //! @@ -212,9 +228,13 @@ //! The converse operation is "sq verify". //! //! USAGE: -//! sq sign [FLAGS] [OPTIONS] [--] [FILE] +//! sq sign [OPTIONS] [--] [FILE] //! -//! FLAGS: +//! ARGS: +//! <FILE> +//! Reads from FILE or stdin if omitted +//! +//! OPTIONS: //! -a, --append //! Appends a signature to existing signature //! @@ -228,16 +248,14 @@ //! Creates a detached signature //! //! -h, --help -//! Prints help information -//! -//! -n, --notarize -//! Signs a message and all existing signatures +//! Print help information //! -//! -//! OPTIONS: //! --merge <SIGNED-MESSAGE> //! Merges signatures from the input and SIGNED-MESSAGE //! +//! -n, --notarize +//! Signs a message and all existing signatures +//! //! --notation <NAME> <VALUE> //! Adds a notation to the certification. A user-defined notation's //! name must be of the form "name@a.domain.you.control.org". If the @@ -245,24 +263,20 @@ //! being critical. If a consumer of a signature doesn't understand a //! critical notation, then it will ignore the signature. The notation //! is marked as being human readable. +//! //! -o, --output <FILE> //! Writes to FILE or stdout if omitted //! //! --private-key-store <KEY_STORE> //! Provides parameters for private key store //! -//! --signer-key <KEY>... +//! --signer-key <KEY> //! Signs using KEY //! //! -t, --time <TIME> //! Chooses keys valid at the specified time and sets the signature's //! creation time //! -//! ARGS: -//! <FILE> -//! Reads from FILE or stdin if omitted -//! -//! //! EXAMPLES: //! //! # Create a signed message @@ -294,32 +308,30 @@ //! The converse operation is "sq sign". //! //! USAGE: -//! sq verify [OPTIONS] [--] [FILE] -//! -//! FLAGS: -//! -h, --help -//! Prints help information +//! sq verify [OPTIONS] [FILE] //! +//! ARGS: +//! <FILE> +//! Reads from FILE or stdin if omitted //! //! OPTIONS: //! --detached <SIG> //! Verifies a detached signature //! -//! -o, --output <FILE> -//! Writes to FILE or stdout if omitted -//! -//! --signer-cert <CERT>... -//! Verifies signatures with CERT +//! -h, --help +//! Print help information //! //! -n, --signatures <N> //! Sets the threshold of valid signatures to N. If this threshold is -//! not reached, the message will not be considered verified. [default: -//! 1] +//! not reached, the message will not be considered verified. +//! +//! [default: 1] //! -//! ARGS: -//! <FILE> -//! Reads from FILE or stdin if omitted +//! -o, --output <FILE> +//! Writes to FILE or stdout if omitted //! +//! --signer-cert <CERT> +//! Verifies signatures with CERT //! //! EXAMPLES: //! @@ -351,19 +363,23 @@ //! USAGE: //! sq key <SUBCOMMAND> //! -//! FLAGS: +//! OPTIONS: //! -h, --help -//! Prints help information -//! +//! Print help information //! //! SUBCOMMANDS: -//! generate Generates a new key -//! password Changes password protecting secrets -//! extract-cert Converts a key to a cert -//! attest-certifications Attests to third-party certifications -//! adopt Binds keys from one certificate to another +//! generate +//! Generates a new key +//! password +//! Changes password protecting secrets +//! extract-cert +//! Converts a key to a cert +//! attest-certifications +//! Attests to third-party certifications +//! adopt +//! Binds keys from one certificate to another //! help -//! Prints this message or the help of the given subcommand(s) +//! Print this message or the help of the given subcommand(s) //! ``` //! //! ### Subcommand key generate @@ -385,12 +401,25 @@ //! uploading it to a keyserver. //! //! USAGE: -//! sq key generate [FLAGS] [OPTIONS] --export <OUTFILE> +//! sq key generate [OPTIONS] --export <OUTFILE> +//! +//! OPTIONS: +//! -c, --cipher-suite <CIPHER-SUITE> +//! Selects the cryptographic algorithms for the key +//! +//! [default: cv25519] +//! [possible values: rsa3k, rsa4k, cv25519] //! -//! FLAGS: //! --can-authenticate //! Adds an authentication-capable subkey (default) //! +//! --can-encrypt <PURPOSE> +//! Adds an encryption-capable subkey. Encryption-capable subkeys can be +//! marked as suitable for transport encryption, storage encryption, or +//! both. [default: universal] +//! +//! [possible values: transport, storage, universal] +//! //! --can-sign //! Adds a signing-capable subkey (default) //! @@ -403,25 +432,6 @@ //! --cannot-sign //! Adds no signing-capable subkey //! -//! -h, --help -//! Prints help information -//! -//! -V, --version -//! Prints version information -//! -//! --with-password -//! Protects the key with a password -//! -//! -//! OPTIONS: -//! --can-encrypt <PURPOSE> -//! Adds an encryption-capable subkey. Encryption-capable subkeys can be -//! marked as suitable for transport encryption, storage encryption, or -//! both. [default: universal] [possible values: transport, storage, -//! universal] -//! -c, --cipher-suite <CIPHER-SUITE> -//! Selects the cryptographic algorithms for the key [default: cv25519] -//! [possible values: rsa3k, rsa4k, cv25519] //! --creation-time <CREATION_TIME> //! Sets the key's creation time to TIME. TIME is interpreted as an ISO //! 8601 @@ -437,21 +447,30 @@ //! //! $ sq key generate --creation-time 20110609T1938+0200 --export //! noam.pgp +//! +//! -e, --export <OUTFILE> +//! Writes the key to OUTFILE +//! //! --expires <TIME> //! Makes the key expire at TIME (as ISO 8601). Use "never" to create //! keys that do not expire. +//! //! --expires-in <DURATION> //! Makes the key expire after DURATION. Either "N[ymwds]", for N years, //! months, weeks, days, seconds, or "never". -//! -e, --export <OUTFILE> -//! Writes the key to OUTFILE +//! +//! -h, --help +//! Print help information //! //! --rev-cert <FILE or -> //! Writes the revocation certificate to FILE. mandatory if OUTFILE is //! "-". [default: <OUTFILE>.rev] -//! -u, --userid <EMAIL>... +//! +//! -u, --userid <EMAIL> //! Adds a userid to the key //! +//! --with-password +//! Protects the key with a password //! //! EXAMPLES: //! @@ -480,9 +499,13 @@ //! supply a zero-length password when prompted for the new password. //! //! USAGE: -//! sq key password [FLAGS] [OPTIONS] [FILE] +//! sq key password [OPTIONS] [FILE] +//! +//! ARGS: +//! <FILE> +//! Reads from FILE or stdin if omitted //! -//! FLAGS: +//! OPTIONS: //! -B, --binary //! Emits binary data //! @@ -490,22 +513,11 @@ //! Emit a key with unencrypted secrets //! //! -h, --help -//! Prints help information -//! -//! -V, --version -//! Prints version information -//! +//! Print help information //! -//! OPTIONS: //! -o, --output <FILE> //! Writes to FILE or stdout if omitted //! -//! -//! ARGS: -//! <FILE> -//! Reads from FILE or stdin if omitted -//! -//! //! EXAMPLES: |