318 lines
8.9 KiB
Perl
Executable file
318 lines
8.9 KiB
Perl
Executable file
#! /usr/bin/perl -w
|
|
$ID = q$Id$;
|
|
#
|
|
# run-tests -- Test signcontrol and pgpverify.
|
|
#
|
|
# Written by Russ Allbery <eagle@eyrie.org>
|
|
# This work is hereby placed in the public domain by its author.
|
|
|
|
use strict;
|
|
use vars qw($ID);
|
|
|
|
##############################################################################
|
|
# Test suite preparation
|
|
##############################################################################
|
|
|
|
# Find a program on the user's path.
|
|
sub find_program {
|
|
my ($program) = @_;
|
|
my @path = split (/:/, $ENV{PATH});
|
|
for (@path) {
|
|
return "$_/$program" if -x "$_/$program";
|
|
}
|
|
return $program;
|
|
}
|
|
|
|
# Given the path to the PGP program to use, generate a fixed version of
|
|
# pgpverify in the current directory. Takes care of a few other things, like
|
|
# making sure that there's a temporary directory for it to put its files.
|
|
# Expects to find normal pgpverify up one directory.
|
|
sub fix_pgpverify {
|
|
my ($path) = @_;
|
|
my $gpg = ($path =~ /gpgv$/);
|
|
mkdir ('tmp', 0755);
|
|
open (BASIC, "../pgpverify") or die "Can't open ../pgpverify: $!\n";
|
|
open (FIXED, "> pgpverify") or die "Can't create pgpverify: $!\n";
|
|
while (<BASIC>) {
|
|
s%^\# \$gpgv = \'.*%\$gpgv = '$path';% if $gpg;
|
|
s%^\$pgp = \'.*%\$pgp = '$path';% unless $gpg;
|
|
s%^\# \$keyring = \'.*%\$keyring = './keyring';%;
|
|
s%^\$tmpdir = \".*%\$tmpdir = './tmp';%;
|
|
s%^\$syslog_method = \'.*%\$syslog_method = '';%;
|
|
print FIXED;
|
|
}
|
|
close BASIC;
|
|
close FIXED;
|
|
chmod (0755, 'pgpverify');
|
|
}
|
|
|
|
# Given the path to the PGP program to use, generate a fixed version of
|
|
# signcontrol in the current directory. It also sets up signcontrol to sign
|
|
# example.* control messages with the testing key. Expects to find the normal
|
|
# signcontrol up one level.
|
|
sub fix_signcontrol {
|
|
my ($path) = @_;
|
|
open (BASIC, "../signcontrol") or die "Can't open ../signcontrol: $!\n";
|
|
open (FIXED, "> signcontrol") or die "Can't create signcontrol: $!\n";
|
|
while (<BASIC>) {
|
|
s/INSERT_YOUR_PGP_USERID/testing/;
|
|
s%^\$pgppassfile = \'.*%\$pgppassfile = 'keyring/passphrase';%;
|
|
s/^\$pgp = \".*/\$pgp = '$path';/;
|
|
s%^\$pgplock = .*%\$pgplock = 'keyring/passphrase';%;
|
|
s/YOUR_ADDRESS_AND_NAME/Test Signer <test\@example.com>/;
|
|
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, 'signcontrol');
|
|
}
|
|
|
|
##############################################################################
|
|
# Individual tests
|
|
##############################################################################
|
|
|
|
# Run pgpverify on a given file, expecting the given signer. Warn if
|
|
# something goes wrong and return true on success and false on failure.
|
|
sub pgpverify {
|
|
my ($file, $expected) = @_;
|
|
my $signer = `./pgpverify < $file`;
|
|
chomp $signer;
|
|
if ($? == 0 && $signer eq $expected) {
|
|
return 1;
|
|
} else {
|
|
print "pgpverify exited with status ", ($? >> 8), "\n" if $? != 0;
|
|
print "pgpverify said the signer was $signer\n" if $signer;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
# Run pgpverify on a given file, expecting failure with the provided status
|
|
# code. Warn if we succeed and return true on success of the test and false
|
|
# on failure.
|
|
sub pgpverify_fail {
|
|
my ($file, $status) = @_;
|
|
my $signer = `./pgpverify < $file 2> /dev/null`;
|
|
chomp $signer;
|
|
if (($? >> 8) == $status && !$signer) {
|
|
return 1;
|
|
} else {
|
|
print "pgpverify exited with status ", ($? >> 8), "\n";
|
|
print "pgpverify said the signer was $signer\n" if $signer;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
##############################################################################
|
|
# Test suite
|
|
##############################################################################
|
|
|
|
# Running totals.
|
|
my $tests = 0;
|
|
my $failed = 0;
|
|
|
|
# Tell signcontrol where to find the PGP keyrings.
|
|
$ENV{PGPPATH} = './keyring';
|
|
$ENV{GNUPGHOME} = './keyring';
|
|
|
|
# Set up pgpverify to use PGP first.
|
|
my $pgp = find_program ('pgp');
|
|
fix_pgpverify ($pgp);
|
|
|
|
# Check the signature on sample.control.
|
|
if (pgpverify ('../sample.control', 'news.announce.newgroups')) {
|
|
print "PASS: pgpverify-pgp\n";
|
|
} else {
|
|
print "FAIL: pgpverify-pgp\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Now, try with GnuPG.
|
|
my $gpgv = find_program ('gpgv');
|
|
fix_pgpverify ($gpgv);
|
|
|
|
# Check the signature on sample.control.
|
|
if (pgpverify ('../sample.control', 'news.announce.newgroups')) {
|
|
print "PASS: pgpverify-gpg\n";
|
|
} else {
|
|
print "FAIL: pgpverify-gpg\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Convert sample.control to wire format and then check its signature.
|
|
open (SAMPLE, '../sample.control')
|
|
or die "Can't open ../sample.control: $!\n";
|
|
open (WIRE, '> signed') or die "Can't create signed: $!\n";
|
|
while (<SAMPLE>) {
|
|
s/\n\z/\r\n/;
|
|
s/^\./../;
|
|
print WIRE;
|
|
}
|
|
print WIRE ".\r\n";
|
|
close SAMPLE;
|
|
close WIRE;
|
|
if (pgpverify ('signed', 'news.announce.newgroups')) {
|
|
print "PASS: pgpverify-wire\n";
|
|
} else {
|
|
print "FAIL: pgpverify-wire\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Sign a message with signcontrol.
|
|
fix_signcontrol ($pgp);
|
|
my $status = system ('./signcontrol < ./messages/newgroup > signed');
|
|
if ($? == 0) {
|
|
print "PASS: signcontrol-pgp\n";
|
|
} else {
|
|
print "signcontrol exited with status ", ($? >> 8), "\n";
|
|
print "FAIL: signcontrol-pgp\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# We still have a GnuPG pgpverify, so check cross-compatibility.
|
|
if (pgpverify ('./signed', 'testing')) {
|
|
print "PASS: signcontrol-pgp-gpg\n";
|
|
} else {
|
|
print "FAIL: signcontrol-pgp-gpg\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Switch to a PGP pgpverify and check again.
|
|
fix_pgpverify ($pgp);
|
|
if (pgpverify ('./signed', 'testing')) {
|
|
print "PASS: signcontrol-pgp-pgp\n";
|
|
} else {
|
|
print "FAIL: signcontrol-pgp-pgp\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Check with an old copy of pgpverify to make sure that the generated
|
|
# signatures still verify properly with a pgpverify that uses attached
|
|
# signatures.
|
|
my $signer = `./pgpverify-old $pgp < ./signed`;
|
|
chomp $signer;
|
|
if ($? == 0 && $signer eq 'testing') {
|
|
print "PASS: signcontrol-pgp-old\n";
|
|
} else {
|
|
print "pgpverify exited with status ", ($? >> 8), "\n" if $? != 0;
|
|
print "pgpverify said the signer was $signer\n" if $signer;
|
|
print "FAIL: signcontrol-pgp-old\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Switch to a GnuPG signcontrol and try again.
|
|
my $gpg = find_program ('gpg');
|
|
fix_signcontrol ($gpg);
|
|
$status = system ('./signcontrol < ./messages/newgroup > signed');
|
|
if ($? == 0) {
|
|
print "PASS: signcontrol-gpg\n";
|
|
} else {
|
|
print "signcontrol exited with status ", ($? >> 8), "\n";
|
|
print "FAIL: signcontrol-gpg\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# This will only verify with a GnuPG pgpverify.
|
|
fix_pgpverify ($gpgv);
|
|
if (pgpverify ('./signed', 'testing')) {
|
|
print "PASS: signcontrol-gpg-gpg\n";
|
|
} else {
|
|
print "FAIL: signcontrol-gpg-gpg\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Generate signed messages with News::Article.
|
|
system ('./sign-newsart', './messages/newgroup');
|
|
|
|
# Verify both with the GnuPG pgpverify.
|
|
if (pgpverify ('./signed.pgp', 'testing')) {
|
|
print "PASS: news-article-pgp-gpg\n";
|
|
} else {
|
|
print "FAIL: news-article-pgp-gpg\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
if (pgpverify ('./signed.gpg', 'testing')) {
|
|
print "PASS: news-article-gpg-gpg\n";
|
|
} else {
|
|
print "FAIL: news-article-gpg-gpg\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Switch to the PGP pgpverify and verify just the PGP one.
|
|
fix_pgpverify ($pgp);
|
|
if (pgpverify ('./signed.pgp', 'testing')) {
|
|
print "PASS: news-article-pgp-pgp\n";
|
|
} else {
|
|
print "FAIL: news-article-pgp-pgp\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Check the return status for a truncated signature.
|
|
if (pgpverify_fail ('./messages/bad-syntax', 255)) {
|
|
print "PASS: pgpverify-pgp-syntax\n";
|
|
} else {
|
|
print "FAIL: pgpverify-pgp-syntax\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Check the return status for a bad signature.
|
|
if (pgpverify_fail ('./messages/bad-corrupt', 3)) {
|
|
print "PASS: pgpverify-pgp-bad\n";
|
|
} else {
|
|
print "FAIL: pgpverify-pgp-bad\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Switch to GnuPG and check the return status for a truncated signature.
|
|
fix_pgpverify ($gpgv);
|
|
if (pgpverify_fail ('./messages/bad-syntax', 255)) {
|
|
print "PASS: pgpverify-gpg-syntax\n";
|
|
} else {
|
|
print "FAIL: pgpverify-gpg-syntax\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Check the return status for a bad signature.
|
|
if (pgpverify_fail ('./messages/bad-corrupt', 3)) {
|
|
print "PASS: pgpverify-gpg-bad\n";
|
|
} else {
|
|
print "FAIL: pgpverify-gpg-bad\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Check the return status for an unknown signer.
|
|
if (pgpverify_fail ('./messages/gnu', 2)) {
|
|
print "PASS: pgpverify-gpg-unknown\n";
|
|
} else {
|
|
print "FAIL: pgpverify-gpg-unknown\n";
|
|
$failed++;
|
|
}
|
|
$tests++;
|
|
|
|
# Print out a summary of the tests.
|
|
unlink ('pgpverify', 'signcontrol', 'signed', 'signed.pgp', 'signed.gpg')
|
|
unless $failed > 0;
|
|
if ($failed == 0) {
|
|
print "All $tests tests passed\n";
|
|
} else {
|
|
print "Failed $failed tests out of $tests total\n";
|
|
exit 1;
|
|
}
|