diff options
author | Justus Winter <justus@pep-project.org> | 2018-01-04 16:33:43 +0100 |
---|---|---|
committer | Justus Winter <justus@pep-project.org> | 2018-01-04 16:33:43 +0100 |
commit | d639f0b77b742b4eda4aeacb5db72d26e68ec227 (patch) | |
tree | d8e5ea2a453adfda6c2bb47adc0d86022ebc28bb /tool | |
parent | 49d10c39ab85d54d440b57522fcfdcce13f9af3f (diff) |
tool: Implement keyserver interactions.
- Implement retrieving and sending keys.
- Improve usage generation to include nested subcommands.
Diffstat (limited to 'tool')
-rw-r--r-- | tool/make-usage.sh | 50 | ||||
-rw-r--r-- | tool/src/main.rs | 105 | ||||
-rw-r--r-- | tool/src/usage.rs | 77 |
3 files changed, 202 insertions, 30 deletions
diff --git a/tool/make-usage.sh b/tool/make-usage.sh index bc150a75..c9c890a2 100644 --- a/tool/make-usage.sh +++ b/tool/make-usage.sh @@ -1,5 +1,7 @@ #!/bin/sh +sq=$1 + quote() { sed 's@^@//! @' | sed 's/ $//' } @@ -12,30 +14,40 @@ end_code() { printf '```\n' } -( - printf "A command-line frontend for Sequoia. +dump_help() { # subcommand, indention + if [ -z "$1" ] + then + printf "\n# Usage\n\n" + set "" "#" + else + printf "\n$2 Subcommand$1\n\n" + fi -# Usage + help="`$sq $1 --help`" -" begin_code - sq --help + printf "$help\n" | tail -n +2 end_code - sq --help | - sed -n '/^SUBCOMMANDS:/,$p' | - tail -n+2 | - while read command desc - do - if [ "$command" = help ]; then - continue - fi - - printf "\n## Subcommand $command\n\n" - begin_code - sq $command --help - end_code - done + if echo $help | fgrep -q SUBCOMMANDS + then + printf "$help\n" | + sed -n '/^SUBCOMMANDS:/,$p' | + tail -n+2 | + while read subcommand desc + do + if [ "$subcommand" = help ]; then + continue + fi + + dump_help "$1 $subcommand" "#$2" + done + fi +} + +( + printf "A command-line frontend for Sequoia.\n" + dump_help ) | quote printf '\ninclude!("main.rs");\n' diff --git a/tool/src/main.rs b/tool/src/main.rs index c1a5f262..d38b1299 100644 --- a/tool/src/main.rs +++ b/tool/src/main.rs @@ -5,12 +5,16 @@ extern crate clap; use clap::{Arg, App, SubCommand, AppSettings}; use std::fs::File; use std::io; +use std::process::exit; extern crate openpgp; extern crate sequoia_core; extern crate sequoia_net; use openpgp::armor; +use openpgp::tpk::TPK; +use sequoia_core::{Context, Result, NetworkPolicy}; +use sequoia_net::KeyServer; fn open_or_stdin(f: Option<&str>) -> Box<io::Read> { match f { @@ -26,11 +30,19 @@ fn create_or_stdout(f: Option<&str>) -> Box<io::Write> { } } -fn real_main() -> Result<(), io::Error> { +fn real_main() -> Result<()> { let matches = App::new("sq") .version("0.1.0") .about("Sequoia is an implementation of OpenPGP. This is a command-line frontend.") .setting(AppSettings::ArgRequiredElseHelp) + .arg(Arg::with_name("domain").value_name("DOMAIN") + .long("domain") + .short("d") + .help("Sets the domain to use")) + .arg(Arg::with_name("policy").value_name("NETWORK-POLICY") + .long("policy") + .short("p") + .help("Sets the network policy to use")) .subcommand(SubCommand::with_name("enarmor") .about("Applies ASCII Armor to a file") .arg(Arg::with_name("input").value_name("FILE") @@ -65,8 +77,51 @@ fn real_main() -> Result<(), io::Error> { .long("dearmor") .short("A") .help("Remove ASCII Armor from input"))) + .subcommand(SubCommand::with_name("keyserver") + .about("Interacts with keyservers") + .arg(Arg::with_name("server").value_name("URI") + .long("server") + .short("s") + .help("Sets the keyserver to use")) + .subcommand(SubCommand::with_name("get") + .about("Retrieves a key") + .arg(Arg::with_name("output").value_name("FILE") + .long("output") + .short("o") + .help("Sets the output file to use")) + .arg(Arg::with_name("armor") + .long("armor") + .short("A") + .help("Write armored data to file")) + .arg(Arg::with_name("keyid").value_name("KEYID") + .required(true) + .help("ID of the key to retrieve"))) + .subcommand(SubCommand::with_name("send") + .about("Sends a key") + .arg(Arg::with_name("input").value_name("FILE") + .long("input") + .short("i") + .help("Sets the input file to use")) + .arg(Arg::with_name("dearmor") + .long("dearmor") + .short("A") + .help("Remove ASCII Armor from input")))) .get_matches(); + let policy = match matches.value_of("policy") { + None => NetworkPolicy::Encrypted, + Some("offline") => NetworkPolicy::Offline, + Some("anonymized") => NetworkPolicy::Anonymized, + Some("encrypted") => NetworkPolicy::Encrypted, + Some("insecure") => NetworkPolicy::Insecure, + Some(_) => { + eprintln!("Bad network policy, must be offline, anonymized, encrypted, or insecure."); + exit(1); + }, + }; + let ctx = Context::configure(matches.value_of("domain").unwrap_or("org.sequoia-pgp.sq")) + .network_policy(policy).build()?; + match matches.subcommand() { ("enarmor", Some(m)) => { let mut input = open_or_stdin(m.value_of("input")); @@ -112,8 +167,54 @@ fn real_main() -> Result<(), io::Error> { ppo = ppo_tmp; } }, + ("keyserver", Some(m)) => { + let mut ks = if let Some(uri) = m.value_of("server") { + KeyServer::new(&ctx, &uri) + } else { + KeyServer::sks_pool(&ctx) + }.expect("Malformed keyserver URI"); + + match m.subcommand() { + ("get", Some(m)) => { + let keyid = m.value_of("keyid").unwrap(); + let id = openpgp::types::KeyId::from_hex(keyid); + if id.is_none() { + eprintln!("Malformed keyid: {:?}", keyid); + exit(1); + } + + let mut output = create_or_stdout(m.value_of("output")); + let mut output = if m.is_present("armor") { + Box::new(armor::Writer::new(&mut output, armor::Kind::PublicKey)) + } else { + output + }; + + ks.get(&id.unwrap()).expect("An error occured") + .serialize(&mut output).expect("An error occured"); + }, + ("send", Some(m)) => { + let mut input = open_or_stdin(m.value_of("input")); + let mut input = if m.is_present("dearmor") { + Box::new(armor::Reader::new(&mut input, armor::Kind::Any)) + } else { + input + }; + + let tpk = TPK::from_reader(&mut input). + expect("Malformed key"); + + ks.send(&tpk).expect("An error occured"); + }, + _ => { + eprintln!("No keyserver subcommand given."); + exit(1); + }, + } + }, _ => { - unreachable!(); + eprintln!("No subcommand given."); + exit(1); }, } diff --git a/tool/src/usage.rs b/tool/src/usage.rs index 3ce13d3b..3c5645bd 100644 --- a/tool/src/usage.rs +++ b/tool/src/usage.rs @@ -3,27 +3,30 @@ //! # Usage //! //! ```text -//! sq 0.1.0 //! Sequoia is an implementation of OpenPGP. This is a command-line frontend. //! //! USAGE: -//! sq [SUBCOMMAND] +//! sq [OPTIONS] [SUBCOMMAND] //! //! FLAGS: //! -h, --help Prints help information //! -V, --version Prints version information //! +//! OPTIONS: +//! -d, --domain <DOMAIN> Sets the domain to use +//! -p, --policy <NETWORK-POLICY> Sets the network policy to use +//! //! SUBCOMMANDS: -//! dearmor Removes ASCII Armor from a file -//! dump Lists OpenPGP packets -//! enarmor Applies ASCII Armor to a file -//! help Prints this message or the help of the given subcommand(s) +//! dearmor Removes ASCII Armor from a file +//! dump Lists OpenPGP packets +//! enarmor Applies ASCII Armor to a file +//! help Prints this message or the help of the given subcommand(s) +//! keyserver Interacts with keyservers //! ``` //! //! ## Subcommand dearmor //! //! ```text -//! sq-dearmor //! Removes ASCII Armor from a file //! //! USAGE: @@ -41,7 +44,6 @@ //! ## Subcommand dump //! //! ```text -//! sq-dump //! Lists OpenPGP packets //! //! USAGE: @@ -60,7 +62,6 @@ //! ## Subcommand enarmor //! //! ```text -//! sq-enarmor //! Applies ASCII Armor to a file //! //! USAGE: @@ -74,5 +75,63 @@ //! -i, --input <FILE> Sets the input file to use //! -o, --output <FILE> Sets the output file to use //! ``` +//! +//! ## Subcommand keyserver +//! +//! ```text +//! Interacts with keyservers +//! +//! USAGE: +//! sq keyserver [OPTIONS] [SUBCOMMAND] +//! +//! FLAGS: +//! -h, --help Prints help information +//! -V, --version Prints version information +//! +//! OPTIONS: +//! -s, --server <URI> Sets the keyserver to use +//! +//! SUBCOMMANDS: +//! get Retrieves a key +//! help Prints this message or the help of the given subcommand(s) +//! send Sends a key +//! ``` +//! +//! ### Subcommand keyserver get +//! +//! ```text +//! Retrieves a key +//! +//! USAGE: +//! sq keyserver get [FLAGS] [OPTIONS] <KEYID> +//! +//! FLAGS: +//! -A, --armor Write armored data to file +//! -h, --help Prints help information +//! -V, --version Prints version information +//! +//! OPTIONS: +//! -o, --output <FILE> Sets the output file to use +//! +//! ARGS: +//! <KEYID> ID of the key to retrieve +//! ``` +//! +//! ### Subcommand keyserver send +//! +//! ```text +//! Sends a key +//! +//! USAGE: +//! sq keyserver send [FLAGS] [OPTIONS] +//! +//! FLAGS: +//! -A, --dearmor Remove ASCII Armor from input +//! -h, --help Prints help information +//! -V, --version Prints version information +//! +//! OPTIONS: +//! -i, --input <FILE> Sets the input file to use +//! ``` include!("main.rs"); |