From 73bd7bf210e28b7385213adf9634d55e3ad31619 Mon Sep 17 00:00:00 2001 From: Nora Widdecke Date: Fri, 3 Jun 2022 11:26:16 +0200 Subject: sq: Derive packet subcommand. - This is part of the effort of moving to clap3's derive API and profit from the added type safety. --- sq/src/sq-usage.rs | 1 - sq/src/sq_cli.rs | 396 ++++++++++++++++++++++++++++++----------------------- 2 files changed, 225 insertions(+), 172 deletions(-) (limited to 'sq') diff --git a/sq/src/sq-usage.rs b/sq/src/sq-usage.rs index 96e63f09..9515aac6 100644 --- a/sq/src/sq-usage.rs +++ b/sq/src/sq-usage.rs @@ -1396,7 +1396,6 @@ //! ## Subcommand packet //! //! ```text -//! //! Low-level packet manipulation //! //! An OpenPGP data stream consists of packets. These tools allow working diff --git a/sq/src/sq_cli.rs b/sq/src/sq_cli.rs index b1e81529..e867d243 100644 --- a/sq/src/sq_cli.rs +++ b/sq/src/sq_cli.rs @@ -962,176 +962,6 @@ $ sq certify --time 20130721T0550+0200 neal.pgp ada.pgp ada .required(true) .index(3) .help("Certifies USERID for CERTIFICATE.")) - ) - - .subcommand(Command::new("packet") - .display_order(610) - .about("Low-level packet manipulation") - .long_about( -" -Low-level packet manipulation - -An OpenPGP data stream consists of packets. These tools allow working -with packet streams. They are mostly of interest to developers, but -\"sq packet dump\" may be helpful to a wider audience both to provide -valuable information in bug reports to OpenPGP-related software, and -as a learning tool. -") - .subcommand_required(true) - .arg_required_else_help(true) - .subcommand(Command::new("dump") - .display_order(100) - .about("Lists packets") - .long_about( -" -Lists packets - -Creates a human-readable description of the packet sequence. -Additionally, it can print cryptographic artifacts, and print the raw -octet stream similar to hexdump(1), annotating specifically which -bytes are parsed into OpenPGP values. - -To inspect encrypted messages, either supply the session key, or see -\"sq decrypt --dump\" or \"sq packet decrypt\". -") - .after_help( -"EXAMPLES: - -# Prints the packets of a certificate -$ sq packet dump juliet.pgp - -# Prints cryptographic artifacts of a certificate -$ sq packet dump --mpis juliet.pgp - -# Prints a hexdump of a certificate -$ sq packet dump --hex juliet.pgp - -# Prints the packets of an encrypted message -$ sq packet dump --session-key AAAABBBBCCCC... ciphertext.pgp -") - .arg(Arg::new("input") - .value_name("FILE") - .help("Reads from FILE or stdin if omitted")) - .arg(Arg::new("output") - .short('o').long("output").value_name("FILE") - .help("Writes to FILE or stdout if omitted")) - .arg(Arg::new("session-key") - .long("session-key").value_name("SESSION-KEY") - .help("Decrypts an encrypted message using \ - SESSION-KEY")) - .arg(Arg::new("mpis") - .long("mpis") - .help("Prints cryptographic artifacts")) - .arg(Arg::new("hex") - .short('x').long("hex") - .help("Prints a hexdump")) - ) - .subcommand(Command::new("decrypt") - .display_order(200) - .about("Unwraps an encryption container") - .long_about( -" -Unwraps an encryption container - -Decrypts a message, dumping the content of the encryption container -without further processing. The result is a valid OpenPGP message -that can, among other things, be inspected using \"sq packet dump\". -") - .after_help( -"EXAMPLES: - -# Unwraps the encryption revealing the signed message -$ sq packet decrypt --recipient-key juliet.pgp ciphertext.pgp -") - .arg(Arg::new("input") - .value_name("FILE") - .help("Reads from FILE or stdin if omitted")) - .arg(Arg::new("output") - .short('o').long("output").value_name("FILE") - .help("Writes to FILE or stdout if omitted")) - .arg(Arg::new("binary") - .short('B').long("binary") - .help("Emits binary data")) - .arg(Arg::new("secret-key-file") - .long("recipient-key").value_name("KEY") - .multiple_occurrences(true) - .help("Decrypts the message with KEY")) - .arg(Arg::new("private-key-store") - .long("private-key-store").value_name("KEY_STORE") - .help("Provides parameters for private key store")) - .arg(Arg::new("dump-session-key") - .long("dump-session-key") - .help("Prints the session key to stderr")) - ) - .subcommand(Command::new("split") - .display_order(300) - .about("Splits a message into packets") - .long_about( -" -Splits a message into packets - -Splitting a packet sequence into individual packets, then recombining -them freely with \"sq packet join\" is a great way to experiment with -OpenPGP data. - -The converse operation is \"sq packet join\". -") - .after_help( -"EXAMPLES: - -# Split a certificate into individual packets -$ sq packet split juliet.pgp -") - .arg(Arg::new("input") - .value_name("FILE") - .help("Reads from FILE or stdin if omitted")) - .arg(Arg::new("prefix") - .short('p').long("prefix").value_name("PREFIX") - .help("Writes to files with PREFIX \ - [defaults: FILE a dash, \ - or \"output\" if read from stdin)")) - ) - .subcommand(Command::new("join") - .display_order(310) - .about("Joins packets split across \ - files") - .long_about( -" -Joins packets split across files - -Splitting a packet sequence into individual packets, then recombining -them freely with \"sq packet join\" is a great way to experiment with -OpenPGP data. - -The converse operation is \"sq packet split\". -") - .after_help( -"EXAMPLES: - -# Split a certificate into individual packets -$ sq packet split juliet.pgp - -# Then join only a subset of these packets -$ sq packet join juliet.pgp-[0-3]* -") - .arg(Arg::new("input") - .value_name("FILE") - .multiple_occurrences(true) - .help("Reads from FILE or stdin if omitted")) - .arg(Arg::new("output") - .short('o').long("output").value_name("FILE") - .help("Writes to FILE or stdout if omitted")) - .arg(Arg::new("kind") - .long("label").value_name("LABEL") - .possible_values(&["auto", "message", - "cert", "key", "sig", - "file"]) - .default_value("auto") - .conflicts_with("binary") - .help("Selects the kind of armor header")) - .arg(Arg::new("binary") - .short('B').long("binary") - .help("Emits binary data"))) ); let app = if ! feature_autocrypt { @@ -1147,7 +977,8 @@ $ sq packet join juliet.pgp-[0-3]* .subcommand(VerifyCommand::command()) .subcommand(WkdCommand::command()) .subcommand(KeyserverCommand::command()) - .subcommand(RevokeCommand::command()); + .subcommand(RevokeCommand::command()) + .subcommand(PacketCommand::command()); app } @@ -1460,6 +1291,229 @@ pub struct SignCommand { pub notation: Option>, } +#[derive(Parser, Debug)] +#[clap( + name = "packet", + display_order = 610, + about = "Low-level packet manipulation", + long_about = +"Low-level packet manipulation + +An OpenPGP data stream consists of packets. These tools allow working +with packet streams. They are mostly of interest to developers, but +\"sq packet dump\" may be helpful to a wider audience both to provide +valuable information in bug reports to OpenPGP-related software, and +as a learning tool. +", + subcommand_required = true, + arg_required_else_help = true, + )] +pub struct PacketCommand { + #[clap(subcommand)] + pub subcommand: PacketSubcommands, +} + +#[derive(Debug, Subcommand)] +pub enum PacketSubcommands { + Dump(PacketDumpCommand), + Decrypt(PacketDecryptCommand), + Split(PacketSplitCommand), + Join(PacketJoinCommand), +} + +#[derive(Debug, Args)] +#[clap( + display_order = 100, + about = "Lists packets", + long_about = +" +Lists packets + +Creates a human-readable description of the packet sequence. +Additionally, it can print cryptographic artifacts, and print the raw +octet stream similar to hexdump(1), annotating specifically which +bytes are parsed into OpenPGP values. + +To inspect encrypted messages, either supply the session key, or see +\"sq decrypt --dump\" or \"sq packet decrypt\". +", + after_help = +"EXAMPLES: + +# Prints the packets of a certificate +$ sq packet dump juliet.pgp + +# Prints cryptographic artifacts of a certificate +$ sq packet dump --mpis juliet.pgp + +# Prints a hexdump of a certificate +$ sq packet dump --hex juliet.pgp + +# Prints the packets of an encrypted message +$ sq packet dump --session-key AAAABBBBCCCC... ciphertext.pgp +", +)] +pub struct PacketDumpCommand { + #[clap(flatten)] + pub io: IoArgs, + #[clap( + long = "session-key", + value_name = "SESSION-KEY", + help = "Decrypts an encrypted message using SESSION-KEY", + )] + pub session_key: Option, + #[clap( + long = "mpis", + help = "Prints cryptographic artifacts", + )] + pub mpis: bool, + #[clap( + short = 'x', + long = "hex", + help = "Prints a hexdump", + )] + pub hex: bool, +} + +#[derive(Debug, Args)] +#[clap( + display_order = 200, + about = "Unwraps an encryption container", + long_about = " +Unwraps an encryption container + +Decrypts a message, dumping the content of the encryption container +without further processing. The result is a valid OpenPGP message +that can, among other things, be inspected using \"sq packet dump\". +", + after_help = +"EXAMPLES: + +# Unwraps the encryption revealing the signed message +$ sq packet decrypt --recipient-key juliet.pgp ciphertext.pgp +", +)] +pub struct PacketDecryptCommand { + #[clap(flatten)] + pub io: IoArgs, + #[clap( + short = 'B', + long, + help = "Emits binary data", + )] + pub binary: bool, + #[clap( + long = "recipient-key", + value_name = "KEY", + help = "Decrypts the message with KEY", + )] + pub secret_key_file: Vec, + #[clap( + long = "private-key-store", + value_name = "KEY_STORE", + help = "Provides parameters for private key store", + )] + pub private_key_store: Option, + #[clap( + long = "dump-session-key", + help = "Prints the session key to stderr", + )] + pub dump_session_key: bool, +} + +#[derive(Debug, Args)] +#[clap( + display_order = 300, + about = "Splits a message into packets", + long_about = " +Splits a message into packets + +Splitting a packet sequence into individual packets, then recombining +them freely with \"sq packet join\" is a great way to experiment with +OpenPGP data. + +The converse operation is \"sq packet join\". +", + after_help = +"EXAMPLES: + +# Split a certificate into individual packets +$ sq packet split juliet.pgp +", +)] +pub struct PacketSplitCommand { + #[clap(value_name = "FILE", help = "Reads from FILE or stdin if omitted")] + pub input: Option, + #[clap( + short = 'p', + long = "prefix", + value_name = "PREFIX", + help = "Writes to files with PREFIX \ + [defaults: FILE a dash, or \"output\" if read from stdin)", + )] + pub prefix: Option, +} + +#[derive(Debug, Args)] +#[clap( + display_order = 310, + about = "Joins packets split across files", + long_about = " +Joins packets split across files + +Splitting a packet sequence into individual packets, then recombining +them freely with \"sq packet join\" is a great way to experiment with +OpenPGP data. + +The converse operation is \"sq packet split\". +", + after_help = +"EXAMPLES: + +# Split a certificate into individual packets +$ sq packet split juliet.pgp + +# Then join only a subset of these packets +$ sq packet join juliet.pgp-[0-3]* +", +)] +pub struct PacketJoinCommand { + #[clap(value_name = "FILE", help = "Reads from FILE or stdin if omitted")] + pub input: Vec, + #[clap( + short, + long, + value_name = "FILE", + help = "Writes to FILE or stdout if omitted" + )] + pub output: Option, + #[clap( + long = "label", + value_name = "LABEL", + default_value_t = PacketKind::Auto, + conflicts_with = "binary", + help = "Selects the kind of armor header", + arg_enum, + )] + pub kind: PacketKind, + #[clap( + short = 'B', + long, + help = "Emits binary data", + )] + pub binary: bool, +} +// TODO: reuse CliArmorKind, requires changes in sq.rs +#[derive(ArgEnum, Clone, Debug)] +pub enum PacketKind { + Auto, + Message, + Cert, + Key, + Sig, + File +} + #[derive(Parser, Debug)] #[clap( name = "revoke", -- cgit v1.2.3