diff --git a/.gitignore b/.gitignore index 806fe1e..4a773d9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /pgpcontrol-*.tar.xz* /pgpverify.8 /staging/ +/tests/tmp/ diff --git a/README.sequoia.md b/README.sequoia.md new file mode 100644 index 0000000..eab1b08 --- /dev/null +++ b/README.sequoia.md @@ -0,0 +1,63 @@ +**Experimental** support for [Sequoia PGP](https://sequoia-pgp.org/) in authentication of Usenet control messages. + +Usage in production is not recommended, especially for verification. +Code reviews, comments and feedback from hierarchy admins and news server admins +are welcome. + +Developed with `sequoia-sq` 1.0.0 installed with `cargo` on Debian "trixie". + +If you are new to Sequoia PGP command line, please see [user guide](https://sequoia-pgp.gitlab.io/user-documentation/about_sequoia.html) +and [manpages](https://sequoia-pgp.gitlab.io/sequoia-sq/man/sq.1.html). + +# Using sequoia for signing + +Import (`sq key import`) your secret signing key in the sequoia keystore. +Old PGP 2.x keys are not supported, if you still use such a key please upgrade to +a modern key. + +Then, edit `signcontrol` as follows + +``` +my $pgpsigner = 'INSERT_YOUR_FINGERPRINT_OR_USERID'; + +# Path to sequoia-sq executable. +# A version that supports CLI 1.0.0 is required +# The program name needs to end in sq +my $pgp = "/usr/local/bin/sq"; + +# set other configuration variables as usual +``` + +# Using sequoia for verification + +Import (`sq cert import`), verify and trust (`sq pki link add`) hierarchy admins +public signing keys in the sequoia certificate store (see [PGPKEYS](https://ftp.isc.org/pub/pgpcontrol/PGPKEYS) +in the ISC ftp site). +Please note that many hierarchy admins still use old PGP 2.x keys. These keys +have been deprecated since 2007 (RFC 4880) and are not supported by Sequoia or +other modern OpenPGP implementations. We urge hierarchy administrators to update +their signing keys. + +Then, edit `pgpverify` as follows + +``` +# Path to sequoia binary. +# A version that supports CLI 1.0.0 is required +$sq = '/usr/local/bin/sq'; + +# Set this if you want to support old signatures with +# MD5 or SHA-1 digest algorithms and/or RSA < 2048 bits +# See the `sq config inspect policy' command and the +# `--policy-as-of' flag in the sq manpage +# Please note that sequoia DOES NOT support old PGP 2.x +# keys. +# $sq_policy_as_of = '19970101'; + +# comment $gpg, $gpgv and $pgp lines + +# Set the absolute path to your sequoia home directory +# (see the --home flag in sq manpage) +$keyring = '/path/to/your/sq/home'; + +# set other configuration variables as usual +``` \ No newline at end of file diff --git a/pgpverify b/pgpverify index 464ee64..64e0bf0 100755 --- a/pgpverify +++ b/pgpverify @@ -6,6 +6,9 @@ # Currently maintained by Russ Allbery # Version 1.30, 2018-01-21 # +# sequoia-sq support written in December 2024 by +# Fabrizio Tarizzo +# # NOTICE TO INN MAINTAINERS: The version that is shipped with INN is the # same as the version that I make available to the rest of the world # (including non-INN sites), so please make all changes through me. @@ -138,6 +141,16 @@ # -- Checks to ensure that the temporary file is really a file, and # not a link or some other weirdness. +# Path to sequoia binary. Requires a version that supports CLI 1.0.0 +# $sq = '/usr/local/bin/sq'; + +# Set this if you want to support old signatures with MD5 and SHA-1 +# digest algorithms and/or RSA < 2048 bits. +# See the `sq config inspect policy' command and the `--policy-as-of' +# flag in the sq manpage +# Please note that sequoia DOES NOT support PGP 2.x keys. +# $sq_policy_as_of = '19970101'; + # Path to the GnuPG gpg binary, if you have GnuPG and don't want to use # gpgv. This will be used in preference to gpgv and PGP. If you have INN # and the script is able to successfully include your INN::Config module, @@ -156,7 +169,7 @@ # Path to pgp binary; for PGP 5.0, set the path to the pgpv binary. If # you have INN and the script is able to successfully include your # INN::Config module, the value of $INN::Config::pgp will override this. -$pgp = '/usr/local/bin/pgp'; +# $pgp = '/usr/local/bin/pgp'; # If you keep your keyring somewhere that is not the default used by pgp, # uncomment the next line and set appropriately. If you have INN and the @@ -164,6 +177,9 @@ $pgp = '/usr/local/bin/pgp'; # will be set to $INN::Config::newsetc/pgp if that directory exists unless # you set it explicitly. GnuPG will use a file named pubring.gpg in this # directory. +# With sequoia, you can use a single keyring file or the absolute path +# to the sequoia home directory. See `--home' and `--signer-file' flags +# in sequoia man pages. # $keyring = '/path/to/your/pgp/config'; # If you have INN and the script is able to successfully include your @@ -220,7 +236,7 @@ $log_date = -t STDOUT; # Do it if STDOUT is to a terminal. require 5; use strict; -use vars qw($gpg $gpgv $pgp $keyring $tmp $tmpdir $lockdir $syslog_method +use vars qw($sq $sq_policy_as_of $gpg $gpgv $pgp $keyring $tmp $tmpdir $lockdir $syslog_method $syslog_facility $syslog_level $log_date $findid $test $messageid); use Fcntl qw(O_WRONLY O_CREAT O_EXCL); @@ -239,6 +255,7 @@ GetOptions( ) or die "Usage: $0 [--findid='string'] [--test] < message\n"; # Grab various defaults from INN::Config if running inside INN. +$sq = $INN::Config::sq if $INN::Config::sq; $pgp = $INN::Config::pgp if $INN::Config::pgp && $INN::Config::pgp ne "no-pgp-found-during-configure"; $gpgv = $INN::Config::gpgv if $INN::Config::gpgv; @@ -254,7 +271,11 @@ if (! $keyring && $INN::Config::newsetc) { $0 =~ s%^.*/%%; # Make sure that the signature verification program can be executed. -if ($gpg) { +if ($sq) { + if (! -x $sq) { + &fail("$0: $sq: " . (-e _ ? "cannot execute" : "no such file") . "\n"); + } +} elsif ($gpg) { if (! -x $gpg) { &fail("$0: $gpg: " . (-e _ ? "cannot execute" : "no such file") . "\n"); } @@ -281,7 +302,7 @@ if ($test) { # should, and the consequences of a multiprocess conflict is failure to # verify. my $lock; -unless ($gpg or $gpgv) { +unless ($sq or $gpg or $gpgv) { $lock = "$lockdir/LOCK.$0"; until (&shlock($lock) > 0) { sleep(2); @@ -290,7 +311,7 @@ unless ($gpg or $gpgv) { # Verify the message. my ($ok, $signer) = pgp_verify($signature, $version, $message); -unless ($gpg or $gpgv) { +unless ($sq or $gpg or $gpgv) { unlink ($lock) or &errmsg("$0: unlink $lock: $!\n"); } print "$signer\n" if $signer; @@ -411,7 +432,7 @@ sub pgp_verify { local $SIG{PIPE} = 'IGNORE'; # Set the PGP style based on whether $gpg or $gpgv is set. - my $pgpstyle = ($gpg || $gpgv ? 'GPG' : 'PGP2'); + my $pgpstyle = ($sq || $gpg || $gpgv ? 'GPG' : 'PGP2'); # Because this is a detached signature, we actually need to save both # the signature and the data to files and then run PGP on the signature @@ -460,7 +481,9 @@ sub pgp_verify { # Figure out what command line we'll be using. my @command; - if ($pgpstyle eq 'GPG') { + if ($sq) { + @command = ($sq, qw/verify --quiet/); + } elsif ($pgpstyle eq 'GPG') { if ($gpg) { @command = ($gpg, qw/--verify --allow-weak-digest-algos/); push (@command, qw/--quiet --status-fd=1 --logger-fd=1/); @@ -482,19 +505,36 @@ sub pgp_verify { # definitely not the logic that I would use if writing this from # scratch, but it has the most backward compatibility. local $ENV{PGPPATH} = $keyring if ($keyring && $pgpstyle ne 'GPG'); - if ($pgpstyle eq 'GPG') { + + if ($sq) { if ($keyring) { - push (@command, "--keyring=$keyring/pubring.gpg"); - } else { - my $home = $ENV{GNUPGHOME} || $ENV{HOME}; - $home .= '/.gnupg' if $home; - if ($home && ! -s "$home/trustedkeys.gpg" && -f "$home/pubring.gpg") { - push (@command, "--keyring=pubring.gpg"); + if (-f $keyring) { + push (@command, "--signer-file=$keyring"); + } elsif (-d $keyring) { + push (@command, "--home=$keyring"); } } + if ($sq_policy_as_of) { + push (@command, "--policy-as-of=$sq_policy_as_of"); + } + + push (@command, "--signature-file=$filename.asc"); + push (@command, $filename); + } else { + if ($pgpstyle eq 'GPG') { + if ($keyring) { + push (@command, "--keyring=$keyring/pubring.gpg"); + } else { + my $home = $ENV{GNUPGHOME} || $ENV{HOME}; + $home .= '/.gnupg' if $home; + if ($home && ! -s "$home/trustedkeys.gpg" && -f "$home/pubring.gpg") { + push (@command, "--keyring=pubring.gpg"); + } + } + } + push (@command, "$filename.asc"); + push (@command, $filename); } - push (@command, "$filename.asc"); - push (@command, $filename); my $input = new FileHandle; my $output = new FileHandle; my $pid = eval { open3 ($input, $output, $output, @command) }; @@ -519,6 +559,8 @@ sub pgp_verify { # Good signature made 1999-02-10 03:29 GMT by key: # 1024 bits, Key ID 0AFC7476, Created 1999-02-10 # "Russ Allbery " + # sequoia 1.0.0: + # Authenticated signature made by KEY_FINGERPRINT (USER_ID (authenticated)) # # Also, PGP v2 prints out "Bad signature" while PGP v5 uses "BAD # signature", and PGP v6 reverts back to "Bad signature". @@ -528,7 +570,19 @@ sub pgp_verify { my $ok = 255; while (<$output>) { print if $test; - if ($pgpstyle eq 'GPG') { + if ($sq) { + if (/Authenticated signature made by (\S+) \((.+)\s+.+\)/) { + $ok = 0; + $signer = $2; + } elsif (/missing certificate/) { + $ok = 2; + last; + } elsif (/Error/) { + # TODO check various error and edge cases + $ok = 3; + last; + } + } elsif ($pgpstyle eq 'GPG') { if (/\[GNUPG:\]\s+GOODSIG\s+\S+\s+(\S+)/) { $ok = 0; $signer = $1; diff --git a/signcontrol b/signcontrol index 9e5ff55..3d8cd61 100755 --- a/signcontrol +++ b/signcontrol @@ -3,6 +3,9 @@ # Currently maintained by Russ Allbery # Version 1.9, 2016-10-17 # +# sequoia-sq support written in December 2024 by +# Fabrizio Tarizzo +# # Changes from 1.8 -> 1.9 # -- Add use strict and explicitly import LOCK_EX. # -- Fix error reporting around lock files with PGP. @@ -51,6 +54,8 @@ use strict; # # $pgp can be set to the path to GnuPG to use GnuPG instead. The program # name needs to end in gpg so that signcontrol knows GnuPG is being used. +# $pgp can be set to the path to sq to use sequoia. The program name needs +# to end in sq so that signcontrol knows sequoia is being used. # # STORING YOUR PASSPHRASE IN A FILE IS A POTENTIAL SECURITY HOLE. # Make sure you know what you're doing if you do it. @@ -58,6 +63,7 @@ use strict; # If you DO use $pgppassfile, it is possible that someone could steal # your passphrase either by gaining access to the file or by seeing # the environment of a running pgpverify program. +# $pgppassfile IS NOT currently supported by sequoia # # $pgplock is used because pgp does not guard itself against concurrent # read/write access to its randseed.bin file. A writable file is needed; @@ -68,7 +74,7 @@ use strict; # this. my $pgpsigner = 'INSERT_YOUR_PGP_USERID'; my $pgppassfile = ''; # file with pass phrase for $pgpsigner -my $pgp = "/usr/local/bin/pgp"; +my $pgp = "/usr/local/bin/sq"; my $pgpheader = "X-PGP-Sig"; my $pgplock = (getpwuid($<))[7] . '/.pgp/config.txt'; @@ -182,7 +188,7 @@ die "Usage: $0 < message\n" if @ARGV > 0; my $LOCK; umask(0022); # flock needs a writable file, if we create it -if ($pgp !~ /gpg$/) { +if ($pgp !~ /gpg$/ && $pgp !~ /sq$/) { open ($LOCK, '>>', $pgplock) || die "$0: open $pgplock: $!, exiting\n"; flock ($LOCK, LOCK_EX); # block until locked } @@ -212,7 +218,7 @@ if ($die) { signit(); -if ($pgp !~ /gpg$/) { +if ($pgp !~ /gpg$/ && $pgp !~ /sq$/) { close ($LOCK) || warn "$0: close $pgplock: $!\n"; } exit 0; @@ -411,15 +417,35 @@ sub pgp_sign { # Determine the PGP style. my $pgpstyle = 'PGP2'; - if ($pgp =~ /pgps$/) { $pgpstyle = 'PGP5' } - elsif ($pgp =~ /gpg$/) { $pgpstyle = 'GPG' } + if ($pgp =~ /pgps$/) { $pgpstyle = 'PGP5' } + elsif ($pgp =~ /gpg$/) { $pgpstyle = 'GPG' } + elsif ($pgp =~ /sq$/) { $pgpstyle = 'SEQUOIA' } # Figure out what command line we'll be using. PGP v6 and PGP v2 use # compatible syntaxes for what we're trying to do. PGP v5 would have, # except that the -s option isn't valid when you call pgps. *sigh* my @command; + my $versioncommand; + if ($pgpstyle eq 'PGP5') { @command = ($pgp, qw/-baft -u/, $keyid); + } elsif ($pgpstyle eq 'SEQUOIA') { + @command = ($pgp, "sign"); + + # Check if $keyid looks like a long Key ID (16 hex digits) + # or a key fingerprint (40 hex digits for RFC 4880 keys and + # 64 hex digits for RFC 9580 keys) + # Short (8 hex digits) Key IDs are deprecated and not supported + my $len = length($keyid); + if ($keyid =~ /^[0-9A-F]+$/ and grep /^$len$/, qw(16 40 64)) { + push (@command, "--signer=$keyid"); + } else { + # otherwise treat it as a User ID + push (@command, "--signer-userid=$keyid"); + } + + push (@command, "--signature-file=-"); + $versioncommand = "$pgp version"; } elsif ($pgpstyle eq 'GPG') { @command = ($pgp, qw/--detach-sign --armor --textmode -u/, $keyid, qw/--force-v3-sigs --pgp2/); @@ -449,6 +475,8 @@ sub pgp_sign { close $writefh; if ($pgpstyle eq 'GPG') { push (@command, '--batch', '--passphrase-fd', $passfh->fileno); + } elsif ($pgpstyle eq 'SEQUOIA') { + # Currently unsupported } else { push (@command, '+batchmode'); $ENV{PGPPASSFD} = $passfh->fileno; @@ -501,6 +529,16 @@ sub pgp_sign { while ($signature[0] ne "\n" && @signature) { $version = $1 if ((shift @signature) =~ /^Version:\s+(.*?)\s*$/); } + + # sequoia does not add the Version header in armored output, + # as per RFC 9580 section 6.2.2.1 + if ($pgpstyle eq 'SEQUOIA') { + my @version = qx/$versioncommand 2>&1/; + $version = shift @version; + chomp $version; + $version =~ s/\s+/_/; + } + shift @signature; pop @signature; $signature = join '', @signature; diff --git a/tests/keyring/.cvsignore b/tests/keyring/.cvsignore index ad06c77..6ef77f1 100644 --- a/tests/keyring/.cvsignore +++ b/tests/keyring/.cvsignore @@ -1,2 +1,4 @@ trustdb.gpg random_seed +tofu.db +*.gpg~ \ No newline at end of file diff --git a/tests/keyring/.gitignore b/tests/keyring/.gitignore new file mode 100644 index 0000000..6ef77f1 --- /dev/null +++ b/tests/keyring/.gitignore @@ -0,0 +1,4 @@ +trustdb.gpg +random_seed +tofu.db +*.gpg~ \ No newline at end of file diff --git a/tests/keyring/pubring.gpg b/tests/keyring/pubring.gpg index 75bf809..25edeae 100644 Binary files a/tests/keyring/pubring.gpg and b/tests/keyring/pubring.gpg differ diff --git a/tests/keyring/sq/big8-cert.asc b/tests/keyring/sq/big8-cert.asc new file mode 100644 index 0000000..2c04e76 --- /dev/null +++ b/tests/keyring/sq/big8-cert.asc @@ -0,0 +1,66 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=oDzt +-----END PGP PUBLIC KEY BLOCK----- \ No newline at end of file diff --git a/tests/keyring/sq/home/data/keystore/keystore.cookie b/tests/keyring/sq/home/data/keystore/keystore.cookie new file mode 100644 index 0000000..e69de29 diff --git a/tests/keyring/sq/home/data/keystore/softkeys/4C5EC64E1D6FAD6CE2CE417B11183ACF87D87F73.pgp b/tests/keyring/sq/home/data/keystore/softkeys/4C5EC64E1D6FAD6CE2CE417B11183ACF87D87F73.pgp new file mode 100644 index 0000000..2894a70 Binary files /dev/null and b/tests/keyring/sq/home/data/keystore/softkeys/4C5EC64E1D6FAD6CE2CE417B11183ACF87D87F73.pgp differ diff --git a/tests/keyring/sq/home/data/pgp.cert.d/4c/5ec64e1d6fad6ce2ce417b11183acf87d87f73 b/tests/keyring/sq/home/data/pgp.cert.d/4c/5ec64e1d6fad6ce2ce417b11183acf87d87f73 new file mode 100644 index 0000000..c88aa9f Binary files /dev/null and b/tests/keyring/sq/home/data/pgp.cert.d/4c/5ec64e1d6fad6ce2ce417b11183acf87d87f73 differ diff --git a/tests/keyring/sq/home/data/pgp.cert.d/66/671371bfe381948952bfa5347293acbec1ee3c b/tests/keyring/sq/home/data/pgp.cert.d/66/671371bfe381948952bfa5347293acbec1ee3c new file mode 100644 index 0000000..0a4c13d Binary files /dev/null and b/tests/keyring/sq/home/data/pgp.cert.d/66/671371bfe381948952bfa5347293acbec1ee3c differ diff --git a/tests/keyring/sq/home/data/pgp.cert.d/8e/181bef0be638962c1a5c98fafe7b550c18c8b7 b/tests/keyring/sq/home/data/pgp.cert.d/8e/181bef0be638962c1a5c98fafe7b550c18c8b7 new file mode 100644 index 0000000..43d8bd1 Binary files /dev/null and b/tests/keyring/sq/home/data/pgp.cert.d/8e/181bef0be638962c1a5c98fafe7b550c18c8b7 differ diff --git a/tests/keyring/sq/home/data/pgp.cert.d/9f/7d81a66c202e74b9f3bf9e4dccd390d8a1cedd b/tests/keyring/sq/home/data/pgp.cert.d/9f/7d81a66c202e74b9f3bf9e4dccd390d8a1cedd new file mode 100644 index 0000000..cca8fa2 Binary files /dev/null and b/tests/keyring/sq/home/data/pgp.cert.d/9f/7d81a66c202e74b9f3bf9e4dccd390d8a1cedd differ diff --git a/tests/keyring/sq/home/data/pgp.cert.d/_sequoia_ca_generated_on_debiantesting.pgp b/tests/keyring/sq/home/data/pgp.cert.d/_sequoia_ca_generated_on_debiantesting.pgp new file mode 100644 index 0000000..474b3e3 Binary files /dev/null and b/tests/keyring/sq/home/data/pgp.cert.d/_sequoia_ca_generated_on_debiantesting.pgp differ diff --git a/tests/keyring/sq/home/data/pgp.cert.d/_sequoia_cert_store_index_v1_on_debiantesting.sqlite b/tests/keyring/sq/home/data/pgp.cert.d/_sequoia_cert_store_index_v1_on_debiantesting.sqlite new file mode 100644 index 0000000..b1e265e Binary files /dev/null and b/tests/keyring/sq/home/data/pgp.cert.d/_sequoia_cert_store_index_v1_on_debiantesting.sqlite differ diff --git a/tests/keyring/sq/home/data/pgp.cert.d/_sequoia_signature_verification_cache_v1_on_debiantesting.sqlite b/tests/keyring/sq/home/data/pgp.cert.d/_sequoia_signature_verification_cache_v1_on_debiantesting.sqlite new file mode 100644 index 0000000..22f04ef Binary files /dev/null and b/tests/keyring/sq/home/data/pgp.cert.d/_sequoia_signature_verification_cache_v1_on_debiantesting.sqlite differ diff --git a/tests/keyring/sq/home/data/pgp.cert.d/trust-root b/tests/keyring/sq/home/data/pgp.cert.d/trust-root new file mode 100644 index 0000000..aae05da Binary files /dev/null and b/tests/keyring/sq/home/data/pgp.cert.d/trust-root differ diff --git a/tests/keyring/sq/home/data/pgp.cert.d/writelock b/tests/keyring/sq/home/data/pgp.cert.d/writelock new file mode 100644 index 0000000..e69de29 diff --git a/tests/keyring/sq/home/data/revocation-certificates/4C5EC64E1D6FAD6CE2CE417B11183ACF87D87F73-revocation.pgp b/tests/keyring/sq/home/data/revocation-certificates/4C5EC64E1D6FAD6CE2CE417B11183ACF87D87F73-revocation.pgp new file mode 100644 index 0000000..6ab198a --- /dev/null +++ b/tests/keyring/sq/home/data/revocation-certificates/4C5EC64E1D6FAD6CE2CE417B11183ACF87D87F73-revocation.pgp @@ -0,0 +1,13 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: Revocation certificate for +Comment: 4C5E C64E 1D6F AD6C E2CE 417B 1118 3ACF 87D8 7F73 +Comment: testing.sq + +xjMEZ2XGvBYJKwYBBAHaRw8BAQdABPRDA8MB8vnczQ9O1bF4D8bWXnBRkGUYVCtJ +IewW5UfCwAsEIBYKAH0FgmdlxrwJEBEYOs+H2H9zRxQAAAAAAB4AIHNhbHRAbm90 +YXRpb25zLnNlcXVvaWEtcGdwLm9yZxtwDQ7X27b4KkX75l/HvAesAAG9BsVnloc6 +aIsvZy1PDR0AVW5zcGVjaWZpZWQWIQRMXsZOHW+tbOLOQXsRGDrPh9h/cwAAIcwB +AN1vmQTw5KzVGfnNi/ZnuU6F9YkVDvDvbUOCNaJG59VbAQDF1Yy6i87tnSrfP41S +wOh2uhVNDSiZEiYeHQSYZHlcBg== +=Nx89 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/keyring/sq/passphrase b/tests/keyring/sq/passphrase new file mode 100644 index 0000000..9a2c773 --- /dev/null +++ b/tests/keyring/sq/passphrase @@ -0,0 +1 @@ +testing \ No newline at end of file diff --git a/tests/keyring/sq/testing-sq-cert.asc b/tests/keyring/sq/testing-sq-cert.asc new file mode 100644 index 0000000..6c4fb89 --- /dev/null +++ b/tests/keyring/sq/testing-sq-cert.asc @@ -0,0 +1,29 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +xjMEZ2XGvBYJKwYBBAHaRw8BAQdABPRDA8MB8vnczQ9O1bF4D8bWXnBRkGUYVCtJ +IewW5UfCwAsEHxYKAH0FgmdlxrwDCwkHCRARGDrPh9h/c0cUAAAAAAAeACBzYWx0 +QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmeF1xwMrlzXh3unYC/hze7aNLSmoIIz +9ShPD68V1i4azAMVCggCmwECHgEWIQRMXsZOHW+tbOLOQXsRGDrPh9h/cwAAOBwB +AOgHwyBu28L963UdswAaRRatBz0wdG6zpFT0G7od3RVvAQCWHVCU2AFMRkGFfD4U +dm46hLThiXntrTDXsdx12eOGB80KdGVzdGluZy5zccLADgQTFgoAgAWCZ2XGvAML +CQcJEBEYOs+H2H9zRxQAAAAAAB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEtcGdw +Lm9yZ6zdefq40SPGB8RvYhZ0+7wA50WPuTc+1lA3qSdIfcubAxUKCAKZAQKbAQIe +ARYhBExexk4db61s4s5BexEYOs+H2H9zAACKeQD/SehQU+t1WOR+Gs3lQHT+UD2C +2ZGFfbLBELSE+cYsMgoBAK+T8Qdx6CEK07zUtfJXslqR1S3HvYZuQGiA/d5UsEwN +zjMEZ2XGvBYJKwYBBAHaRw8BAQdARYzhpGcUffzURCk8XfMdtqr/p/fGD0NHbNZo +ZEMRdYDCwL8EGBYKATEFgmdlxrwJEBEYOs+H2H9zRxQAAAAAAB4AIHNhbHRAbm90 +YXRpb25zLnNlcXVvaWEtcGdwLm9yZ3wLL4vyWIYOLLbgJozwq3Rf57mla5BLBVAX +8Mw/0PLHApsCvqAEGRYKAG8FgmdlxrwJEAqBASI4QwmGRxQAAAAAAB4AIHNhbHRA +bm90YXRpb25zLnNlcXVvaWEtcGdwLm9yZyFklqyDpRDbJ47ArbCUrEJOlR6jRu2Y +rPBnqKJMDByqFiEEOWYN7+uB2H6FXwUdCoEBIjhDCYYAAOxLAP96sDjqESfEZVAi +IzinBRxvpJN9bAtEx+0lUsVppN+xCgEAqpG38iIRXw718AVaTZzGGBjAH6eGbUyU +iFOWeSFxywoWIQRMXsZOHW+tbOLOQXsRGDrPh9h/cwAAnsEBAIrdznoudNPXvanj +/BMd7uXLt0zPxQqSW+VY9x39gIM4AQDqSQBtI5syYdvzLFuIneBu+mKUo2lJ7VNk +WhwMSLEnAM44BGdlxrwSCisGAQQBl1UBBQEBB0DnHwWDChPdDLmSAGSoi9PQCY3W +IqPmgwN8AOt0mXDLewMBCAfCwAAEGBYKAHIFgmdlxrwJEBEYOs+H2H9zRxQAAAAA +AB4AIHNhbHRAbm90YXRpb25zLnNlcXVvaWEtcGdwLm9yZ+XVxtgFzdgHDLSXNAd5 +XPrRmViNruVrTkt1bw0tVHWZApsMFiEETF7GTh1vrWzizkF7ERg6z4fYf3MAAN0B +AP9QiCpKYdf7yxxeLYybmLg66i5MxkV05qs/9SNyR9dgNwD/UC5IjShHr3t201Op +d12Q+13lrJ8vczSrMXy6cDKLJgo= +=aHt9 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/messages/comp.lang.go-corrupted.newgroup b/tests/messages/comp.lang.go-corrupted.newgroup new file mode 100644 index 0000000..5e1743a --- /dev/null +++ b/tests/messages/comp.lang.go-corrupted.newgroup @@ -0,0 +1,40 @@ +Path: news.eyrie.org!bounce-back +From: group-admin@isc.org +Newsgroups: comp.lang.go +Subject: cmsg newgroup comp.lang.go +Control: newgroup comp.lang.go +Approved: group-admin@isc.org +Date: Thu, 09 Nov 2023 13:00:02 -0800 +Message-ID: +X-Info: https://www.big-8.org/ + https://www.eyrie.org/~eagle/big-8/ +X-PGP-Sig: GnuPG Subject,Control,Message-ID,Date,From,Sender + iQIzBAEBCgAdFiEEjhgb7wvmOJYsGlyY+v57VQwYyLcFAmVNSFMACgkQ+v57VQwY + yLdG4g//bjHd8neeT+TV/wnJSaKRYHybfkrtzMtEOY9FrlXcMt/AjQLC2oJ0aS9u + l6TM04hfVuVCNYKyflOEYCpW0/9ei0yxr0JEATBsFdLN8fppEYzn5ziCxkLgDokN + JFt1oiAok4YbJ7H/4YXM4R8RcHThPVtpWhMI4pMzBwF4pOsgb6hYmiPwJBux0Bgd + pi74e5pFlrDB8tMoZetGvSSlH2qQTTUbZjd7qJJr6HqMFfIlSGWmw61rWMSehcQp + YCNW3ibbkJ4zPlfs+Q/5KbGobbyZ9fWl/sgHvZ3p8qJZHzqCtjeHyXNP3Q2BIiaj + kgdmJ6ZggQNNEEU/pupRIR4WpEjGZTRFDBGBa+5J1yQsV0FWSDyMpmvCkjlCoOhh + RMVs+YroSiEQxAYsYE7zFZok763MSiKQw00uvKR0gwd/Ov4QbC53AGZHKmW2Q8O+ + m80AmKWa6YOaVFPgaou4TI+1qrTe0Hb/+72wT+Ep730JSuiJYQ+XZ/nZqsjegvV7 + qPr2SpnWH43cSNi2MNBCPcWNGqVRUYxXfD2bouoS+9VACx9jkIgK8I8MleryXCwa + A6hs0T/+i/FqcNlwC/ZBxiKwjSzg8Vj90cteSjY+5ovTZOb5xCNtEbp4Pm3hbgeT + Qjtl738/hxyZUmgTEVzBv2CBahJ1ICkiYgzFa19WaIhAsDm4Mns= + =qThC +Xref: news.eyrie.org control.newgroup:100 + +*CORRUPTED* +The Last Call for Comments (LCC) on 2023-09-25 initiated a five-day +period for final comments. Following this comment period, the Big-8 +Management Board voted to create the unmoderated newsgroup comp.lang.go. +The vote was 2 in favour and 0 opposed. One member did not vote. + +For your newsgroups file: +comp.lang.go The Go programming language (Golang). + +CHARTER: + +comp.lang.go will be a unmoderated group where people interested in the +Go programming language can share ideas and topics, help each other, and +keep up with interesting projects. diff --git a/tests/messages/comp.lang.go.newgroup b/tests/messages/comp.lang.go.newgroup new file mode 100644 index 0000000..b58ff71 --- /dev/null +++ b/tests/messages/comp.lang.go.newgroup @@ -0,0 +1,39 @@ +Path: news.eyrie.org!bounce-back +From: group-admin@isc.org +Newsgroups: comp.lang.go +Subject: cmsg newgroup comp.lang.go +Control: newgroup comp.lang.go +Approved: group-admin@isc.org +Date: Thu, 09 Nov 2023 13:00:02 -0800 +Message-ID: +X-Info: https://www.big-8.org/ + https://www.eyrie.org/~eagle/big-8/ +X-PGP-Sig: GnuPG Subject,Control,Message-ID,Date,From,Sender + iQIzBAEBCgAdFiEEjhgb7wvmOJYsGlyY+v57VQwYyLcFAmVNSFMACgkQ+v57VQwY + yLdG4g//bjHd8neeT+TV/wnJSaKRYHybfkrtzMtEOY9FrlXcMt/AjQLC2oJ0aS9u + l6TM04hfVuVCNYKyflOEYCpW0/9ei0yxr0JEATBsFdLN8fppEYzn5ziCxkLgDokN + JFt1oiAok4YbJ7H/4YXM4R8RcHThPVtpWhMI4pMzBwF4pOsgb6hYmiPwJBux0Bgd + pi74e5pFlrDB8tMoZetGvSSlH2qQTTUbZjd7qJJr6HqMFfIlSGWmw61rWMSehcQp + YCNW3ibbkJ4zPlfs+Q/5KbGobbyZ9fWl/sgHvZ3p8qJZHzqCtjeHyXNP3Q2BIiaj + kgdmJ6ZggQNNEEU/pupRIR4WpEjGZTRFDBGBa+5J1yQsV0FWSDyMpmvCkjlCoOhh + RMVs+YroSiEQxAYsYE7zFZok763MSiKQw00uvKR0gwd/Ov4QbC53AGZHKmW2Q8O+ + m80AmKWa6YOaVFPgaou4TI+1qrTe0Hb/+72wT+Ep730JSuiJYQ+XZ/nZqsjegvV7 + qPr2SpnWH43cSNi2MNBCPcWNGqVRUYxXfD2bouoS+9VACx9jkIgK8I8MleryXCwa + A6hs0T/+i/FqcNlwC/ZBxiKwjSzg8Vj90cteSjY+5ovTZOb5xCNtEbp4Pm3hbgeT + Qjtl738/hxyZUmgTEVzBv2CBahJ1ICkiYgzFa19WaIhAsDm4Mns= + =qThC +Xref: news.eyrie.org control.newgroup:100 + +The Last Call for Comments (LCC) on 2023-09-25 initiated a five-day +period for final comments. Following this comment period, the Big-8 +Management Board voted to create the unmoderated newsgroup comp.lang.go. +The vote was 2 in favour and 0 opposed. One member did not vote. + +For your newsgroups file: +comp.lang.go The Go programming language (Golang). + +CHARTER: + +comp.lang.go will be a unmoderated group where people interested in the +Go programming language can share ideas and topics, help each other, and +keep up with interesting projects. diff --git a/tests/sequoia-tests.pl b/tests/sequoia-tests.pl new file mode 100755 index 0000000..21ff773 --- /dev/null +++ b/tests/sequoia-tests.pl @@ -0,0 +1,153 @@ +#! /usr/bin/perl -w + +use constant VERIFY_OK => 0; +use constant VERIFY_BADDATA => 1; +use constant VERIFY_NOCERT => 2; +use constant VERIFY_BADSIG => 3; + +my $sq = '/usr/local/bin/sq'; +my $gpg = '/usr/bin/gpg'; +my $sq_home = "$ENV{'PWD'}/keyring/sq/home/"; +$ENV{SEQUOIA_HOME} = $sq_home; + +my $failed = 0; +my $tests = 0; + +sub pgpverify { + my ($file, $expected) = @_; + my $signer = `./tmp/pgpverify < $file`; + chomp $signer; + if ($? == VERIFY_OK && $signer eq $expected) { + return VERIFY_OK; + } else { + print "pgpverify exited with status ", ($? >> 8), "\n" if $? != VERIFY_OK; + print "pgpverify said the signer was $signer\n" if $signer; + return $? >> 8; + } +} + +sub fix_pgpverify { + my ($path, $keyring) = @_; + open (BASIC, "../pgpverify") or die "Can't open ../pgpverify: $!\n"; + open (FIXED, "> tmp/pgpverify") or die "Can't create pgpverify: $!\n"; + while () { + s%^\# \$sq = \'.*%\$sq = '$path';% if $path =~ /sq$/; + s%^\# \$sq_policy_as_of = \'.*%\$sq_policy_as_of = '19970101';% if $path =~ /sq$/; + s%^\# \$gpg = \'.*%\$gpg = '$path';% if $path =~ /gpg$/; + s%^\# \$keyring = \'.*%\$keyring = '$keyring';% if $keyring; + s%^\$syslog_method = \'.*%\$syslog_method = '';%; + print FIXED; + } + close BASIC; + close FIXED; + chmod (0755, 'tmp/pgpverify'); +} + +sub fix_signcontrol { + my ($path, $signer) = @_; + open (BASIC, "../signcontrol") or die "Can't open ../signcontrol: $!\n"; + open (FIXED, "> tmp/signcontrol") or die "Can't create signcontrol: $!\n"; + while () { + s/INSERT_YOUR_PGP_USERID/$signer/; + s/^my \$pgp = \".*/my \$pgp = '$path';/; + s/YOUR_ADDRESS_AND_NAME/Test Signer /; + s/ADDRESS_FOR_Approved_HEADER/test\@example.com/; + s/FULL_HOST_NAME/example.com/; + s/HIERARCHIES/example/; + print FIXED; + } + close BASIC; + close FIXED; + chmod (0755, 'tmp/signcontrol'); +} + +sub sign_verify_roundtrip_test { + my ($testname, $sign_exec, $verify_exec, $signer) = @_; + + my $signedfile = "./tmp/signed_$testname"; + fix_signcontrol ($sign_exec, $signer); + my $status = system ("./tmp/signcontrol < ./messages/newgroup > $signedfile"); + + if ($? == 0) { + print "PASS: $testname (sign)\n"; + } else { + print "signcontrol exited with status ", ($? >> 8), "\n"; + print "FAIL: $testname (sign)\n"; + $failed++; + } + $tests++; + + fix_pgpverify ($verify_exec); + if (pgpverify ($signedfile, 'testing.sq') == VERIFY_OK) { + print "PASS: $testname (verify)\n"; + } else { + print "FAIL: $testname (verify)\n"; + $failed++; + } + $tests++; +} + +fix_pgpverify ($sq); +if (pgpverify ('./messages/comp.lang.go.newgroup', 'news.announce.newgroups') == VERIFY_OK) { + print "PASS: big8 newgroup (verify from default cert store)\n"; +} else { + print "FAIL: big8 newgroup (verify from default cert store)\n"; + $failed++; +} +$tests++; + +fix_pgpverify ($sq, './keyring/sq/big8-cert.asc'); +if (pgpverify ('./messages/comp.lang.go.newgroup', 'news.announce.newgroups') == VERIFY_OK) { + print "PASS: big8 newgroup (verify from cert file)\n"; +} else { + print "FAIL: big8 newgroup (verify from cert file)\n"; + $failed++; +} +$tests++; + +fix_pgpverify ($sq, $sq_home); +if (pgpverify ('./messages/comp.lang.go.newgroup', 'news.announce.newgroups') == VERIFY_OK) { + print "PASS: big8 newgroup (verify from custom cert store)\n"; +} else { + print "FAIL: big8 newgroup (verify from custom cert store)\n"; + $failed++; +} +$tests++; + +# Corrupted message, should fail with status VERIFY_BADSIG +fix_pgpverify ($sq); +if (pgpverify ('./messages/comp.lang.go-corrupted.newgroup', 'news.announce.newgroups') == VERIFY_BADSIG) { + print "PASS: BAD big8 newgroup (verify)\n"; +} else { + print "FAIL: BAD big8 newgroup (verify)\n"; + $failed++; +} +$tests++; + +# Unknown signer, should fail with status VERIFY_NOCERT +fix_pgpverify ($sq); +if (pgpverify ('./messages/gnu', 'usenet@gnu.org') == VERIFY_NOCERT) { + print "PASS: Unknown signer (verify)\n"; +} else { + print "FAIL: Unknown signer (verify)\n"; + $failed++; +} +$tests++; + +sign_verify_roundtrip_test ('signcontrol-sq-fingerprint', $sq, $sq, '4C5EC64E1D6FAD6CE2CE417B11183ACF87D87F73'); +sign_verify_roundtrip_test ('signcontrol-sq-userid', $sq, $sq, 'testing.sq'); + +# Interoperability test - verify with GnuPG the message signed +# with sq +fix_pgpverify ($gpg, './keyring/'); +if (pgpverify ('./tmp/signed_signcontrol-sq-userid', 'testing.sq') == VERIFY_OK) { + print "PASS: Sign with sq, verify with gpg\n"; +} else { + print "FAIL: Sign with sq, verify with gpg\n"; + $failed++; +} +$tests++; + +print "\nTOTAL: Tests $tests Failed $failed\n"; + + diff --git a/tests/sequoia-tests.sh b/tests/sequoia-tests.sh new file mode 100755 index 0000000..67bddfb --- /dev/null +++ b/tests/sequoia-tests.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +if [ -d tests/tmp ]; then + rm -fR tests/tmp +fi + +echo -e "Please insert $(cat tests/keyring/sq/passphrase) as passphrase when required\n" +cd tests && mkdir tmp && ./sequoia-tests.pl \ No newline at end of file