merged usage() information from master
[fwknop.git] / test / test-fwknop.pl
index 30d1af8..7ffd3a8 100755 (executable)
@@ -4,6 +4,7 @@ use File::Copy;
 use File::Path;
 use IO::Socket;
 use Data::Dumper;
+use Cwd;
 use Getopt::Long 'GetOptions';
 use strict;
 
@@ -22,10 +23,15 @@ my $gpg_client_home_dir = "$conf_dir/client-gpg";
 my $nat_conf            = "$conf_dir/nat_fwknopd.conf";
 my $default_conf        = "$conf_dir/default_fwknopd.conf";
 my $default_access_conf = "$conf_dir/default_access.conf";
+my $ecb_mode_access_conf = "$conf_dir/ecb_mode_access.conf";
+my $ctr_mode_access_conf = "$conf_dir/ctr_mode_access.conf";
+my $cfb_mode_access_conf = "$conf_dir/cfb_mode_access.conf";
+my $ofb_mode_access_conf = "$conf_dir/ofb_mode_access.conf";
 my $expired_access_conf = "$conf_dir/expired_stanza_access.conf";
 my $future_expired_access_conf = "$conf_dir/future_expired_stanza_access.conf";
 my $expired_epoch_access_conf = "$conf_dir/expired_epoch_stanza_access.conf";
 my $invalid_expire_access_conf = "$conf_dir/invalid_expire_access.conf";
+my $invalid_source_access_conf = "$conf_dir/invalid_source_access.conf";
 my $force_nat_access_conf = "$conf_dir/force_nat_access.conf";
 my $dual_key_usage_access_conf = "$conf_dir/dual_key_usage_access.conf";
 my $gpg_access_conf     = "$conf_dir/gpg_access.conf";
@@ -86,7 +92,9 @@ my $valgrind_str = '';
 my $saved_last_results = 0;
 my $diff_mode = 0;
 my $enable_recompilation_warnings_check = 0;
+my $enable_profile_coverage_check = 0;
 my $sudo_path = '';
+my $gcov_path = '';
 my $platform = '';
 my $help = 0;
 my $YES = 1;
