diff --git a/config.sample/dnsbl_allow b/config.sample/dnsbl_allow new file mode 100644 index 0000000..a9c72d5 --- /dev/null +++ b/config.sample/dnsbl_allow @@ -0,0 +1,2 @@ +# test entry for dnsbl plugin +192.168.99.5 diff --git a/plugins/check_badmailfrom b/plugins/check_badmailfrom index 975cecc..7b29316 100644 --- a/plugins/check_badmailfrom +++ b/plugins/check_badmailfrom @@ -58,7 +58,8 @@ sub hook_mail { @badmailfrom = @{$self->{_badmailfrom_config}}; }; - return DECLINED if $self->is_immune( $sender, \@badmailfrom ); + return DECLINED if $self->is_immune(); + return DECLINED if $self->is_immune_sender( $sender, \@badmailfrom ); my $host = lc $sender->host; my $from = lc($sender->user) . '@' . $host; @@ -104,7 +105,7 @@ sub hook_rcpt { return (DENY, $note); } -sub is_immune { +sub is_immune_sender { my ($self, $sender, $badmf ) = @_; if ( ! scalar @$badmf ) { diff --git a/plugins/check_badrcptto b/plugins/check_badrcptto index c13fb76..7b5f7d9 100644 --- a/plugins/check_badrcptto +++ b/plugins/check_badrcptto @@ -49,12 +49,15 @@ use Qpsmtpd::DSN; sub hook_rcpt { my ($self, $transaction, $recipient, %param) = @_; - return (DECLINED) if $self->qp->connection->relay_client(); + return (DECLINED) if $self->is_immune(); my ($host, $to) = $self->get_host_and_to( $recipient ) or return (DECLINED); - my @badrcptto = $self->qp->config("badrcptto") or return (DECLINED); + my @badrcptto = $self->qp->config("badrcptto") or do { + $self->log(LOGINFO, "skip: empty config"); + return (DECLINED); + }; for my $line (@badrcptto) { $line =~ s/^\s+//g; # trim leading whitespace diff --git a/plugins/check_earlytalker b/plugins/check_earlytalker index 7df31a2..b4b8e95 100644 --- a/plugins/check_earlytalker +++ b/plugins/check_earlytalker @@ -1,4 +1,5 @@ #!perl -w + =head1 NAME check_earlytalker - Check that the client doesn't talk before we send the SMTP banner @@ -16,9 +17,7 @@ on all mail/rcpt commands in the transaction. =head1 CONFIGURATION -=over 4 - -=item wait [integer] +=head2 wait [integer] The number of seconds to delay the initial greeting to see if the connecting host speaks first. The default is 1. Do not select a value that is too high, @@ -27,32 +26,40 @@ greeting timeouts -- these are known to range as low as 30 seconds, and may in some cases be configured lower by mailserver admins. Network transit time must also be allowed for. -=item action [string: deny, denysoft, log] +=head2 reject -What to do when matching an early-talker -- the options are I, -I or I. +Do we reject/deny connections to early talkers? -If I is specified, the connection will be allowed to proceed as normal, -and only a warning will be logged. + check_earlytalker reject [ 0 | 1 ] -The default is I. +Default: I -=item defer-reject [boolean] +=head2 reject_type [ temp | perm ] + +What type of rejection to send. A temporary rejection tells the remote server to try again later. A permanent error tells it to give up permanently. + +Default I. + +=head2 defer-reject [boolean] When an early-talker is detected, if this option is set to a true value, the SMTP greeting will be issued as usual, but all RCPT/MAIL commands will be -issued a deny or denysoft (depending on the value of I). The default +issued a deny or denysoft (depending on the value of I). The default is to react at the SMTP greeting stage by issuing the apropriate response code and terminating the SMTP connection. -=item check-at [ CONNECT | DATA ] + check_earlytalker defer-reject [ 0 | 1 ] + +=head2 check-at [ CONNECT | DATA ] Specifies when to check for early talkers. You can specify this option multiple times to check more than once. The default is I only. -=back +=head2 loglevel + +Adjust the quantity of logging for this plugin. See docs/logging.pod =cut @@ -67,7 +74,7 @@ sub register { if (@args % 2) { $self->log(LOGERROR, "Unrecognized/mismatched arguments"); - return undef; + return; } my %check_at; for (0..$#args) { @@ -82,11 +89,20 @@ sub register { } $self->{_args} = { 'wait' => 1, - 'action' => 'denysoft', - 'defer-reject' => 0, @args, 'check-at' => \%check_at, }; +# backwards compat with old 'action' argument + if ( defined $self->{_args}{action} && ! defined $self->{_args}{reject} ) { + $self->{_args}{reject} = $self->{_args}{action} =~ /^deny/i ? 1 : 0; + }; + if ( defined $self->{_args}{'defer-reject'} && ! defined $self->{_args}{reject_type} ) { + $self->{_args}{reject_type} = $self->{_args}{action} == 'denysoft' ? 'temp' : 'perm'; + }; + if ( ! defined $self->{_args}{reject_type} ) { + $self->{_args}{reject_type} = 'perm'; + }; +# /end compat if ( $qp->{conn} && $qp->{conn}->isa('Apache2::Connection')) { require APR::Const; APR::Const->import(qw(POLLIN SUCCESS)); @@ -98,117 +114,115 @@ sub register { $self->register_hook('data', 'data_handler'); } $self->register_hook('mail', 'mail_handler') - if $self->{_args}->{'defer-reject'}; - 1; + if $self->{_args}{'defer-reject'}; + $self->{_args}{reject} = 1 if ! defined $self->{_args}{reject}; } sub apr_connect_handler { my ($self, $transaction) = @_; return DECLINED unless $self->{_args}{'check-at'}{CONNECT}; - return DECLINED if ($self->connection->notes('whitelisthost')); - my $ip = $self->qp->connection->remote_ip; + return DECLINED if $self->is_immune(); - my $c = $self->qp->{conn}; - my $socket = $c->client_socket; - my $timeout = $self->{_args}->{'wait'} * 1_000_000; + my $c = $self->qp->{conn} or return DECLINED; + my $socket = $c->client_socket or return DECLINED; + my $timeout = $self->{_args}{'wait'} * 1_000_000; my $rc = $socket->poll($c->pool, $timeout, APR::Const::POLLIN()); if ($rc == APR::Const::SUCCESS()) { - $self->log(LOGNOTICE, "remote host started talking before we said hello [$ip]"); - if ($self->{_args}->{'defer-reject'}) { - $self->connection->notes('earlytalker', 1); - } - else { - my $msg = 'Connecting host started transmitting before SMTP greeting'; - return (DENY,$msg) if $self->{_args}->{'action'} eq 'deny'; - return (DENYSOFT,$msg) if $self->{_args}->{'action'} eq 'denysoft'; - } - } - else { - $self->log(LOGINFO, "pass: remote host said nothing spontaneous"); - } + if ($self->{_args}{'defer-reject'}) { + $self->qp->connection->notes('earlytalker', 1); + return DECLINED; + }; + return $self->log_and_deny(); + }; + return $self->log_and_pass(); } sub apr_data_handler { my ($self, $transaction) = @_; return DECLINED unless $self->{_args}{'check-at'}{DATA}; - return DECLINED if ($self->connection->notes('whitelisthost')); - my $ip = $self->qp->connection->remote_ip; + return DECLINED if $self->is_immune(); - my $c = $self->qp->{conn}; - my $socket = $c->client_socket; - my $timeout = $self->{_args}->{'wait'} * 1_000_000; + my $c = $self->qp->{conn} or return DECLINED; + my $socket = $c->client_socket or return DECLINED; + my $timeout = $self->{_args}{'wait'} * 1_000_000; my $rc = $socket->poll($c->pool, $timeout, APR::Const::POLLIN()); if ($rc == APR::Const::SUCCESS()) { - $self->log(LOGNOTICE, "remote host started talking before we said hello [$ip]"); - my $msg = 'Connecting host started transmitting before SMTP greeting'; - return (DENY,$msg) if $self->{_args}->{'action'} eq 'deny'; - return (DENYSOFT,$msg) if $self->{_args}->{'action'} eq 'denysoft'; - } - else { - $self->log(LOGINFO, "pass: remote host said nothing spontaneous"); - } + return $self->log_and_deny(); + }; + return $self->log_and_pass(); } sub connect_handler { - my ($self, $transaction) = @_; - my $in = new IO::Select; - my $ip = $self->qp->connection->remote_ip; + my ($self, $transaction) = @_; + my $in = new IO::Select; - return DECLINED unless $self->{_args}{'check-at'}{CONNECT}; - return DECLINED - if ($self->connection->notes('whitelisthost')); + return DECLINED unless $self->{_args}{'check-at'}{CONNECT}; + return DECLINED if $self->is_immune(); - $in->add(\*STDIN) || return DECLINED; - if ($in->can_read($self->{_args}->{'wait'})) { - $self->log(LOGNOTICE, "remote host started talking before we said hello [$ip]"); - if ($self->{_args}->{'defer-reject'}) { - $self->connection->notes('earlytalker', 1); - } else { - my $msg = 'Connecting host started transmitting before SMTP greeting'; - return (DENY,$msg) if $self->{_args}->{'action'} eq 'deny'; - return (DENYSOFT,$msg) if $self->{_args}->{'action'} eq 'denysoft'; - } - } else { - $self->log(LOGINFO, 'pass: remote host said nothing spontaneous'); - } - return DECLINED; + $in->add(\*STDIN) or return DECLINED; + if (! $in->can_read($self->{_args}{'wait'})) { + return $self->log_and_pass(); + }; + + if ( ! $self->{_args}{'defer-reject'}) { + return $self->log_and_deny(); + }; + + $self->qp->connection->notes('earlytalker', 1); + return DECLINED; } sub data_handler { - my ($self, $transaction) = @_; - my $in = new IO::Select; - my $ip = $self->qp->connection->remote_ip; + my ($self, $transaction) = @_; + my $in = new IO::Select; - return DECLINED unless $self->{_args}{'check-at'}{DATA}; - return DECLINED - if ($self->connection->notes('whitelisthost')); + return DECLINED unless $self->{_args}{'check-at'}{DATA}; + return DECLINED if $self->is_immune(); - $in->add(\*STDIN) || return DECLINED; - if ($in->can_read($self->{_args}->{'wait'})) { - $self->log(LOGNOTICE, "remote host started talking before we said hello [$ip]"); + $in->add(\*STDIN) or return DECLINED; + if ( ! $in->can_read($self->{_args}{'wait'})) { + return $self->log_and_pass(); + }; + + return $self->log_and_deny(); +}; + +sub log_and_pass { + my $self = shift; + my $ip = $self->qp->connection->remote_ip || 'remote host'; + $self->log(LOGINFO, "pass: $ip said nothing spontaneous"); + return DECLINED; +} + +sub log_and_deny { + my $self = shift; + + my $ip = $self->qp->connection->remote_ip || 'remote host'; my $msg = 'Connecting host started transmitting before SMTP greeting'; - return (DENY,$msg) if $self->{_args}->{'action'} eq 'deny'; - return (DENYSOFT,$msg) if $self->{_args}->{'action'} eq 'denysoft'; - } - else { - $self->log(LOGINFO, 'pass: remote host said nothing spontaneous'); - } - return DECLINED; + + $self->qp->connection->notes('earlytalker', 1); + $self->log(LOGNOTICE, "fail: $ip started talking before we said hello"); + + return ( $self->get_reject_type(), $msg ) if $self->{_args}{reject}; + return DECLINED; } sub mail_handler { my ($self, $transaction) = @_; - my $msg = 'Connecting host started transmitting before SMTP greeting'; - return DECLINED unless $self->connection->notes('earlytalker'); - return (DENY,$msg) if $self->{_args}->{'action'} eq 'deny'; - return (DENYSOFT,$msg) if $self->{_args}->{'action'} eq 'denysoft'; - return DECLINED; + return DECLINED unless $self->qp->connection->notes('earlytalker'); + return $self->log_and_deny(); } -1; +sub get_reject_type { + my $self = shift; + my $deny = $self->{_args}{reject_type} or return DENY; + return $deny eq 'temp' ? DENYSOFT + : $deny eq 'disconnect' ? DENY_DISCONNECT + : DENY; +}; diff --git a/plugins/dnsbl b/plugins/dnsbl index 3ecbed8..43b2e58 100644 --- a/plugins/dnsbl +++ b/plugins/dnsbl @@ -136,6 +136,7 @@ sub hook_connect { # perform RBLSMTPD checks to mimic Dan Bernstein's rblsmtpd return DECLINED if $self->is_set_rblsmtpd(); + return DECLINED if $self->is_immune(); return DECLINED if $self->ip_whitelisted(); my %dnsbl_zones = map { (split /:/, $_, 2)[0,1] } $self->qp->config('dnsbl_zones'); @@ -196,24 +197,13 @@ sub is_set_rblsmtpd { }; sub ip_whitelisted { - my ($self) = @_; + my $self = shift; - my $remote_ip = $self->qp->connection->remote_ip; - my $white = $self->connection->notes('whitelisthost'); - if ( $white ) { - $self->log(LOGDEBUG, "skip: whitelist overrode blacklist: $white"); - return 1; - }; + my $remote_ip = shift || $self->qp->connection->remote_ip; - if ( $self->qp->connection->relay_client() ) { - $self->log(LOGWARN, "skip: don't blacklist relay/auth clients"); - return 1; - }; - - return grep { s/\.?$/./; - $_ eq substr($remote_ip . '.', 0, length $_) - } - $self->qp->config('dnsbl_allow'); + return + grep { s/\.?$/./; $_ eq substr($remote_ip . '.', 0, length $_) } + $self->qp->config('dnsbl_allow'); }; sub process_sockets { @@ -306,6 +296,8 @@ sub process_sockets { sub hook_rcpt { my ($self, $transaction, $rcpt, %param) = @_; + return DECLINED if $self->is_immune(); + # RBLSMTPD being non-empty means it contains the failure message to return if (defined $ENV{'RBLSMTPD'} && $ENV{'RBLSMTPD'} ne '') { my $result = $ENV{'RBLSMTPD'}; @@ -346,6 +338,6 @@ sub get_reject_type { return $self->{_args}{reject_type} eq 'temp' ? DENYSOFT : $self->{_args}{reject_type} eq 'disconnect' ? DENY_DISCONNECT - : DENY; + : $default; }; diff --git a/plugins/domainkeys b/plugins/domainkeys index dd8a371..aaebed3 100644 --- a/plugins/domainkeys +++ b/plugins/domainkeys @@ -88,6 +88,8 @@ sub data_post_handler { return DECLINED; }; + return DECLINED if $self->is_immune(); + my $body = $self->assemble_body( $transaction ); my $message = load Mail::DomainKeys::Message( diff --git a/plugins/greylisting b/plugins/greylisting index e247402..556fbf1 100644 --- a/plugins/greylisting +++ b/plugins/greylisting @@ -17,7 +17,7 @@ has configurable timeout periods (black/grey/white) to control whether connections are allowed, instead of using connection counts or rates. Automatic whitelisting is enabled for relayclients, whitelisted hosts, -whitelisted senders, TLS connections, p0f matches, and geoip matches. +whitelisted senders, p0f matches, and geoip matches. =head1 TRIPLETS @@ -169,7 +169,7 @@ use strict; use warnings; use Qpsmtpd::Constants; -my $VERSION = '0.10'; +my $VERSION = '0.11'; BEGIN { @AnyDBM_File::ISA = qw(DB_File GDBM_File NDBM_File) } use AnyDBM_File; @@ -268,6 +268,8 @@ sub greylist { join(',',map { $_ . '=' . $config->{$_} } sort keys %$config)); return DECLINED if $self->is_immune(); + return DECLINED if ! $self->is_p0f_match(); + return DECLINED if $self->geoip_match(); my $db = $self->get_db_location(); my $lock = $self->get_db_lock( $db ) or return DECLINED; @@ -516,6 +518,8 @@ sub prune_db { sub p0f_match { my $self = shift; + return if ! $self->{_args}{p0f}; + my $p0f = $self->connection->notes('p0f'); if ( !$p0f || !ref $p0f ) { # p0f fingerprint info not found $self->LOGINFO(LOGERROR, "p0f info missing"); @@ -559,6 +563,8 @@ sub p0f_match { sub geoip_match { my $self = shift; + return if ! $self->{_args}{geoip}; + my $country = $self->connection->notes('geoip_country'); my $c_name = $self->connection->notes('geoip_country_name') || ''; diff --git a/plugins/rhsbl b/plugins/rhsbl index 2ba0b5f..5706f0c 100644 --- a/plugins/rhsbl +++ b/plugins/rhsbl @@ -25,6 +25,10 @@ to return in the SMTP conversation e.g. =cut +use strict; +use warnings; + +use Qpsmtpd::Constants; sub register { my ($self, $qp, $denial ) = @_; @@ -34,12 +38,25 @@ sub register { else { $self->{_rhsbl}->{DENY} = DENY; } - } sub hook_mail { my ($self, $transaction, $sender, %param) = @_; + return DECLINED if $self->is_immune(); + + if ($sender->format eq '<>') { + $self->log(LOGINFO, 'skip, null sender'); + return DECLINED; + }; + + my %rhsbl_zones = map { (split /\s+/, $_, 2)[0,1] } $self->qp->config('rhsbl_zones'); + + if ( ! %rhsbl_zones ) { + $self->log(LOGINFO, 'skip, no zones'); + return DECLINED; + }; + my $res = new Net::DNS::Resolver; my $sel = IO::Select->new(); my %rhsbl_zones_map = (); @@ -48,9 +65,6 @@ sub hook_mail { # here and pick up any results in the RCPT handler. # MTAs gets confused when you reject mail during MAIL FROM: - my %rhsbl_zones = map { (split /\s+/, $_, 2)[0,1] } $self->qp->config('rhsbl_zones'); - - if ($sender->format ne '<>' and %rhsbl_zones) { push(my @hosts, $sender->host); #my $helo = $self->qp->connection->hello_host; #push(@hosts, $helo) if $helo && $helo ne $sender->host; @@ -70,28 +84,29 @@ sub hook_mail { %{$self->{_rhsbl_zones_map}} = %rhsbl_zones_map; $transaction->notes('rhsbl_sockets', $sel); - } else { - $self->log(LOGDEBUG, 'no RHS checks necessary'); - } return DECLINED; } sub hook_rcpt { my ($self, $transaction, $rcpt) = @_; - my $host = $transaction->sender->host; - my $hello = $self->qp->connection->hello_host; - my $result = $self->process_sockets; - if ($result && defined($self->{_rhsbl_zones_map}{$result})) { + my $result = $self->process_sockets or do { + $self->log(LOGINFO, "pass"); + return DECLINED; + }; + + + if ( defined($self->{_rhsbl_zones_map}{$result}) ) { + my $host = $transaction->sender->host; if ($result =~ /^$host\./ ) { return ($self->{_rhsbl}->{DENY}, "Mail from $host rejected because it " . $self->{_rhsbl_zones_map}{$result}); } else { + my $hello = $self->qp->connection->hello_host; return ($self->{_rhsbl}->{DENY}, "Mail from HELO $hello rejected because it " . $self->{_rhsbl_zones_map}{$result}); } } - return ($self->{_rhsbl}->{DENY}, $result) if $result; - return DECLINED; + return ($self->{_rhsbl}->{DENY}, $result); } sub process_sockets { diff --git a/plugins/sender_permitted_from b/plugins/sender_permitted_from index 17805f1..d7baca9 100644 --- a/plugins/sender_permitted_from +++ b/plugins/sender_permitted_from @@ -80,6 +80,8 @@ sub register { sub hook_mail { my ($self, $transaction, $sender, %param) = @_; + return (DECLINED) if $self->is_immune(); + if ( ! $self->{_args}{reject} ) { $self->log( LOGINFO, "skip: disabled in config" ); return (DECLINED); @@ -91,7 +93,7 @@ sub hook_mail { return (DECLINED, "SPF - null sender"); }; - if ( $self->is_relayclient() ) { + if ( $self->is_in_relayclients() ) { return (DECLINED, "SPF - relaying permitted"); }; @@ -189,16 +191,11 @@ sub hook_data_post { return DECLINED; } -sub is_relayclient { +sub is_in_relayclients { my $self = shift; # If we are receiving from a relay permitted host, then we are probably # not the delivery system, and so we shouldn't check - if ( $self->qp->connection->relay_client() ) { - $self->log( LOGINFO, "skip: relaying permitted (relay_client)" ); - return 1; - }; - my $client_ip = $self->qp->connection->remote_ip; my @relay_clients = $self->qp->config('relayclients'); my $more_relay_clients = $self->qp->config('morerelayclients', 'map'); diff --git a/plugins/spamassassin b/plugins/spamassassin index 8bac5a5..1101f8e 100644 --- a/plugins/spamassassin +++ b/plugins/spamassassin @@ -163,15 +163,12 @@ sub register { sub hook_data_post { my ($self, $transaction) = @_; + return (DECLINED) if $self->is_immune(); + if ( $transaction->data_size > 500_000 ) { $self->log(LOGINFO, "skip: too large (".$transaction->data_size.")"); return (DECLINED); }; - if ( $self->{_args}{relayclient} && $self->{_args}{relayclient} eq 'skip' - && $self->qp->connection->relay_client() ) { - $self->log(LOGINFO, "skip: relayclient" ); - return (DECLINED); - }; my $SPAMD = $self->connect_to_spamd() or return (DECLINED); my $username = $self->select_spamd_username( $transaction ); diff --git a/plugins/uribl b/plugins/uribl index 163797a..ab7498b 100644 --- a/plugins/uribl +++ b/plugins/uribl @@ -478,6 +478,8 @@ sub collect_results { sub data_handler { my ($self, $transaction) = @_; + return (DECLINED) if $self->is_immune(); + my $queries = $self->lookup_start($transaction, sub { my ($self, $name) = @_; return $self->send_query($name); diff --git a/t/plugin_tests/check_badmailfrom b/t/plugin_tests/check_badmailfrom index 60610fe..5b7bde1 100644 --- a/t/plugin_tests/check_badmailfrom +++ b/t/plugin_tests/check_badmailfrom @@ -8,36 +8,36 @@ use Qpsmtpd::Address; sub register_tests { my $self = shift; - $self->register_test("test_badmailfrom_is_immune", 5); + $self->register_test("test_badmailfrom_is_immune_sender", 5); $self->register_test("test_badmailfrom_match", 7); $self->register_test("test_badmailfrom_hook_mail", 4); $self->register_test("test_badmailfrom_hook_rcpt", 2); } -sub test_badmailfrom_is_immune { +sub test_badmailfrom_is_immune_sender { my $self = shift; my $transaction = $self->qp->transaction; my $test_email = 'matt@test.com'; my $address = Qpsmtpd::Address->new( "<$test_email>" ); $transaction->sender($address); - ok( $self->is_immune( $transaction->sender, [] ), "is_immune, empty list"); + ok( $self->is_immune_sender( $transaction->sender, [] ), "empty list"); $address = Qpsmtpd::Address->new( '<>' ); $transaction->sender($address); - ok( $self->is_immune( $transaction->sender, ['bad@example.com'] ), "is_immune, null sender"); + ok( $self->is_immune_sender( $transaction->sender, ['bad@example.com'] ), "null sender"); $address = Qpsmtpd::Address->new( '' ); $transaction->sender($address); - ok( $self->is_immune( $transaction->sender, ['bad@example.com'] ), "is_immune, missing host"); + ok( $self->is_immune_sender( $transaction->sender, ['bad@example.com'] ), "missing host"); $address = Qpsmtpd::Address->new( '<@example.com>' ); $transaction->sender($address); - ok( $self->is_immune( $transaction->sender, ['bad@example.com'] ), "is_immune, missing user"); + ok( $self->is_immune_sender( $transaction->sender, ['bad@example.com'] ), "missing user"); $address = Qpsmtpd::Address->new( '' ); $transaction->sender($address); - ok( ! $self->is_immune( $transaction->sender, ['bad@example.com'] ), "is_immune, false"); + ok( ! $self->is_immune_sender( $transaction->sender, ['bad@example.com'] ), "false"); }; sub test_badmailfrom_hook_mail { diff --git a/t/plugin_tests/check_earlytalker b/t/plugin_tests/check_earlytalker new file mode 100644 index 0000000..570aebd --- /dev/null +++ b/t/plugin_tests/check_earlytalker @@ -0,0 +1,147 @@ +#!perl -w + +use strict; +use warnings; + +use Qpsmtpd::Constants; + +sub register_tests { + my $self = shift; + + $self->register_test('test_reject_type', 3); + $self->register_test('test_log_and_pass', 1); + $self->register_test('test_log_and_deny', 3); + $self->register_test('test_data_handler', 3); + $self->register_test('test_connect_handler', 3); + $self->register_test('test_apr_data_handler', 3); + $self->register_test('test_apr_connect_handler', 3); + $self->register_test('test_mail_handler', 4); +} + +sub test_apr_connect_handler { + my $self = shift; + + $self->{_args}{'check-at'} = undef; + my ($code, $mess) = $self->apr_connect_handler(); + cmp_ok( $code, '==', DECLINED, "no check-at set"); + + $self->{_args}{'check-at'}{'DATA'} = 1; + $self->qp->connection->notes('whitelisthost', 1); + ($code, $mess) = $self->apr_connect_handler(); + cmp_ok( $code, '==', DECLINED, "whitelisted host"); + + $self->qp->connection->notes('whitelisthost', 0); + ($code, $mess) = $self->apr_connect_handler(); + cmp_ok( $code, '==', DECLINED, "not sure"); +}; + +sub test_apr_data_handler { + my $self = shift; + + $self->{_args}{'check-at'} = undef; + my ($code, $mess) = $self->apr_data_handler(); + cmp_ok( $code, '==', DECLINED, "no check-at set"); + + $self->{_args}{'check-at'}{'DATA'} = 1; + $self->qp->connection->notes('whitelisthost', 1); + ($code, $mess) = $self->apr_data_handler(); + cmp_ok( $code, '==', DECLINED, "whitelisted host"); + + $self->qp->connection->notes('whitelisthost', 0); + ($code, $mess) = $self->apr_data_handler(); + cmp_ok( $code, '==', DECLINED, "not sure"); +}; + +sub test_connect_handler { + my $self = shift; + + $self->{_args}{'check-at'} = undef; + my ($code, $mess) = $self->connect_handler(); + cmp_ok( $code, '==', DECLINED, "no check-at set"); + + $self->{_args}{'check-at'}{'CONNECT'} = 1; + $self->qp->connection->notes('whitelisthost', 1); + ($code, $mess) = $self->connect_handler(); + cmp_ok( $code, '==', DECLINED, "whitelisted host"); + + $self->qp->connection->notes('whitelisthost', 0); + ($code, $mess) = $self->connect_handler(); + cmp_ok( $code, '==', DECLINED, "not sure"); +}; + +sub test_data_handler { + my $self = shift; + + $self->{_args}{'check-at'} = undef; + my ($code, $mess) = $self->data_handler(); + cmp_ok( $code, '==', DECLINED, "no check-at set"); + + $self->{_args}{'check-at'}{'DATA'} = 1; + $self->qp->connection->notes('whitelisthost', 1); + ($code, $mess) = $self->data_handler(); + cmp_ok( $code, '==', DECLINED, "whitelisted host"); + + $self->qp->connection->notes('whitelisthost', 0); + ($code, $mess) = $self->data_handler(); + cmp_ok( $code, '==', DECLINED, "not sure"); +}; + +sub test_log_and_pass { + my $self = shift; + + my ($code, $mess) = $self->log_and_pass(); + cmp_ok( $code, '==', DECLINED, "default"); +}; + +sub test_log_and_deny { + my $self = shift; + + $self->{_args}{reject_type} = undef; + + my ($code, $mess) = $self->log_and_deny(); + cmp_ok( $code, '==', DENY, "default"); + + $self->{_args}{reject_type} = 'temp'; + ($code, $mess) = $self->log_and_deny(); + cmp_ok( $code, '==', DENYSOFT, "bad, temp"); + + $self->{_args}{reject_type} = 'disconnect'; + ($code, $mess) = $self->log_and_deny(); + cmp_ok( $code, '==', DENY_DISCONNECT, "bad, disconnect"); +}; + +sub test_mail_handler { + my $self = shift; + + $self->{_args}{reject_type} = undef; + $self->qp->connection->notes('earlytalker', 0); + + my ($code, $mess) = $self->mail_handler(); + cmp_ok( $code, '==', DECLINED, "good"); + + $self->qp->connection->notes('earlytalker', 1); + ($code, $mess) = $self->mail_handler(); + cmp_ok( $code, '==', DENY, "bad"); + + $self->{_args}{reject_type} = 'temp'; + ($code, $mess) = $self->mail_handler(); + cmp_ok( $code, '==', DENYSOFT, "bad, temp"); + + $self->{_args}{reject_type} = 'disconnect'; + ($code, $mess) = $self->mail_handler(); + cmp_ok( $code, '==', DENY_DISCONNECT, "bad, disconnect"); +}; + +sub test_reject_type { + my $self = shift; + + $self->{_args}{reject_type} = undef; + cmp_ok( $self->get_reject_type(), '==', DENY, "default"); + + $self->{_args}{reject_type} = 'temp'; + cmp_ok( $self->get_reject_type(), '==', DENYSOFT, "defer"); + + $self->{_args}{reject_type} = 'disconnect'; + cmp_ok( $self->get_reject_type(), '==', DENY_DISCONNECT, "disconnect"); +}; + diff --git a/t/plugin_tests/dnsbl b/t/plugin_tests/dnsbl index 76fe046..ca14b7c 100644 --- a/t/plugin_tests/dnsbl +++ b/t/plugin_tests/dnsbl @@ -19,17 +19,16 @@ sub register_tests { sub test_ip_whitelisted { my $self = shift; - $self->qp->connection->remote_ip('10.1.1.1'); + $self->qp->connection->remote_ip('192.168.99.5'); + ok( $self->ip_whitelisted(), "+"); - $self->qp->connection->relay_client(1); - ok( $self->ip_whitelisted('10.1.1.1'), "yes, +"); + $self->qp->connection->remote_ip('192.168.99.6'); + ok( ! $self->ip_whitelisted(), "-"); - $self->qp->connection->relay_client(0); - ok( ! $self->ip_whitelisted('10.1.1.1'), "no, -"); - - $self->connection->notes('whitelisthost', 'hello honey!'); - ok( $self->ip_whitelisted('10.1.1.1'), "yes, +"); - $self->connection->notes('whitelisthost', undef); + $self->qp->connection->remote_ip('192.168.99.5'); + $self->qp->connection->notes('whitelisthost', 'hello honey!'); + ok( $self->ip_whitelisted(), "+"); + $self->qp->connection->notes('whitelisthost', undef); }; sub test_is_set_rblsmtpd {