Automatically disconnect DENY'd server if it doesn't go willingly.

Implement queue_pre and queue_post hooks.

git-svn-id: https://svn.perl.org/qpsmtpd/branches/0.3x@626 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
John Peacock 2006-03-01 16:46:55 +00:00
parent 4a824a2e7d
commit 82a32ed558
3 changed files with 46 additions and 7 deletions

View File

@ -433,6 +433,14 @@ sub auth_mechanism {
my $self = shift; my $self = shift;
return (defined $self->{_auth_mechanism} ? $self->{_auth_mechanism} : "" ); return (defined $self->{_auth_mechanism} ? $self->{_auth_mechanism} : "" );
} }
sub denied {
my ($self, $value) = @_;
$self->transaction->{_denied} = $value if defined $value;
return (defined $self->transaction->{_denied}
? $self->transaction->{_denied}
: "" );
}
1; 1;

View File

@ -2,11 +2,13 @@ package Qpsmtpd::Plugin;
use Qpsmtpd::Constants; use Qpsmtpd::Constants;
use strict; use strict;
# more or less in the order they will fire
our @hooks = qw( our @hooks = qw(
logging config queue data data_post quit rcpt mail ehlo helo logging config pre-connection connect ehlo helo
auth auth-plain auth-login auth-cram-md5 auth auth-plain auth-login auth-cram-md5
connect reset_transaction unrecognized_command disconnect rcpt mail data data_post queue_pre queue queue_post
deny ok pre-connection post-connection quit reset_transaction disconnect post-connection
unrecognized_command deny ok
); );
our %hooks = map { $_ => 1 } @hooks; our %hooks = map { $_ => 1 } @hooks;

View File

@ -50,6 +50,12 @@ sub dispatch {
$self->{_counter}++; $self->{_counter}++;
if ( $cmd !~ /^(rset|quit)$/ and $self->denied ) { # RFC non-compliant
$self->log(LOGWARN, "non-RFC compliant MTA disconnected");
$self->respond(521, "non-RFC compliant MTA disconnected (#5.7.0)");
$self->disconnect;
}
if ($cmd !~ /^(\w{1,12})$/ or !exists $self->{_commands}->{$1}) { if ($cmd !~ /^(\w{1,12})$/ or !exists $self->{_commands}->{$1}) {
my ($rc, $msg) = $self->run_hooks("unrecognized_command", $cmd, @_); my ($rc, $msg) = $self->run_hooks("unrecognized_command", $cmd, @_);
if ($rc == DENY_DISCONNECT) { if ($rc == DENY_DISCONNECT) {
@ -150,8 +156,10 @@ sub helo {
if ($rc == DONE) { if ($rc == DONE) {
# do nothing # do nothing
} elsif ($rc == DENY) { } elsif ($rc == DENY) {
$self->denied(1);
$self->respond(550, $msg); $self->respond(550, $msg);
} elsif ($rc == DENYSOFT) { } elsif ($rc == DENYSOFT) {
$self->denied(1);
$self->respond(450, $msg); $self->respond(450, $msg);
} elsif ($rc == DENY_DISCONNECT) { } elsif ($rc == DENY_DISCONNECT) {
$self->respond(550, $msg); $self->respond(550, $msg);
@ -178,8 +186,10 @@ sub ehlo {
if ($rc == DONE) { if ($rc == DONE) {
# do nothing # do nothing
} elsif ($rc == DENY) { } elsif ($rc == DENY) {
$self->denied(1);
$self->respond(550, $msg); $self->respond(550, $msg);
} elsif ($rc == DENYSOFT) { } elsif ($rc == DENYSOFT) {
$self->denied(1);
$self->respond(450, $msg); $self->respond(450, $msg);
} elsif ($rc == DENY_DISCONNECT) { } elsif ($rc == DENY_DISCONNECT) {
$self->respond(550, $msg); $self->respond(550, $msg);
@ -290,11 +300,13 @@ sub mail {
return 1; return 1;
} }
elsif ($rc == DENY) { elsif ($rc == DENY) {
$self->denied(1);
$msg ||= $from->format . ', denied'; $msg ||= $from->format . ', denied';
$self->log(LOGINFO, "deny mail from " . $from->format . " ($msg)"); $self->log(LOGINFO, "deny mail from " . $from->format . " ($msg)");
$self->respond(550, $msg); $self->respond(550, $msg);
} }
elsif ($rc == DENYSOFT) { elsif ($rc == DENYSOFT) {
$self->denied(1);
$msg ||= $from->format . ', temporarily denied'; $msg ||= $from->format . ', temporarily denied';
$self->log(LOGINFO, "denysoft mail from " . $from->format . " ($msg)"); $self->log(LOGINFO, "denysoft mail from " . $from->format . " ($msg)");
$self->respond(450, $msg); $self->respond(450, $msg);
@ -336,10 +348,12 @@ sub rcpt {
return 1; return 1;
} }
elsif ($rc == DENY) { elsif ($rc == DENY) {
$self->denied(1);
$msg ||= 'relaying denied'; $msg ||= 'relaying denied';
$self->respond(550, $msg); $self->respond(550, $msg);
} }
elsif ($rc == DENYSOFT) { elsif ($rc == DENYSOFT) {
$self->denied(1);
$msg ||= 'relaying denied'; $msg ||= 'relaying denied';
return $self->respond(450, $msg); return $self->respond(450, $msg);
} }
@ -558,7 +572,7 @@ sub data {
$self->respond(452, $msg || "Message denied temporarily"); $self->respond(452, $msg || "Message denied temporarily");
} }
else { else {
$self->queue($self->transaction); $self->queue($self->transaction);
} }
# DATA is always the end of a "transaction" # DATA is always the end of a "transaction"
@ -578,7 +592,18 @@ sub getline {
sub queue { sub queue {
my ($self, $transaction) = @_; my ($self, $transaction) = @_;
my ($rc, $msg) = $self->run_hooks("queue"); # First fire any queue_pre hooks
my ($rc, $msg) = $self->run_hooks("queue_pre");
if ($rc == DONE) {
return 1;
}
elsif ($rc != OK and $rc != DECLINED) {
return $self->log(LOGERROR, "pre plugin returned illegal value");
return 0;
}
# If we got this far, run the queue hooks
($rc, $msg) = $self->run_hooks("queue");
if ($rc == DONE) { if ($rc == DONE) {
return 1; return 1;
} }
@ -586,16 +611,20 @@ sub queue {
$self->respond(250, ($msg || 'Queued')); $self->respond(250, ($msg || 'Queued'));
} }
elsif ($rc == DENY) { elsif ($rc == DENY) {
$self->denied(1);
$self->respond(552, $msg || "Message denied"); $self->respond(552, $msg || "Message denied");
} }
elsif ($rc == DENYSOFT) { elsif ($rc == DENYSOFT) {
$self->denied(1);
$self->respond(452, $msg || "Message denied temporarily"); $self->respond(452, $msg || "Message denied temporarily");
} }
else { else {
$self->respond(451, $msg || "Queuing declined or disabled; try again later" ); $self->respond(451, $msg || "Queuing declined or disabled; try again later" );
} }
# And finally run any queue_post hooks
($rc, $msg) = $self->run_hooks("queue_post");
$self->log(LOGERROR, $msg) unless $rc == OK;
} }