155 lines
5.0 KiB
Perl
155 lines
5.0 KiB
Perl
#!/usr/bin/perl
|
|
# Unit tests for Fail2Ban incremental-ban helpers.
|
|
|
|
use strict;
|
|
use warnings;
|
|
no warnings 'once';
|
|
use Test::More;
|
|
use File::Basename qw(dirname);
|
|
use File::Spec;
|
|
use Cwd qw(abs_path);
|
|
|
|
BEGIN {
|
|
# fail2ban-lib.pl imports WebminCore and initializes module globals at
|
|
# load time. Stub only those load-time dependencies so its pure helpers
|
|
# can be tested without a Webmin installation.
|
|
$INC{'WebminCore.pm'} = 1;
|
|
package WebminCore;
|
|
sub import
|
|
{
|
|
my $caller = caller;
|
|
no strict 'refs';
|
|
*{$caller.'::init_config'} = sub { };
|
|
*{$caller.'::get_module_acl'} = sub { return (); };
|
|
*{$caller.'::compare_version_numbers'} = sub {
|
|
my ($left, $right) = @_;
|
|
my @left = split(/\./, $left);
|
|
my @right = split(/\./, $right);
|
|
my $count = @left > @right ? scalar(@left) : scalar(@right);
|
|
for(my $i = 0; $i < $count; $i++) {
|
|
my $cmp = ($left[$i] || 0) <=> ($right[$i] || 0);
|
|
return $cmp if ($cmp);
|
|
}
|
|
return 0;
|
|
};
|
|
}
|
|
}
|
|
|
|
my $root = abs_path(File::Spec->catdir(dirname(__FILE__), '..'));
|
|
chdir($root) or die "chdir($root): $!";
|
|
do './fail2ban/fail2ban-lib.pl' or die $@ || $!;
|
|
|
|
subtest 'version support' => sub {
|
|
ok(!main::supports_bantime_increment('0.10.6'), '0.10 is unsupported');
|
|
ok(!main::supports_bantime_increment('0.11.0'), '0.11.0 is unsupported');
|
|
ok(main::supports_bantime_increment('0.11.1'), '0.11.1 is supported');
|
|
ok(main::supports_bantime_increment('0.11.2'), 'newer 0.11 is supported');
|
|
ok(main::supports_bantime_increment('1.0.0'), '1.0 is supported');
|
|
};
|
|
|
|
subtest 'boolean canonicalization' => sub {
|
|
is(main::canonical_fail2ban_boolean(undef), '', 'undefined stays unset');
|
|
is(main::canonical_fail2ban_boolean('YES'), 'true', 'yes becomes true');
|
|
is(main::canonical_fail2ban_boolean('on'), 'true', 'on becomes true');
|
|
is(main::canonical_fail2ban_boolean('0'), 'false', 'zero becomes false');
|
|
is(main::canonical_fail2ban_boolean('No'), 'false', 'no becomes false');
|
|
is(main::canonical_fail2ban_boolean('invalid'), 'invalid',
|
|
'unknown values remain visible for correction');
|
|
};
|
|
|
|
subtest 'positive duration validation' => sub {
|
|
foreach my $duration ('600', '30m', '1d 12h', '1d12h',
|
|
'2 weeks', '1month 2days', '0.5h') {
|
|
ok(main::valid_positive_fail2ban_duration($duration),
|
|
"accepts $duration");
|
|
}
|
|
foreach my $duration ('', '0', '0m', '-1', '1d+12h',
|
|
'1d;system("id")', 'forever', '1m 2',
|
|
"1\nm", "1\r\nm") {
|
|
ok(!main::valid_positive_fail2ban_duration($duration),
|
|
"rejects $duration");
|
|
}
|
|
};
|
|
|
|
subtest 'non-negative duration validation' => sub {
|
|
foreach my $duration ('0', '0m', '0 hours', '600', '30m', '1d 12h') {
|
|
ok(main::valid_nonnegative_fail2ban_duration($duration),
|
|
"accepts $duration");
|
|
}
|
|
foreach my $duration ('', '-1', '1d+12h', 'forever') {
|
|
ok(!main::valid_nonnegative_fail2ban_duration($duration),
|
|
"rejects $duration");
|
|
}
|
|
};
|
|
|
|
subtest 'growth factor validation' => sub {
|
|
foreach my $factor ('1', '2', '0.5', '.25', '24.0') {
|
|
ok(main::valid_bantime_factor($factor), "accepts $factor");
|
|
}
|
|
foreach my $factor ('', '0', '-1', '1+1', 'inf', '1.') {
|
|
ok(!main::valid_bantime_factor($factor), "rejects $factor");
|
|
}
|
|
};
|
|
|
|
subtest 'form validation' => sub {
|
|
my %valid = (
|
|
'bantime_increment' => '',
|
|
'bantime_factor_def' => 1,
|
|
'bantime_maxtime_def' => 1,
|
|
'bantime_overalljails' => '',
|
|
'bantime_rndtime_def' => 1,
|
|
);
|
|
is(main::validate_bantime_increment_inputs(\%valid), undef,
|
|
'all-default input is valid');
|
|
|
|
my %invalid = (%valid, 'bantime_increment' => 'maybe');
|
|
is(main::validate_bantime_increment_inputs(\%invalid),
|
|
'jail_ebantime_increment', 'invalid enable value is identified');
|
|
|
|
%invalid = (%valid, 'bantime_factor_def' => 0,
|
|
'bantime_factor' => '2 * 3');
|
|
is(main::validate_bantime_increment_inputs(\%invalid),
|
|
'jail_ebantime_factor', 'factor expressions are rejected');
|
|
|
|
%invalid = (%valid, 'bantime_maxtime_def' => 0,
|
|
'bantime_maxtime' => '0');
|
|
is(main::validate_bantime_increment_inputs(\%invalid),
|
|
'jail_ebantime_maxtime', 'zero maximum time is rejected');
|
|
|
|
my %zero_rndtime = (%valid, 'bantime_rndtime_def' => 0,
|
|
'bantime_rndtime' => '0');
|
|
is(main::validate_bantime_increment_inputs(\%zero_rndtime), undef,
|
|
'zero random time is accepted to disable inherited jitter');
|
|
};
|
|
|
|
subtest 'save mapping' => sub {
|
|
my @saved;
|
|
my $jail = { 'name' => 'sshd' };
|
|
my %input = (
|
|
'bantime_increment' => 'true',
|
|
'bantime_factor_def' => 1,
|
|
'bantime_maxtime_def' => 0,
|
|
'bantime_maxtime' => '5w',
|
|
'bantime_overalljails' => 'false',
|
|
'bantime_rndtime_def' => 1,
|
|
);
|
|
{
|
|
no warnings 'redefine';
|
|
local *main::save_directive = sub {
|
|
my ($name, $value, $section) = @_;
|
|
push(@saved, [ $name, $value, $section ]);
|
|
};
|
|
main::save_bantime_increment_options(\%input, $jail);
|
|
}
|
|
is_deeply(
|
|
[ map { [ $_->[0], $_->[1] ] } @saved ],
|
|
[ [ 'bantime.increment', 'true' ],
|
|
[ 'bantime.factor', undef ],
|
|
[ 'bantime.maxtime', '5w' ],
|
|
[ 'bantime.overalljails', 'false' ],
|
|
[ 'bantime.rndtime', undef ] ],
|
|
'form fields map through standard directive handling');
|
|
};
|
|
|
|
done_testing();
|