Add testing for greylist()
This commit is contained in:
parent
1f43e30de1
commit
c01cdffb08
@ -360,7 +360,7 @@ sub greylist {
|
||||
my $value = $self->db->get($key);
|
||||
if ( ! $value ) {
|
||||
# new IP or entry timed out - record new
|
||||
$self->db->set( $key, sprintf $fmt, time, 1, 0, 0 );
|
||||
$self->db->set( $key, sprintf $fmt, $self->now, 1, 0, 0 );
|
||||
$self->log(LOGWARN, "fail: initial DENYSOFT, unknown");
|
||||
return $self->cleanup_and_return();
|
||||
}
|
||||
@ -371,8 +371,8 @@ sub greylist {
|
||||
if ($white) {
|
||||
|
||||
# white IP - accept unless timed out
|
||||
if (time - $ts < $config->{white_timeout}) {
|
||||
$self->db->set( $key, sprintf $fmt, time, $new, $black, ++$white );
|
||||
if ( $self->now - $ts < $config->{white_timeout} ) {
|
||||
$self->db->set( $key, sprintf $fmt, $self->now, $new, $black, ++$white );
|
||||
$self->log(LOGINFO, "pass: white, $white deliveries");
|
||||
return $self->cleanup_and_return(DECLINED);
|
||||
}
|
||||
@ -382,7 +382,7 @@ sub greylist {
|
||||
}
|
||||
|
||||
# Black IP - deny, but don't update timestamp
|
||||
if (time - $ts < $config->{black_timeout}) {
|
||||
if ( $self->now - $ts < $config->{black_timeout} ) {
|
||||
$self->db->set( $key, sprintf $fmt, $ts, $new, ++$black, 0 );
|
||||
$self->log(LOGWARN,
|
||||
"fail: black DENYSOFT - $black deferred connections");
|
||||
@ -390,8 +390,8 @@ sub greylist {
|
||||
}
|
||||
|
||||
# Grey IP - accept unless timed out
|
||||
elsif (time - $ts < $config->{grey_timeout}) {
|
||||
$self->db->set( $key, sprintf $fmt, time, $new, $black, 1 );
|
||||
elsif ( $self->now - $ts < $config->{grey_timeout} ) {
|
||||
$self->db->set( $key, sprintf $fmt, $self->now, $new, $black, 1 );
|
||||
$self->log(LOGWARN, "pass: updated grey->white");
|
||||
return $self->cleanup_and_return(DECLINED);
|
||||
}
|
||||
@ -400,6 +400,9 @@ sub greylist {
|
||||
return $self->cleanup_and_return(DECLINED);
|
||||
}
|
||||
|
||||
# This exists purely to be overridden for testing
|
||||
sub now { time() }
|
||||
|
||||
sub cleanup_and_return {
|
||||
my ($self, $return_val) = @_;
|
||||
|
||||
@ -461,7 +464,7 @@ sub prune_db {
|
||||
my $pruned = 0;
|
||||
foreach my $key ( $self->db->get_keys ) {
|
||||
my ($ts, $new, $black, $white) = split /:/, $self->db->get($key);
|
||||
my $age = time - $ts;
|
||||
my $age = $self->now - $ts;
|
||||
next if $age < $self->{_args}{white_timeout};
|
||||
$pruned++;
|
||||
$self->db->delete($key);
|
||||
|
@ -26,6 +26,7 @@ sub register_tests {
|
||||
$self->register_test("test_greylist_p0f_link");
|
||||
$self->register_test("test_greylist_p0f_uptime");
|
||||
$self->register_test('test_exclude_file_match');
|
||||
$self->register_test('test_greylist');
|
||||
}
|
||||
|
||||
sub test_load_exclude_files {
|
||||
@ -219,6 +220,68 @@ sub test_greylist_p0f_uptime {
|
||||
ok( ! $self->p0f_match(), 'p0f uptime miss');
|
||||
}
|
||||
|
||||
my $mocktime;
|
||||
sub test_greylist {
|
||||
my ( $self ) = @_;
|
||||
$self->{_args} = {
|
||||
remote_ip => 1,
|
||||
sender => 0,
|
||||
recipient => 0,
|
||||
reject => 1,
|
||||
black_timeout => 50 * 60, # 50m
|
||||
grey_timeout => 3 * 3600 + 20 * 60, # 3h:20m
|
||||
white_timeout => 36 * 3600 * 24, # 36 days
|
||||
p0f => 0,
|
||||
geoip => 0,
|
||||
};
|
||||
$self->connection->remote_host('example.com');
|
||||
$self->connection->remote_ip('1.2.3.4');
|
||||
my $sender = Qpsmtpd::Address->new( "<$test_email>" );
|
||||
my $rcpt = Qpsmtpd::Address->new( "<$test_email>" );
|
||||
my $start = time() - 40 * 3600 * 24; # 40 days ago
|
||||
$mocktime = $start;
|
||||
is( $self->rc( $self->greylist( $self->transaction, $sender, $rcpt ) ),
|
||||
'DENYSOFT: This mail is temporarily denied',
|
||||
'Initial connection attempt greylisted' );
|
||||
$mocktime = $start + 60 * 49;
|
||||
is( $self->rc( $self->greylist( $self->transaction, $sender, $rcpt ) ),
|
||||
'DENYSOFT: This mail is temporarily denied',
|
||||
'Greylisted 49 minutes later' );
|
||||
$mocktime = $start + 60 * 51;
|
||||
is( $self->rc( $self->greylist( $self->transaction, $sender, $rcpt ) ),
|
||||
'DECLINED',
|
||||
'Allowed 51 minutes later' );
|
||||
$mocktime = $start + 60 * 52 + 36 * 3600 * 24;
|
||||
$self->prune_db;
|
||||
is( $self->rc( $self->greylist( $self->transaction, $sender, $rcpt ) ),
|
||||
'DENYSOFT: This mail is temporarily denied',
|
||||
're-greylisted 36 days later' );
|
||||
|
||||
$self->connection->remote_ip('4.3.2.1');
|
||||
$mocktime = $start;
|
||||
is( $self->rc( $self->greylist( $self->transaction, $sender, $rcpt ) ),
|
||||
'DENYSOFT: This mail is temporarily denied',
|
||||
'Initial connection attempt greylisted for new IP' );
|
||||
$mocktime = $start + 36 * 3600 * 24 - 60;
|
||||
is( $self->rc( $self->greylist( $self->transaction, $sender, $rcpt ) ),
|
||||
# 'DENYSOFT: This mail is temporarily denied',
|
||||
# 'New IP still greylisted when greylist_timeout window is missed' );
|
||||
'DECLINED',
|
||||
"New IP allowed for 36 days, just like 'white' clients (huh?)" );
|
||||
}
|
||||
|
||||
{
|
||||
no warnings qw( redefine );
|
||||
sub now { $mocktime || time() }
|
||||
}
|
||||
|
||||
sub rc {
|
||||
my ( $self, $r, $msg ) = @_;
|
||||
return '' if ! defined $r;
|
||||
return return_code($r) if ! defined $msg;
|
||||
return return_code($r) . ": $msg";
|
||||
}
|
||||
|
||||
sub _reset_transaction {
|
||||
my $self = shift;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user