summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@pep-project.org>2018-01-04 16:33:43 +0100
committerJustus Winter <justus@pep-project.org>2018-01-04 16:33:43 +0100
commitd639f0b77b742b4eda4aeacb5db72d26e68ec227 (patch)
treed8e5ea2a453adfda6c2bb47adc0d86022ebc28bb
parent49d10c39ab85d54d440b57522fcfdcce13f9af3f (diff)
tool: Implement keyserver interactions.
- Implement retrieving and sending keys. - Improve usage generation to include nested subcommands.
-rw-r--r--tool/make-usage.sh50
-rw-r--r--tool/src/main.rs105
-rw-r--r--tool/src/usage.rs77
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");