summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNora Widdecke <nora@sequoia-pgp.org>2021-07-08 15:31:44 +0200
committerNora Widdecke <nora@sequoia-pgp.org>2021-07-09 21:54:51 +0200
commitc84b096add1d05afc41cc94b35a9db15bac0afea (patch)
tree3bcf860de8a5ea56ca55a69ca7dbebbfdd378964
parentc1a03f229e61402e9418ee31609f1b22cbe13e4a (diff)
sqv: Move to https://gitlab.com/sequoia-pgp/sequoia-sqv
- From this point on, the crate sequoia-sqv will be maintained in its own repository.
-rw-r--r--.Makefile2
-rw-r--r--.gitlab-ci.yml6
-rw-r--r--Cargo.lock11
-rw-r--r--Cargo.toml1
-rw-r--r--sqv/Cargo.toml43
l---------sqv/LICENSE.txt1
-rw-r--r--sqv/Makefile34
-rw-r--r--sqv/NEWS7
-rw-r--r--sqv/README.md8
-rw-r--r--sqv/build.rs101
-rw-r--r--sqv/src/sqv-usage.rs42
-rw-r--r--sqv/src/sqv.rs367
-rw-r--r--sqv/src/sqv_cli.rs50
-rw-r--r--sqv/tests/bad-subkey.rs16
-rw-r--r--sqv/tests/data/bad-subkey-keyring.pgpbin18064 -> 0 bytes
-rw-r--r--sqv/tests/data/bad-subkey-keyring.txt12
-rw-r--r--sqv/tests/data/bad-subkey.txt1
-rw-r--r--sqv/tests/data/bad-subkey.txt.sigbin310 -> 0 bytes
-rw-r--r--sqv/tests/data/msg.txt1
-rw-r--r--sqv/tests/data/no-signing-caps.keybin1718 -> 0 bytes
-rw-r--r--sqv/tests/data/no-signing-caps.sigbin438 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-not-revoked.pgpbin985 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-compromised.pgpbin1140 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-compromised.sk.pgpbin1140 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-key_retired.pgpbin1140 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-key_retired.sk.pgpbin1140 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-no_subpacket.pgpbin1104 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-no_subpacket.sk.pgpbin1104 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-private.pgpbin1149 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-private.sk.pgpbin1149 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-superseded.pgpbin1124 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-superseded.sk.pgpbin1124 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-uid_retired.pgpbin1145 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-uid_retired.sk.pgpbin1145 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-unknown.pgpbin1136 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-unknown.sk.pgpbin1136 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-unspecified.pgpbin1126 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-cert-revoked-unspecified.sk.pgpbin1126 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-sig-t0.pgpbin119 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-sig-t0.sk.pgpbin119 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-sig-t1-t2.pgpbin119 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-sig-t1-t2.sk.pgpbin119 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-sig-t2-t3.pgpbin119 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-sig-t2-t3.sk.pgpbin119 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-sig-t3-now.pgpbin119 -> 0 bytes
-rw-r--r--sqv/tests/data/revoked-key-sig-t3-now.sk.pgpbin119 -> 0 bytes
-rw-r--r--sqv/tests/duplicate-signatures.rs30
-rw-r--r--sqv/tests/multiple-signatures.rs23
-rw-r--r--sqv/tests/not-before-after.rs60
-rw-r--r--sqv/tests/revoked-key.rs488
-rw-r--r--sqv/tests/wrong-key-flags.rs66
51 files changed, 2 insertions, 1368 deletions
diff --git a/.Makefile b/.Makefile
index f3a6a654..7e8eb636 100644
--- a/.Makefile
+++ b/.Makefile
@@ -106,7 +106,6 @@ build-release:
$(MAKE) -Copenpgp-ffi build-release
$(MAKE) -Cffi build-release
$(MAKE) -Csq build-release
- $(MAKE) -Csqv build-release
# "install" needs "build-release" as it builds the project
# with optimizations enabled.
@@ -115,7 +114,6 @@ install: build-release
$(MAKE) -Copenpgp-ffi install
$(MAKE) -Cffi install
$(MAKE) -Csq install
- $(MAKE) -Csqv install
# Infrastructure for creating source distributions.
.PHONY: dist
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2adabc14..e8d7e3b7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -26,7 +26,6 @@ build-bullseye:
- $MAKE_TOP
- if ! git diff --quiet Cargo.lock ; then echo "Cargo.lock changed. Please add the change to the corresponding commit." ; false ; fi
- if ! git diff --quiet sq ; then echo "Please commit the changes to sq/src/sq-usage.rs." ; false ; fi
- - if ! git diff --quiet sqv ; then echo "Please commit the changes to sqv/src/sqv-usage.rs." ; false ; fi
- if ! git diff --quiet ; then echo "The build changed the source. Please investigate." ; git diff ; fi
variables:
CARGO_TARGET_DIR: /target
@@ -50,7 +49,6 @@ build-bullseye:arm64:
- $MAKE_TOP
- if ! git diff --quiet Cargo.lock ; then echo "Cargo.lock changed. Please add the change to the corresponding commit." ; false ; fi
- if ! git diff --quiet sq ; then echo "Please commit the changes to sq/src/sq-usage.rs." ; false ; fi
- - if ! git diff --quiet sqv ; then echo "Please commit the changes to sqv/src/sqv-usage.rs." ; false ; fi
- if ! git diff --quiet ; then echo "The build changed the source. Please investigate." ; git diff ; fi
variables:
CARGO_TARGET_DIR: /target
@@ -198,7 +196,7 @@ rust-stable:
- cargo --version
- clang --version
script:
- - CARGO_PACKAGES="-p buffered-reader -p sequoia-openpgp -p sequoia-sqv" $MAKE_TOP test
+ - CARGO_PACKAGES="-p buffered-reader -p sequoia-openpgp" $MAKE_TOP test
variables:
CARGO_TARGET_DIR: /target
CARGO_HOME: /cargo
@@ -222,7 +220,7 @@ rust-stable:arm64:
- cargo --version
- clang --version
script:
- - CARGO_PACKAGES="-p buffered-reader -p sequoia-openpgp -p sequoia-sqv" $MAKE_TOP test
+ - CARGO_PACKAGES="-p buffered-reader -p sequoia-openpgp" $MAKE_TOP test
variables:
CARGO_TARGET_DIR: /target
CARGO_HOME: /cargo
diff --git a/Cargo.lock b/Cargo.lock
index a6aab920..0e4a5580 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2205,17 +2205,6 @@ dependencies = [
]
[[package]]
-name = "sequoia-sqv"
-version = "1.0.0"
-dependencies = [
- "anyhow",
- "assert_cli",
- "chrono",
- "clap",
- "sequoia-openpgp",
-]
-
-[[package]]
name = "sequoia-store"
version = "0.22.0"
dependencies = [
diff --git a/Cargo.toml b/Cargo.toml
index a391ad61..a4f48520 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,7 +10,6 @@ members = [
"openpgp",
"openpgp-ffi",
"sq",
- "sqv",
"store",
]
diff --git a/sqv/Cargo.toml b/sqv/Cargo.toml
deleted file mode 100644
index 79663083..00000000
--- a/sqv/Cargo.toml
+++ /dev/null
@@ -1,43 +0,0 @@
-[package]
-name = "sequoia-sqv"
-description = "A simple OpenPGP signature verification program"
-version = "1.0.0"
-authors = [
- "Justus Winter <justus@sequoia-pgp.org>",
- "Kai Michaelis <kai@sequoia-pgp.org>",
- "Neal H. Walfield <neal@sequoia-pgp.org>",
-]
-documentation = "https://docs.sequoia-pgp.org/0.21.0/sqv"
-homepage = "https://sequoia-pgp.org/"
-repository = "https://gitlab.com/sequoia-pgp/sequoia"
-readme = "README.md"
-keywords = ["cryptography", "openpgp", "pgp", "signature", "verification"]
-categories = ["cryptography", "command-line-utilities"]
-license = "GPL-2.0-or-later"
-edition = "2018"
-
-[badges]
-gitlab = { repository = "sequoia-pgp/sequoia" }
-maintenance = { status = "actively-developed" }
-
-[dependencies]
-sequoia-openpgp = { path = "../openpgp", version = "1.0.0", default-features = false }
-anyhow = "1.0.18"
-chrono = "0.4.10"
-clap = { version = "2.33", features = ["wrap_help"] }
-
-[build-dependencies]
-clap = "2.33"
-
-[dev-dependencies]
-assert_cli = "0.6"
-
-[[bin]]
-name = "sqv"
-path = "src/sqv-usage.rs"
-bench = false
-
-[features]
-default = ["crypto-nettle"]
-crypto-nettle = ["sequoia-openpgp/crypto-nettle"]
-crypto-cng = ["sequoia-openpgp/crypto-cng"]
diff --git a/sqv/LICENSE.txt b/sqv/LICENSE.txt
deleted file mode 120000
index 4ab43736..00000000
--- a/sqv/LICENSE.txt
+++ /dev/null
@@ -1 +0,0 @@
-../LICENSE.txt \ No newline at end of file
diff --git a/sqv/Makefile b/sqv/Makefile
deleted file mode 100644
index 1ec2c975..00000000
--- a/sqv/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-# Configuration.
-CARGO_TARGET_DIR ?= $(shell pwd)/../target
-# We currently only support absolute paths.
-CARGO_TARGET_DIR := $(abspath $(CARGO_TARGET_DIR))
-SQV ?= $(CARGO_TARGET_DIR)/debug/sqv
-
-# Tools.
-CARGO ?= cargo
-
-ifneq ($(filter Darwin %BSD,$(shell uname -s)),)
- INSTALL ?= ginstall
-else
- INSTALL ?= install
-endif
-
-# Installation.
-.PHONY: build-release
-build-release:
- CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) \
- $(CARGO) build $(CARGO_FLAGS) --release --package sequoia-sqv
-
-.PHONY: install
-install: build-release
- $(INSTALL) -d $(DESTDIR)$(PREFIX)/bin
- $(INSTALL) -t $(DESTDIR)$(PREFIX)/bin $(CARGO_TARGET_DIR)/release/sqv
- $(INSTALL) -d $(DESTDIR)$(PREFIX)/share/zsh/site-functions
- $(INSTALL) -t $(DESTDIR)$(PREFIX)/share/zsh/site-functions \
- $(CARGO_TARGET_DIR)/_sqv
- $(INSTALL) -d $(DESTDIR)$(PREFIX)/share/bash-completion/completions
- $(INSTALL) $(CARGO_TARGET_DIR)/sqv.bash \
- $(DESTDIR)$(PREFIX)/share/bash-completion/completions/sqv
- $(INSTALL) -d $(DESTDIR)$(PREFIX)/share/fish/completions
- $(INSTALL) -t $(DESTDIR)$(PREFIX)/share/fish/completions \
- $(CARGO_TARGET_DIR)/sqv.fish
diff --git a/sqv/NEWS b/sqv/NEWS
deleted file mode 100644
index 6169330a..00000000
--- a/sqv/NEWS
+++ /dev/null
@@ -1,7 +0,0 @@
- -*- org -*-
-#+TITLE: sequoia-sqv NEWS – history of user-visible changes
-#+STARTUP: content hidestars
-
-* Changes in 1.0.0
-
-This is the initial stable release.
diff --git a/sqv/README.md b/sqv/README.md
deleted file mode 100644
index 7cfb9c04..00000000
--- a/sqv/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-A simple signature verification program.
-
-`sqv` verifies detached OpenPGP signatures. It is a replacement for
-`gpgv`. Unlike `gpgv`, it can take additional constraints on the
-signature into account.
-
-See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=872271 for
-the motivation.
diff --git a/sqv/build.rs b/sqv/build.rs
deleted file mode 100644
index 921e71ff..00000000
--- a/sqv/build.rs
+++ /dev/null
@@ -1,101 +0,0 @@
-use std::env;
-use std::fs;
-use std::io::{self, Write};
-use clap::Shell;
-
-mod sqv_cli {
- include!("src/sqv_cli.rs");
-}
-
-fn main() {
- println!("cargo:rerun-if-changed=build.rs");
-
- // XXX: Revisit once
- // https://github.com/rust-lang/rust/issues/44732 is stabilized.
-
- let mut sqv = sqv_cli::configure(clap::App::new("sqv").set_term_width(80));
- let mut main = fs::File::create("src/sqv-usage.rs").unwrap();
- dump_help(&mut main,
- &mut sqv,
- vec![],
- "#").unwrap();
-
- writeln!(main, "\n#![doc(html_favicon_url = \"https://docs.sequoia-pgp.org/favicon.png\")]")
- .unwrap();
- writeln!(main, "#![doc(html_logo_url = \"https://docs.sequoia-pgp.org/logo.svg\")]")
- .unwrap();
- writeln!(main, "\ninclude!(\"sqv.rs\");").unwrap();
-
- let outdir = match env::var_os("CARGO_TARGET_DIR") {
- None => return,
- Some(outdir) => outdir,
- };
- fs::create_dir_all(&outdir).unwrap();
- let mut sqv = sqv_cli::build();
- for shell in &[Shell::Bash, Shell::Fish, Shell::Zsh, Shell::PowerShell,
- Shell::Elvish] {
- sqv.gen_completions("sqv", *shell, &outdir);
- }
-}
-
-fn dump_help(sink: &mut dyn io::Write,
- sqv: &mut clap::App,
- cmd: Vec<String>,
- heading: &str)
- -> io::Result<()>
-{
-
- if cmd.is_empty() {
- writeln!(sink, "//! A command-line frontend for Sequoia.")?;
- writeln!(sink, "//!")?;
- writeln!(sink, "//! # Usage")?;
- } else {
- writeln!(sink, "//!")?;
- writeln!(sink, "//! {} Subcommand {}", heading, cmd.join(" "))?;
- }
-
- writeln!(sink, "//!")?;
-
- let args = std::iter::once("sqv")
- .chain(cmd.iter().map(|s| s.as_str()))
- .chain(std::iter::once("--help"))
- .collect::<Vec<_>>();
-
- let help = sqv.get_matches_from_safe_borrow(&args)
- .unwrap_err().to_string();
-
- writeln!(sink, "//! ```text")?;
- for line in help.trim_end().split('\n').skip(1) {
- if line.is_empty() {
- writeln!(sink, "//!")?;
- } else {
- writeln!(sink, "//! {}", line.trim_end())?;
- }
- }
- writeln!(sink, "//! ```")?;
-
- // Recurse.
- let mut found_subcommands = false;
- for subcmd in help.split('\n').filter_map(move |line| {
- if line == "SUBCOMMANDS:" {
- found_subcommands = true;
- None
- } else if found_subcommands {
- if line.chars().nth(4).map(|c| ! c.is_ascii_whitespace())
- .unwrap_or(false)
- {
- line.trim_start().split(' ').next()
- } else {
- None
- }
- } else {
- None
- }
- }).filter(|subcmd| *subcmd != "help") {
- let mut c = cmd.clone();
- c.push(subcmd.into());
- dump_help(sink, sqv, c, &format!("{}#", heading))?;
- }
-
- Ok(())
-}
diff --git a/sqv/src/sqv-usage.rs b/sqv/src/sqv-usage.rs
deleted file mode 100644
index 1838d6cd..00000000
--- a/sqv/src/sqv-usage.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-//! A command-line frontend for Sequoia.
-//!
-//! # Usage
-//!
-//! ```text
-//! sqv is a command-line OpenPGP signature verification tool.
-//!
-//! USAGE:
-//! sqv [FLAGS] [OPTIONS] <SIG-FILE> <FILE> --keyring <FILE>...
-//!
-//! FLAGS:
-//! -h, --help Prints help information
-//! -V, --version Prints version information
-//! -v, --verbose Be verbose.
-//!
-//! OPTIONS:
-//! --keyring <FILE>... A keyring. Can be given multiple times.
-//! --not-after <TIMESTAMP>
-//! Consider signatures created after TIMESTAMP as invalid. If a date
-//! is given, 23:59:59 is used for the time.
-//! [default: now]
-//! --not-before <TIMESTAMP>
-//! Consider signatures created before TIMESTAMP as invalid. If a date
-//! is given, 00:00:00 is used for the time.
-//! [default: no constraint]
-//! -n, --signatures <N>
-//! The number of valid signatures to return success. Default: 1
-//!
-//!
-//! ARGS:
-//! <SIG-FILE> File containing the detached signature.
-//! <FILE> File to verify.
-//!
-//! TIMESTAMPs must be given in ISO 8601 format (e.g. '2017-03-04T13:25:35Z', '2017-
-//! 03-04T13:25', '20170304T1325+0830', '2017-03-04', '2017031', ...). If no
-//! timezone is specified, UTC is assumed.
-//! ```
-
-#![doc(html_favicon_url = "https://docs.sequoia-pgp.org/favicon.png")]
-#![doc(html_logo_url = "https://docs.sequoia-pgp.org/logo.svg")]
-
-include!("sqv.rs");
diff --git a/sqv/src/sqv.rs b/sqv/src/sqv.rs
deleted file mode 100644
index 08beef3c..00000000
--- a/sqv/src/sqv.rs
+++ /dev/null
@@ -1,367 +0,0 @@
-/// A simple signature verification program.
-///
-/// See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=872271 for
-/// the motivation.
-
-use std::process::exit;
-
-use chrono::{DateTime, offset::Utc};
-use anyhow::Context;
-
-use sequoia_openpgp as openpgp;
-
-use crate::openpgp::{
- Cert,
- KeyHandle,
- Result,
- parse::Parse,
-};
-use crate::openpgp::parse::stream::{
- DetachedVerifierBuilder,
- MessageLayer,
- MessageStructure,
- VerificationHelper,
- GoodChecksum,
- VerificationError,
-};
-use crate::openpgp::cert::prelude::*;
-use crate::openpgp::policy::StandardPolicy as P;
-
-mod sqv_cli;
-
-struct VHelper<'a> {
- not_before: Option<std::time::SystemTime>,
- not_after: std::time::SystemTime,
-
- good: usize,
- total: usize,
- threshold: usize,
-
- keyrings: clap::OsValues<'a>,
-}
-
-impl<'a> std::fmt::Debug for VHelper<'a> {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- f.debug_struct("VHelper")
- .field("not_before", &self.not_before)
- .field("not_after", &self.not_after)
- .field("good", &self.good)
- .field("total", &self.total)
- .field("threshold", &self.threshold)
- .field("keyrings", &self.keyrings)
- .finish()
- }
-}
-
-impl<'a> VHelper<'a> {
- fn new(threshold: usize,
- not_before: Option<std::time::SystemTime>,
- not_after: std::time::SystemTime,
- keyrings: clap::OsValues<'a>) -> Self {
- VHelper {
- not_before: not_before,
- not_after: not_after,
- good: 0,
- total: 0,
- threshold: threshold,
- keyrings: keyrings,
- }
- }
-}
-
-impl<'a> VerificationHelper for VHelper<'a> {
- fn get_certs(&mut self, ids: &[crate::KeyHandle]) -> Result<Vec<Cert>> {
- let mut certs = Vec::with_capacity(ids.len());
-
- // Load relevant keys from the keyring.
- for filename in self.keyrings.clone() {
- for cert in CertParser::from_file(filename)
- .with_context(|| format!("Failed to parse keyring {:?}",
- filename))?
- .unvalidated_cert_filter(|cert, _| {
- // We don't skip keys that are valid (not revoked,
- // alive, etc.) so that
- cert.keys().key_handles(ids.iter()).next().is_some()
- })
- {
- certs.push(cert.with_context(|| {
- format!("Malformed certificate in keyring {:?}", filename)
- })?);
- }
- }
-
- // Dedup. To avoid cloning the certificates, we don't use
- // Vec::dedup.
- certs.sort_by(|a, b| a.fingerprint().cmp(&b.fingerprint()));
- let count = certs.len();
- let (certs, errs) = certs.into_iter().fold(
- (Vec::with_capacity(count), Vec::new()),
- |(mut certs, mut errs), a| {
- if certs.is_empty() {
- certs.push(a);
- } else if certs[certs.len() - 1].fingerprint() == a.fingerprint() {
- // Merge `a` into the last element.
- match certs.pop().expect("non-empty vec").merge_public(a) {
- Ok(cert) => certs.push(cert),
- Err(err) => errs.push(err),
- }
- } else {
- certs.push(a);
- }
-
- (certs, errs)
- });
-
- if !errs.is_empty() {
- eprintln!("Error merging duplicate keys:");
- for err in errs.iter() {
- eprintln!(" {}", err);
- }
- Err(errs.into_iter().next().expect("non-empty vec"))
- } else {
- Ok(certs)
- }
- }
-
- fn check(&mut self, structure: MessageStructure) -> Result<()> {
- use self::VerificationError::*;
-
- let mut signers = Vec::with_capacity(2);
- let mut verification_err = None;
-
- for layer in structure.into_iter() {
- match layer {
- MessageLayer::SignatureGroup { results } =>
- for result in results {
- self.total += 1;
- match result {
- Ok(GoodChecksum { sig, ka, .. }) => {
- match (sig.signature_creation_time(),
- self.not_before,
- self.not_after)
- {
- (None, _, _) => {
- eprintln!("Malformed signature:");
- print_error_chain(&anyhow::anyhow!(
- "no signature creation time"));
- },
- (Some(t), Some(not_before), not_after) => {
- if t < not_before {
- eprintln!(
- "Signature by {:X} was created before \
-