summaryrefslogtreecommitdiffstats
path: root/sq/src/sq.rs
diff options
context:
space:
mode:
Diffstat (limited to 'sq/src/sq.rs')
-rw-r--r--sq/src/sq.rs211
1 files changed, 42 insertions, 169 deletions
diff --git a/sq/src/sq.rs b/sq/src/sq.rs
index 2a6f1c65..d84c51e8 100644
--- a/sq/src/sq.rs
+++ b/sq/src/sq.rs
@@ -4,7 +4,6 @@ use crossterm;
use crossterm::terminal;
use anyhow::Context as _;
-use prettytable::{Table, Cell, Row, row, cell};
use std::fs::OpenOptions;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
@@ -15,7 +14,7 @@ use buffered_reader::File;
use sequoia_openpgp as openpgp;
use sequoia_core;
use sequoia_net;
-use sequoia_store as store;
+use sequoia_store::Mapping;
use openpgp::{
Result,
@@ -37,11 +36,9 @@ use crate::openpgp::policy::StandardPolicy as P;
use sequoia_core::Context;
use sequoia_net as net;
use sequoia_net::{KeyServer, wkd};
-use store::{Mapping, LogIter};
mod sq_cli;
mod commands;
-use commands::dump::Convert;
fn open_or_stdin(f: Option<&str>) -> Result<Box<dyn io::Read + Send + Sync>> {
match f {
@@ -238,6 +235,14 @@ fn help_warning(arg: &str) {
}
}
+pub struct Config {
+ force: bool,
+ network_policy: net::Policy,
+ context: sequoia_core::Context,
+ realm_name: String,
+ mapping_name: String,
+}
+
fn main() -> Result<()> {
let policy = &mut P::new();
@@ -273,6 +278,16 @@ fn main() -> Result<()> {
builder = builder.home(dir);
}
let ctx = builder.build()?;
+
+ let config = Config {
+ force,
+ network_policy,
+ context: ctx,
+ realm_name: realm_name.into(),
+ mapping_name: mapping_name.into(),
+ };
+
+
let mut rt = tokio::runtime::Builder::new()
.basic_scheduler()
.enable_io()
@@ -291,18 +306,22 @@ fn main() -> Result<()> {
let secrets = m.values_of("secret-key-file")
.map(load_keys)
.unwrap_or(Ok(vec![]))?;
- let mut mapping = Mapping::open(&ctx, network_policy, realm_name,
- mapping_name)
+ let mut mapping = Mapping::open(&config.context,
+ config.network_policy,
+ &config.realm_name,
+ &config.mapping_name)
.context("Failed to open the mapping")?;
- commands::decrypt(&ctx, policy, &mut mapping,
+ commands::decrypt(&config.context, policy, &mut mapping,
&mut input, &mut output,
signatures, certs, secrets,
m.is_present("dump-session-key"),
m.is_present("dump"), m.is_present("hex"))?;
},
("encrypt", Some(m)) => {
- let mapping = Mapping::open(&ctx, network_policy, realm_name,
- mapping_name)
+ let mapping = Mapping::open(&config.context,
+ config.network_policy,
+ &config.realm_name,
+ &config.mapping_name)
.context("Failed to open the mapping")?;
let mut recipients = m.values_of("recipients-cert-file")
.map(load_certs)
@@ -386,10 +405,12 @@ fn main() -> Result<()> {
let certs = m.values_of("sender-cert-file")
.map(load_certs)
.unwrap_or(Ok(vec![]))?;
- let mut mapping = Mapping::open(&ctx, network_policy, realm_name,
- mapping_name)
+ let mut mapping = Mapping::open(&config.context,
+ config.network_policy,
+ &config.realm_name,
+ &config.mapping_name)
.context("Failed to open the mapping")?;
- commands::verify(&ctx, policy, &mut mapping, &mut input,
+ commands::verify(&config.context, policy, &mut mapping, &mut input,
detached.as_mut().map(|r| r as &mut (dyn io::Read + Sync + Send)),
&mut output, signatures, certs)?;
},
@@ -482,11 +503,13 @@ fn main() -> Result<()> {
let secrets = m.values_of("secret-key-file")
.map(load_keys)
.unwrap_or(Ok(vec![]))?;
- let mut mapping = Mapping::open(&ctx, network_policy,
- realm_name, mapping_name)
+ let mut mapping = Mapping::open(&config.context,
+ config.network_policy,
+ &config.realm_name,
+ &config.mapping_name)
.context("Failed to open the mapping")?;
commands::decrypt::decrypt_unwrap(
- &ctx, policy, &mut mapping,
+ &config.context, policy, &mut mapping,
&mut input, &mut output,
secrets, m.is_present("dump-session-key"))?;
output.finalize()?;
@@ -585,117 +608,10 @@ fn main() -> Result<()> {
_ => unreachable!(),
}
},
- ("mapping", Some(m)) => {
- let mapping = Mapping::open(&ctx, network_policy, realm_name,
- mapping_name)
- .context("Failed to open the mapping")?;
-
- match m.subcommand() {
- ("list", Some(_)) => {
- list_bindings(&mapping, realm_name, mapping_name)?;
- },
- ("add", Some(m)) => {
- let fp = m.value_of("fingerprint").unwrap().parse()
- .expect("Malformed fingerprint");
- mapping.add(m.value_of("label").unwrap(), &fp)?;
- },
- ("import", Some(m)) => {
- let label = m.value_of("label").unwrap();
- help_warning(label);
- let mut input = open_or_stdin(m.value_of("input"))?;
- let cert = Cert::from_reader(&mut input)?;
- mapping.import(label, &cert)?;
- },
- ("export", Some(m)) => {
- let cert = mapping.lookup(m.value_of("label").unwrap())?.cert()?;
- let mut output = create_or_stdout(m.value_of("output"), force)?;
- if m.is_present("binary") {
- cert.serialize(&mut output)?;
- } else {
- cert.armored().serialize(&mut output)?;
- }
- },
- ("delete", Some(m)) => {
- if m.is_present("label") == m.is_present("the-mapping") {
- eprintln!("Please specify either a label or --the-mapping.");
- exit(1);
- }
-
- if m.is_present("the-mapping") {
- mapping.delete().context("Failed to delete the mapping")?;
- } else {
- let binding = mapping.lookup(m.value_of("label").unwrap())
- .context("Failed to get key")?;
- binding.delete().context("Failed to delete the binding")?;
- }
- },
- ("stats", Some(m)) => {
- commands::mapping_print_stats(&mapping,
- m.value_of("label").unwrap())?;
- },
- ("log", Some(m)) => {
- if m.is_present("label") {
- let binding = mapping.lookup(m.value_of("label").unwrap())
- .context("No such key")?;
- print_log(binding.log().context("Failed to get log")?, false);
- } else {
- print_log(mapping.log().context("Failed to get log")?, true);
- }
- },
- _ => unreachable!(),
- }
- },
- ("list", Some(m)) => {
- match m.subcommand() {
- ("mappings", Some(m)) => {
- let mut table = Table::new();
- table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
- table.set_titles(row!["realm", "name", "network policy"]);
-
- for (realm, name, network_policy, _)
- in Mapping::list(&ctx, m.value_of("prefix").unwrap_or(""))? {
- table.add_row(Row::new(vec![
- Cell::new(&realm),
- Cell::new(&name),
- Cell::new(&format!("{:?}", network_policy))
- ]));
- }
-
- table.printstd();
- },
- ("bindings", Some(m)) => {
- for (realm, name, _, mapping)
- in Mapping::list(&ctx, m.value_of("prefix").unwrap_or(""))? {
- list_bindings(&mapping, &realm, &name)?;
- }
- },
- ("keys", Some(_)) => {
- let mut table = Table::new();
- table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
- table.set_titles(row!["fingerprint", "updated", "status"]);
-
- for (fingerprint, key) in store::Store::list_keys(&ctx)? {
- let stats = key.stats()
- .context("Failed to get key stats")?;
- table.add_row(Row::new(vec![
- Cell::new(&fingerprint.to_string()),
- if let Some(t) = stats.updated {
- Cell::new(&t.convert().to_string())
- } else {
- Cell::new("")
- },
- Cell::new("")
- ]));
- }
-
- table.printstd();
- },
- ("log", Some(_)) => {
- print_log(store::Store::server_log(&ctx)?, true);
- },
- _ => unreachable!(),
- }
- },
+ ("mapping", Some(m)) =>
+ commands::mappings::dispatch_mapping(config, m)?,
+ ("list", Some(m)) =>
+ commands::mappings::dispatch_list(config, m)?,
("key", Some(m)) => match m.subcommand() {
("generate", Some(m)) => commands::key::generate(m, force)?,
("adopt", Some(m)) => commands::key::adopt(m, policy)?,
@@ -758,49 +674,6 @@ fn main() -> Result<()> {
return Ok(())
}
-fn list_bindings(mapping: &Mapping, realm: &str, name: &str)
- -> Result<()> {
- if mapping.iter()?.count() == 0 {
- println!("No label-key bindings in the \"{}/{}\" mapping.",
- realm, name);
- return Ok(());
- }
-
- println!("Realm: {:?}, mapping: {:?}:", realm, name);
-
- let mut table = Table::new();
- table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
- table.set_titles(row!["label", "fingerprint"]);
- for (label, fingerprint, _) in mapping.iter()? {
- table.add_row(Row::new(vec![
- Cell::new(&label),
- Cell::new(&fingerprint.to_string())]));
- }
- table.printstd();
- Ok(())
-}
-
-fn print_log(iter: LogIter, with_slug: bool) {
- let mut table = Table::new();
- table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
- let mut head = row!["timestamp", "message"];
- if with_slug {
- head.insert_cell(1, Cell::new("slug"));
- }
- table.set_titles(head);
-
- for entry in iter {
- let mut row = row![&entry.timestamp.convert().to_string(),
- &entry.short()];
- if with_slug {
- row.insert_cell(1, Cell::new(&entry.slug));
- }
- table.add_row(row);
- }
-
- table.printstd();
-}
-
/// Parses the given string depicting a ISO 8601 timestamp.
fn parse_iso8601(s: &str, pad_date_with: chrono::NaiveTime)
-> Result<DateTime<Utc>>