dns_whitelist_soft: tiny tweaks of little consequence

This commit is contained in:
Matt Simerson 2012-06-23 00:43:20 -04:00
parent 8156341c6e
commit 3e223ef9dc

View File

@ -1,4 +1,5 @@
#!perl -w #!perl -w
=head1 NAME =head1 NAME
dns_whitelist_soft - dns-based whitelist override for other qpsmtpd plugins dns_whitelist_soft - dns-based whitelist override for other qpsmtpd plugins
@ -48,6 +49,17 @@ based on the 'whitelist' plugin by Devin Carraway <qpsmtpd@devin.com>.
=cut =cut
use strict;
use warnings;
use Qpsmtpd::Constants;
sub register {
my ( $self, $qp ) = (shift, shift);
$self->log(LOGERROR, "Bad arguments") if @_ % 2;
$self->{_args} = { @_ };
}
sub hook_connect { sub hook_connect {
my ($self, $transaction) = @_; my ($self, $transaction) = @_;
@ -58,7 +70,7 @@ sub hook_connect {
return DECLINED unless %whitelist_zones; return DECLINED unless %whitelist_zones;
my $reversed_ip = join(".", reverse(split(/\./, $remote_ip))); my $reversed_ip = join('.', reverse(split(/\./, $remote_ip)));
# we queue these lookups in the background and just fetch the # we queue these lookups in the background and just fetch the
# results in the first rcpt handler # results in the first rcpt handler
@ -68,11 +80,10 @@ sub hook_connect {
for my $dnsbl (keys %whitelist_zones) { for my $dnsbl (keys %whitelist_zones) {
$self->log(LOGDEBUG, "Checking $reversed_ip.$dnsbl in the background"); $self->log(LOGDEBUG, "Checking $reversed_ip.$dnsbl in the background");
$sel->add($res->bgsend("$reversed_ip.$dnsbl", "TXT")); $sel->add($res->bgsend("$reversed_ip.$dnsbl", 'TXT'));
} }
$self->connection->notes('whitelist_sockets', $sel); $self->connection->notes('whitelist_sockets', $sel);
return DECLINED; return DECLINED;
} }
@ -81,55 +92,54 @@ sub process_sockets {
my $conn = $self->connection; my $conn = $self->connection;
return $conn->notes('whitelisthost') return $conn->notes('whitelisthost') if $conn->notes('whitelisthost');
if $conn->notes('whitelisthost');
my $res = new Net::DNS::Resolver; my $res = new Net::DNS::Resolver;
my $sel = $conn->notes('whitelist_sockets') or return ""; my $sel = $conn->notes('whitelist_sockets') or return '';
my $result;
$self->log(LOGDEBUG, "waiting for whitelist dns"); $self->log(LOGDEBUG, "waiting for whitelist dns");
# don't wait more than 4 seconds here # don't wait more than 4 seconds here
my @ready = $sel->can_read(4); my @ready = $sel->can_read(4);
$self->log(LOGDEBUG, "DONE waiting for whitelist dns, got ", $self->log(LOGDEBUG, "done waiting for whitelist dns, got ",
scalar @ready, " answers ...") ; scalar @ready, " answers ...");
return '' unless @ready; return '' unless @ready;
for my $socket (@ready) { my $result;
my $query = $res->bgread($socket);
$sel->remove($socket);
undef $socket;
my $whitelist; for my $socket (@ready) {
my $query = $res->bgread($socket);
$sel->remove($socket);
undef $socket;
if ($query) { my $whitelist;
my $a_record = 0;
foreach my $rr ($query->answer) {
$a_record = 1 if $rr->type eq "A";
my $name = $rr->name;
($whitelist) = ($name =~ m/(?:\d+\.){4}(.*)/) unless $whitelist;
$whitelist = $name unless $whitelist;
$self->log(LOGDEBUG, "name ", $rr->name);
next unless $rr->type eq "TXT";
$self->log(LOGDEBUG, "got txt record");
$result = $rr->txtdata and last;
}
$a_record and $result = "Blocked by $whitelist";
}
else {
$self->log(LOGERROR, "$whitelist query failed: ", $res->errorstring)
unless $res->errorstring eq "NXDOMAIN";
}
if ($result) { if ($query) {
#kill any other pending I/O my $a_record = 0;
$conn->notes('whitelist_sockets', undef); foreach my $rr ($query->answer) {
return $conn->notes('whitelisthost', $result); $a_record = 1 if $rr->type eq 'A';
my $name = $rr->name;
($whitelist) = ($name =~ m/(?:\d+\.){4}(.*)/) unless $whitelist;
$whitelist = $name unless $whitelist;
$self->log(LOGDEBUG, 'name ', $rr->name);
next unless $rr->type eq 'TXT';
$self->log(LOGDEBUG, "got txt record");
$result = $rr->txtdata and last;
}
$a_record and $result = "Blocked by $whitelist";
}
else {
$self->log(LOGERROR, "$whitelist query failed: ", $res->errorstring)
if $res->errorstring ne "NXDOMAIN";
}
if ($result) {
# kill any other pending I/O
$conn->notes('whitelist_sockets', undef);
return $conn->notes('whitelisthost', $result);
}
} }
}
if ($sel->count) { if ($sel->count) {
# loop around if we have dns blacklists left to see results from # loop around if we have dns blacklists left to see results from
@ -142,12 +152,11 @@ sub process_sockets {
$conn->notes('whitelist_sockets', undef); $conn->notes('whitelist_sockets', undef);
return $conn->notes('whitelisthost', $result); return $conn->notes('whitelisthost', $result);
} }
sub hook_rcpt { sub hook_rcpt {
my ($self, $transaction, $rcpt, %param) = @_; my ($self, $transaction, $rcpt, %param) = @_;
my $ip = $self->qp->connection->remote_ip || return (DECLINED); my $ip = $self->qp->connection->remote_ip or return (DECLINED);
my $note = $self->process_sockets; my $note = $self->process_sockets;
if ( $note ) { if ( $note ) {
$self->log(LOGNOTICE,"Host $ip is whitelisted: $note"); $self->log(LOGNOTICE,"Host $ip is whitelisted: $note");
@ -155,4 +164,3 @@ sub hook_rcpt {
return DECLINED; return DECLINED;
} }
1;