Fix to prevent denying mail from some otherwise valid hosts
Fix to prevent run_continuation being incorrectly called (both Radu Greab) git-svn-id: https://svn.perl.org/qpsmtpd/trunk@857 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
parent
ddb7cd19d8
commit
694b9fd148
@ -37,8 +37,14 @@ sub hook_mail_start {
|
|||||||
return Qpsmtpd::DSN->addr_bad_from_system( DENYSOFT,
|
return Qpsmtpd::DSN->addr_bad_from_system( DENYSOFT,
|
||||||
"FQDN required in the envelope sender" );
|
"FQDN required in the envelope sender" );
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->check_dns( $sender->host );
|
return DECLINED if $sender->host =~ m/^\[(\d{1,3}\.){3}\d{1,3}\]$/;
|
||||||
|
|
||||||
|
unless ($self->check_dns( $sender->host )) {
|
||||||
|
return Qpsmtpd::DSN->temp_resolver_failed(
|
||||||
|
"Could not resolve " . $sender->host );
|
||||||
|
}
|
||||||
|
|
||||||
return YIELD;
|
return YIELD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,62 +69,77 @@ sub check_dns {
|
|||||||
my ( $self, $host ) = @_;
|
my ( $self, $host ) = @_;
|
||||||
my @host_answers;
|
my @host_answers;
|
||||||
|
|
||||||
return if $host =~ m/^\[(\d{1,3}\.){3}\d{1,3}\]$/;
|
|
||||||
|
|
||||||
my $qp = $self->qp;
|
my $qp = $self->qp;
|
||||||
|
$qp->input_sock->pause_read;
|
||||||
|
|
||||||
my $a_records = [];
|
my $a_records = [];
|
||||||
my $num_queries = $has_ipv6 ? 2 : 1;
|
my $num_queries = $has_ipv6 ? 3 : 2; # queries in progress
|
||||||
|
|
||||||
ParaDNS->new(
|
ParaDNS->new(
|
||||||
callback => sub {
|
callback => sub {
|
||||||
my $mx = shift;
|
my $mx = shift;
|
||||||
return if $mx =~ /^[A-Z]+$/; # error
|
return if $mx =~ /^[A-Z]+$/; # error
|
||||||
|
|
||||||
my $addr = $mx->[0];
|
my $addr = $mx->[0];
|
||||||
|
|
||||||
$num_queries++;
|
$num_queries++;
|
||||||
ParaDNS->new(
|
ParaDNS->new(
|
||||||
callback => sub { push @$a_records, $_[0] if $_[0] !~ /^[A-Z]+$/; },
|
callback => sub { push @$a_records, $_[0] if $_[0] !~ /^[A-Z]+$/; },
|
||||||
finished => sub { $num_queries--; $self->finish_up($qp, $a_records) unless $num_queries; },
|
finished => sub { $num_queries--; $self->finish_up($qp, $a_records, $num_queries) },
|
||||||
host => $addr,
|
host => $addr,
|
||||||
type => 'A',
|
type => 'A',
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($has_ipv6) {
|
if ($has_ipv6) {
|
||||||
$num_queries++;
|
$num_queries++;
|
||||||
ParaDNS->new(
|
ParaDNS->new(
|
||||||
callback => sub { push @$a_records, $_[0] if $_[0] !~ /^[A-Z]+$/; },
|
callback => sub { push @$a_records, $_[0] if $_[0] !~ /^[A-Z]+$/; },
|
||||||
finished => sub { $num_queries--; $self->finish_up($qp, $a_records) unless $num_queries; },
|
finished => sub { $num_queries--; $self->finish_up($qp, $a_records, $num_queries) },
|
||||||
host => $addr,
|
host => $addr,
|
||||||
type => 'AAAA',
|
type => 'AAAA',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
finished => sub { $num_queries--; $self->finish_up($qp, $a_records, $num_queries) },
|
||||||
host => $host,
|
host => $host,
|
||||||
type => 'MX',
|
type => 'MX',
|
||||||
);
|
) or return;
|
||||||
ParaDNS->new(
|
ParaDNS->new(
|
||||||
callback => sub { push @$a_records, $_[0] if $_[0] !~ /^[A-Z]+$/; },
|
callback => sub { push @$a_records, $_[0] if $_[0] !~ /^[A-Z]+$/; },
|
||||||
finished => sub { $num_queries--; $self->finish_up($qp, $a_records) unless $num_queries },
|
finished => sub { $num_queries--; $self->finish_up($qp, $a_records, $num_queries) },
|
||||||
host => $host,
|
host => $host,
|
||||||
type => 'A',
|
type => 'A',
|
||||||
);
|
) or return;
|
||||||
ParaDNS->new(
|
ParaDNS->new(
|
||||||
callback => sub { push @$a_records, $_[0] if $_[0] !~ /^[A-Z]+$/; },
|
callback => sub { push @$a_records, $_[0] if $_[0] !~ /^[A-Z]+$/; },
|
||||||
finished => sub { $num_queries--; $self->finish_up($qp, $a_records) unless $num_queries },
|
finished => sub { $num_queries--; $self->finish_up($qp, $a_records, $num_queries) },
|
||||||
host => $host,
|
host => $host,
|
||||||
type => 'AAAA',
|
type => 'AAAA',
|
||||||
) if $has_ipv6;
|
) or return if $has_ipv6;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub finish_up {
|
sub finish_up {
|
||||||
my ($self, $qp, $a_records) = @_;
|
my ($self, $qp, $a_records, $num_queries, $source) = @_;
|
||||||
|
|
||||||
|
return if defined $qp->transaction->notes('resolvable_fromhost');
|
||||||
|
|
||||||
foreach my $addr (@$a_records) {
|
foreach my $addr (@$a_records) {
|
||||||
if (is_valid($addr)) {
|
if (is_valid($addr)) {
|
||||||
$qp->transaction->notes('resolvable_fromhost', 1);
|
$qp->transaction->notes('resolvable_fromhost', 1);
|
||||||
last;
|
$qp->input_sock->continue_read;
|
||||||
|
$qp->run_continuation;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$qp->run_continuation;
|
unless ($num_queries) {
|
||||||
|
# all queries returned no valid response
|
||||||
|
$qp->transaction->notes('resolvable_fromhost', 0);
|
||||||
|
$qp->input_sock->continue_read;
|
||||||
|
$qp->run_continuation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub is_valid {
|
sub is_valid {
|
||||||
|
Loading…
Reference in New Issue
Block a user