@@ -116,6 +124,7 @@ exit 1 unless GetOptions(
     'test-exclude=s'    => \$test_exclude,
     'exclude=s'         => \$test_exclude,  ### synonym
     'enable-recompile-check' => \$enable_recompilation_warnings_check,
+    'enable-profile-coverage-check' => \$enable_profile_coverage_check,
     'List-mode'         => \$list_mode,
     'enable-valgrind'   => \$use_valgrind,
     'valgrind-path=s'   => \$valgrindCmd,
@@ -646,6 +655,20 @@ my @tests = (
     {
         'category' => 'Rijndael SPA',
         'subcategory' => 'client+server',
+        'detail'   => 'invalid SOURCE (tcp/22 ssh)',
+        'err_msg'  => 'SPA packet accepted',
+        'function' => \&spa_cycle,
+        'cmdline'  => $default_client_args,
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $default_conf -a $invalid_source_access_conf " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [qr/Fatal\serror\sparsing\sIP\sto\sint/],
+        'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael SPA',
+        'subcategory' => 'client+server',
         'detail'   => 'expired stanza (tcp/22 ssh)',
         'err_msg'  => 'SPA packet accepted',
         'function' => \&spa_cycle,
@@ -949,6 +972,81 @@ my @tests = (
         'server_conf' => $nat_conf,
         'fatal'    => $NO
     },
+    {
+        'category' => 'Rijndael SPA',
+        'subcategory' => 'client+server',
+        'detail'   => 'ECB mode (tcp/22 ssh)',
+        'err_msg'  => 'could not complete SPA cycle',
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args -M ecb",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $default_conf -a $ecb_mode_access_conf " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_negative_output_matches' => [qr/Decryption\sfailed/i],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael SPA',
+        'subcategory' => 'client+server',
+        'detail'   => 'CFB mode (tcp/22 ssh)',
+        'err_msg'  => 'could not complete SPA cycle',
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args -M cfb",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $default_conf -a $cfb_mode_access_conf " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_negative_output_matches' => [qr/Decryption\sfailed/i],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael SPA',
+        'subcategory' => 'client+server',
+        'detail'   => 'CTR mode (tcp/22 ssh)',
+        'err_msg'  => 'could not complete SPA cycle',
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args -M ctr",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $default_conf -a $ctr_mode_access_conf " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_negative_output_matches' => [qr/Decryption\sfailed/i],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'fatal'    => $NO
+    },
+    {
+        'category' => 'Rijndael SPA',
+        'subcategory' => 'client+server',
+        'detail'   => 'OFB mode (tcp/22 ssh)',
+        'err_msg'  => 'could not complete SPA cycle',
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args -M ofb",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $default_conf -a $ofb_mode_access_conf " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_negative_output_matches' => [qr/Decryption\sfailed/i],
+        'fw_rule_created' => $NEW_RULE_REQUIRED,
+        'fw_rule_removed' => $NEW_RULE_REMOVED,
+        'fatal'    => $NO
+    },
+
+    {
+        'category' => 'Rijndael SPA',
+        'subcategory' => 'client+server',
+        'detail'   => 'mode mismatch (tcp/22 ssh)',
+        'err_msg'  => 'server accepted mismatch enc mode',
+        'function' => \&spa_cycle,
+        'cmdline'  => "$default_client_args -M ecb",
+        'fwknopd_cmdline'  => "LD_LIBRARY_PATH=$lib_dir $valgrind_str " .
+            "$fwknopdCmd -c $default_conf -a $default_access_conf " .
+            "-d $default_digest_file -p $default_pid_file $intf_str",
+        'server_positive_output_matches' => [qr/Decryption\sfailed/i],
+        'fw_rule_created' => $REQUIRE_NO_NEW_RULE,
+        'fatal'    => $NO
+    },
 
     {
         'category' => 'Rijndael SPA',
@@ -1254,6 +1352,14 @@ my @tests = (
         'function' => \&digest_cache_structure,
         'fatal'    => $NO
     },
+
+    {
+        'category' => 'profile coverage',
+        'detail'   => 'gcov profile coverage',
+        'err_msg'  => 'profile coverage failed',
+        'function' => \&profile_coverage,
+        'fatal'    => $NO
+    },
 );
 
 if ($use_valgrind) {
@@ -1490,7 +1596,8 @@ sub compile_warnings() {
 
     ### look for compilation warnings - something like:
     ###     warning: ‘test’ is used uninitialized in this function
-    return 0 if &file_find_regex([qr/\swarning:\s/, qr/gcc\:.*\sunused/], $current_test_file);
+    return 0 if &file_find_regex([qr/\swarning:\s/, qr/gcc\:.*\sunused/],
+        $current_test_file);
 
     ### the new binaries should exist
     unless (-e $fwknopCmd and -x $fwknopCmd) {
@@ -1505,6 +1612,32 @@ sub compile_warnings() {
     return 1;
 }
 
+sub profile_coverage() {
+
+    ### check for any *.gcno files - if they don't exist, then fwknop was
+    ### not compiled with profile support
+    unless (glob('../client/*.gcno') and glob('../server/*.gcno')) {
+        &write_test_file("[-] ../client/*.gcno and " .
+            "../server/*.gcno files do not exist.\n", $current_test_file);
+        return 0;
+    }
+
+    my $curr_dir = getcwd() or die $!;
+
+    ### gcov -b ../client/*.gcno
+    for my $dir ('../client', '../server', '../lib/.libs') {
+        next unless -d $dir;
+        chdir $dir or die $!;
+        system "$gcov_path -b -u *.gcno > /dev/null 2>&1";
+        chdir $curr_dir or die $!;
+
+        &run_cmd(qq|grep "called 0 returned" $dir/*.gcov|,
+                $cmd_out_tmp, $current_test_file);
+    }
+
+    return 1;
+}
+
 sub binary_exists() {
     my $test_hr = shift;
     return 0 unless $test_hr->{'binary'};
@@ -2540,6 +2673,10 @@ sub init() {
         push @tests_to_exclude, 'recompilation';
     }
 
+    unless ($enable_profile_coverage_check) {
+        push @tests_to_exclude, 'profile coverage';
+    }
+
     $sudo_path = &find_command('sudo');
 
     unless ((&find_command('cc') or &find_command('gcc')) and &find_command('make')) {
@@ -2547,6 +2684,19 @@ sub init() {
         push @tests_to_exclude, 'recompilation';
     }
 
+    $gcov_path = &find_command('gcov');
+
+    if ($gcov_path) {
+        if ($enable_profile_coverage_check) {
+            for my $extension ('*.gcov', '*.gcda') {
+                ### remove profile output from any previous run
+                system qq{find .. -name $extension | xargs rm 2> /dev/null};
+            }
+        }
+    } else {
+        push @tests_to_exclude, 'profile coverage';
+    }
+
     open UNAME, "uname |" or die "[*] Could not execute uname: $!";
     while (<UNAME>) {
         if (/linux/i) {