|
@@ -0,0 +1,997 @@
|
|
|
|
|
+#!/usr/bin/perl
|
|
|
|
|
+
|
|
|
|
|
+#%# Copyright (C) 2014-2024 Christoph Biedl <debian.axhn@manchmal.in-ulm.de>
|
|
|
|
|
+#%# License: GPL-2.0+
|
|
|
|
|
+
|
|
|
|
|
+=head1 NAME
|
|
|
|
|
+
|
|
|
|
|
+ngircd-test-tls-link - test certificate validation in ngircd's TLS based s2s links
|
|
|
|
|
+
|
|
|
|
|
+=head1 VERSION
|
|
|
|
|
+
|
|
|
|
|
+Version YYYY.MM.DD
|
|
|
|
|
+
|
|
|
|
|
+=cut
|
|
|
|
|
+
|
|
|
|
|
+our $VERSION = 'YYYY.MM.DD';
|
|
|
|
|
+
|
|
|
|
|
+=head1 SYNOPSIS
|
|
|
|
|
+
|
|
|
|
|
+ ngircd-test-tls-link --x509-dir /path/to/dir --x509-populate
|
|
|
|
|
+
|
|
|
|
|
+ ngircd-test-tls-link --x509-dir /path/to/dir [<test-name> ...]
|
|
|
|
|
+
|
|
|
|
|
+=cut
|
|
|
|
|
+
|
|
|
|
|
+use 5.010;
|
|
|
|
|
+use strict;
|
|
|
|
|
+use warnings;
|
|
|
|
|
+
|
|
|
|
|
+use Test::More;
|
|
|
|
|
+
|
|
|
|
|
+use File::Basename;
|
|
|
|
|
+use File::Copy;
|
|
|
|
|
+use File::Slurp;
|
|
|
|
|
+use File::Temp qw<tempdir>;
|
|
|
|
|
+use Getopt::Long;
|
|
|
|
|
+use Pod::Usage;
|
|
|
|
|
+use Proc::Simple;
|
|
|
|
|
+use Socket;
|
|
|
|
|
+use Time::HiRes qw<sleep time>;
|
|
|
|
|
+
|
|
|
|
|
+my $ngircd_exe_default = '/usr/sbin/ngircd';
|
|
|
|
|
+my @ngircd_exe = ( $ngircd_exe_default );
|
|
|
|
|
+my @tls_mode;
|
|
|
|
|
+my $x509_dir;
|
|
|
|
|
+my $x509_populate;
|
|
|
|
|
+my $verbose = 0;
|
|
|
|
|
+
|
|
|
|
|
+=head1 OPTIONS
|
|
|
|
|
+
|
|
|
|
|
+=over
|
|
|
|
|
+
|
|
|
|
|
+=cut
|
|
|
|
|
+
|
|
|
|
|
+{
|
|
|
|
|
+ my $help;
|
|
|
|
|
+ my $man;
|
|
|
|
|
+ my %GetOptions = (
|
|
|
|
|
+ 'help|?' => \$help,
|
|
|
|
|
+ 'man' => \$man,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+=item B<--x509-dir> F<directory>
|
|
|
|
|
+
|
|
|
|
|
+A directory to hold the x509 credentials needed. Default: Use a
|
|
|
|
|
+temporary directory which is deleted upon exit. This delays every
|
|
|
|
|
+execution of this program by a few seconds.
|
|
|
|
|
+
|
|
|
|
|
+=cut
|
|
|
|
|
+
|
|
|
|
|
+ $GetOptions{'x509-dir=s'} = \$x509_dir;
|
|
|
|
|
+
|
|
|
|
|
+=item B<--x509-populate>
|
|
|
|
|
+
|
|
|
|
|
+Populate a given C<--x509-dir> with the files needed, then exit.
|
|
|
|
|
+
|
|
|
|
|
+=cut
|
|
|
|
|
+
|
|
|
|
|
+ $GetOptions{'x509-populate'} = \$x509_populate;
|
|
|
|
|
+
|
|
|
|
|
+=item B<--tls-mode> C<mode>
|
|
|
|
|
+
|
|
|
|
|
+One of C<openssl> or C<gnutls>.
|
|
|
|
|
+
|
|
|
|
|
+The type of TLS configuration to use. Must match ngircd's compilation
|
|
|
|
|
+option. Use only if auto-detection failed, and report a bug then.
|
|
|
|
|
+
|
|
|
|
|
+For TLS interoperability tests, you can provide two strings, separated
|
|
|
|
|
+by C<:> (colon).
|
|
|
|
|
+
|
|
|
|
|
+Default: Detect from the binary.
|
|
|
|
|
+
|
|
|
|
|
+=cut
|
|
|
|
|
+
|
|
|
|
|
+ $GetOptions{'tls-mode=s'} = sub {
|
|
|
|
|
+ @tls_mode = split (/:/, $_[1], 2);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+=item B<--ngircd> F<program>
|
|
|
|
|
+
|
|
|
|
|
+The ngircd binary. For TLS interoperability tests, you can provide two
|
|
|
|
|
+programs, separated by C<:> (colon).
|
|
|
|
|
+
|
|
|
|
|
+Default: F</usr/sbin/ngircd>
|
|
|
|
|
+
|
|
|
|
|
+=cut
|
|
|
|
|
+
|
|
|
|
|
+ $GetOptions{'ngircd=s'} = sub {
|
|
|
|
|
+ @ngircd_exe = split (/:/, $_[1], 2);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+=item B<--verbose>
|
|
|
|
|
+
|
|
|
|
|
+Add verbosity.
|
|
|
|
|
+
|
|
|
|
|
+=cut
|
|
|
|
|
+
|
|
|
|
|
+ $GetOptions{'verbose+'} = \$verbose++;
|
|
|
|
|
+
|
|
|
|
|
+=item B<--Version>
|
|
|
|
|
+
|
|
|
|
|
+Show the version number and exit.
|
|
|
|
|
+
|
|
|
|
|
+=cut
|
|
|
|
|
+
|
|
|
|
|
+ $GetOptions{'Version'} = sub {
|
|
|
|
|
+ printf "%s version %s\n",
|
|
|
|
|
+ (split (/\//, $0))[-1],
|
|
|
|
|
+ $VERSION;
|
|
|
|
|
+ exit 1;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+=item [ <test> ... ]
|
|
|
|
|
+
|
|
|
|
|
+Select specific tests to run only. Default: Run all tests.
|
|
|
|
|
+
|
|
|
|
|
+=back
|
|
|
|
|
+
|
|
|
|
|
+=cut
|
|
|
|
|
+
|
|
|
|
|
+ GetOptions (%GetOptions) or pod2usage (2);
|
|
|
|
|
+ $help and pod2usage (1);
|
|
|
|
|
+ $man and pod2usage (-exitstatus => 0, -verbose => 2);
|
|
|
|
|
+
|
|
|
|
|
+ if (@tls_mode) {
|
|
|
|
|
+ foreach my $m (@tls_mode) {
|
|
|
|
|
+ ($m =~ /^(openssl|gnutls)$/) or
|
|
|
|
|
+ die ("Invalid '--tls-mode' value '$m'");
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ for (my $i = 0; $i < scalar (@ngircd_exe); $i++) {
|
|
|
|
|
+ my $x = $ngircd_exe[$i];
|
|
|
|
|
+ my $tls_mode;
|
|
|
|
|
+ (-x $x) or
|
|
|
|
|
+ die ("Not an executable: '$x'");
|
|
|
|
|
+ my $pipe;
|
|
|
|
|
+ open ($pipe, '-|', 'ldd', $x) or
|
|
|
|
|
+ die ("Cannot run ldd on '$x': $!");
|
|
|
|
|
+ while (defined (my $line = <$pipe>)) {
|
|
|
|
|
+ if ($line =~ /^\tlibssl\.so\./) {
|
|
|
|
|
+ $tls_mode = 'openssl';
|
|
|
|
|
+ last;
|
|
|
|
|
+ } elsif ($line =~ /^\tlibgnutls/) {
|
|
|
|
|
+ $tls_mode = 'gnutls';
|
|
|
|
|
+ last;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ close ($pipe);
|
|
|
|
|
+ if ($tls_mode) {
|
|
|
|
|
+ note ("Auto-detected TLS mode for '$x' is '$tls_mode'");
|
|
|
|
|
+ $tls_mode[$i] = $tls_mode;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ die ("BUG: Failed to determine TLS mode for '$x'");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ $ngircd_exe[1] //= $ngircd_exe[0];
|
|
|
|
|
+ $tls_mode[1] //= $tls_mode[0];
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+my $temp_dir = tempdir (
|
|
|
|
|
+ "ngircd-test-tls-link.$$.XXXXX",
|
|
|
|
|
+ 'TMPDIR' => 1,
|
|
|
|
|
+ 'CLEANUP' => 1,
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+my $exit_after_x509_populate;
|
|
|
|
|
+if ($x509_dir) {
|
|
|
|
|
+ (-d $x509_dir || $x509_populate) or
|
|
|
|
|
+ die ("Not a directory: '$x509_dir' - perhaps you forgot --x509-populate?");
|
|
|
|
|
+ $exit_after_x509_populate = $x509_populate;
|
|
|
|
|
+} else {
|
|
|
|
|
+ # not provided, use a temporary directoryy
|
|
|
|
|
+ $x509_dir = "$temp_dir/CA";
|
|
|
|
|
+ # always populate it, and continue
|
|
|
|
|
+ $x509_populate and
|
|
|
|
|
+ note ('Ignoring --x509-populate option as no --x509-dir was provided');
|
|
|
|
|
+ $x509_populate = 1;
|
|
|
|
|
+ $exit_after_x509_populate = undef;
|
|
|
|
|
+}
|
|
|
|
|
+my $conf_dir = "$temp_dir/conf";
|
|
|
|
|
+my $hosts_file ="$temp_dir/hosts";
|
|
|
|
|
+
|
|
|
|
|
+write_file (
|
|
|
|
|
+ $hosts_file,
|
|
|
|
|
+ <<__EOS__,
|
|
|
|
|
+127.0.0.1 server1
|
|
|
|
|
+127.0.0.1 server2
|
|
|
|
|
+127.0.0.1 server1.example.com
|
|
|
|
|
+127.0.0.1 server2.example.com
|
|
|
|
|
+__EOS__
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+foreach my $dir (($x509_dir, $conf_dir)) {
|
|
|
|
|
+ (
|
|
|
|
|
+ -d $dir ||
|
|
|
|
|
+ mkdir ($dir)
|
|
|
|
|
+ ) or die ("Cannot create directory '$dir'");
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+my $src_dir = dirname ($0);
|
|
|
|
|
+
|
|
|
|
|
+my $one_month_future = $^T + 30*86400;
|
|
|
|
|
+
|
|
|
|
|
+my %tests = (
|
|
|
|
|
+ 'regular' => {
|
|
|
|
|
+ 'expect' => 'pass',
|
|
|
|
|
+ 'fail' => qr/Connection [0-9]+ with "server2:6692" closed/,
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'different-CAs' => {
|
|
|
|
|
+ 'expect' => 'pass',
|
|
|
|
|
+ 'server1-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA2/root-ca.crt",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ 'server2-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA2/server2.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA2/server2.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'CN-mismatch' => {
|
|
|
|
|
+ # using certificate with wrong CN, must fail
|
|
|
|
|
+ 'expect' => 'fail',
|
|
|
|
|
+ 'server2-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA1/server3.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA1/server3.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ 'pass' => qr/Peer certificate check failed for/,
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'using-peer-cert-as-CA' => {
|
|
|
|
|
+ # using peer cert as CA a.k.a. self-signed
|
|
|
|
|
+ 'unsupported' => 1, # fails on openssl
|
|
|
|
|
+ 'expect' => 'pass',
|
|
|
|
|
+ 'server1-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA1/server2.example.com.crt",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'peer-cert-signed-by-unknown-CA' => {
|
|
|
|
|
+ # peer cert signed by unknown CA, must fail
|
|
|
|
|
+ 'expect' => 'fail',
|
|
|
|
|
+ 'server2-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA2/server2.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA2/server2.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'peer-cert-signed-by-unknown-CA-but-verify-disabled' => {
|
|
|
|
|
+ 'expect' => 'pass',
|
|
|
|
|
+ 'server1-extra' => {
|
|
|
|
|
+ 'Server' => {
|
|
|
|
|
+ 'SSLVerify' => 'no',
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ 'server2-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA2/server2.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA2/server2.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ 'pass' => qr/Synchronization with "ngircd\.test\.server2" done/,
|
|
|
|
|
+ 'noop' => qr/Certificate validation failed/,
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'peer-cert-revoked' => {
|
|
|
|
|
+ # certificate is revoked, must fail
|
|
|
|
|
+ 'expect' => 'fail',
|
|
|
|
|
+ 'server1-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA3/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA3/server1.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA3/server1.example.com.key",
|
|
|
|
|
+ 'CRLFile' => "$x509_dir/CA3/crl.pem",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ 'server2-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA3/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA3/server2.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA3/server2.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'peer-cert-revoked-but-verify-disabled' => {
|
|
|
|
|
+ 'expect' => 'pass',
|
|
|
|
|
+ 'server1-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA3/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA3/server1.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA3/server1.example.com.key",
|
|
|
|
|
+ 'CRLFile' => "$x509_dir/CA3/crl.pem",
|
|
|
|
|
+ },
|
|
|
|
|
+ 'Server' => {
|
|
|
|
|
+ 'SSLVerify' => 'no',
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ 'server2-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA3/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA3/server2.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA3/server2.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ 'pass' => qr/Synchronization with "ngircd\.test\.server2" done/,
|
|
|
|
|
+ 'noop' => qr/Certificate validation failed/,
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'revocation-by-wrong-CA' => {
|
|
|
|
|
+ # CRL signed by a different CA
|
|
|
|
|
+ 'expect' => 'fail',
|
|
|
|
|
+ 'server1-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CRLFile' => "$x509_dir/CA2/crl.pem",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'wildcard-cert' => {
|
|
|
|
|
+ # server uses a wildcard certificate
|
|
|
|
|
+ 'expect' => 'pass',
|
|
|
|
|
+ 'server1-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA4/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA4/server1.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA4/server1.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ 'server2-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA4/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA4/*.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA4/*.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'mixed-case' => {
|
|
|
|
|
+ # uppercase letters in certificate name
|
|
|
|
|
+ 'expect' => 'pass',
|
|
|
|
|
+ 'server1-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA5/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA5/server1.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA5/server1.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ 'server2-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA5/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA5/Server2.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA5/Server2.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'subject-alternate-name' => {
|
|
|
|
|
+ 'expect' => 'pass',
|
|
|
|
|
+ 'server1-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA6/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA6/server1.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA6/server1.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ 'server2-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA6/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA6/server2.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA6/server2.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'subject-alternate-name-mismatch' => {
|
|
|
|
|
+ 'expect' => 'fail',
|
|
|
|
|
+ 'pass' => qr/Failed to verify the hostname, expected/,
|
|
|
|
|
+ 'server1-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA6/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA6/server1.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA6/server1.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ 'server2-extra' => {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA6/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA6/server3.example.com.crt",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA6/server3.example.com.key",
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
|
|
+ 'cert-expired' => {
|
|
|
|
|
+ 'expect' => 'fail',
|
|
|
|
|
+ 'pass' => qr/SSL error: A TLS fatal alert has been received/,
|
|
|
|
|
+ 'prefix' => [ 'faketime', "\@$one_month_future" ],
|
|
|
|
|
+ ':order' => __LINE__,
|
|
|
|
|
+ },
|
|
|
|
|
+);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+sub write_config {
|
|
|
|
|
+ my ($file, $number, $tls_mode, @extras) = @_;
|
|
|
|
|
+
|
|
|
|
|
+ my $cipher_list = ($tls_mode =~ /^o/ ?
|
|
|
|
|
+ 'HIGH:!aNULL:@STRENGTH:!SSLv3' :
|
|
|
|
|
+ 'SECURE128:-VERS-SSL3.0'
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ my $peer_number = 3 - $number;
|
|
|
|
|
+
|
|
|
|
|
+ # write server configurations
|
|
|
|
|
+ my %config = (
|
|
|
|
|
+ 'Global' => {
|
|
|
|
|
+ 'Name' => "ngircd.test.server$number",
|
|
|
|
|
+ 'Info' => "ngIRCd Test-Server $number",
|
|
|
|
|
+ 'Listen' => '127.0.0.1',
|
|
|
|
|
+ 'Ports' => "678$number",
|
|
|
|
|
+ 'AdminEMail' => "admin\@server$number.example",
|
|
|
|
|
+ 'ServerUID' => $<,
|
|
|
|
|
+ 'ServerGID' => $(,
|
|
|
|
|
+ 'MotdFile' => '/dev/null',
|
|
|
|
|
+ },
|
|
|
|
|
+ 'Options' => {
|
|
|
|
|
+ 'OperCanUseMode' => 'yes',
|
|
|
|
|
+ 'Ident' => 'no',
|
|
|
|
|
+ 'IncludeDir' => '',
|
|
|
|
|
+ 'PAM' => 'no',
|
|
|
|
|
+ },
|
|
|
|
|
+ 'Operator' => {
|
|
|
|
|
+ 'Name' => 'TestOp',
|
|
|
|
|
+ 'Password' => '123',
|
|
|
|
|
+ },
|
|
|
|
|
+ 'Server' => {
|
|
|
|
|
+ 'Name' => "ngircd.test.server$peer_number",
|
|
|
|
|
+ 'Host' => "server$peer_number.example.com",
|
|
|
|
|
+ 'Port' => "669$peer_number",
|
|
|
|
|
+ 'MyPassword' => "pwd$number",
|
|
|
|
|
+ 'PeerPassword' => "pwd$peer_number",
|
|
|
|
|
+ 'SSLConnect' => 'yes',
|
|
|
|
|
+ 'SSLVerify' => 'yes',
|
|
|
|
|
+ },
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'CAFile' => "$x509_dir/CA1/root-ca.crt",
|
|
|
|
|
+ 'CertFile' => "$x509_dir/CA1/server$number.example.com.crt",
|
|
|
|
|
+ 'CipherList' => $cipher_list,
|
|
|
|
|
+ 'DHFile' => "$x509_dir/dhparams.pem",
|
|
|
|
|
+ 'KeyFile' => "$x509_dir/CA1/server$number.example.com.key",
|
|
|
|
|
+ 'Ports' => "669$number",
|
|
|
|
|
+ },
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ foreach my $extra (@extras) {
|
|
|
|
|
+ foreach my $section (keys %$extra) {
|
|
|
|
|
+ foreach my $key (keys %{$extra->{$section}}) {
|
|
|
|
|
+ if (
|
|
|
|
|
+ exists ($config{$section}{$key}) &&
|
|
|
|
|
+ defined ($config{$section}{$key}) &&
|
|
|
|
|
+ exists ($extra->{$section}{$key}) &&
|
|
|
|
|
+ defined ($extra->{$section}{$key}) &&
|
|
|
|
|
+ $config{$section}{$key} eq $extra->{$section}{$key}
|
|
|
|
|
+ ) {
|
|
|
|
|
+ note ("W: Identical re-definition of server/section/key: $number/$section/$key");
|
|
|
|
|
+ }
|
|
|
|
|
+ $config{$section}{$key} = $extra->{$section}{$key};
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ my $return = '';
|
|
|
|
|
+ my $fh;
|
|
|
|
|
+ open ($fh, '>', \$return);
|
|
|
|
|
+ foreach my $section (sort keys %config) {
|
|
|
|
|
+ print $fh "[$section]\n";
|
|
|
|
|
+ foreach my $key (sort keys %{$config{$section}}) {
|
|
|
|
|
+ my $value = $config{$section}{$key};
|
|
|
|
|
+ defined ($value) and
|
|
|
|
|
+ printf $fh " %s = %s\n", $key, $value;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ close ($fh);
|
|
|
|
|
+
|
|
|
|
|
+ write_file ($file, $return);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+sub write_configs {
|
|
|
|
|
+ my (
|
|
|
|
|
+ $server1_config_file,
|
|
|
|
|
+ $server2_config_file,
|
|
|
|
|
+ $server1_config_extra,
|
|
|
|
|
+ $server2_config_extra,
|
|
|
|
|
+ ) = @_;
|
|
|
|
|
+
|
|
|
|
|
+ write_config (
|
|
|
|
|
+ $server1_config_file,
|
|
|
|
|
+ '1',
|
|
|
|
|
+ $tls_mode[0],
|
|
|
|
|
+ {
|
|
|
|
|
+ 'SSL' => {
|
|
|
|
|
+ 'Ports' => undef,
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ $server1_config_extra,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ write_config (
|
|
|
|
|
+ $server2_config_file,
|
|
|
|
|
+ '2',
|
|
|
|
|
+ $tls_mode[1],
|
|
|
|
|
+ {
|
|
|
|
|
+ 'Server' => {
|
|
|
|
|
+ 'Passive' => 'yes',
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
|
|
+ $server2_config_extra,
|
|
|
|
|
+ );
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+sub test1 {
|
|
|
|
|
+ my ($name, $test) = @_;
|
|
|
|
|
+
|
|
|
|
|
+ {
|
|
|
|
|
+ my $l = length ($name);
|
|
|
|
|
+ note ('+-' . ('-' x $l) . '-+');
|
|
|
|
|
+ note ("| $name | ");
|
|
|
|
|
+ note ('+-' . ('-' x $l) . '-+');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ my $server1_config = "$conf_dir/ngircd-test1.conf";
|
|
|
|
|
+ my $server2_config = "$conf_dir/ngircd-test2.conf";
|
|
|
|
|
+ write_configs (
|
|
|
|
|
+ $server1_config,
|
|
|
|
|
+ $server2_config,
|
|
|
|
|
+ $test->{'server1-extra'},
|
|
|
|
|
+ $test->{'server2-extra'},
|
|
|
|
|
+ ),
|
|
|
|
|
+
|
|
|
|
|
+ my $prefix = $test->{'prefix'} // [];
|
|
|
|
|
+
|
|
|
|
|
+ # start the receiving server2 first, it might need a
|
|
|
|
|
+ # little extra time
|
|
|
|
|
+ my $server2_log = "$temp_dir/server2.log";
|
|
|
|
|
+ write_file ($server2_log, ''); # so open below won't fail
|
|
|
|
|
+ my $server2 = Proc::Simple->new;
|
|
|
|
|
+ $server2->redirect_output ($server2_log, $server2_log);
|
|
|
|
|
+ $server2->start ((
|
|
|
|
|
+ @$prefix,
|
|
|
|
|
+ $ngircd_exe[1],
|
|
|
|
|
+ '--config', $server2_config,
|
|
|
|
|
+ '--nodaemon',
|
|
|
|
|
+ ));
|
|
|
|
|
+ $server2->kill_on_destroy (1);
|
|
|
|
|
+ sleep (0.5);
|
|
|
|
|
+
|
|
|
|
|
+ # start connecting server1
|
|
|
|
|
+ my $server1_log = "$temp_dir/server1.log";
|
|
|
|
|
+ write_file ($server1_log, ''); # so open below won't fail
|
|
|
|
|
+ my $server1 = Proc::Simple->new;
|
|
|
|
|
+ $server1->redirect_output ($server1_log, $server1_log);
|
|
|
|
|
+ $server1->start ((
|
|
|
|
|
+ @$prefix,
|
|
|
|
|
+ $ngircd_exe[0],
|
|
|
|
|
+ '--config', $server1_config,
|
|
|
|
|
+ '--nodaemon',
|
|
|
|
|
+ ));
|
|
|
|
|
+ $server1->kill_on_destroy (1);
|
|
|
|
|
+ sleep (0.5);
|
|
|
|
|
+
|
|
|
|
|
+ my $fh;
|
|
|
|
|
+ open ($fh, '<', $server1_log) or
|
|
|
|
|
+ die ("Cannot read '$server1_log': $!");
|
|
|
|
|
+
|
|
|
|
|
+ # read output from server1, find 'pass' or 'fail' line
|
|
|
|
|
+ my $timeout = time + 10;
|
|
|
|
|
+
|
|
|
|
|
+ my $t0 = time;
|
|
|
|
|
+ my $firstline;
|
|
|
|
|
+ my $got_verdict;
|
|
|
|
|
+TAIL:
|
|
|
|
|
+ while (1) {
|
|
|
|
|
+ if (time > $timeout) {
|
|
|
|
|
+ fail (sprintf ('Timeout (%u sec)', time - $t0));
|
|
|
|
|
+ last TAIL;
|
|
|
|
|
+ }
|
|
|
|
|
+ my $curpos;
|
|
|
|
|
+ my $line;
|
|
|
|
|
+ for ($curpos = tell ($fh); $line = <$fh>; $curpos = tell ($fh)) {
|
|
|
|
|
+ chomp ($line);
|
|
|
|
|
+ $firstline //= $line;
|
|
|
|
|
+ $verbose and note (sprintf ('%.2f %s', time-$t0, $line));
|
|
|
|
|
+
|
|
|
|
|
+ # generic pass/fail pattern
|
|
|
|
|
+ my $passed;
|
|
|
|
|
+ if ($line =~ /(Can't bind socket to address 127\.0\.0\.1.*$)/) {
|
|
|
|
|
+ # previous instance running
|
|
|
|
|
+ fail ($1);
|
|
|
|
|
+ $got_verdict = 1;
|
|
|
|
|
+ last TAIL;
|
|
|
|
|
+ } elsif (
|
|
|
|
|
+ # configured pass/fail pattern
|
|
|
|
|
+ $test->{'pass'} && $line =~ /$test->{'pass'}/
|
|
|
|
|
+ ) {
|
|
|
|
|
+ $passed = 1;
|
|
|
|
|
+ } elsif ($test->{'fail'} && $line =~ /$test->{'fail'}/) {
|
|
|
|
|
+ $passed = 0;
|
|
|
|
|
+ } elsif ($test->{'noop'} && $line =~ /$test->{'noop'}/) {
|
|
|
|
|
+ next;
|
|
|
|
|
+ } elsif ($line =~ /Synchronization with "ngircd\.test\.server2" done/) {
|
|
|
|
|
+ $passed = $test->{'expect'};
|
|
|
|
|
+ } elsif ($line =~ /Certificate validation failed/) {
|
|
|
|
|
+ $passed = 1 - $test->{'expect'};
|
|
|
|
|
+ } elsif ($line =~ /Fatail: /) {
|
|
|
|
|
+ # some fatal error
|
|
|
|
|
+ fail ($1);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (defined ($passed)) {
|
|
|
|
|
+ if ($passed) {
|
|
|
|
|
+ pass ("Got expected line: '$line'");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ fail ("Got line that should not be there: '$line'");
|
|
|
|
|
+ }
|
|
|
|
|
+ $got_verdict = 1;
|
|
|
|
|
+ last TAIL;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!$server1->poll) {
|
|
|
|
|
+ note ('server1 has left the building');
|
|
|
|
|
+ $got_verdict = 1;
|
|
|
|
|
+ last TAIL;
|
|
|
|
|
+ }
|
|
|
|
|
+ sleep (0.1);
|
|
|
|
|
+ seek ($fh, $curpos, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ close ($fh);
|
|
|
|
|
+
|
|
|
|
|
+ $server1->kill;
|
|
|
|
|
+ $server2->kill;
|
|
|
|
|
+
|
|
|
|
|
+ wait;
|
|
|
|
|
+
|
|
|
|
|
+ ok ($got_verdict, 'have a verdict');
|
|
|
|
|
+
|
|
|
|
|
+ if ($firstline && $firstline =~ /^\[[0-9]+:[0-9] +[0-9]+\./) {
|
|
|
|
|
+ # have absolute timestamps
|
|
|
|
|
+ my @log = read_file ($server1_log);
|
|
|
|
|
+ my $first_server2_line = scalar (@log);
|
|
|
|
|
+ push @log, read_file ($server2_log);
|
|
|
|
|
+
|
|
|
|
|
+my $RED = "\e[1;31m";
|
|
|
|
|
+my $GREEN = "\e[1;32m";
|
|
|
|
|
+my $NORMAL = "\e[0m";
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ my @log_sorter;
|
|
|
|
|
+ for (my $i = 0; $i < scalar (@log); $i++) {
|
|
|
|
|
+ my $line = $log[$i];
|
|
|
|
|
+ chomp ($line);
|
|
|
|
|
+ my $srt;
|
|
|
|
|
+ my $server = $i < $first_server2_line ? 1 : 2;
|
|
|
|
|
+ if ($line =~ /^
|
|
|
|
|
+ \[
|
|
|
|
|
+ (?<pid>[0-9]+):
|
|
|
|
|
+ (?<prio>[0-9])\s+
|
|
|
|
|
+ (?<time>[0-9]+\.[0-9]+)
|
|
|
|
|
+ \]\s(?<msg>.+)
|
|
|
|
|
+ $/x) {
|
|
|
|
|
+ $srt = [
|
|
|
|
|
+ $+{'time'},
|
|
|
|
|
+ $server,
|
|
|
|
|
+ $+{'prio'},
|
|
|
|
|
+ $+{'msg'},
|
|
|
|
|
+ ];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ fail ("Cannot parse log line '$line'");
|
|
|
|
|
+ $srt = [ 0, $server, 0, $line ];
|
|
|
|
|
+ }
|
|
|
|
|
+ $log_sorter[$i] = $srt;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ # sort the log file by time, process, line
|
|
|
|
|
+ my @idx = sort {
|
|
|
|
|
+ $log_sorter[$a][0] <=> $log_sorter[$b][0] ||
|
|
|
|
|
+ $log_sorter[$a][1] <=> $log_sorter[$b][1] ||
|
|
|
|
|
+ $log_sorter[$a][3] cmp $log_sorter[$b][3] ||
|
|
|
|
|
+ $a cmp $b
|
|
|
|
|
+ } 0..$#log_sorter;
|
|
|
|
|
+
|
|
|
|
|
+ note ('combined log ([server:prio ms])');
|
|
|
|
|
+ my $t1 = $log_sorter[$idx[0]][0];
|
|
|
|
|
+ foreach my $idx (@idx) {
|
|
|
|
|
+ my $data = $log_sorter[$idx];
|
|
|
|
|
+ note (sprintf (
|
|
|
|
|
+ '| %s[%s:%d %.6f] %s%s',
|
|
|
|
|
+ ($data->[1] == 1 ? $GREEN : $RED),
|
|
|
|
|
+ $data->[1],
|
|
|
|
|
+ $data->[2],
|
|
|
|
|
+ $data->[0] - $t1,
|
|
|
|
|
+ $data->[3],
|
|
|
|
|
+ $NORMAL,
|
|
|
|
|
+ ));
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ # Just combine
|
|
|
|
|
+ my @log;
|
|
|
|
|
+ @log = read_file ($server1_log);
|
|
|
|
|
+ note ('server 1 log:');
|
|
|
|
|
+ foreach my $line (@log) {
|
|
|
|
|
+ note ("1: $line");
|
|
|
|
|
+ }
|
|
|
|
|
+ @log = read_file ($server2_log);
|
|
|
|
|
+ note ('server 2 log:');
|
|
|
|
|
+ foreach my $line (@log) {
|
|
|
|
|
+ note ("2: $line");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+# start the show
|
|
|
|
|
+
|
|
|
|
|
+if ($x509_populate) {
|
|
|
|
|
+ note ('setting up x509 stuff');
|
|
|
|
|
+
|
|
|
|
|
+ my $fail_x509;
|
|
|
|
|
+
|
|
|
|
|
+ $ENV{'RNDFILE'} = "$temp_dir/.rnd";
|
|
|
|
|
+
|
|
|
|
|
+ for my $f (qw<dhparams.pem openssl.cnf openssl.san.cnf>) {
|
|
|
|
|
+ copy ("$src_dir/data/$f", "$x509_dir/$f") or
|
|
|
|
|
+ die ("Failed to copy $f: $!");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ foreach my $command ((
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<CA1 server1.example.com> ],
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<CA1 server2.example.com> ],
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<CA1 server3.example.com> ],
|
|
|
|
|
+
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<CA2 server2.example.com> ],
|
|
|
|
|
+
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<CA3 server1.example.com> ],
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<--revoke CA3 server2.example.com> ],
|
|
|
|
|
+
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<CA4 server1.example.com> ],
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<CA4 *.example.com> ],
|
|
|
|
|
+
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<CA5 server1.example.com> ],
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<CA5 Server2.example.com> ],
|
|
|
|
|
+
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<CA6 server1.example.com> ],
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<--san CA6 server2.example.com> ],
|
|
|
|
|
+ [ "$src_dir/gen-x509-stuff", $x509_dir, qw<--san CA6 server3.example.com> ],
|
|
|
|
|
+ )) {
|
|
|
|
|
+ my $run = Proc::Simple->new;
|
|
|
|
|
+ my $log = "$temp_dir/gen-stuff.log";
|
|
|
|
|
+ write_file ($log, '');
|
|
|
|
|
+ $run->redirect_output ($log, $log);
|
|
|
|
|
+ $run->start (@$command);
|
|
|
|
|
+ my $exit = $run->wait;
|
|
|
|
|
+ my $fail = !is (
|
|
|
|
|
+ $exit,
|
|
|
|
|
+ 0,
|
|
|
|
|
+ 'gen-x509-stuff ' . join (' ', @$command[2..$#$command]),
|
|
|
|
|
+ );
|
|
|
|
|
+ $fail and $fail_x509++;
|
|
|
|
|
+ if ($fail || $verbose) {
|
|
|
|
|
+ my $out = read_file ($log);
|
|
|
|
|
+ $log and note ("Output:\n$out");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ $fail_x509 and exit 1;
|
|
|
|
|
+ if ($exit_after_x509_populate) {
|
|
|
|
|
+ pass ('here we go');
|
|
|
|
|
+ done_testing;
|
|
|
|
|
+ exit 0;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+$ENV{'LD_PRELOAD'} = 'libnss_wrapper.so';
|
|
|
|
|
+$ENV{'NSS_WRAPPER_HOSTS'} = $hosts_file;
|
|
|
|
|
+
|
|
|
|
|
+note ('checking mocked resolver');
|
|
|
|
|
+{
|
|
|
|
|
+ my $fail;
|
|
|
|
|
+
|
|
|
|
|
+ foreach my $hostname (qw<server1 server2>) {
|
|
|
|
|
+ my $output = `getent hosts $hostname`;
|
|
|
|
|
+ is ($?, 0, "resolve $hostname") or $fail++;
|
|
|
|
|
+ is ($?, 0, "resolve $hostname.example.com") or $fail++;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+my @tests;
|
|
|
|
|
+# check test description integrity
|
|
|
|
|
+{
|
|
|
|
|
+ my $fail;
|
|
|
|
|
+ my @required = qw<expect :order>; # NB: pass and fail may be missing
|
|
|
|
|
+ foreach my $test (sort keys %tests) {
|
|
|
|
|
+ foreach my $r (@required) {
|
|
|
|
|
+ exists ($tests{$test}{$r}) and next;
|
|
|
|
|
+ fail ("No '$r' field in test '$test'");
|
|
|
|
|
+ $fail++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ $fail and die ('Cannot continue');
|
|
|
|
|
+ @tests =
|
|
|
|
|
+ sort { $tests{$a}{':order'} <=> $tests{$b}{':order'} }
|
|
|
|
|
+ keys %tests;
|
|
|
|
|
+
|
|
|
|
|
+ foreach my $test (@tests) {
|
|
|
|
|
+ my $got = $tests{$test}{'expect'};
|
|
|
|
|
+ if ($got =~ /^(pass|fail)$/) {
|
|
|
|
|
+ $tests{$test}{'expect'} = $got eq 'pass' ? 1 : 0;
|
|
|
|
|
+ next;
|
|
|
|
|
+ }
|
|
|
|
|
+ fail ("The 'expect' in test '$test' is '$got', not 'pass' or 'fail'");
|
|
|
|
|
+ $fail++;
|
|
|
|
|
+ }
|
|
|
|
|
+ $fail and die ('Cannot continue');
|
|
|
|
|
+ # drop those who are expected to fail
|
|
|
|
|
+ @tests = grep { !$tests{$_}{'unsupported'} } @tests;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (@ARGV) {
|
|
|
|
|
+ my $warned;
|
|
|
|
|
+ foreach my $t (@ARGV) {
|
|
|
|
|
+ if (exists ($tests{$t})) {
|
|
|
|
|
+ $tests{$t}{'unsupported'} and
|
|
|
|
|
+ note ("Warn: Test '$t' is marked unsupported. Expect breakage");
|
|
|
|
|
+ test1 ($t, $tests{$t});
|
|
|
|
|
+ next;
|
|
|
|
|
+ }
|
|
|
|
|
+ fail ("Don't know how to test '$t'");
|
|
|
|
|
+ if (!$warned) {
|
|
|
|
|
+ note ("Available tests:\n" . join ("\n", map { " $_" } @tests));
|
|
|
|
|
+ $warned = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+} else {
|
|
|
|
|
+ # run all
|
|
|
|
|
+ foreach my $test (@tests) {
|
|
|
|
|
+ test1 ($test, $tests{$test});
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+done_testing;
|
|
|
|
|
+
|
|
|
|
|
+exit 0;
|
|
|
|
|
+
|
|
|
|
|
+=head1 DESCRIPTION
|
|
|
|
|
+
|
|
|
|
|
+Build ngircd for both TLS linkages, possibly using the following script:
|
|
|
|
|
+
|
|
|
|
|
+ #!/bin/sh
|
|
|
|
|
+ set -e
|
|
|
|
|
+ case "$1" in
|
|
|
|
|
+ openssl | gnutls)
|
|
|
|
|
+ [ -f ./configure ] || ./autogen.sh
|
|
|
|
|
+ ./configure \
|
|
|
|
|
+ --prefix=/usr \
|
|
|
|
|
+ --mandir="\${prefix}/share/man" \
|
|
|
|
|
+ --infodir="\${prefix}/share/info" \
|
|
|
|
|
+ --sysconfdir=/etc/ngircd \
|
|
|
|
|
+ "--with-$1"
|
|
|
|
|
+ make 2>&1 | tee "../build.$1.log"
|
|
|
|
|
+ cp src/ngircd/ngircd "../ngircd-$1"
|
|
|
|
|
+ ;;
|
|
|
|
|
+ *)
|
|
|
|
|
+ echo "Usage: $0 <gnutls|openssl>"
|
|
|
|
|
+ exit 1
|
|
|
|
|
+ ;;
|
|
|
|
|
+ esac
|
|
|
|
|
+
|
|
|
|
|
+One time only: Create the certificates
|
|
|
|
|
+
|
|
|
|
|
+ perl ngircd-test-tls-link \
|
|
|
|
|
+ --x509-populate \
|
|
|
|
|
+ --x509-dir ../x509-data/ \
|
|
|
|
|
+ --ngircd <path to any ngircd binary>
|
|
|
|
|
+
|
|
|
|
|
+Then run this program
|
|
|
|
|
+
|
|
|
|
|
+For GnuTLS:
|
|
|
|
|
+
|
|
|
|
|
+ ngircd-test-tls-link \
|
|
|
|
|
+ --x509-dir ../x509-data/ \
|
|
|
|
|
+ --ngircd ../ngircd-gnutls
|
|
|
|
|
+
|
|
|
|
|
+Likewise for OpenSSL:
|
|
|
|
|
+
|
|
|
|
|
+ (...)
|
|
|
|
|
+ --ngircd ../ngircd-openssl
|
|
|
|
|
+
|
|
|
|
|
+For interoperability tests:
|
|
|
|
|
+
|
|
|
|
|
+ ngircd-test-tls-link \
|
|
|
|
|
+ --x509-dir ../x509-data/ \
|
|
|
|
|
+ --ngircd ../ngircd-gnutls:../ngircd-openssl
|
|
|
|
|
+
|
|
|
|
|
+... also with the two binaries swapped.
|
|
|
|
|
+
|
|
|
|
|
+=head1 DEPENDENCIES
|
|
|
|
|
+
|
|
|
|
|
+The following programs, libraries and Perl modules must be installed:
|
|
|
|
|
+
|
|
|
|
|
+ faketime
|
|
|
|
|
+ openssl
|
|
|
|
|
+ libnss-wrapper
|
|
|
|
|
+ File::Slurp
|
|
|
|
|
+ Proc::Simple
|
|
|
|
|
+
|
|
|
|
|
+=head1 BUGS
|
|
|
|
|
+
|
|
|
|
|
+Hack.
|
|
|
|
|
+
|
|
|
|
|
+=head1 SEE ALSO
|
|
|
|
|
+
|
|
|
|
|
+ngircd(8)
|
|
|
|
|
+
|
|
|
|
|
+=head1 AUTHOR
|
|
|
|
|
+
|
|
|
|
|
+Christoph Biedl C<< <debian.axhn@manchmal.in-ulm.de> >>
|
|
|
|
|
+
|
|
|
|
|
+=head1 ACKNOWLEDGEMENTS
|
|
|
|
|
+
|
|
|
|
|
+Alex Barton for ngircd.
|
|
|
|
|
+
|
|
|
|
|
+=head1 COPYRIGHT & LICENSE
|
|
|
|
|
+
|
|
|
|
|
+ Copyright (C) 2014-2024 Christoph Biedl <debian.axhn@manchmal.in-ulm.de>
|
|
|
|
|
+
|
|
|
|
|
+ This program is free software; you can redistribute it and/or
|
|
|
|
|
+ modify it under the terms of the GNU General Public License as
|
|
|
|
|
+ published by the Free Software Foundation; either version 2 of the
|
|
|
|
|
+ License, or (at your option) any later version.
|
|
|
|
|
+
|
|
|
|
|
+ This package is distributed in the hope that it will be useful,
|
|
|
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
+ GNU General Public License for more details.
|
|
|
|
|
+
|
|
|
|
|
+ You should have received a copy of the GNU General Public License
|
|
|
|
|
+ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
|
+
|
|
|
|
|
+ On Debian systems, the complete text of the GNU General Public
|
|
|
|
|
+ License version 2 can be found in
|
|
|
|
|
+ "/usr/share/common-licenses/GPL-2".
|
|
|
|
|
+
|
|
|
|
|
+=cut
|