diff options
-rw-r--r-- | Cargo.lock | 66 | ||||
-rw-r--r-- | sq/Cargo.toml | 4 | ||||
-rw-r--r-- | sq/src/commands/mappings.rs | 222 | ||||
-rw-r--r-- | sq/src/commands/mod.rs | 52 | ||||
-rw-r--r-- | sq/src/sq-usage.rs | 222 | ||||
-rw-r--r-- | sq/src/sq.rs | 41 | ||||
-rw-r--r-- | sq/src/sq_cli.rs | 85 |
7 files changed, 7 insertions, 685 deletions
@@ -227,18 +227,6 @@ dependencies = [ ] [[package]] -name = "bstr" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - -[[package]] name = "buffered-reader" version = "1.0.0" dependencies = [ @@ -500,28 +488,6 @@ dependencies = [ ] [[package]] -name = "csv" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d58633299b24b515ac72a3f869f8b91306a3cec616a602843a383acd6f9e97" -dependencies = [ - "bstr", - "csv-core", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] name = "ctor" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -699,12 +665,6 @@ dependencies = [ ] [[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] name = "environment" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1662,20 +1622,6 @@ dependencies = [ ] [[package]] -name = "prettytable-rs" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fd04b170004fa2daccf418a7f8253aaf033c27760b5f225889024cf66d7ac2e" -dependencies = [ - "atty", - "csv", - "encode_unicode", - "lazy_static", - "term", - "unicode-width", -] - -[[package]] name = "proc-macro-hack" version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1786,15 +1732,6 @@ dependencies = [ ] [[package]] -name = "regex-automata" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" -dependencies = [ - "byteorder", -] - -[[package]] name = "regex-syntax" version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2061,14 +1998,11 @@ dependencies = [ "crossterm", "itertools", "predicates", - "prettytable-rs", "rpassword", "sequoia-autocrypt", - "sequoia-core", "sequoia-ipc", "sequoia-net", "sequoia-openpgp", - "sequoia-store", "tempfile", "tokio", ] diff --git a/sq/Cargo.toml b/sq/Cargo.toml index 1c79f069..a32c32b6 100644 --- a/sq/Cargo.toml +++ b/sq/Cargo.toml @@ -25,15 +25,12 @@ maintenance = { status = "actively-developed" } buffered-reader = { path = "../buffered-reader", version = "1.0.0", default-features = false } sequoia-openpgp = { path = "../openpgp", version = "1.0.0", default-features = false } sequoia-autocrypt = { path = "../autocrypt", version = "0.22", default-features = false } -sequoia-core = { path = "../core", version = "0.22", default-features = false } sequoia-ipc = { path = "../ipc", version = "0.22", default-features = false } sequoia-net = { path = "../net", version = "0.22", default-features = false } -sequoia-store = { path = "../store", version = "0.22", default-features = false } anyhow = "1.0.18" chrono = "0.4.10" clap = "2.33" itertools = "0.9" -prettytable-rs = "0.8.0" tempfile = "3.1" crossterm = "0.13" tokio = { version = "0.2.19", features = ["rt-core", "io-util", "io-driver"] } @@ -55,7 +52,6 @@ path = "src/sq-usage.rs" default = [ "buffered-reader/compression", "sequoia-openpgp/default", - "sequoia-store/background-services" ] crypto-nettle = ["sequoia-openpgp/crypto-nettle"] crypto-cng = ["sequoia-openpgp/crypto-cng"] diff --git a/sq/src/commands/mappings.rs b/sq/src/commands/mappings.rs deleted file mode 100644 index 0846cb52..00000000 --- a/sq/src/commands/mappings.rs +++ /dev/null @@ -1,222 +0,0 @@ -use anyhow::Context; - -use prettytable::{Table, Cell, Row, row, cell}; - -use sequoia_openpgp as openpgp; -use openpgp::{ - Result, - cert::{ - Cert, - }, - parse::Parse, - serialize::Serialize, -}; -use sequoia_store as store; -use store::{ - Mapping, - LogIter, -}; - -use crate::{ - Config, - help_warning, - commands::dump::Convert, - open_or_stdin, - create_or_stdout, -}; - -pub fn dispatch_mapping(config: Config, m: &clap::ArgMatches) -> Result<()> { - let mapping = Mapping::open(&config.context, config.network_policy, - &config.realm_name, &config.mapping_name) - .context("Failed to open the mapping")?; - - match m.subcommand() { - ("list", Some(_)) => { - list_bindings(&mapping, &config.realm_name, &config.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"), - config.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") { - return Err(anyhow::anyhow!( - "Please specify either a label or --the-mapping.")); - } - - 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)) => { - 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!(), - } - - Ok(()) -} - -pub fn dispatch_list(config: Config, m: &clap::ArgMatches) -> Result<()> { - 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(&config.context, 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(&config.context, 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(&config.context)? { - 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(&config.context)?, true); - }, - _ => unreachable!(), - } - - 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(); -} - -pub fn mapping_print_stats(mapping: &store::Mapping, label: &str) -> Result<()> { - fn print_stamps(st: &store::Stamps) -> Result<()> { - println!("{} messages using this key", st.count); - if let Some(t) = st.first { - println!(" First: {}", t.convert()); - } - if let Some(t) = st.last { - println!(" Last: {}", t.convert()); - } - Ok(()) - } - - fn print_stats(st: &store::Stats) -> Result<()> { - if let Some(t) = st.created { - println!(" Created: {}", t.convert()); - } - if let Some(t) = st.updated { - println!(" Updated: {}", t.convert()); - } - print!(" Encrypted "); - print_stamps(&st.encryption)?; - print!(" Verified "); - print_stamps(&st.verification)?; - Ok(()) - } - - let binding = mapping.lookup(label)?; - println!("Binding {:?}", label); - print_stats(&binding.stats().context("Failed to get stats")?)?; - let key = binding.key().context("Failed to get key")?; - println!("Key"); - print_stats(&key.stats().context("Failed to get stats")?)?; - Ok(()) -} diff --git a/sq/src/commands/mod.rs b/sq/src/commands/mod.rs index 330c71bd..96246ec7 100644 --- a/sq/src/commands/mod.rs +++ b/sq/src/commands/mod.rs @@ -25,7 +25,6 @@ use crate::openpgp::serialize::stream::{ padding::Padder, }; use crate::openpgp::policy::Policy; -use sequoia_store as store; use crate::{ Config, @@ -43,7 +42,6 @@ pub mod key; pub mod merge_signatures; pub use self::merge_signatures::merge_signatures; pub mod certring; -pub mod mappings; /// Returns suitable signing keys from a given list of Certs. fn get_signing_keys(certs: &[openpgp::Cert], p: &dyn Policy, @@ -200,6 +198,7 @@ pub fn encrypt<'a>(policy: &'a dyn Policy, } struct VHelper { + #[allow(dead_code)] config: Config, signatures: usize, certs: Option<Vec<Cert>>, @@ -325,8 +324,8 @@ impl VHelper { } impl VerificationHelper for VHelper { - fn get_certs(&mut self, ids: &[openpgp::KeyHandle]) -> Result<Vec<Cert>> { - let mut certs = self.certs.take().unwrap(); + fn get_certs(&mut self, _ids: &[openpgp::KeyHandle]) -> Result<Vec<Cert>> { + let certs = self.certs.take().unwrap(); // Get all keys. let seen: HashSet<_> = certs.iter() .flat_map(|cert| { @@ -336,51 +335,6 @@ impl VerificationHelper for VHelper { // Explicitly provided keys are trusted. self.trusted = seen.clone(); - use sequoia_store::Mapping; - let mapping = Mapping::open(&self.config.context, - self.config.network_policy, - &self.config.realm_name, - &self.config.mapping_name) - .context("Failed to open the mapping")?; - - // Try to get missing Certs from the mapping. - for id in ids.iter().map(|i| KeyID::from(i)) - .filter(|i| !seen.contains(i)) - { - let _ = - mapping.lookup_by_subkeyid(&id) - .and_then(|binding| { - self.labels.insert(id.clone(), binding.label()?); - - // Keys from our mapping are trusted. - self.trusted.insert(id.clone()); - - binding.cert() - }) - .and_then(|cert| { - certs.push(cert); - Ok(()) - }); - } - - // Update seen. - let seen = self.trusted.clone(); - - // Try to get missing Certs from the pool. - for id in ids.iter().map(|i| KeyID::from(i.clone())) - .filter(|i| !seen.contains(i)) - { - let _ = - store::Store::lookup_by_subkeyid(&self.config.context, &id) - .and_then(|key| { - // Keys from the pool are NOT trusted. - key.cert() - }) - .and_then(|cert| { - certs.push(cert); - Ok(()) - }); - } Ok(certs) } diff --git a/sq/src/sq-usage.rs b/sq/src/sq-usage.rs index 9519d098..5c0ff4f1 100644 --- a/sq/src/sq-usage.rs +++ b/sq/src/sq-usage.rs @@ -14,11 +14,9 @@ //! -V, --version Prints version information //! //! OPTIONS: -//! --home <DIRECTORY> Sets the home directory to use //! --known-notation <NOTATION>... The notation name is considered known. This is used when validating //! signatures. Signatures that have unknown notations with the critical bit set //! are considered invalid. -//! -m, --mapping <MAPPING> Sets the realm and mapping to use [default: org.sequoia-pgp.contacts/default] //! -p, --policy <NETWORK-POLICY> Sets the network policy to use //! //! SUBCOMMANDS: @@ -26,7 +24,6 @@ //! encrypt Encrypts a message //! sign Signs a message //! verify Verifies a message -//! mapping Interacts with key mappings //! merge-signatures Merges two signatures //! keyserver Interacts with keyservers //! autocrypt Autocrypt support @@ -36,7 +33,6 @@ //! help Prints this message or the help of the given subcommand(s) //! inspect Inspects a sequence of OpenPGP packets //! key Manipulates keys -//! list Lists key mappings and known keys //! packet OpenPGP Packet manipulation //! wkd Interacts with Web Key Directories //! ``` @@ -92,7 +88,6 @@ //! transport encryption, rest selects those for encrypting data at rest, and all selects all encryption-capable //! subkeys [default: all] [possible values: transport, rest, all] //! -o, --output <FILE> Sets the output file to use -//! -r, --recipient <LABEL>... Recipient to encrypt for (can be given multiple times) //! --recipients-cert-file <CERTS-FILE>... //! Recipients to encrypt for, given as a file (can be given multiple times) //! @@ -154,145 +149,6 @@ //! <FILE> Sets the input file to use //! ``` //! -//! ## Subcommand mapping -//! -//! ```text -//! Interacts with key mappings -//! -//! USAGE: -//! sq mapping <SUBCOMMAND> -//! -//! FLAGS: -//! -h, --help Prints help information -//! -V, --version Prints version information -//! -//! SUBCOMMANDS: -//! add Add a key identified by fingerprint -//! delete Deletes bindings or mappings -//! export Exports a key -//! help Prints this message or the help of the given subcommand(s) -//! import Imports a key -//! list Lists keys in the mapping -//! log Lists the keystore log -//! stats Get stats for the given label -//! ``` -//! -//! ### Subcommand mapping add -//! -//! ```text -//! Add a key identified by fingerprint -//! -//! USAGE: -//! sq mapping add <LABEL> <FINGERPRINT> -//! -//! FLAGS: -//! -h, --help Prints help information -//! -V, --version Prints version information -//! -//! ARGS: -//! <LABEL> Label to use -//! <FINGERPRINT> Key to add -//! ``` -//! -//! ### Subcommand mapping delete -//! -//! ```text -//! Deletes bindings or mappings -//! -//! USAGE: -//! sq mapping delete [FLAGS] [LABEL] -//! -//! FLAGS: -//! -h, --help Prints help information -//! --the-mapping Delete the selected mapping (change with --mapping) -//! -V, --version Prints version information -//! -//! ARGS: -//! <LABEL> Delete binding with this label -//! ``` -//! -//! ### Subcommand mapping export -//! -//! ```text -//! Exports a key -//! -//! USAGE: -//! sq mapping export [FLAGS] [OPTIONS] <LABEL> -//! -//! FLAGS: -//! -B, --binary Don't ASCII-armor encode the OpenPGP data -//! -h, --help Prints help information -//! -V, --version Prints version information -//! -//! OPTIONS: -//! -o, --output <FILE> Sets the output file to use -//! -//! ARGS: -//! <LABEL> Label to use -//! ``` -//! -//! ### Subcommand mapping import -//! -//! ```text -//! Imports a key -//! -//! USAGE: -//! sq mapping import <LABEL> [FILE] -//! -//! FLAGS: -//! -h, --help Prints help information -//! -V, --version Prints version information -//! -//! ARGS: -//! <LABEL> Label to use -//! <FILE> Sets the input file to use -//! ``` -//! -//! ### Subcommand mapping list -//! -//! ```text -//! Lists keys in the mapping -//! -//! USAGE: -//! sq mapping list -//! -//! FLAGS: -//! -h, --help Prints help information -//! -V, --version Prints version information -//! ``` -//! -//! ### Subcommand mapping log -//! -//! ```text -//! Lists the keystore log -//! -//! USAGE: -//! sq mapping log [LABEL] -//! -//! FLAGS: -//! -h, --help Prints help information -//! -V, --version Prints version information -//! -//! ARGS: -//! <LABEL> List messages related to this label -//! ``` -//! -//! ### Subcommand mapping stats -//! -//! ```text -//! Get stats for the given label -//! -//! USAGE: -//! sq mapping stats <LABEL> -//! -//! FLAGS: -//! -h, --help Prints help information -//! -V, --version Prints version information -//! -//! ARGS: -//! <LABEL> Label to use -//! ``` -//! //! ## Subcommand merge-signatures //! //! ```text @@ -678,84 +534,6 @@ //! -u, --userid <EMAIL>... Add userid to the key (can be given multiple times) //! ``` //! -//! ## Subcommand list -//! -//! ```text -//! Lists key mappings and known keys -//! -//! USAGE: -//! sq list <SUBCOMMAND> -//! -//! FLAGS: -//! -h, --help Prints help information -//! -V, --version Prints version information -//! -//! SUBCOMMANDS: -//! bindings Lists all bindings in all key mappings -//! help Prints this message or the help of the given subcommand(s) -//! keys Lists all keys in the common key pool -//! log Lists the server log -//! mappings Lists key mappings -//! ``` -//! -//! ### Subcommand list bindings -//! -//! ```text -//! Lists all bindings in all key mappings -//! -//! USAGE: -//! sq list bindings [PREFIX] -//! -//! FLAGS: -//! -h, --help Prints help information -//! -V, --version Prints version information -//! -//! ARGS: -//! <PREFIX> List only bindings from mappings with the given realm prefix -//! ``` -//! -//! ### Subcommand list keys -//! -//! ```text -//! Lists all keys in the common key pool -//! -//! USAGE: -//! sq list keys -//! -//! FLAGS: -//! -h, --help Prints help information -//! -V, --version Prints version information -//! ``` -//! -//! ### Subcommand list log -//! -//! ```text -//! Lists the server log -//! -//! USAGE: -//! sq list log -//! -//! FLAGS: -//! -h, --help Prints help information -//! -V, --version Prints version information -//! ``` -//! -//! ### Subcommand list mappings -//! -//! ```text -//! Lists key mappings -//! -//! USAGE: -//! sq list mappings [PREFIX] -//! -//! FLAGS: -//! -h, --help Prints help information -//! -V, --version Prints version information -//! -//! ARGS: -//! <PREFIX> List only mappings with the given realm prefix -//! ``` -//! //! ## Subcommand packet //! //! ```text diff --git a/sq/src/sq.rs b/sq/src/sq.rs index 148ea8e0..f9777c2c 100644 --- a/sq/src/sq.rs +++ b/sq/src/sq.rs @@ -12,9 +12,7 @@ use chrono::{DateTime, offset::Utc}; use buffered_reader::File; use sequoia_openpgp as openpgp; -use sequoia_core; use sequoia_net; -use sequoia_store::Mapping; use openpgp::{ Result, @@ -33,7 +31,6 @@ use crate::openpgp::parse::Parse; use crate::openpgp::serialize::{Serialize, stream::{Message, Armorer}}; use crate::openpgp::cert::prelude::*; use crate::openpgp::policy::StandardPolicy as P; -use sequoia_core::Context; use sequoia_net as net; use sequoia_net::{KeyServer, wkd}; @@ -228,6 +225,7 @@ fn decrypt_key<R>(key: Key<key::SecretParts, R>, passwords: &mut Vec<String>) /// /// This should be used wherever a positional argument is followed by /// an optional positional argument. +#[allow(dead_code)] fn help_warning(arg: &str) { if arg == "help" { eprintln!("Warning: \"help\" is not a subcommand here. \ @@ -235,12 +233,10 @@ fn help_warning(arg: &str) { } } +#[allow(dead_code)] pub struct Config { force: bool, network_policy: net::Policy, - context: sequoia_core::Context, - realm_name: String, - mapping_name: String, } fn main() -> Result<()> { @@ -265,26 +261,10 @@ fn main() -> Result<()> { }, }; let force = matches.is_present("force"); - let (realm_name, mapping_name) = { - let s = matches.value_of("mapping").expect("has a default value"); - if let Some(i) = s.find('/') { - (&s[..i], &s[i+1..]) - } else { - (s, "default") - } - }; - let mut builder = Context::configure(); - if let Some(dir) = matches.value_of("home") { - 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(), }; @@ -313,20 +293,9 @@ fn main() -> Result<()> { m.is_present("dump"), m.is_present("hex"))?; }, ("encrypt", Some(m)) => { - 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") + let recipients = m.values_of("recipients-cert-file") .map(load_certs) .unwrap_or(Ok(vec![]))?; - if let Some(r) = m.values_of("recipient") { - for recipient in r { - recipients.push(mapping.lookup(recipient) - .context("No such key found")?.cert()?); - } - } let mut input = open_or_stdin(m.value_of("input"))?; let output = create_or_stdout_pgp(m.value_of("output"), force, @@ -593,10 +562,6 @@ fn main() -> Result<()> { _ => 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)?, |