Merge pull request #119 from flimzy/return_cleanups
Remove a ton of 'return ()', and a few other minor readability tweaks.
This commit is contained in:
commit
72f1a7a962
@ -65,14 +65,14 @@ should be configured to run I<last>, like B<rcpt_ok>.
|
|||||||
my ($self, $transaction, $recipient) = @_;
|
my ($self, $transaction, $recipient) = @_;
|
||||||
my ($rc, @msg) = $self->SUPER::hook_rcpt($transaction, $recipient);
|
my ($rc, @msg) = $self->SUPER::hook_rcpt($transaction, $recipient);
|
||||||
|
|
||||||
return ($rc, @msg)
|
return $rc, @msg
|
||||||
unless (($rc == DENY) and $self->{_count_relay_max});
|
unless (($rc == DENY) and $self->{_count_relay_max});
|
||||||
|
|
||||||
my $count =
|
my $count =
|
||||||
($self->connection->notes('count_relay_attempts') || 0) + 1;
|
($self->connection->notes('count_relay_attempts') || 0) + 1;
|
||||||
$self->connection->notes('count_relay_attempts', $count);
|
$self->connection->notes('count_relay_attempts', $count);
|
||||||
|
|
||||||
return ($rc, @msg) unless ($count > $self->{_count_relay_max});
|
return $rc, @msg unless ($count > $self->{_count_relay_max});
|
||||||
return Qpsmtpd::DSN->relaying_denied(DENY_DISCONNECT,
|
return Qpsmtpd::DSN->relaying_denied(DENY_DISCONNECT,
|
||||||
"Too many relaying attempts");
|
"Too many relaying attempts");
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ auth method if the first one fails.
|
|||||||
|
|
||||||
Plugins may also return an optional message with the return code, e.g.
|
Plugins may also return an optional message with the return code, e.g.
|
||||||
|
|
||||||
return (DENY, "If you forgot your password, contact your admin");
|
return DENY, "If you forgot your password, contact your admin";
|
||||||
|
|
||||||
and this will be appended to whatever response is sent to the remote SMTP
|
and this will be appended to whatever response is sent to the remote SMTP
|
||||||
client. There is no guarantee that the end user will see this information,
|
client. There is no guarantee that the end user will see this information,
|
||||||
|
@ -712,9 +712,9 @@ plugin didn't find the requested value
|
|||||||
|
|
||||||
requested values as C<@list>, example:
|
requested values as C<@list>, example:
|
||||||
|
|
||||||
return (OK, @{$config{$key}})
|
return OK, @{$config{$key}}
|
||||||
if exists $config{$key};
|
if exists $config{$key};
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
@ -744,9 +744,9 @@ plugin didn't find the requested value
|
|||||||
|
|
||||||
requested values as C<@list>, example:
|
requested values as C<@list>, example:
|
||||||
|
|
||||||
return (OK, @{$config{$key}})
|
return OK, @{$config{$key}}
|
||||||
if exists $config{$key};
|
if exists $config{$key};
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
|
@ -257,7 +257,9 @@ sub run_hooks {
|
|||||||
|
|
||||||
sub run_hooks_no_respond {
|
sub run_hooks_no_respond {
|
||||||
my ($self, $hook) = (shift, shift);
|
my ($self, $hook) = (shift, shift);
|
||||||
return (0, '') if !$hooks->{$hook};
|
if (!$hooks->{$hook}) {
|
||||||
|
return 0,'';
|
||||||
|
}
|
||||||
|
|
||||||
my @r;
|
my @r;
|
||||||
for my $code (@{$hooks->{$hook}}) {
|
for my $code (@{$hooks->{$hook}}) {
|
||||||
@ -425,17 +427,17 @@ sub size_threshold {
|
|||||||
|
|
||||||
sub authenticated {
|
sub authenticated {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return (defined $self->{_auth} ? $self->{_auth} : '');
|
return defined $self->{_auth} ? $self->{_auth} : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
sub auth_user {
|
sub auth_user {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return (defined $self->{_auth_user} ? $self->{_auth_user} : '');
|
return defined $self->{_auth_user} ? $self->{_auth_user} : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
sub auth_mechanism {
|
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 address {
|
sub address {
|
||||||
|
@ -213,22 +213,24 @@ sub canonify {
|
|||||||
return "" if $path eq "";
|
return "" if $path eq "";
|
||||||
|
|
||||||
# bare postmaster is permissible, perl RFC-2821 (4.5.1)
|
# bare postmaster is permissible, perl RFC-2821 (4.5.1)
|
||||||
return ("postmaster", undef) if $path =~ m/^postmaster$/i;
|
if ( $path =~ m/^postmaster$/i ) {
|
||||||
|
return "postmaster", undef;
|
||||||
|
}
|
||||||
|
|
||||||
my ($localpart, $domainpart) = ($path =~ /^(.*)\@($domain)$/);
|
my ($localpart, $domainpart) = ($path =~ /^(.*)\@($domain)$/);
|
||||||
return (undef) unless defined $localpart;
|
return undef if !defined $localpart;
|
||||||
|
|
||||||
if ($localpart =~ /^$atom_expr(\.$atom_expr)*/) {
|
if ($localpart =~ /^$atom_expr(\.$atom_expr)*/) {
|
||||||
|
|
||||||
# simple case, we are done
|
# simple case, we are done
|
||||||
return ($localpart, $domainpart);
|
return $localpart, $domainpart;
|
||||||
}
|
}
|
||||||
if ($localpart =~ /^"(($qtext_expr|\\$text_expr)*)"$/) {
|
if ($localpart =~ /^"(($qtext_expr|\\$text_expr)*)"$/) {
|
||||||
$localpart = $1;
|
$localpart = $1;
|
||||||
$localpart =~ s/\\($text_expr)/$1/g;
|
$localpart =~ s/\\($text_expr)/$1/g;
|
||||||
return ($localpart, $domainpart);
|
return $localpart, $domainpart;
|
||||||
}
|
}
|
||||||
return (undef);
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
=head2 parse()
|
=head2 parse()
|
||||||
@ -374,7 +376,7 @@ sub _addr_cmp {
|
|||||||
($right, $left) = ($left, $right);
|
($right, $left) = ($left, $right);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($left cmp $right);
|
return $left cmp $right;
|
||||||
}
|
}
|
||||||
|
|
||||||
=head1 COPYRIGHT
|
=head1 COPYRIGHT
|
||||||
|
@ -14,7 +14,7 @@ sub e64 {
|
|||||||
my ($arg) = @_;
|
my ($arg) = @_;
|
||||||
my $res = encode_base64($arg);
|
my $res = encode_base64($arg);
|
||||||
chomp($res);
|
chomp($res);
|
||||||
return ($res);
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub SASL {
|
sub SASL {
|
||||||
@ -110,7 +110,7 @@ sub get_auth_details_plain {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($loginas, $user, $passClear);
|
return $loginas, $user, $passClear;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_auth_details_login {
|
sub get_auth_details_login {
|
||||||
@ -127,7 +127,7 @@ sub get_auth_details_login {
|
|||||||
|
|
||||||
my $passClear = get_base64_response($session, 'Password:') or return;
|
my $passClear = get_base64_response($session, 'Password:') or return;
|
||||||
|
|
||||||
return ($user, $passClear);
|
return $user, $passClear;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_auth_details_cram_md5 {
|
sub get_auth_details_cram_md5 {
|
||||||
@ -157,7 +157,7 @@ sub get_auth_details_cram_md5 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$session->{auth}{ticket} = $ticket;
|
$session->{auth}{ticket} = $ticket;
|
||||||
return ($ticket, $user, $passHash);
|
return $ticket, $user, $passHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_base64_response {
|
sub get_base64_response {
|
||||||
@ -188,40 +188,40 @@ sub validate_password {
|
|||||||
|
|
||||||
if (!$src_crypt && !$src_clear) {
|
if (!$src_crypt && !$src_clear) {
|
||||||
$self->log(LOGINFO, "fail: missing password");
|
$self->log(LOGINFO, "fail: missing password");
|
||||||
return ($deny, "$file - no such user");
|
return $deny, "$file - no such user";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$src_clear && $method =~ /CRAM-MD5/i) {
|
if (!$src_clear && $method =~ /CRAM-MD5/i) {
|
||||||
$self->log(LOGINFO, "skip: cram-md5 not supported w/o clear pass");
|
$self->log(LOGINFO, "skip: cram-md5 not supported w/o clear pass");
|
||||||
return (DECLINED, $file);
|
return DECLINED, $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defined $attempt_clear) {
|
if (defined $attempt_clear) {
|
||||||
if ($src_clear && $src_clear eq $attempt_clear) {
|
if ($src_clear && $src_clear eq $attempt_clear) {
|
||||||
$self->log(LOGINFO, "pass: clear match");
|
$self->log(LOGINFO, "pass: clear match");
|
||||||
return (OK, $file);
|
return OK, $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($src_crypt && $src_crypt eq crypt($attempt_clear, $src_crypt)) {
|
if ($src_crypt && $src_crypt eq crypt($attempt_clear, $src_crypt)) {
|
||||||
$self->log(LOGINFO, "pass: crypt match");
|
$self->log(LOGINFO, "pass: crypt match");
|
||||||
return (OK, $file);
|
return OK, $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defined $attempt_hash && $src_clear) {
|
if (defined $attempt_hash && $src_clear) {
|
||||||
if (!$ticket) {
|
if (!$ticket) {
|
||||||
$self->log(LOGERROR, "skip: missing ticket");
|
$self->log(LOGERROR, "skip: missing ticket");
|
||||||
return (DECLINED, $file);
|
return DECLINED, $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($attempt_hash eq hmac_md5_hex($ticket, $src_clear)) {
|
if ($attempt_hash eq hmac_md5_hex($ticket, $src_clear)) {
|
||||||
$self->log(LOGINFO, "pass: hash match");
|
$self->log(LOGINFO, "pass: hash match");
|
||||||
return (OK, $file);
|
return OK, $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "fail: wrong password");
|
$self->log(LOGINFO, "fail: wrong password");
|
||||||
return ($deny, "$file - wrong password");
|
return $deny, "$file - wrong password";
|
||||||
}
|
}
|
||||||
|
|
||||||
# tag: qpsmtpd plugin that sets RELAYCLIENT when the user authenticates
|
# tag: qpsmtpd plugin that sets RELAYCLIENT when the user authenticates
|
||||||
|
@ -33,21 +33,21 @@ Inside a plugin
|
|||||||
|
|
||||||
sub hook_unrecognized_command_parse {
|
sub hook_unrecognized_command_parse {
|
||||||
my ($self, $transaction, $cmd) = @_;
|
my ($self, $transaction, $cmd) = @_;
|
||||||
return (OK, \&bdat_parser) if ($cmd eq 'bdat');
|
return OK, \&bdat_parser if $cmd eq 'bdat';
|
||||||
}
|
}
|
||||||
|
|
||||||
sub bdat_parser {
|
sub bdat_parser {
|
||||||
my ($self,$cmd,$line) = @_;
|
my ($self,$cmd,$line) = @_;
|
||||||
# .. do something with $line...
|
# .. do something with $line...
|
||||||
return (DENY, "Invalid arguments")
|
return DENY, "Invalid arguments"
|
||||||
if $some_reason_why_there_is_a_syntax_error;
|
if $some_reason_why_there_is_a_syntax_error;
|
||||||
return (OK, @args);
|
return OK, @args;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub hook_unrecognized_command {
|
sub hook_unrecognized_command {
|
||||||
my ($self, $transaction, $cmd, @args) = @_;
|
my ($self, $transaction, $cmd, @args) = @_;
|
||||||
return (DECLINED) if ($self->qp->connection->hello eq 'helo');
|
return DECLINED if $self->qp->connection->hello eq 'helo';
|
||||||
return (DECLINED) unless ($cmd eq 'bdat');
|
return DECLINED if $cmd ne 'bdat';
|
||||||
....
|
....
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ use vars qw(@ISA);
|
|||||||
|
|
||||||
sub parse {
|
sub parse {
|
||||||
my ($me, $cmd, $line, $sub) = @_;
|
my ($me, $cmd, $line, $sub) = @_;
|
||||||
return (OK) unless defined $line; # trivial case
|
return OK if !defined $line; # trivial case
|
||||||
my $self = {};
|
my $self = {};
|
||||||
bless $self, $me;
|
bless $self, $me;
|
||||||
$cmd = lc $cmd;
|
$cmd = lc $cmd;
|
||||||
@ -69,7 +69,7 @@ sub parse {
|
|||||||
my @ret = eval { $sub->($self, $cmd, $line); };
|
my @ret = eval { $sub->($self, $cmd, $line); };
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$self->log(LOGERROR, "Failed to parse command [$cmd]: $@");
|
$self->log(LOGERROR, "Failed to parse command [$cmd]: $@");
|
||||||
return (DENY, $line, ());
|
return DENY, $line;
|
||||||
}
|
}
|
||||||
## my @log = @ret;
|
## my @log = @ret;
|
||||||
## for (@log) {
|
## for (@log) {
|
||||||
@ -85,22 +85,22 @@ sub parse {
|
|||||||
my @out = eval { $self->$parse($cmd, $line); };
|
my @out = eval { $self->$parse($cmd, $line); };
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$self->log(LOGERROR, "$parse($cmd,$line) failed: $@");
|
$self->log(LOGERROR, "$parse($cmd,$line) failed: $@");
|
||||||
return (DENY, "Failed to parse line");
|
return DENY, "Failed to parse line";
|
||||||
}
|
}
|
||||||
return @out;
|
return @out;
|
||||||
}
|
}
|
||||||
return (OK, split(/ +/, $line)); # default :)
|
return OK, split(/ +/, $line); # default :)
|
||||||
}
|
}
|
||||||
|
|
||||||
sub parse_rcpt {
|
sub parse_rcpt {
|
||||||
my ($self, $cmd, $line) = @_;
|
my ($self, $cmd, $line) = @_;
|
||||||
return (DENY, "Syntax error in command") unless $line =~ s/^to:\s*//i;
|
return DENY, "Syntax error in command" if $line !~ s/^to:\s*//i;
|
||||||
return &_get_mail_params($cmd, $line);
|
return &_get_mail_params($cmd, $line);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub parse_mail {
|
sub parse_mail {
|
||||||
my ($self, $cmd, $line) = @_;
|
my ($self, $cmd, $line) = @_;
|
||||||
return (DENY, "Syntax error in command") unless $line =~ s/^from:\s*//i;
|
return DENY, "Syntax error in command" if $line !~ s/^from:\s*//i;
|
||||||
return &_get_mail_params($cmd, $line);
|
return &_get_mail_params($cmd, $line);
|
||||||
}
|
}
|
||||||
### RFC 1869:
|
### RFC 1869:
|
||||||
@ -141,33 +141,29 @@ sub _get_mail_params {
|
|||||||
|
|
||||||
# parameter syntax error, i.e. not all of the arguments were
|
# parameter syntax error, i.e. not all of the arguments were
|
||||||
# stripped by the while() loop:
|
# stripped by the while() loop:
|
||||||
return (DENY, "Syntax error in parameters")
|
return DENY, "Syntax error in parameters" if $line =~ /\@.*\s/;
|
||||||
if ($line =~ /\@.*\s/);
|
return OK, $line, @params;
|
||||||
return (OK, $line, @params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$line = shift @params;
|
$line = shift @params;
|
||||||
if ($cmd eq "mail") {
|
if ($cmd eq "mail") {
|
||||||
return (OK, "<>") unless $line; # 'MAIL FROM:' --> 'MAIL FROM:<>'
|
return OK, "<>" if !$line; # 'MAIL FROM:' --> 'MAIL FROM:<>'
|
||||||
return (DENY, "Syntax error in parameters")
|
return DENY, "Syntax error in parameters" if $line =~ /\@.*\s/; # parameter syntax error
|
||||||
if ($line =~ /\@.*\s/); # parameter syntax error
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ($line =~ /\@/) {
|
if ($line =~ /\@/) {
|
||||||
return (DENY, "Syntax error in parameters")
|
return DENY, "Syntax error in parameters" if $line =~ /\@.*\s/;
|
||||||
if ($line =~ /\@.*\s/);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
# XXX: what about 'abuse' in Qpsmtpd::Address?
|
# XXX: what about 'abuse' in Qpsmtpd::Address?
|
||||||
return (DENY, "Syntax error in parameters") if $line =~ /\s/;
|
return DENY, "Syntax error in parameters" if $line =~ /\s/;
|
||||||
return (DENY, "Syntax error in address")
|
return DENY, "Syntax error in address" if $line !~ /^(postmaster|abuse)$/i;
|
||||||
unless ($line =~ /^(postmaster|abuse)$/i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
## XXX: No: let this do a plugin, so it's not up to us to decide
|
## XXX: No: let this do a plugin, so it's not up to us to decide
|
||||||
## if we require <> around an address :-)
|
## if we require <> around an address :-)
|
||||||
## unless ($line =~ /^<.*>$/) { $line = "<".$line.">"; }
|
## unless ($line =~ /^<.*>$/) { $line = "<".$line.">"; }
|
||||||
return (OK, $line, @params);
|
return OK, $line, @params;
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -154,7 +154,7 @@ sub _dsn {
|
|||||||
if (defined $reason) {
|
if (defined $reason) {
|
||||||
$msg = $reason;
|
$msg = $reason;
|
||||||
}
|
}
|
||||||
return ($return, "$msg (#$class.$subject.$detail)");
|
return $return, "$msg (#$class.$subject.$detail)";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub unspecified { shift->_dsn(shift, shift, DENYSOFT, 0, 0); }
|
sub unspecified { shift->_dsn(shift, shift, DENYSOFT, 0, 0); }
|
||||||
|
@ -232,7 +232,7 @@ sub get_reject {
|
|||||||
|
|
||||||
# they asked for reject, we give them reject
|
# they asked for reject, we give them reject
|
||||||
$self->log(LOGINFO, "fail" . $log_mess);
|
$self->log(LOGINFO, "fail" . $log_mess);
|
||||||
return ($self->get_reject_type(), $smtp_mess);
|
return $self->get_reject_type(), $smtp_mess;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_reject_type {
|
sub get_reject_type {
|
||||||
@ -264,7 +264,7 @@ sub store_deferred_reject {
|
|||||||
$self->connection->notes('naughty_reject_type',
|
$self->connection->notes('naughty_reject_type',
|
||||||
$self->{_args}{reject_type});
|
$self->{_args}{reject_type});
|
||||||
}
|
}
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub store_auth_results {
|
sub store_auth_results {
|
||||||
|
@ -373,7 +373,7 @@ sub mail_parse_respond {
|
|||||||
|
|
||||||
# to support addresses without <> we now require a plugin
|
# to support addresses without <> we now require a plugin
|
||||||
# hooking "mail_pre" to
|
# hooking "mail_pre" to
|
||||||
# return (OK, "<$from>");
|
# return OK, "<$from>";
|
||||||
# (...or anything else parseable by Qpsmtpd::Address ;-))
|
# (...or anything else parseable by Qpsmtpd::Address ;-))
|
||||||
# see also comment in sub rcpt()
|
# see also comment in sub rcpt()
|
||||||
$self->run_hooks("mail_pre", $from, \%param);
|
$self->run_hooks("mail_pre", $from, \%param);
|
||||||
@ -464,7 +464,7 @@ sub rcpt_parse_respond {
|
|||||||
|
|
||||||
# to support addresses without <> we now require a plugin
|
# to support addresses without <> we now require a plugin
|
||||||
# hooking "rcpt_pre" to
|
# hooking "rcpt_pre" to
|
||||||
# return (OK, "<$rcpt>");
|
# return OK, "<$rcpt>";
|
||||||
# (... or anything else parseable by Qpsmtpd::Address ;-))
|
# (... or anything else parseable by Qpsmtpd::Address ;-))
|
||||||
# this means, a plugin can decide to (pre-)accept
|
# this means, a plugin can decide to (pre-)accept
|
||||||
# addresses like <user@example.com.> or <user@example.com >
|
# addresses like <user@example.com.> or <user@example.com >
|
||||||
|
@ -131,7 +131,7 @@ sub respond {
|
|||||||
if (!$self->check_socket()) {
|
if (!$self->check_socket()) {
|
||||||
$self->log(LOGERROR,
|
$self->log(LOGERROR,
|
||||||
"Lost connection to client, cannot send response.");
|
"Lost connection to client, cannot send response.");
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (my $msg = shift @messages) {
|
while (my $msg = shift @messages) {
|
||||||
@ -178,7 +178,7 @@ sub lrpip {
|
|||||||
$nto_iaddr =~ s/::ffff://;
|
$nto_iaddr =~ s/::ffff://;
|
||||||
$nto_laddr =~ s/::ffff://;
|
$nto_laddr =~ s/::ffff://;
|
||||||
|
|
||||||
return ($port, $iaddr, $lport, $laddr, $nto_iaddr, $nto_laddr);
|
return $port, $iaddr, $lport, $laddr, $nto_iaddr, $nto_laddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub tcpenv {
|
sub tcpenv {
|
||||||
@ -188,8 +188,8 @@ sub tcpenv {
|
|||||||
my $TCPREMOTEIP = $nto_iaddr;
|
my $TCPREMOTEIP = $nto_iaddr;
|
||||||
|
|
||||||
if ($no_rdns) {
|
if ($no_rdns) {
|
||||||
return ($TCPLOCALIP, $TCPREMOTEIP,
|
return $TCPLOCALIP, $TCPREMOTEIP,
|
||||||
$TCPREMOTEIP ? "[$ENV{TCPREMOTEIP}]" : "[noip!]");
|
$TCPREMOTEIP ? "[$ENV{TCPREMOTEIP}]" : "[noip!]";
|
||||||
}
|
}
|
||||||
my $res = Net::DNS::Resolver->new( dnsrch => 0 );
|
my $res = Net::DNS::Resolver->new( dnsrch => 0 );
|
||||||
$res->tcp_timeout(3);
|
$res->tcp_timeout(3);
|
||||||
@ -202,7 +202,7 @@ sub tcpenv {
|
|||||||
$TCPREMOTEHOST = $rr->ptrdname;
|
$TCPREMOTEHOST = $rr->ptrdname;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ($TCPLOCALIP, $TCPREMOTEIP, $TCPREMOTEHOST || 'Unknown');
|
return $TCPLOCALIP, $TCPREMOTEIP, $TCPREMOTEHOST || 'Unknown';
|
||||||
}
|
}
|
||||||
|
|
||||||
sub check_socket() {
|
sub check_socket() {
|
||||||
|
@ -57,7 +57,7 @@ sub respond {
|
|||||||
if (!$self->check_socket()) {
|
if (!$self->check_socket()) {
|
||||||
$self->log(LOGERROR,
|
$self->log(LOGERROR,
|
||||||
"Lost connection to client, cannot send response.");
|
"Lost connection to client, cannot send response.");
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (my $msg = shift @messages) {
|
while (my $msg = shift @messages) {
|
||||||
|
69
log/log2sql
69
log/log2sql
@ -274,7 +274,7 @@ sub check_logfile {
|
|||||||
print "Updating current -> $file\n";
|
print "Updating current -> $file\n";
|
||||||
exec_query('UPDATE log SET name=? WHERE inode=? AND name=?',
|
exec_query('UPDATE log SET name=? WHERE inode=? AND name=?',
|
||||||
[$file, $inode, 'current']);
|
[$file, $inode, 'current']);
|
||||||
return ($exists->[0]{id}, $exists->[0]{size}); # continue parsing
|
return $exists->[0]{id}, $exists->[0]{size}; # continue parsing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +284,7 @@ sub check_logfile {
|
|||||||
if (@$exists) {
|
if (@$exists) {
|
||||||
exec_query('UPDATE log SET size=? WHERE inode=? AND name=?',
|
exec_query('UPDATE log SET size=? WHERE inode=? AND name=?',
|
||||||
[$size, $inode, 'current']);
|
[$size, $inode, 'current']);
|
||||||
return ($exists->[0]{id}, $exists->[0]{size}); # continue parsing
|
return $exists->[0]{id}, $exists->[0]{size}; # continue parsing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +299,7 @@ sub check_logfile {
|
|||||||
[$inode, $size, $file, stat($path)->ctime]
|
[$inode, $size, $file, stat($path)->ctime]
|
||||||
);
|
);
|
||||||
print "new file id: $id\n";
|
print "new file id: $id\n";
|
||||||
return ($id);
|
return $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_log_dir {
|
sub get_log_dir {
|
||||||
@ -348,64 +348,65 @@ sub parse_line {
|
|||||||
|
|
||||||
# lines seen many times per connection
|
# lines seen many times per connection
|
||||||
return parse_line_plugin($line) if substr($message, 0, 1) eq '(';
|
return parse_line_plugin($line) if substr($message, 0, 1) eq '(';
|
||||||
return ('dispatch', $pid, undef, undef, $message)
|
return 'dispatch', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 12) eq 'dispatching ';
|
if substr($message, 0, 12) eq 'dispatching ';
|
||||||
return ('queue', $pid, undef, undef, $message)
|
return 'queue', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 11) eq '250 Queued!';
|
if substr($message, 0, 11) eq '250 Queued!';
|
||||||
return ('response', $pid, undef, undef, $message)
|
return 'response', $pid, undef, undef, $message
|
||||||
if $message =~ /^[2|3]\d\d/;
|
if $message =~ /^[2|3]\d\d/;
|
||||||
|
|
||||||
# lines seen about once per connection
|
# lines seen about once per connection
|
||||||
return ('init', $pid, undef, undef, $message)
|
return 'init', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 19) eq 'Accepted connection';
|
if substr($message, 0, 19) eq 'Accepted connection';
|
||||||
return ('connect', $pid, undef, undef, substr($message, 16))
|
return 'connect', $pid, undef, undef, substr($message, 16)
|
||||||
if substr($message, 0, 15) eq 'Connection from';
|
if substr($message, 0, 15) eq 'Connection from';
|
||||||
return ('connect', $pid, undef, undef, substr($message, 16))
|
return 'connect', $pid, undef, undef, substr($message, 16)
|
||||||
if substr($message, 0, 8) eq 'connect ';
|
if substr($message, 0, 8) eq 'connect ';
|
||||||
return ('close', $pid, undef, undef, $message)
|
return 'close', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 6) eq 'close ';
|
if substr($message, 0, 6) eq 'close ';
|
||||||
return ('close', $pid, undef, undef, $message)
|
return 'close', $pid, undef, undef, $message
|
||||||
if $message eq 'Connection Timed Out';
|
if $message eq 'Connection Timed Out';
|
||||||
return ('close', $pid, undef, undef, $message)
|
return 'close', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 20) eq 'click, disconnecting';
|
if substr($message, 0, 20) eq 'click, disconnecting';
|
||||||
return parse_line_cleanup($line)
|
return parse_line_cleanup($line)
|
||||||
if substr($message, 0, 11) eq 'cleaning up';
|
if substr($message, 0, 11) eq 'cleaning up';
|
||||||
|
|
||||||
# lines seen less than once per connection
|
# lines seen less than once per connection
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if $message eq 'spooling message to disk';
|
if $message eq 'spooling message to disk';
|
||||||
return ('reject', $pid, undef, undef, $message) if $message =~ /^[4|5]\d\d/;
|
return 'reject', $pid, undef, undef, $message
|
||||||
return ('reject', $pid, undef, undef, $message)
|
if $message =~ /^[4|5]\d\d/;
|
||||||
|
return 'reject', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 14) eq 'deny mail from';
|
if substr($message, 0, 14) eq 'deny mail from';
|
||||||
return ('reject', $pid, undef, undef, $message)
|
return 'reject', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 18) eq 'denysoft mail from';
|
if substr($message, 0, 18) eq 'denysoft mail from';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 15) eq 'Lost connection';
|
if substr($message, 0, 15) eq 'Lost connection';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if $message eq 'auth success cleared naughty';
|
if $message eq 'auth success cleared naughty';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 15) eq 'Running as user';
|
if substr($message, 0, 15) eq 'Running as user';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 16) eq 'Loaded Qpsmtpd::';
|
if substr($message, 0, 16) eq 'Loaded Qpsmtpd::';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 24) eq 'Permissions on spool_dir';
|
if substr($message, 0, 24) eq 'Permissions on spool_dir';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 13) eq 'Listening on ';
|
if substr($message, 0, 13) eq 'Listening on ';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 18) eq 'size_threshold set';
|
if substr($message, 0, 18) eq 'size_threshold set';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 12) eq 'tls: ciphers';
|
if substr($message, 0, 12) eq 'tls: ciphers';
|
||||||
return ('error', $pid, undef, undef, $message)
|
return 'error', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 22) eq 'of uninitialized value';
|
if substr($message, 0, 22) eq 'of uninitialized value';
|
||||||
return ('error', $pid, undef, undef, $message)
|
return 'error', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 8) eq 'symbol "';
|
if substr($message, 0, 8) eq 'symbol "';
|
||||||
return ('error', $pid, undef, undef, $message)
|
return 'error', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 9) eq 'error at ';
|
if substr($message, 0, 9) eq 'error at ';
|
||||||
return ('error', $pid, undef, undef, $message)
|
return 'error', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 15) eq 'Could not print';
|
if substr($message, 0, 15) eq 'Could not print';
|
||||||
|
|
||||||
print "UNKNOWN LINE: $line\n";
|
print "UNKNOWN LINE: $line\n";
|
||||||
return ('unknown', $pid, undef, undef, $message);
|
return 'unknown', $pid, undef, undef, $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub parse_line_plugin {
|
sub parse_line_plugin {
|
||||||
@ -438,7 +439,7 @@ sub parse_line_plugin {
|
|||||||
$message = 'pass' if $message =~ /^pass/;
|
$message = 'pass' if $message =~ /^pass/;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ('plugin', $pid, $hook, $plugin, $message);
|
return 'plugin', $pid, $hook, $plugin, $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub parse_line_plugin_dspam {
|
sub parse_line_plugin_dspam {
|
||||||
@ -454,7 +455,7 @@ sub parse_line_plugin_dspam {
|
|||||||
$message = "fail, $1";
|
$message = "fail, $1";
|
||||||
}
|
}
|
||||||
|
|
||||||
return ('plugin', $pid, $hook, $plugin, $message);
|
return 'plugin', $pid, $hook, $plugin, $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub parse_line_plugin_spamassassin {
|
sub parse_line_plugin_spamassassin {
|
||||||
@ -470,7 +471,7 @@ sub parse_line_plugin_spamassassin {
|
|||||||
$message = "fail, $1";
|
$message = "fail, $1";
|
||||||
}
|
}
|
||||||
|
|
||||||
return ('plugin', $pid, $hook, $plugin, $message);
|
return 'plugin', $pid, $hook, $plugin, $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub parse_line_plugin_p0f {
|
sub parse_line_plugin_p0f {
|
||||||
@ -503,7 +504,7 @@ sub parse_line_plugin_p0f {
|
|||||||
$message = 'Cisco' if $message =~ /^Cisco/i;
|
$message = 'Cisco' if $message =~ /^Cisco/i;
|
||||||
$message = 'Netware' if $message =~ /Netware/i;
|
$message = 'Netware' if $message =~ /Netware/i;
|
||||||
|
|
||||||
return ('plugin', $pid, $hook, $plugin, $message);
|
return 'plugin', $pid, $hook, $plugin, $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub parse_line_cleanup {
|
sub parse_line_cleanup {
|
||||||
@ -512,7 +513,7 @@ sub parse_line_cleanup {
|
|||||||
# @tai 85931 cleaning up after 3210
|
# @tai 85931 cleaning up after 3210
|
||||||
my $pid = (split /\s+/, $line)[-1];
|
my $pid = (split /\s+/, $line)[-1];
|
||||||
$has_cleanup++;
|
$has_cleanup++;
|
||||||
return ('cleanup', $pid, undef, undef, $line);
|
return 'cleanup', $pid, undef, undef, $line;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_score {
|
sub get_score {
|
||||||
|
@ -164,50 +164,51 @@ sub parse_line {
|
|||||||
|
|
||||||
# lines seen many times per connection
|
# lines seen many times per connection
|
||||||
return parse_line_plugin($line) if substr($message, 0, 1) eq '(';
|
return parse_line_plugin($line) if substr($message, 0, 1) eq '(';
|
||||||
return ('dispatch', $pid, undef, undef, $message)
|
return 'dispatch', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 12) eq 'dispatching ';
|
if substr($message, 0, 12) eq 'dispatching ';
|
||||||
return ('response', $pid, undef, undef, $message)
|
return 'response', $pid, undef, undef, $message
|
||||||
if $message =~ /^[2|3]\d\d/;
|
if $message =~ /^[2|3]\d\d/;
|
||||||
return ('tcpserver', $pid, undef, undef, undef)
|
return 'tcpserver', $pid, undef, undef, undef
|
||||||
if substr($pid, 0, 10) eq 'tcpserver:';
|
if substr($pid, 0, 10) eq 'tcpserver:';
|
||||||
|
|
||||||
# lines seen about once per connection
|
# lines seen about once per connection
|
||||||
return ('init', $pid, undef, undef, $message)
|
return 'init', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 19) eq 'Accepted connection';
|
if substr($message, 0, 19) eq 'Accepted connection';
|
||||||
return ('connect', $pid, undef, undef, substr($message, 16))
|
return 'connect', $pid, undef, undef, substr($message, 16)
|
||||||
if substr($message, 0, 15) eq 'Connection from';
|
if substr($message, 0, 15) eq 'Connection from';
|
||||||
return ('close', $pid, undef, undef, $message)
|
return 'close', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 6) eq 'close ';
|
if substr($message, 0, 6) eq 'close ';
|
||||||
return ('close', $pid, undef, undef, $message)
|
return 'close', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 20) eq 'click, disconnecting';
|
if substr($message, 0, 20) eq 'click, disconnecting';
|
||||||
return parse_line_cleanup($line)
|
return parse_line_cleanup($line)
|
||||||
if substr($message, 0, 11) eq 'cleaning up';
|
if substr($message, 0, 11) eq 'cleaning up';
|
||||||
|
|
||||||
# lines seen less than once per connection
|
# lines seen less than once per connection
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if $message eq 'spooling message to disk';
|
if $message eq 'spooling message to disk';
|
||||||
return ('reject', $pid, undef, undef, $message) if $message =~ /^[4|5]\d\d/;
|
return 'reject', $pid, undef, undef, $message
|
||||||
return ('reject', $pid, undef, undef, $message)
|
if $message =~ /^[4|5]\d\d/;
|
||||||
|
return 'reject', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 14) eq 'deny mail from';
|
if substr($message, 0, 14) eq 'deny mail from';
|
||||||
return ('reject', $pid, undef, undef, $message)
|
return 'reject', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 18) eq 'denysoft mail from';
|
if substr($message, 0, 18) eq 'denysoft mail from';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 15) eq 'Lost connection';
|
if substr($message, 0, 15) eq 'Lost connection';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if $message eq 'auth success cleared naughty';
|
if $message eq 'auth success cleared naughty';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 15) eq 'Running as user';
|
if substr($message, 0, 15) eq 'Running as user';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 16) eq 'Loaded Qpsmtpd::';
|
if substr($message, 0, 16) eq 'Loaded Qpsmtpd::';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 24) eq 'Permissions on spool_dir';
|
if substr($message, 0, 24) eq 'Permissions on spool_dir';
|
||||||
return ('info', $pid, undef, undef, $message)
|
return 'info', $pid, undef, undef, $message
|
||||||
if substr($message, 0, 13) eq 'Listening on ';
|
if substr($message, 0, 13) eq 'Listening on ';
|
||||||
|
|
||||||
return ('err', $pid, undef, undef, $message)
|
return 'err', $pid, undef, undef, $message)
|
||||||
if $line =~ /at [\S]+ line \d/; # generic perl error
|
if $line =~ /at [\S]+ line \d/; # generic perl error
|
||||||
print "UNKNOWN LINE: $line\n";
|
print "UNKNOWN LINE: $line\n";
|
||||||
return ('unknown', $pid, undef, undef, $message);
|
return 'unknown', $pid, undef, undef, $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub parse_line_plugin {
|
sub parse_line_plugin {
|
||||||
@ -231,7 +232,7 @@ sub parse_line_plugin {
|
|||||||
$message = 'pass';
|
$message = 'pass';
|
||||||
}
|
}
|
||||||
|
|
||||||
return ('plugin', $pid, $hook, $plugin, $message);
|
return 'plugin', $pid, $hook, $plugin, $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub parse_line_cleanup {
|
sub parse_line_cleanup {
|
||||||
@ -240,7 +241,7 @@ sub parse_line_cleanup {
|
|||||||
# @tai 85931 cleaning up after 3210
|
# @tai 85931 cleaning up after 3210
|
||||||
my $pid = (split /\s+/, $line)[-1];
|
my $pid = (split /\s+/, $line)[-1];
|
||||||
$has_cleanup++;
|
$has_cleanup++;
|
||||||
return ('cleanup', $pid, undef, undef, $line);
|
return 'cleanup', $pid, undef, undef, $line;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub print_auto_format {
|
sub print_auto_format {
|
||||||
|
@ -137,12 +137,12 @@ sub auth_checkpassword {
|
|||||||
|
|
||||||
if ($status != 0) {
|
if ($status != 0) {
|
||||||
$self->log(LOGNOTICE, "fail, auth failed: $status");
|
$self->log(LOGNOTICE, "fail, auth failed: $status");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->connection->notes('authuser', $user);
|
$self->connection->notes('authuser', $user);
|
||||||
$self->log(LOGINFO, "pass, auth success with $method");
|
$self->log(LOGINFO, "pass, auth success with $method");
|
||||||
return (OK, "auth_checkpassword");
|
return OK, "auth_checkpassword";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_checkpw {
|
sub get_checkpw {
|
||||||
@ -151,8 +151,8 @@ sub get_checkpw {
|
|||||||
my ($checkpw) = $args->{checkpw} =~ /^(.*)$/ if $args->{checkpw}; # untaint
|
my ($checkpw) = $args->{checkpw} =~ /^(.*)$/ if $args->{checkpw}; # untaint
|
||||||
my ($true) = $args->{true} =~ /^(.*)$/ if $args->{true}; # untaint
|
my ($true) = $args->{true} =~ /^(.*)$/ if $args->{true}; # untaint
|
||||||
|
|
||||||
return ($checkpw, $true)
|
return $checkpw, $true
|
||||||
if ($checkpw && $true && -x $checkpw && -x $true);
|
if $checkpw && $true && -x $checkpw && -x $true;
|
||||||
|
|
||||||
my $missing_config =
|
my $missing_config =
|
||||||
"disabled due to invalid configuration. See 'perldoc plugins/auth/auth_checkpassword' for how to configure.";
|
"disabled due to invalid configuration. See 'perldoc plugins/auth/auth_checkpassword' for how to configure.";
|
||||||
@ -170,7 +170,7 @@ sub get_checkpw {
|
|||||||
$self->log(LOGERROR, $missing_config);
|
$self->log(LOGERROR, $missing_config);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return ($checkpw, $true);
|
return $checkpw, $true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_sudo {
|
sub get_sudo {
|
||||||
@ -191,4 +191,3 @@ sub get_sudo {
|
|||||||
return $sudo if $binary !~ /vchkpw$/;
|
return $sudo if $binary !~ /vchkpw$/;
|
||||||
return "$sudo -u vpopmail";
|
return "$sudo -u vpopmail";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,12 +92,12 @@ sub authcvm_plain {
|
|||||||
|
|
||||||
if ($user =~ /\x00/) {
|
if ($user =~ /\x00/) {
|
||||||
$self->log(LOGERROR, "deny: invalid username");
|
$self->log(LOGERROR, "deny: invalid username");
|
||||||
return (DENY, "authcvm, invalid username");
|
return DENY, "authcvm, invalid username";
|
||||||
};
|
};
|
||||||
|
|
||||||
socket(SOCK, PF_UNIX, SOCK_STREAM, 0) or do {
|
socket(SOCK, PF_UNIX, SOCK_STREAM, 0) or do {
|
||||||
$self->log(LOGERROR, "skip: socket creation attempt for: $user");
|
$self->log(LOGERROR, "skip: socket creation attempt for: $user");
|
||||||
return (DENY, "authcvm");
|
return DENY, "authcvm";
|
||||||
};
|
};
|
||||||
|
|
||||||
# DENY, really? Should this plugin return a DENY when it cannot connect
|
# DENY, really? Should this plugin return a DENY when it cannot connect
|
||||||
@ -106,7 +106,7 @@ sub authcvm_plain {
|
|||||||
|
|
||||||
connect(SOCK, sockaddr_un($self->{_cvm_socket})) or do {
|
connect(SOCK, sockaddr_un($self->{_cvm_socket})) or do {
|
||||||
$self->log(LOGERROR, "skip: socket connection attempt for: $user");
|
$self->log(LOGERROR, "skip: socket connection attempt for: $user");
|
||||||
return (DENY, "authcvm, connection failed");
|
return DENY, "authcvm, connection failed";
|
||||||
};
|
};
|
||||||
|
|
||||||
my $o = select(SOCK);
|
my $o = select(SOCK);
|
||||||
@ -125,19 +125,19 @@ sub authcvm_plain {
|
|||||||
|
|
||||||
if (!defined $s) {
|
if (!defined $s) {
|
||||||
$self->log(LOGERROR, "skip: no response from cvm for $user");
|
$self->log(LOGERROR, "skip: no response from cvm for $user");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($s == 0) {
|
if ($s == 0) {
|
||||||
$self->log(LOGINFO, "pass: authentication for: $user");
|
$self->log(LOGINFO, "pass: authentication for: $user");
|
||||||
return (OK, "auth success for $user");
|
return OK, "auth success for $user";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($s == 100) {
|
if ($s == 100) {
|
||||||
$self->log(LOGINFO, "fail: authentication failure for: $user");
|
$self->log(LOGINFO, "fail: authentication failure for: $user");
|
||||||
return (DENY, 'auth failure (100)');
|
return DENY, 'auth failure (100)';
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGERROR, "skip: unknown response from cvm for $user");
|
$self->log(LOGERROR, "skip: unknown response from cvm for $user");
|
||||||
return (DECLINED, "unknown result code ($s)");
|
return DECLINED, "unknown result code ($s)";
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ sub auth_flat_file {
|
|||||||
|
|
||||||
if (!defined $passClear && !defined $passHash) {
|
if (!defined $passClear && !defined $passHash) {
|
||||||
$self->log(LOGINFO, "fail: missing password");
|
$self->log(LOGINFO, "fail: missing password");
|
||||||
return (DENY, "authflat - missing password");
|
return DENY, "authflat - missing password";
|
||||||
}
|
}
|
||||||
|
|
||||||
my ($pw_name, $pw_domain) = split /@/, lc($user);
|
my ($pw_name, $pw_domain) = split /@/, lc($user);
|
||||||
|
@ -135,7 +135,7 @@ sub authldap {
|
|||||||
# log error here and DECLINE if no baseDN, because a custom baseDN is required:
|
# log error here and DECLINE if no baseDN, because a custom baseDN is required:
|
||||||
unless ($ldbase) {
|
unless ($ldbase) {
|
||||||
$self->log(LOGERROR, "skip: please configure ldap_base");
|
$self->log(LOGERROR, "skip: please configure ldap_base");
|
||||||
return (DECLINED, "authldap - temporary auth error");
|
return DECLINED, "authldap - temporary auth error";
|
||||||
}
|
}
|
||||||
$ldwait = $self->{"ldconf"}->{'ldap_timeout'};
|
$ldwait = $self->{"ldconf"}->{'ldap_timeout'};
|
||||||
$ldmattr = $self->{"ldconf"}->{'ldap_auth_filter_attr'};
|
$ldmattr = $self->{"ldconf"}->{'ldap_auth_filter_attr'};
|
||||||
@ -145,7 +145,7 @@ sub authldap {
|
|||||||
# find dn of user matching supplied username
|
# find dn of user matching supplied username
|
||||||
$ldh = Net::LDAP->new($ldhost, port => $ldport, timeout => $ldwait) or do {
|
$ldh = Net::LDAP->new($ldhost, port => $ldport, timeout => $ldwait) or do {
|
||||||
$self->log(LOGALERT, "skip: error in initial conn");
|
$self->log(LOGALERT, "skip: error in initial conn");
|
||||||
return (DECLINED, "authldap - temporary auth error");
|
return DECLINED, "authldap - temporary auth error";
|
||||||
};
|
};
|
||||||
|
|
||||||
# find the user's DN
|
# find the user's DN
|
||||||
@ -159,14 +159,14 @@ sub authldap {
|
|||||||
)
|
)
|
||||||
or do {
|
or do {
|
||||||
$self->log(LOGALERT, "skip: err in search for user");
|
$self->log(LOGALERT, "skip: err in search for user");
|
||||||
return (DECLINED, "authldap - temporary auth error");
|
return DECLINED, "authldap - temporary auth error";
|
||||||
};
|
};
|
||||||
|
|
||||||
# deal with errors if they exist
|
# deal with errors if they exist
|
||||||
if ($mesg->code) {
|
if ($mesg->code) {
|
||||||
$self->log(LOGALERT,
|
$self->log(LOGALERT,
|
||||||
"skip: err " . $mesg->code . " in search for user");
|
"skip: err " . $mesg->code . " in search for user");
|
||||||
return (DECLINED, "authldap - temporary auth error");
|
return DECLINED, "authldap - temporary auth error";
|
||||||
}
|
}
|
||||||
|
|
||||||
# unbind, so as to allow a rebind below
|
# unbind, so as to allow a rebind below
|
||||||
@ -175,12 +175,12 @@ sub authldap {
|
|||||||
# bind against directory as user with password supplied
|
# bind against directory as user with password supplied
|
||||||
if (!$mesg->count || $lduserdn = $mesg->entry->dn) {
|
if (!$mesg->count || $lduserdn = $mesg->entry->dn) {
|
||||||
$self->log(LOGALERT, "fail: user not found");
|
$self->log(LOGALERT, "fail: user not found");
|
||||||
return (DECLINED, "authldap - wrong username or password");
|
return DECLINED, "authldap - wrong username or password";
|
||||||
}
|
}
|
||||||
|
|
||||||
$ldh = Net::LDAP->new($ldhost, port => $ldport, timeout => $ldwait) or do {
|
$ldh = Net::LDAP->new($ldhost, port => $ldport, timeout => $ldwait) or do {
|
||||||
$self->log(LOGALERT, "skip: err in user conn");
|
$self->log(LOGALERT, "skip: err in user conn");
|
||||||
return (DECLINED, "authldap - temporary auth error");
|
return DECLINED, "authldap - temporary auth error";
|
||||||
};
|
};
|
||||||
|
|
||||||
# here's the whole reason for the script
|
# here's the whole reason for the script
|
||||||
@ -190,11 +190,10 @@ sub authldap {
|
|||||||
# deal with errors if they exist, or allow success
|
# deal with errors if they exist, or allow success
|
||||||
if ($mesg->code) {
|
if ($mesg->code) {
|
||||||
$self->log(LOGALERT, "fail: error in user bind");
|
$self->log(LOGALERT, "fail: error in user bind");
|
||||||
return (DECLINED, "authldap - wrong username or password");
|
return DECLINED, "authldap - wrong username or password";
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "pass: $user auth success");
|
$self->log(LOGINFO, "pass: $user auth success");
|
||||||
$self->log(LOGDEBUG, "user: $user, pass: $passClear");
|
$self->log(LOGDEBUG, "user: $user, pass: $passClear");
|
||||||
return (OK, "authldap");
|
return OK, "authldap";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ use Qpsmtpd::Constants;
|
|||||||
sub register {
|
sub register {
|
||||||
my ($self, $qp) = @_;
|
my ($self, $qp) = @_;
|
||||||
|
|
||||||
return (DECLINED) if !$self->test_vpopmail_module();
|
return DECLINED if !$self->test_vpopmail_module();
|
||||||
|
|
||||||
$self->register_hook("auth-plain", "auth_vpopmail");
|
$self->register_hook("auth-plain", "auth_vpopmail");
|
||||||
$self->register_hook("auth-login", "auth_vpopmail");
|
$self->register_hook("auth-login", "auth_vpopmail");
|
||||||
@ -67,7 +67,7 @@ sub auth_vpopmail {
|
|||||||
|
|
||||||
if (!$pw || (!$pw_clear_passwd && !$pw_passwd)) {
|
if (!$pw || (!$pw_clear_passwd && !$pw_passwd)) {
|
||||||
$self->log(LOGINFO, "fail: invalid user $user");
|
$self->log(LOGINFO, "fail: invalid user $user");
|
||||||
return (DENY, "auth_vpopmail - invalid user");
|
return DENY, "auth_vpopmail - invalid user";
|
||||||
|
|
||||||
# change DENY to DECLINED to support multiple auth plugins
|
# change DENY to DECLINED to support multiple auth plugins
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ sub auth_vmysql {
|
|||||||
|
|
||||||
if (!$u->{pw_passwd} && !$u->{pw_clear_passwd}) {
|
if (!$u->{pw_passwd} && !$u->{pw_clear_passwd}) {
|
||||||
$self->log(LOGINFO, "fail: no such user");
|
$self->log(LOGINFO, "fail: no such user");
|
||||||
return (DENY, "auth_vmysql - no such user");
|
return DENY, "auth_vmysql - no such user";
|
||||||
}
|
}
|
||||||
|
|
||||||
# at this point, the user name has matched
|
# at this point, the user name has matched
|
||||||
|
@ -52,7 +52,7 @@ sub auth_vpopmaild {
|
|||||||
# check for successful login (single line (+OK) or multiline (+OK+))
|
# check for successful login (single line (+OK) or multiline (+OK+))
|
||||||
if ($response =~ /^\+OK/) {
|
if ($response =~ /^\+OK/) {
|
||||||
$self->log(LOGINFO, "pass, clear");
|
$self->log(LOGINFO, "pass, clear");
|
||||||
return (OK, 'auth_vpopmaild');
|
return OK, 'auth_vpopmaild';
|
||||||
}
|
}
|
||||||
|
|
||||||
chomp $response;
|
chomp $response;
|
||||||
|
@ -18,6 +18,6 @@ sub hook_auth {
|
|||||||
|
|
||||||
$self->log(LOGWARN, "fail: cannot authenticate");
|
$self->log(LOGWARN, "fail: cannot authenticate");
|
||||||
|
|
||||||
return (DECLINED, "$user is not free to abuse my relay");
|
return DECLINED, "$user is not free to abuse my relay";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ sub hook_mail {
|
|||||||
$transaction->notes('badmailfromto', $bad);
|
$transaction->notes('badmailfromto', $bad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub hook_rcpt {
|
sub hook_rcpt {
|
||||||
@ -50,16 +50,17 @@ sub hook_rcpt {
|
|||||||
my $recipient = lc($rcpt->user) . '@' . lc($rcpt->host);
|
my $recipient = lc($rcpt->user) . '@' . lc($rcpt->host);
|
||||||
my $sender = $transaction->notes('badmailfromto') or do {
|
my $sender = $transaction->notes('badmailfromto') or do {
|
||||||
$self->log(LOGDEBUG, "pass, sender not listed");
|
$self->log(LOGDEBUG, "pass, sender not listed");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach ($self->qp->config("badmailfromto")) {
|
foreach ($self->qp->config("badmailfromto")) {
|
||||||
my ($from, $to) = m/^\s*(\S+)\t(\S+).*/;
|
my ($from, $to) = m/^\s*(\S+)\t(\S+).*/;
|
||||||
return (DENY, "mail to $recipient not accepted here")
|
if ( lc($from) eq $sender && lc($to) eq $recipient ) {
|
||||||
if lc($from) eq $sender && lc($to) eq $recipient;
|
return DENY, "mail to $recipient not accepted here";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$self->log(LOGDEBUG, "pass, recipient not listed");
|
$self->log(LOGDEBUG, "pass, recipient not listed");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub is_sender_immune {
|
sub is_sender_immune {
|
||||||
|
@ -49,14 +49,14 @@ use Qpsmtpd::DSN;
|
|||||||
sub hook_rcpt {
|
sub hook_rcpt {
|
||||||
my ($self, $transaction, $recipient, %param) = @_;
|
my ($self, $transaction, $recipient, %param) = @_;
|
||||||
|
|
||||||
return (DECLINED) if $self->is_immune();
|
return DECLINED if $self->is_immune();
|
||||||
|
|
||||||
my ($host, $to) = $self->get_host_and_to($recipient)
|
my ($host, $to) = $self->get_host_and_to($recipient)
|
||||||
or return (DECLINED);
|
or return DECLINED;
|
||||||
|
|
||||||
my @badrcptto = $self->qp->config("badrcptto") or do {
|
my @badrcptto = $self->qp->config("badrcptto") or do {
|
||||||
$self->log(LOGINFO, "skip, empty config");
|
$self->log(LOGINFO, "skip, empty config");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
};
|
};
|
||||||
|
|
||||||
for my $line (@badrcptto) {
|
for my $line (@badrcptto) {
|
||||||
@ -66,7 +66,7 @@ sub hook_rcpt {
|
|||||||
if ($self->is_match($to, lc($bad), $host)) {
|
if ($self->is_match($to, lc($bad), $host)) {
|
||||||
$self->adjust_karma(-2);
|
$self->adjust_karma(-2);
|
||||||
if ($reason) {
|
if ($reason) {
|
||||||
return (DENY, "mail to $bad not accepted here");
|
return DENY, "mail to $bad not accepted here";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return Qpsmtpd::DSN->no_such_user(
|
return Qpsmtpd::DSN->no_such_user(
|
||||||
@ -75,7 +75,7 @@ sub hook_rcpt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$self->log(LOGINFO, 'pass');
|
$self->log(LOGINFO, 'pass');
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub is_match {
|
sub is_match {
|
||||||
@ -127,5 +127,5 @@ sub get_host_and_to {
|
|||||||
}
|
}
|
||||||
|
|
||||||
my $host = lc $recipient->host;
|
my $host = lc $recipient->host;
|
||||||
return ($host, lc($recipient->user) . '@' . $host);
|
return $host, lc($recipient->user) . '@' . $host;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ sub connect_handler {
|
|||||||
if ($self->hook_name eq 'connect' && defined $self->{_connection_start});
|
if ($self->hook_name eq 'connect' && defined $self->{_connection_start});
|
||||||
$self->{_connection_start} = [gettimeofday];
|
$self->{_connection_start} = [gettimeofday];
|
||||||
$self->log(LOGDEBUG, "started at " . scalar gettimeofday);
|
$self->log(LOGDEBUG, "started at " . scalar gettimeofday);
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub hook_post_connection {
|
sub hook_post_connection {
|
||||||
@ -67,12 +67,11 @@ sub hook_post_connection {
|
|||||||
|
|
||||||
if (!$self->{_connection_start}) {
|
if (!$self->{_connection_start}) {
|
||||||
$self->log(LOGERROR, "Start time not set?!");
|
$self->log(LOGERROR, "Start time not set?!");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $elapsed = tv_interval($self->{_connection_start}, [gettimeofday]);
|
my $elapsed = tv_interval($self->{_connection_start}, [gettimeofday]);
|
||||||
|
|
||||||
$self->log(LOGINFO, sprintf "%.3f s.", $elapsed);
|
$self->log(LOGINFO, sprintf "%.3f s.", $elapsed);
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ sub hook_data_post {
|
|||||||
# as a decent default, log on a per-day-basis
|
# as a decent default, log on a per-day-basis
|
||||||
my $date = strftime("%Y%m%d", localtime(time));
|
my $date = strftime("%Y%m%d", localtime(time));
|
||||||
open(my $out, ">>mail/$date")
|
open(my $out, ">>mail/$date")
|
||||||
or return (DECLINED, "Could not open log file.. continuing anyway");
|
or return DECLINED, "Could not open log file.. continuing anyway";
|
||||||
|
|
||||||
$transaction->header->print($out);
|
$transaction->header->print($out);
|
||||||
$transaction->body_resetpos;
|
$transaction->body_resetpos;
|
||||||
@ -21,5 +21,5 @@ sub hook_data_post {
|
|||||||
|
|
||||||
close $out;
|
close $out;
|
||||||
|
|
||||||
return (DECLINED, "successfully saved message.. continuing");
|
return DECLINED, "successfully saved message.. continuing";
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,7 @@ sub hook_unrecognized_command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "fail, '$cmd' ($count)");
|
$self->log(LOGINFO, "fail, '$cmd' ($count)");
|
||||||
return (DENY_DISCONNECT,
|
return DENY_DISCONNECT,
|
||||||
"Closing connection, $count unrecognized commands. Perhaps you should read RFC 2821?"
|
"Closing connection, $count unrecognized commands. Perhaps you should read RFC 2821?";
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ sub handle_sig_temperror {
|
|||||||
my ($self, $dkim, $mess) = @_;
|
my ($self, $dkim, $mess) = @_;
|
||||||
|
|
||||||
$self->log(LOGINFO, "error, $mess");
|
$self->log(LOGINFO, "error, $mess");
|
||||||
return (DENYSOFT, "Please try again later - $dkim->result_detail");
|
return DENYSOFT, "Please try again later - $dkim->result_detail";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub handle_sig_invalid {
|
sub handle_sig_invalid {
|
||||||
@ -447,7 +447,7 @@ sub get_keydir {
|
|||||||
$self->log(LOGINFO, "error, unable to read dkim key from $dir/private");
|
$self->log(LOGINFO, "error, unable to read dkim key from $dir/private");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return ($domain, $dir);
|
return $domain, $dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub save_signatures_to_note {
|
sub save_signatures_to_note {
|
||||||
|
@ -156,7 +156,7 @@ sub process_sockets {
|
|||||||
|
|
||||||
sub hook_rcpt {
|
sub hook_rcpt {
|
||||||
my ($self, $transaction, $rcpt, %param) = @_;
|
my ($self, $transaction, $rcpt, %param) = @_;
|
||||||
my $ip = $self->qp->connection->remote_ip or 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");
|
||||||
|
@ -283,7 +283,7 @@ sub return_env_message {
|
|||||||
$result =~ s/%IP%/$remote_ip/g;
|
$result =~ s/%IP%/$remote_ip/g;
|
||||||
my $msg = $self->qp->config('dnsbl_rejectmsg');
|
my $msg = $self->qp->config('dnsbl_rejectmsg');
|
||||||
$self->log(LOGINFO, "fail, $msg");
|
$self->log(LOGINFO, "fail, $msg");
|
||||||
return ($self->get_reject_type(), join(' ', $msg, $result));
|
return $self->get_reject_type(), join(' ', $msg, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub hook_rcpt {
|
sub hook_rcpt {
|
||||||
|
@ -124,7 +124,7 @@ sub data_post_handler {
|
|||||||
$self->log(LOGERROR, "fail, signature invalid");
|
$self->log(LOGERROR, "fail, signature invalid");
|
||||||
return DECLINED if !$self->{reject};
|
return DECLINED if !$self->{reject};
|
||||||
my $deny = $self->{reject_type} eq 'temp' ? DENYSOFT : DENY;
|
my $deny = $self->{reject_type} eq 'temp' ? DENYSOFT : DENY;
|
||||||
return ($deny, "DomainKeys signature validation failed");
|
return $deny, "DomainKeys signature validation failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_message_status {
|
sub get_message_status {
|
||||||
|
@ -28,7 +28,7 @@ sub hook_mail_pre {
|
|||||||
$self->adjust_karma(-2);
|
$self->adjust_karma(-2);
|
||||||
$self->log(LOGINFO, "fail, added MAIL angle brackets");
|
$self->log(LOGINFO, "fail, added MAIL angle brackets");
|
||||||
}
|
}
|
||||||
return (OK, $addr);
|
return OK, $addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub hook_rcpt_pre {
|
sub hook_rcpt_pre {
|
||||||
@ -38,5 +38,5 @@ sub hook_rcpt_pre {
|
|||||||
$self->adjust_karma(-2);
|
$self->adjust_karma(-2);
|
||||||
$self->log(LOGINFO, "fail, added RCPT angle brackets");
|
$self->log(LOGINFO, "fail, added RCPT angle brackets");
|
||||||
}
|
}
|
||||||
return (OK, $addr);
|
return OK, $addr;
|
||||||
}
|
}
|
||||||
|
@ -244,11 +244,11 @@ sub data_post_handler {
|
|||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $transaction = shift || $self->qp->transaction;
|
my $transaction = shift || $self->qp->transaction;
|
||||||
|
|
||||||
return (DECLINED) if $self->is_immune();
|
return DECLINED if $self->is_immune();
|
||||||
|
|
||||||
if ($transaction->data_size > 500_000) {
|
if ($transaction->data_size > 500_000) {
|
||||||
$self->log(LOGINFO, "skip, too big (" . $transaction->data_size . ")");
|
$self->log(LOGINFO, "skip, too big (" . $transaction->data_size . ")");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $user = $self->select_username($transaction);
|
my $user = $self->select_username($transaction);
|
||||||
@ -260,7 +260,7 @@ sub data_post_handler {
|
|||||||
my $response = $self->dspam_process($filtercmd, $transaction);
|
my $response = $self->dspam_process($filtercmd, $transaction);
|
||||||
if (!$response->{result}) {
|
if (!$response->{result}) {
|
||||||
$self->log(LOGWARN, "error, no dspam response. Check logs for errors.");
|
$self->log(LOGWARN, "error, no dspam response. Check logs for errors.");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
$transaction->notes('dspam', $response);
|
$transaction->notes('dspam', $response);
|
||||||
@ -512,7 +512,7 @@ sub reject_agree {
|
|||||||
$self->adjust_karma(-2);
|
$self->adjust_karma(-2);
|
||||||
$self->log(LOGINFO, "fail, agree, $status");
|
$self->log(LOGINFO, "fail, agree, $status");
|
||||||
my $reject = $self->get_reject_type();
|
my $reject = $self->get_reject_type();
|
||||||
return ($reject, 'we agree, no spam please');
|
return $reject, 'we agree, no spam please';
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "fail, disagree, $status");
|
$self->log(LOGINFO, "fail, disagree, $status");
|
||||||
|
@ -234,7 +234,7 @@ sub mail_handler {
|
|||||||
return DECLINED if $status != DENYSOFT;
|
return DECLINED if $status != DENYSOFT;
|
||||||
|
|
||||||
if (!$self->{_args}{deny_late}) {
|
if (!$self->{_args}{deny_late}) {
|
||||||
return (DENYSOFT, $msg);
|
return DENYSOFT, $msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
$transaction->notes('greylist', $msg);
|
$transaction->notes('greylist', $msg);
|
||||||
@ -346,7 +346,7 @@ sub cleanup_and_return {
|
|||||||
return $return_val if defined $return_val; # explicit override
|
return $return_val if defined $return_val; # explicit override
|
||||||
return DECLINED
|
return DECLINED
|
||||||
if defined $self->{_args}{reject} && !$self->{_args}{reject};
|
if defined $self->{_args}{reject} && !$self->{_args}{reject};
|
||||||
return (DENYSOFT, $DENYMSG);
|
return DENYSOFT, $DENYMSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_db_key {
|
sub get_db_key {
|
||||||
|
@ -152,7 +152,7 @@ sub hook_data_post {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$self->log(LOGINFO, 'pass');
|
$self->log(LOGINFO, 'pass');
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub has_required_headers {
|
sub has_required_headers {
|
||||||
|
35
plugins/helo
35
plugins/helo
@ -280,7 +280,7 @@ sub data_post_handler {
|
|||||||
$transaction->header->delete('X-HELO');
|
$transaction->header->delete('X-HELO');
|
||||||
$transaction->header->add('X-HELO', $self->qp->connection->hello_host, 0);
|
$transaction->header->add('X-HELO', $self->qp->connection->hello_host, 0);
|
||||||
|
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub populate_tests {
|
sub populate_tests {
|
||||||
@ -311,7 +311,7 @@ sub is_in_badhelo {
|
|||||||
return $self->is_regex_match($host, $bad);
|
return $self->is_regex_match($host, $bad);
|
||||||
}
|
}
|
||||||
if ($host eq lc $bad) {
|
if ($host eq lc $bad) {
|
||||||
return ($error, "in badhelo");
|
return $error, "in badhelo";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -328,14 +328,14 @@ sub is_regex_match {
|
|||||||
if ($host !~ /$pattern/) {
|
if ($host !~ /$pattern/) {
|
||||||
|
|
||||||
#$self->log( LOGDEBUG, "matched ($pattern)");
|
#$self->log( LOGDEBUG, "matched ($pattern)");
|
||||||
return ($error, "badhelo pattern match ($pattern)");
|
return $error, "badhelo pattern match ($pattern)";
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($host =~ /$pattern/) {
|
if ($host =~ /$pattern/) {
|
||||||
|
|
||||||
#$self->log( LOGDEBUG, "matched ($pattern)");
|
#$self->log( LOGDEBUG, "matched ($pattern)");
|
||||||
return ($error, "badhelo pattern match ($pattern)");
|
return $error, "badhelo pattern match ($pattern)";
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -352,7 +352,7 @@ sub invalid_localhost {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#$self->log( LOGINFO, "fail, not localhost" );
|
#$self->log( LOGINFO, "fail, not localhost" );
|
||||||
return ("You are not localhost", "invalid localhost");
|
return "You are not localhost", "invalid localhost";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub is_plain_ip {
|
sub is_plain_ip {
|
||||||
@ -360,7 +360,7 @@ sub is_plain_ip {
|
|||||||
return if !Qpsmtpd::Base->is_valid_ip($host);
|
return if !Qpsmtpd::Base->is_valid_ip($host);
|
||||||
|
|
||||||
$self->log(LOGDEBUG, "fail, plain IP");
|
$self->log(LOGDEBUG, "fail, plain IP");
|
||||||
return ("Plain IP is invalid HELO hostname (RFC 2821)", "plain IP");
|
return "Plain IP is invalid HELO hostname (RFC 2821)", "plain IP";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub is_address_literal {
|
sub is_address_literal {
|
||||||
@ -372,8 +372,7 @@ sub is_address_literal {
|
|||||||
return if !Qpsmtpd::Base->is_valid_ip($ip);
|
return if !Qpsmtpd::Base->is_valid_ip($ip);
|
||||||
|
|
||||||
$self->log(LOGDEBUG, "fail, bracketed IP");
|
$self->log(LOGDEBUG, "fail, bracketed IP");
|
||||||
return ("RFC 2821 allows an address literal, but we do not",
|
return "RFC 2821 allows an address literal, but we do not","bracketed IP";
|
||||||
"bracketed IP");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub is_forged_literal {
|
sub is_forged_literal {
|
||||||
@ -383,18 +382,17 @@ sub is_forged_literal {
|
|||||||
# should we add exceptions for reserved internal IP space? (192.168,10., etc)
|
# should we add exceptions for reserved internal IP space? (192.168,10., etc)
|
||||||
$host = substr $host, 1, -1;
|
$host = substr $host, 1, -1;
|
||||||
return if $host eq $self->qp->connection->remote_ip;
|
return if $host eq $self->qp->connection->remote_ip;
|
||||||
return ("Forged IPs not accepted here", "forged IP literal");
|
return "Forged IPs not accepted here", "forged IP literal";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub is_not_fqdn {
|
sub is_not_fqdn {
|
||||||
my ($self, $host) = @_;
|
my ($self, $host) = @_;
|
||||||
return if $host =~ m/^\[(\d{1,3}\.){3}\d{1,3}\]$/; # address literal, skip
|
return if $host =~ m/^\[(\d{1,3}\.){3}\d{1,3}\]$/; # address literal, skip
|
||||||
if ($host !~ /\./) { # has no dots
|
if ($host !~ /\./) { # has no dots
|
||||||
return ("HELO name is not fully qualified. Read RFC 2821", "not FQDN");
|
return "HELO name is not fully qualified. Read RFC 2821", "not FQDN";
|
||||||
}
|
}
|
||||||
if ($host =~ /[^a-zA-Z0-9\-\.]/) {
|
if ($host =~ /[^a-zA-Z0-9\-\.]/) {
|
||||||
return ("HELO name contains invalid FQDN characters. Read RFC 1035",
|
return "HELO name contains invalid FQDN characters. Read RFC 1035","invalid FQDN chars";
|
||||||
"invalid FQDN chars");
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -411,7 +409,7 @@ sub no_forward_dns {
|
|||||||
|
|
||||||
if (!$query) {
|
if (!$query) {
|
||||||
if ($res->errorstring eq 'NXDOMAIN') {
|
if ($res->errorstring eq 'NXDOMAIN') {
|
||||||
return ("HELO hostname does not exist", "no such host");
|
return "HELO hostname does not exist", "no such host";
|
||||||
}
|
}
|
||||||
$self->log(LOGERROR, "skip, query failed (", $res->errorstring, ")");
|
$self->log(LOGERROR, "skip, query failed (", $res->errorstring, ")");
|
||||||
return;
|
return;
|
||||||
@ -427,7 +425,7 @@ sub no_forward_dns {
|
|||||||
$self->log(LOGDEBUG, "pass, forward DNS") if $hits;
|
$self->log(LOGDEBUG, "pass, forward DNS") if $hits;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return ("HELO hostname did not resolve", "no forward DNS");
|
return "HELO hostname did not resolve", "no forward DNS";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub no_reverse_dns {
|
sub no_reverse_dns {
|
||||||
@ -438,11 +436,10 @@ sub no_reverse_dns {
|
|||||||
|
|
||||||
my $query = $res->query($ip) or do {
|
my $query = $res->query($ip) or do {
|
||||||
if ($res->errorstring eq 'NXDOMAIN') {
|
if ($res->errorstring eq 'NXDOMAIN') {
|
||||||
return ("no rDNS for $ip", "no rDNS");
|
return "no rDNS for $ip", "no rDNS";
|
||||||
}
|
}
|
||||||
$self->log(LOGINFO, $res->errorstring);
|
$self->log(LOGINFO, $res->errorstring);
|
||||||
return ("error getting reverse DNS for $ip",
|
return "error getting reverse DNS for $ip", "rDNS " . $res->errorstring;
|
||||||
"rDNS " . $res->errorstring);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
my $hits = 0;
|
my $hits = 0;
|
||||||
@ -456,7 +453,7 @@ sub no_reverse_dns {
|
|||||||
$self->log(LOGDEBUG, "has rDNS");
|
$self->log(LOGDEBUG, "has rDNS");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return ("no reverse DNS for $ip", "no rDNS");
|
return "no reverse DNS for $ip", "no rDNS";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub no_matching_dns {
|
sub no_matching_dns {
|
||||||
@ -485,7 +482,7 @@ sub no_matching_dns {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "fail, no forward or reverse DNS match");
|
$self->log(LOGINFO, "fail, no forward or reverse DNS match");
|
||||||
return ("That HELO hostname fails FCrDNS", "no matching DNS");
|
return "That HELO hostname fails FCrDNS", "no matching DNS";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub check_ip_match {
|
sub check_ip_match {
|
||||||
|
@ -80,7 +80,7 @@ sub hook_pre_connection {
|
|||||||
if ($num_conn > $max) {
|
if ($num_conn > $max) {
|
||||||
my $err_mess = "too many connections from $remote";
|
my $err_mess = "too many connections from $remote";
|
||||||
$self->log(LOGINFO, "fail: $err_mess ($num_conn > $max)");
|
$self->log(LOGINFO, "fail: $err_mess ($num_conn > $max)");
|
||||||
return (DENYSOFT, "$err_mess, try again later");
|
return DENYSOFT, "$err_mess, try again later";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ sub hook_pre_connection {
|
|||||||
return @r if scalar @r;
|
return @r if scalar @r;
|
||||||
|
|
||||||
$self->log(LOGDEBUG, "pass");
|
$self->log(LOGDEBUG, "pass");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub in_hosts_allow {
|
sub in_hosts_allow {
|
||||||
@ -109,7 +109,7 @@ sub in_hosts_allow {
|
|||||||
$self->log(LOGINFO, "fail, $message");
|
$self->log(LOGINFO, "fail, $message");
|
||||||
}
|
}
|
||||||
$self->log(LOGDEBUG, "pass, $const, $message");
|
$self->log(LOGDEBUG, "pass, $const, $message");
|
||||||
return ($const, $message);
|
return $const, $message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,8 +45,7 @@ sub hook_config {
|
|||||||
@config = grep { $_ and $_ !~ m/^\s*#/ and $_ =~ m/\S/ } @config;
|
@config = grep { $_ and $_ !~ m/^\s*#/ and $_ =~ m/\S/ } @config;
|
||||||
close CF;
|
close CF;
|
||||||
|
|
||||||
# $self->log(LOGNOTICE, "returning http_config for $config ",Data::Dumper->Dump([\@config], [qw(config)]));
|
return OK, @config if @config;
|
||||||
return (OK, @config) if @config;
|
|
||||||
}
|
}
|
||||||
return DECLINED;
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,7 @@ sub get_my_lat_lon {
|
|||||||
return if !$self->{_geoip_city};
|
return if !$self->{_geoip_city};
|
||||||
|
|
||||||
if ($self->{_latitude} && $self->{_longitude}) {
|
if ($self->{_latitude} && $self->{_longitude}) {
|
||||||
return ($self->{_latitude}, $self->{_longitude}); # cached
|
return $self->{_latitude}, $self->{_longitude}; # cached
|
||||||
}
|
}
|
||||||
|
|
||||||
my $ip = $self->{_args}{distance} or return;
|
my $ip = $self->{_args}{distance} or return;
|
||||||
@ -325,7 +325,7 @@ sub get_my_lat_lon {
|
|||||||
if (!$self->{_latitude} || !$self->{_longitude}) {
|
if (!$self->{_latitude} || !$self->{_longitude}) {
|
||||||
$self->log(LOGNOTICE, "could not get my lat/lon");
|
$self->log(LOGNOTICE, "could not get my lat/lon");
|
||||||
}
|
}
|
||||||
return ($self->{_latitude}, $self->{_longitude});
|
return $self->{_latitude}, $self->{_longitude};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_sender_lat_lon {
|
sub get_sender_lat_lon {
|
||||||
@ -337,6 +337,6 @@ sub get_sender_lat_lon {
|
|||||||
$self->log(LOGNOTICE, "could not get sender lat/lon");
|
$self->log(LOGNOTICE, "could not get sender lat/lon");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return ($lat, $lon);
|
return $lat, $lon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ sub rcpt_handler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
# limit # of recipients if host has negative or unknown karma
|
# limit # of recipients if host has negative or unknown karma
|
||||||
return (DENY, "too many recipients for karma $karma (h: $history)");
|
return DENY, "too many recipients for karma $karma (h: $history)";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub data_handler {
|
sub data_handler {
|
||||||
@ -475,7 +475,7 @@ sub parse_db_record {
|
|||||||
$naughty ||= 0;
|
$naughty ||= 0;
|
||||||
$connects ||= 0;
|
$connects ||= 0;
|
||||||
}
|
}
|
||||||
return ($penalty_start_ts, $naughty, $nice, $connects);
|
return $penalty_start_ts, $naughty, $nice, $connects;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub calc_karma {
|
sub calc_karma {
|
||||||
@ -493,8 +493,8 @@ sub cleanup_and_return {
|
|||||||
|
|
||||||
untie $tied;
|
untie $tied;
|
||||||
close $lock;
|
close $lock;
|
||||||
return ($return_val) if defined $return_val; # explicit override
|
return $return_val if defined $return_val; # explicit override
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_db_key {
|
sub get_db_key {
|
||||||
|
@ -98,10 +98,10 @@ sub loadcheck {
|
|||||||
|
|
||||||
if ($self->{_load} > $self->{_args}{max_load}) {
|
if ($self->{_load} > $self->{_args}{max_load}) {
|
||||||
$self->log(LOGERROR, "local load too high: $self->{_load}");
|
$self->log(LOGERROR, "local load too high: $self->{_load}");
|
||||||
return (DENYSOFT, "Server load too high, please try again later.");
|
return DENYSOFT, "Server load too high, please try again later.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return (DECLINED, "continuing with load: $self->{_load}");
|
return DECLINED, "continuing with load: $self->{_load}";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_load_method {
|
sub get_load_method {
|
||||||
|
@ -143,7 +143,7 @@ sub hook_helo {
|
|||||||
eval {
|
eval {
|
||||||
$self->check_results($transaction, "HELO", $milter->send_helo($host));
|
$self->check_results($transaction, "HELO", $milter->send_helo($host));
|
||||||
};
|
};
|
||||||
return (DENY, $@) if $@;
|
return DENY, $@ if $@;
|
||||||
|
|
||||||
return DECLINED;
|
return DECLINED;
|
||||||
}
|
}
|
||||||
@ -159,7 +159,7 @@ sub hook_mail {
|
|||||||
$self->check_results($transaction, "MAIL FROM",
|
$self->check_results($transaction, "MAIL FROM",
|
||||||
$milter->send_mail_from($address->format));
|
$milter->send_mail_from($address->format));
|
||||||
};
|
};
|
||||||
return (DENY, $@) if $@;
|
return DENY, $@ if $@;
|
||||||
|
|
||||||
return DECLINED;
|
return DECLINED;
|
||||||
}
|
}
|
||||||
@ -176,7 +176,7 @@ sub hook_rcpt {
|
|||||||
$self->check_results($transaction, "RCPT TO",
|
$self->check_results($transaction, "RCPT TO",
|
||||||
$milter->send_rcpt_to($address->format));
|
$milter->send_rcpt_to($address->format));
|
||||||
};
|
};
|
||||||
return (DENY, $@) if $@;
|
return DENY, $@ if $@;
|
||||||
|
|
||||||
return DECLINED;
|
return DECLINED;
|
||||||
}
|
}
|
||||||
@ -201,7 +201,7 @@ sub hook_data_post {
|
|||||||
$self->check_results($transaction, "header $h",
|
$self->check_results($transaction, "header $h",
|
||||||
$milter->send_header($h, $val));
|
$milter->send_header($h, $val));
|
||||||
};
|
};
|
||||||
return (DENY, $@) if $@;
|
return DENY, $@ if $@;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ sub hook_data_post {
|
|||||||
$self->check_results($transaction, "end headers",
|
$self->check_results($transaction, "end headers",
|
||||||
$milter->send_end_headers());
|
$milter->send_end_headers());
|
||||||
};
|
};
|
||||||
return (DENY, $@) if $@;
|
return DENY, $@ if $@;
|
||||||
|
|
||||||
$transaction->body_resetpos;
|
$transaction->body_resetpos;
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ sub hook_data_post {
|
|||||||
$self->check_results($transaction, "body",
|
$self->check_results($transaction, "body",
|
||||||
$milter->send_body($data));
|
$milter->send_body($data));
|
||||||
};
|
};
|
||||||
return (DENY, $@) if $@;
|
return DENY, $@ if $@;
|
||||||
$data = '';
|
$data = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,7 +240,7 @@ sub hook_data_post {
|
|||||||
$self->check_results($transaction, "body",
|
$self->check_results($transaction, "body",
|
||||||
$milter->send_body($data));
|
$milter->send_body($data));
|
||||||
};
|
};
|
||||||
return (DENY, $@) if $@;
|
return DENY, $@ if $@;
|
||||||
$data = '';
|
$data = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +248,7 @@ sub hook_data_post {
|
|||||||
$self->check_results($transaction, "end of DATA",
|
$self->check_results($transaction, "end of DATA",
|
||||||
$milter->send_end_body());
|
$milter->send_end_body());
|
||||||
};
|
};
|
||||||
return (DENY, $@) if $@;
|
return DENY, $@ if $@;
|
||||||
|
|
||||||
my $milter_header_changes = $transaction->notes('milter_header_changes');
|
my $milter_header_changes = $transaction->notes('milter_header_changes');
|
||||||
|
|
||||||
|
@ -140,6 +140,5 @@ sub naughty {
|
|||||||
$self->log(LOGINFO, "disconnecting");
|
$self->log(LOGINFO, "disconnecting");
|
||||||
my $rtype = $self->connection->notes( 'naughty_reject_type' );
|
my $rtype = $self->connection->notes( 'naughty_reject_type' );
|
||||||
my $type = $self->get_reject_type( 'disconnect', $rtype );
|
my $type = $self->get_reject_type( 'disconnect', $rtype );
|
||||||
return ($type, $naughty);
|
return $type, $naughty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,19 +35,18 @@ sub hook_noop {
|
|||||||
++$self->{_noop_count};
|
++$self->{_noop_count};
|
||||||
### the following block is not used, RFC 2821 says we SHOULD ignore
|
### the following block is not used, RFC 2821 says we SHOULD ignore
|
||||||
### any arguments... so we MAY return an error if we want to :-)
|
### any arguments... so we MAY return an error if we want to :-)
|
||||||
# return (DENY, "Syntax error, NOOP does not take any arguments")
|
# return DENY, "Syntax error, NOOP does not take any arguments"
|
||||||
# if $args[0];
|
# if $args[0];
|
||||||
|
|
||||||
if ($self->{_noop_count} >= $self->{_max_noop}) {
|
if ($self->{_noop_count} >= $self->{_max_noop}) {
|
||||||
return (DENY_DISCONNECT,
|
return DENY_DISCONNECT, "Stop wasting my time, too many consecutive NOOPs";
|
||||||
"Stop wasting my time, too many consecutive NOOPs");
|
|
||||||
}
|
}
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub reset_noop_counter {
|
sub reset_noop_counter {
|
||||||
$_[0]->{_noop_count} = 0;
|
$_[0]->{_noop_count} = 0;
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
# and bind the counter reset to the hooks, QUIT not useful here:
|
# and bind the counter reset to the hooks, QUIT not useful here:
|
||||||
|
@ -24,50 +24,47 @@ use Qpsmtpd::Constants;
|
|||||||
|
|
||||||
sub hook_mail_parse {
|
sub hook_mail_parse {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return (OK, \&_parse) if ($self->qp->connection->hello eq 'helo');
|
return OK, \&_parse if $self->qp->connection->hello eq 'helo';
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub hook_rcpt_parse {
|
sub hook_rcpt_parse {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return (OK, \&_parse) if ($self->qp->connection->hello eq 'helo');
|
return OK, \&_parse if $self->qp->connection->hello eq 'helo';
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub _parse {
|
sub _parse {
|
||||||
my ($self, $cmd, $line) = @_;
|
my ($self, $cmd, $line) = @_;
|
||||||
$self->log(LOGDEBUG, "_parse() cmd=[$cmd], line=[$line]");
|
$self->log(LOGDEBUG, "_parse() cmd=[$cmd], line=[$line]");
|
||||||
if ($cmd eq 'mail') {
|
if ($cmd eq 'mail') {
|
||||||
return (DENY, "Syntax error in command")
|
return DENY, "Syntax error in command" if $line !~ s/^from:\s*//i;
|
||||||
unless ($line =~ s/^from:\s*//i);
|
|
||||||
}
|
}
|
||||||
else { # cmd eq 'rcpt'
|
else { # cmd eq 'rcpt'
|
||||||
return (DENY, "Syntax error in command")
|
return DENY, "Syntax error in command" if $line !~ s/^to:\s*//i;
|
||||||
unless ($line =~ s/^to:\s*//i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($line =~ s/^(<.*>)\s*//) {
|
if ($line =~ s/^(<.*>)\s*//) {
|
||||||
my $addr = $1;
|
my $addr = $1;
|
||||||
return (DENY, "No parameters allowed in " . uc($cmd))
|
return DENY, "No parameters allowed in " . uc($cmd)
|
||||||
if ($line =~ /^\S/);
|
if $line =~ /^\S/;
|
||||||
return (OK, $addr, ());
|
return OK, $addr, ();
|
||||||
}
|
}
|
||||||
|
|
||||||
## now, no <> are given
|
## now, no <> are given
|
||||||
$line =~ s/\s*$//;
|
$line =~ s/\s*$//;
|
||||||
if ($line =~ /\@/) {
|
if ($line =~ /\@/) {
|
||||||
return (DENY, "No parameters allowed in " . uc($cmd))
|
return DENY, "No parameters allowed in " . uc($cmd)
|
||||||
if ($line =~ /\@\S+\s+\S/);
|
if $line =~ /\@\S+\s+\S/;
|
||||||
return (OK, $line, ());
|
return OK, $line, ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($cmd eq "mail") {
|
if ($cmd eq "mail") {
|
||||||
return (OK, "<>") unless $line; # 'MAIL FROM:' -> 'MAIL FROM:<>'
|
return OK, "<>" if !$line; # 'MAIL FROM:' -> 'MAIL FROM:<>'
|
||||||
return (DENY, "Could not parse your MAIL FROM command");
|
return DENY, "Could not parse your MAIL FROM command";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return (DENY, "Could not parse your RCPT TO command")
|
return DENY, "Could not parse your RCPT TO command"
|
||||||
unless $line =~ /^(postmaster|abuse)$/i;
|
if $line !~ /^(postmaster|abuse)$/i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ sub rcpt_handler {
|
|||||||
my $s = $transaction->sender->address;
|
my $s = $transaction->sender->address;
|
||||||
if (!$s || $s eq '<>') {
|
if (!$s || $s eq '<>') {
|
||||||
$self->adjust_karma(-1);
|
$self->adjust_karma(-1);
|
||||||
return (DENY, "mailing lists do not accept null senders");
|
return DENY, "mailing lists do not accept null senders";
|
||||||
};
|
};
|
||||||
$self->log(LOGINFO, "pass, ezmlm list");
|
$self->log(LOGINFO, "pass, ezmlm list");
|
||||||
$k++;
|
$k++;
|
||||||
|
@ -83,14 +83,14 @@ sub hook_queue {
|
|||||||
|
|
||||||
unless ($transaction->header) {
|
unless ($transaction->header) {
|
||||||
$self->log(LOGERROR, "No header parsed for transaction; can't enqueue");
|
$self->log(LOGERROR, "No header parsed for transaction; can't enqueue");
|
||||||
return (DENY, 'Mail unqueuable');
|
return DENY, 'Mail unqueuable';
|
||||||
}
|
}
|
||||||
my $tmp_dir = $self->qp->config('spool_dir') || '/tmp';
|
my $tmp_dir = $self->qp->config('spool_dir') || '/tmp';
|
||||||
$tmp_dir = $1 if ($tmp_dir =~ /(.*)/);
|
$tmp_dir = $1 if ($tmp_dir =~ /(.*)/);
|
||||||
my ($tmp, $tmpfn) = tempfile("exim-bsmtp.$$.XXXXXX", DIR => $tmp_dir);
|
my ($tmp, $tmpfn) = tempfile("exim-bsmtp.$$.XXXXXX", DIR => $tmp_dir);
|
||||||
unless ($tmp && $tmpfn) {
|
unless ($tmp && $tmpfn) {
|
||||||
$self->log(LOGERROR, "Couldn't create tempfile: $!");
|
$self->log(LOGERROR, "Couldn't create tempfile: $!");
|
||||||
return (DECLINED, 'Internal error enqueueing mail');
|
return DECLINED, 'Internal error enqueueing mail';
|
||||||
}
|
}
|
||||||
|
|
||||||
print $tmp "HELO ", hostname(), "\n",
|
print $tmp "HELO ", hostname(), "\n",
|
||||||
@ -112,7 +112,7 @@ sub hook_queue {
|
|||||||
unless ($exim) {
|
unless ($exim) {
|
||||||
$self->log(LOGERROR, "Could not execute $self->{_exim_path}: $!");
|
$self->log(LOGERROR, "Could not execute $self->{_exim_path}: $!");
|
||||||
unlink $tmpfn or $self->log(LOGERROR, "unlink: $tmpfn: $!");
|
unlink $tmpfn or $self->log(LOGERROR, "unlink: $tmpfn: $!");
|
||||||
return (DECLINED, "Internal error enqueuing mail");
|
return DECLINED, "Internal error enqueuing mail";
|
||||||
}
|
}
|
||||||
|
|
||||||
# Normally exim produces no output in BSMTP mode; anything that
|
# Normally exim produces no output in BSMTP mode; anything that
|
||||||
@ -135,7 +135,7 @@ sub hook_queue {
|
|||||||
if ($bsmtp_error && $bsmtp_error >= 400 && $bsmtp_error < 600) {
|
if ($bsmtp_error && $bsmtp_error >= 400 && $bsmtp_error < 600) {
|
||||||
$self->log(LOGERROR,
|
$self->log(LOGERROR,
|
||||||
"BSMTP enqueue failed; response $bsmtp_error" . " ($bsmtp_msg)");
|
"BSMTP enqueue failed; response $bsmtp_error" . " ($bsmtp_msg)");
|
||||||
return ($bsmtp_error < 400 ? DECLINED : DENY, $bsmtp_msg);
|
return $bsmtp_error < 400 ? DECLINED : DENY, $bsmtp_msg;
|
||||||
}
|
}
|
||||||
elsif (($exit >> 8) != 0 || $bsmtp_error) {
|
elsif (($exit >> 8) != 0 || $bsmtp_error) {
|
||||||
$self->log(LOGERROR,
|
$self->log(LOGERROR,
|
||||||
@ -143,10 +143,9 @@ sub hook_queue {
|
|||||||
. ($exit >> 8)
|
. ($exit >> 8)
|
||||||
. " from $self->{_exim_path} -bS"
|
. " from $self->{_exim_path} -bS"
|
||||||
);
|
);
|
||||||
return (DECLINED, 'Internal error enqueuing mail');
|
return DECLINED, 'Internal error enqueuing mail';
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "Enqueued to exim via BSMTP");
|
$self->log(LOGINFO, "Enqueued to exim via BSMTP");
|
||||||
return (OK, "Queued!");
|
return OK, "Queued!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,18 +144,18 @@ sub hook_queue {
|
|||||||
($rc, @msg) = $self->deliver_user($transaction, $addr);
|
($rc, @msg) = $self->deliver_user($transaction, $addr);
|
||||||
unless ($rc == OK) {
|
unless ($rc == OK) {
|
||||||
umask $old_umask;
|
umask $old_umask;
|
||||||
return ($rc, @msg);
|
return $rc, @msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
umask $old_umask;
|
umask $old_umask;
|
||||||
return (OK, @msg); # last @msg is the same like any other before...
|
return OK, @msg; # last @msg is the same like any other before...
|
||||||
}
|
}
|
||||||
|
|
||||||
$transaction->header->add('Delivered-To', $_->address, 0)
|
$transaction->header->add('Delivered-To', $_->address, 0)
|
||||||
for $transaction->recipients;
|
for $transaction->recipients;
|
||||||
($rc, @msg) = $self->write_file($transaction, $self->{_maildir});
|
($rc, @msg) = $self->write_file($transaction, $self->{_maildir});
|
||||||
umask $old_umask;
|
umask $old_umask;
|
||||||
return ($rc, @msg);
|
return $rc, @msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub write_file {
|
sub write_file {
|
||||||
@ -170,7 +170,7 @@ sub write_file {
|
|||||||
|
|
||||||
open(MF, ">$maildir/tmp/$file")
|
open(MF, ">$maildir/tmp/$file")
|
||||||
or $self->log(LOGWARN, "could not open $maildir/tmp/$file: $!"),
|
or $self->log(LOGWARN, "could not open $maildir/tmp/$file: $!"),
|
||||||
return (DECLINED, "queue error (open)");
|
return DECLINED, "queue error (open)";
|
||||||
|
|
||||||
print MF "Return-Path: ", $transaction->sender->format, "\n";
|
print MF "Return-Path: ", $transaction->sender->format, "\n";
|
||||||
|
|
||||||
@ -184,20 +184,20 @@ sub write_file {
|
|||||||
}
|
}
|
||||||
close MF
|
close MF
|
||||||
or $self->log(LOGWARN, "could not close $maildir/tmp/$file: $!")
|
or $self->log(LOGWARN, "could not close $maildir/tmp/$file: $!")
|
||||||
and return (DECLINED, "queue error (close)");
|
and return DECLINED, "queue error (close)";
|
||||||
|
|
||||||
link "$maildir/tmp/$file",
|
link "$maildir/tmp/$file",
|
||||||
"$maildir/new/$file"
|
"$maildir/new/$file"
|
||||||
or $self->log(LOGWARN,
|
or $self->log(LOGWARN,
|
||||||
"could not link $maildir/tmp/$file to $maildir/new/$file: $!")
|
"could not link $maildir/tmp/$file to $maildir/new/$file: $!")
|
||||||
and return (DECLINED, "queue error (link)");
|
and return DECLINED, "queue error (link)";
|
||||||
|
|
||||||
unlink "$maildir/tmp/$file";
|
unlink "$maildir/tmp/$file";
|
||||||
|
|
||||||
my $msg_id = $transaction->header->get('Message-Id') || '';
|
my $msg_id = $transaction->header->get('Message-Id') || '';
|
||||||
$msg_id =~ s/[\r\n].*//s;
|
$msg_id =~ s/[\r\n].*//s;
|
||||||
|
|
||||||
return (OK, "Queued! $msg_id");
|
return OK, "Queued! $msg_id";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub deliver_user {
|
sub deliver_user {
|
||||||
|
@ -180,24 +180,23 @@ sub hook_queue {
|
|||||||
my $stat = eval $key # keys have the same names as the constants
|
my $stat = eval $key # keys have the same names as the constants
|
||||||
or next;
|
or next;
|
||||||
if ($status & $stat) {
|
if ($status & $stat) {
|
||||||
return (DENYSOFT, $reason || $cleanup_soft{$key});
|
return DENYSOFT, $reason || $cleanup_soft{$key};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach my $key (keys %cleanup_hard) {
|
foreach my $key (keys %cleanup_hard) {
|
||||||
my $stat = eval $key # keys have the same names as the constants
|
my $stat = eval $key # keys have the same names as the constants
|
||||||
or next;
|
or next;
|
||||||
if ($status & $stat) {
|
if ($status & $stat) {
|
||||||
return (DENY, $reason || $cleanup_hard{$key});
|
return DENY, $reason || $cleanup_hard{$key};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# we have no idea why we're here.
|
# we have no idea why we're here.
|
||||||
return (DECLINED,
|
return DECLINED, $reason || "Unable to queue message ($status, $reason)";
|
||||||
$reason || "Unable to queue message ($status, $reason)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
my $msg_id = $transaction->header->get('Message-Id') || '';
|
my $msg_id = $transaction->header->get('Message-Id') || '';
|
||||||
$msg_id =~ s/[\r\n].*//s; # don't allow newlines in the Message-Id here
|
$msg_id =~ s/[\r\n].*//s; # don't allow newlines in the Message-Id here
|
||||||
return (OK, "Queued! $msg_id (Queue-Id: $qid)");
|
return OK, "Queued! $msg_id (Queue-Id: $qid)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,18 +74,18 @@ sub hook_queue {
|
|||||||
my @rcpt = map { "T" . $_->address } $transaction->recipients;
|
my @rcpt = map { "T" . $_->address } $transaction->recipients;
|
||||||
my $from = "F" . ($transaction->sender->address || "");
|
my $from = "F" . ($transaction->sender->address || "");
|
||||||
print ENVELOPE_WRITER "$from\0", join("\0", @rcpt), "\0\0"
|
print ENVELOPE_WRITER "$from\0", join("\0", @rcpt), "\0\0"
|
||||||
or return (DECLINED, "Could not print addresses to queue");
|
or return DECLINED, "Could not print addresses to queue";
|
||||||
|
|
||||||
close ENVELOPE_WRITER;
|
close ENVELOPE_WRITER;
|
||||||
waitpid($child, 0);
|
waitpid($child, 0);
|
||||||
my $exit_code = $? >> 8;
|
my $exit_code = $? >> 8;
|
||||||
$exit_code
|
$exit_code
|
||||||
and return (DECLINED, "Unable to queue message ($exit_code)");
|
and return DECLINED, "Unable to queue message ($exit_code)";
|
||||||
|
|
||||||
my $msg_id = $transaction->header->get('Message-Id') || '';
|
my $msg_id = $transaction->header->get('Message-Id') || '';
|
||||||
$msg_id =~ s/[\r\n].*//s; # don't allow newlines in the Message-Id here
|
$msg_id =~ s/[\r\n].*//s; # don't allow newlines in the Message-Id here
|
||||||
$msg_id = "<$msg_id>" unless $msg_id =~ /^<.*>$/; # surround in <>'s
|
$msg_id = "<$msg_id>" unless $msg_id =~ /^<.*>$/; # surround in <>'s
|
||||||
return (OK, "Queued! " . time . " qp $child $msg_id");
|
return OK, "Queued! " . time . " qp $child $msg_id";
|
||||||
}
|
}
|
||||||
elsif (defined $child) {
|
elsif (defined $child) {
|
||||||
|
|
||||||
|
@ -77,27 +77,27 @@ sub hook_queue {
|
|||||||
return(DECLINED, $xcret) if defined $xcret;
|
return(DECLINED, $xcret) if defined $xcret;
|
||||||
|
|
||||||
$smtp->mail($transaction->sender->address || "")
|
$smtp->mail($transaction->sender->address || "")
|
||||||
or return (DECLINED, "Unable to queue message ($!)");
|
or return DECLINED, "Unable to queue message ($!)";
|
||||||
for ($transaction->recipients) {
|
for ($transaction->recipients) {
|
||||||
$smtp->to($_->address)
|
$smtp->to($_->address)
|
||||||
or return (DECLINED, "Unable to queue message ($!)");
|
or return DECLINED, "Unable to queue message ($!)";
|
||||||
}
|
}
|
||||||
$smtp->data() or return (DECLINED, "Unable to queue message ($!)");
|
$smtp->data() or return DECLINED, "Unable to queue message ($!)";
|
||||||
$smtp->datasend($transaction->header->as_string)
|
$smtp->datasend($transaction->header->as_string)
|
||||||
or return (DECLINED, "Unable to queue message ($!)");
|
or return DECLINED, "Unable to queue message ($!)";
|
||||||
$transaction->body_resetpos;
|
$transaction->body_resetpos;
|
||||||
while (my $line = $transaction->body_getline) {
|
while (my $line = $transaction->body_getline) {
|
||||||
$smtp->datasend($line)
|
$smtp->datasend($line)
|
||||||
or return (DECLINED, "Unable to queue message ($!)");
|
or return DECLINED, "Unable to queue message ($!)";
|
||||||
}
|
}
|
||||||
$smtp->dataend() or return (DECLINED, "Unable to queue message ($!)");
|
$smtp->dataend() or return DECLINED, "Unable to queue message ($!)";
|
||||||
my $qid = $smtp->message();
|
my $qid = $smtp->message();
|
||||||
my @list = split(' ', $qid);
|
my @list = split(' ', $qid);
|
||||||
$qid = pop(@list);
|
$qid = pop(@list);
|
||||||
|
|
||||||
$smtp->quit() or return (DECLINED, "Unable to queue message ($!)");
|
$smtp->quit() or return DECLINED, "Unable to queue message ($!)";
|
||||||
$self->log(LOGINFO, "finished queueing");
|
$self->log(LOGINFO, "finished queueing");
|
||||||
return (OK, "queued as $qid");
|
return OK, "queued as $qid";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub xclient {
|
sub xclient {
|
||||||
|
@ -5,10 +5,10 @@ sub hook_quit {
|
|||||||
|
|
||||||
# if she talks EHLO she is probably too sophisticated to enjoy the
|
# if she talks EHLO she is probably too sophisticated to enjoy the
|
||||||
# fun, so skip it.
|
# fun, so skip it.
|
||||||
return (DECLINED) if ($qp->connection->hello || '') eq "ehlo";
|
return DECLINED if ($qp->connection->hello || '') eq "ehlo";
|
||||||
|
|
||||||
my $fortune = '/usr/games/fortune';
|
my $fortune = '/usr/games/fortune';
|
||||||
return DECLINED unless -e $fortune;
|
return DECLINED if !-e $fortune;
|
||||||
|
|
||||||
my @fortune = `$fortune -s`;
|
my @fortune = `$fortune -s`;
|
||||||
@fortune = map { chop; s/^/ \/ /; $_ } @fortune;
|
@fortune = map { chop; s/^/ \/ /; $_ } @fortune;
|
||||||
|
@ -57,8 +57,8 @@ or
|
|||||||
$_[0]->log(LOGINFO,
|
$_[0]->log(LOGINFO,
|
||||||
"to fail, rand(1) must be more than " . ($successp**(1 / 6)));
|
"to fail, rand(1) must be more than " . ($successp**(1 / 6)));
|
||||||
rand(1) < ($successp**(1 / 6)) and return NEXT;
|
rand(1) < ($successp**(1 / 6)) and return NEXT;
|
||||||
rand(5) < 2 and return (DENYSOFT_DISCONNECT, "random failure");
|
rand(5) < 2 and return DENYSOFT_DISCONNECT, "random failure";
|
||||||
return (DENYSOFT, "random failure");
|
return DENYSOFT, "random failure";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub hook_connect {
|
sub hook_connect {
|
||||||
|
@ -175,14 +175,14 @@ sub read_map {
|
|||||||
|
|
||||||
sub hook_rcpt {
|
sub hook_rcpt {
|
||||||
my ($self, $transaction, $recipient) = @_;
|
my ($self, $transaction, $recipient) = @_;
|
||||||
return (DECLINED)
|
return DECLINED
|
||||||
unless $recipient->host && $recipient->user;
|
unless $recipient->host && $recipient->user;
|
||||||
|
|
||||||
return (DECLINED)
|
return DECLINED
|
||||||
unless lc($recipient->host) eq $self->{_domain};
|
unless lc($recipient->host) eq $self->{_domain};
|
||||||
|
|
||||||
my $rcpt = lc $recipient->user . '@' . lc $recipient->host;
|
my $rcpt = lc $recipient->user . '@' . lc $recipient->host;
|
||||||
return (@{$self->{_default}})
|
return @{$self->{_default}}
|
||||||
unless exists $map{$rcpt};
|
unless exists $map{$rcpt};
|
||||||
|
|
||||||
return @{$map{$rcpt}};
|
return @{$map{$rcpt}};
|
||||||
|
@ -30,15 +30,15 @@ use Qpsmtpd::DSN;
|
|||||||
sub hook_rcpt {
|
sub hook_rcpt {
|
||||||
my ($self, $transaction, $recipient, %param) = @_;
|
my ($self, $transaction, $recipient, %param) = @_;
|
||||||
|
|
||||||
return (OK) if $self->is_immune(); # relay_client or whitelist
|
return OK if $self->is_immune(); # relay_client or whitelist
|
||||||
|
|
||||||
# Allow 'no @' addresses for 'postmaster' and 'abuse'
|
# Allow 'no @' addresses for 'postmaster' and 'abuse'
|
||||||
# qmail-smtpd will do this for all users without a domain, but we'll
|
# qmail-smtpd will do this for all users without a domain, but we'll
|
||||||
# be a bit more picky. Maybe that's a bad idea.
|
# be a bit more picky. Maybe that's a bad idea.
|
||||||
my $host = $self->get_rcpt_host($recipient) or return (OK);
|
my $host = $self->get_rcpt_host($recipient) or return OK;
|
||||||
|
|
||||||
return (OK) if $self->is_in_rcpthosts($host);
|
return OK if $self->is_in_rcpthosts($host);
|
||||||
return (OK) if $self->is_in_morercpthosts($host);
|
return OK if $self->is_in_morercpthosts($host);
|
||||||
|
|
||||||
# default of relaying_denied is obviously DENY,
|
# default of relaying_denied is obviously DENY,
|
||||||
# we use the default "Relaying denied" message...
|
# we use the default "Relaying denied" message...
|
||||||
|
@ -45,7 +45,7 @@ use Qpsmtpd::Constants;
|
|||||||
|
|
||||||
sub hook_rcpt {
|
sub hook_rcpt {
|
||||||
my ($self, $transaction, $recipient) = @_;
|
my ($self, $transaction, $recipient) = @_;
|
||||||
return (DECLINED)
|
return DECLINED
|
||||||
unless $recipient->host && $recipient->user;
|
unless $recipient->host && $recipient->user;
|
||||||
|
|
||||||
my $rcpt = lc $recipient->user . '@' . $recipient->host;
|
my $rcpt = lc $recipient->user . '@' . $recipient->host;
|
||||||
@ -93,7 +93,7 @@ sub hook_rcpt {
|
|||||||
$self->log(LOGDEBUG, "RE $re matched $rcpt, returning $ok");
|
$self->log(LOGDEBUG, "RE $re matched $rcpt, returning $ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($const, $comment);
|
return $const, $comment;
|
||||||
}
|
}
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
@ -227,13 +227,13 @@ sub hook_connect {
|
|||||||
$self->qp->connection->relay_client(0);
|
$self->qp->connection->relay_client(0);
|
||||||
delete $ENV{RELAYCLIENT};
|
delete $ENV{RELAYCLIENT};
|
||||||
$self->log(LOGINFO, "fail, disabled by norelayclients");
|
$self->log(LOGINFO, "fail, disabled by norelayclients");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($ENV{RELAYCLIENT}) {
|
if ($ENV{RELAYCLIENT}) {
|
||||||
$self->qp->connection->relay_client(1);
|
$self->qp->connection->relay_client(1);
|
||||||
$self->log(LOGINFO, "pass, enabled by env");
|
$self->log(LOGINFO, "pass, enabled by env");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->populate_relayclients();
|
$self->populate_relayclients();
|
||||||
@ -242,18 +242,17 @@ sub hook_connect {
|
|||||||
|
|
||||||
if ($self->is_in_cidr_block() || $self->is_octet_match()) {
|
if ($self->is_in_cidr_block() || $self->is_octet_match()) {
|
||||||
$self->qp->connection->relay_client(1);
|
$self->qp->connection->relay_client(1);
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "skip, no match");
|
$self->log(LOGINFO, "skip, no match");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub relay_only {
|
sub relay_only {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
if ($self->qp->connection->relay_client) {
|
if ($self->qp->connection->relay_client) {
|
||||||
return (OK);
|
return OK;
|
||||||
}
|
}
|
||||||
return (DENY);
|
return DENY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ sub mail_handler {
|
|||||||
scope => 'mfrom',
|
scope => 'mfrom',
|
||||||
result => 'pass',
|
result => 'pass',
|
||||||
} );
|
} );
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
};
|
};
|
||||||
|
|
||||||
my $format = $sender->format;
|
my $format = $sender->format;
|
||||||
@ -105,7 +105,7 @@ sub mail_handler {
|
|||||||
scope => 'helo',
|
scope => 'helo',
|
||||||
result => 'none',
|
result => 'none',
|
||||||
} );
|
} );
|
||||||
return (DECLINED, "SPF - null sender");
|
return DECLINED, "SPF - null sender";
|
||||||
}
|
}
|
||||||
|
|
||||||
my $from = $sender->user . '@' . lc($sender->host);
|
my $from = $sender->user . '@' . lc($sender->host);
|
||||||
@ -147,8 +147,8 @@ sub mail_handler {
|
|||||||
|
|
||||||
if (!$code) {
|
if (!$code) {
|
||||||
$self->log(LOGINFO, "fail, no response");
|
$self->log(LOGINFO, "fail, no response");
|
||||||
return (DENYSOFT, "SPF - no response") if $reject >= 2;
|
return DENYSOFT, "SPF - no response" if $reject >= 2;
|
||||||
return (DECLINED, "SPF - no response");
|
return DECLINED, "SPF - no response";
|
||||||
}
|
}
|
||||||
|
|
||||||
$transaction->notes('dmarc_spf', {
|
$transaction->notes('dmarc_spf', {
|
||||||
@ -163,12 +163,12 @@ sub mail_handler {
|
|||||||
$self->adjust_karma(1);
|
$self->adjust_karma(1);
|
||||||
$transaction->notes('spf_pass_host', lc $sender->host);
|
$transaction->notes('spf_pass_host', lc $sender->host);
|
||||||
$self->log(LOGINFO, "pass, $why");
|
$self->log(LOGINFO, "pass, $why");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$reject) {
|
if (!$reject) {
|
||||||
$self->log(LOGINFO, "skip, tolerated ($code: $why)");
|
$self->log(LOGINFO, "skip, tolerated ($code: $why)");
|
||||||
return (DECLINED, "SPF - $code: $why");
|
return DECLINED, "SPF - $code: $why";
|
||||||
}
|
}
|
||||||
|
|
||||||
# SPF result codes: pass fail softfail neutral none error permerror temperror
|
# SPF result codes: pass fail softfail neutral none error permerror temperror
|
||||||
@ -179,27 +179,27 @@ sub mail_handler {
|
|||||||
if ($code eq 'neutral') {
|
if ($code eq 'neutral') {
|
||||||
if ($reject >= 5 ) {
|
if ($reject >= 5 ) {
|
||||||
$self->log(LOGINFO, "fail, $code, $why");
|
$self->log(LOGINFO, "fail, $code, $why");
|
||||||
return (DENY, "SPF - $code: $why");
|
return DENY, "SPF - $code: $why";
|
||||||
};
|
};
|
||||||
$self->log(LOGINFO, "fail, tolerated, $code, $why");
|
$self->log(LOGINFO, "fail, tolerated, $code, $why");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
if ($code =~ /(?:permerror|error)/ ) {
|
if ($code =~ /(?:permerror|error)/ ) {
|
||||||
$self->log(LOGINFO, "fail, $code, $why") if $reject > 3;
|
$self->log(LOGINFO, "fail, $code, $why") if $reject > 3;
|
||||||
return (DENY, "SPF - $code: $why") if $reject >= 6;
|
return DENY, "SPF - $code: $why" if $reject >= 6;
|
||||||
return (DENYSOFT, "SPF - $code: $why") if $reject > 3;
|
return DENYSOFT, "SPF - $code: $why" if $reject > 3;
|
||||||
$self->log(LOGINFO, "fail, tolerated, $code, $why");
|
$self->log(LOGINFO, "fail, tolerated, $code, $why");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
if ($code eq 'temperror') {
|
if ($code eq 'temperror') {
|
||||||
$self->log(LOGINFO, "fail, $code, $why");
|
$self->log(LOGINFO, "fail, $code, $why");
|
||||||
return (DENYSOFT, "SPF - $code: $why") if $reject >= 2;
|
return DENYSOFT, "SPF - $code: $why" if $reject >= 2;
|
||||||
$self->log(LOGINFO, "fail, tolerated, $code, $why");
|
$self->log(LOGINFO, "fail, tolerated, $code, $why");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "SPF from $from was $code: $why");
|
$self->log(LOGINFO, "SPF from $from was $code: $why");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub handle_code_none {
|
sub handle_code_none {
|
||||||
@ -207,7 +207,7 @@ sub handle_code_none {
|
|||||||
|
|
||||||
if ($reject >= 6) {
|
if ($reject >= 6) {
|
||||||
$self->log(LOGINFO, "fail, none, $why");
|
$self->log(LOGINFO, "fail, none, $why");
|
||||||
return (DENY, "SPF - none: $why");
|
return DENY, "SPF - none: $why";
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "skip, tolerated, none, $why");
|
$self->log(LOGINFO, "skip, tolerated, none, $why");
|
||||||
@ -221,8 +221,8 @@ sub handle_code_fail {
|
|||||||
|
|
||||||
if ($reject >= 2) {
|
if ($reject >= 2) {
|
||||||
$self->log(LOGINFO, "fail, $why");
|
$self->log(LOGINFO, "fail, $why");
|
||||||
return (DENY, "SPF - forgery: $why") if $reject >= 3;
|
return DENY, "SPF - forgery: $why" if $reject >= 3;
|
||||||
return (DENYSOFT, "SPF - fail: $why");
|
return DENYSOFT, "SPF - fail: $why";
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "fail, tolerated, $why");
|
$self->log(LOGINFO, "fail, tolerated, $why");
|
||||||
@ -236,8 +236,8 @@ sub handle_code_softfail {
|
|||||||
|
|
||||||
if ($reject >= 3) {
|
if ($reject >= 3) {
|
||||||
$self->log(LOGINFO, "fail, soft, $why");
|
$self->log(LOGINFO, "fail, soft, $why");
|
||||||
return (DENY, "SPF - fail: $why") if $reject >= 4;
|
return DENY, "SPF - fail: $why" if $reject >= 4;
|
||||||
return (DENYSOFT, "SPF - fail: $why") if $reject >= 3;
|
return DENYSOFT, "SPF - fail: $why" if $reject >= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "fail, tolerated, soft, $why");
|
$self->log(LOGINFO, "fail, tolerated, soft, $why");
|
||||||
@ -250,7 +250,7 @@ sub data_post_handler {
|
|||||||
my $result = $transaction->notes('spfquery') or return DECLINED;
|
my $result = $transaction->notes('spfquery') or return DECLINED;
|
||||||
|
|
||||||
# if we skipped processing in mail_handler, we should skip here too
|
# if we skipped processing in mail_handler, we should skip here too
|
||||||
return (DECLINED) if $self->is_immune();
|
return DECLINED if $self->is_immune();
|
||||||
|
|
||||||
$self->log(LOGDEBUG, "result was $result->code");
|
$self->log(LOGDEBUG, "result was $result->code");
|
||||||
|
|
||||||
|
@ -170,22 +170,22 @@ sub register {
|
|||||||
sub data_post_handler {
|
sub data_post_handler {
|
||||||
my ($self, $transaction) = @_;
|
my ($self, $transaction) = @_;
|
||||||
|
|
||||||
return (DECLINED) if $self->is_immune();
|
return DECLINED if $self->is_immune();
|
||||||
|
|
||||||
if ($transaction->data_size > 500_000) {
|
if ($transaction->data_size > 500_000) {
|
||||||
$self->log(LOGINFO,
|
$self->log(LOGINFO,
|
||||||
"skip, too large (" . $transaction->data_size . ")");
|
"skip, too large (" . $transaction->data_size . ")");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $SPAMD = $self->connect_to_spamd() or return (DECLINED);
|
my $SPAMD = $self->connect_to_spamd() or return DECLINED;
|
||||||
my $username = $self->select_spamd_username($transaction);
|
my $username = $self->select_spamd_username($transaction);
|
||||||
my $message = $self->assemble_message($transaction);
|
my $message = $self->assemble_message($transaction);
|
||||||
my $length = length $message;
|
my $length = length $message;
|
||||||
|
|
||||||
$self->print_to_spamd($SPAMD, $message, $length, $username);
|
$self->print_to_spamd($SPAMD, $message, $length, $username);
|
||||||
shutdown($SPAMD, 1); # close our side of the socket (tell spamd we're done)
|
shutdown($SPAMD, 1); # close our side of the socket (tell spamd we're done)
|
||||||
my $headers = $self->parse_spamd_response($SPAMD) or return (DECLINED);
|
my $headers = $self->parse_spamd_response($SPAMD) or return DECLINED;
|
||||||
|
|
||||||
$self->insert_spam_headers($transaction, $headers, $username);
|
$self->insert_spam_headers($transaction, $headers, $username);
|
||||||
$self->munge_subject($transaction);
|
$self->munge_subject($transaction);
|
||||||
@ -430,7 +430,7 @@ sub reject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "fail, $status, > $reject, $learn");
|
$self->log(LOGINFO, "fail, $status, > $reject, $learn");
|
||||||
return ($self->get_reject_type(), "spam score exceeded threshold");
|
return $self->get_reject_type(), "spam score exceeded threshold";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub munge_subject {
|
sub munge_subject {
|
||||||
|
@ -160,7 +160,7 @@ sub hook_connect {
|
|||||||
|
|
||||||
unless (_convert_to_ssl($self)) {
|
unless (_convert_to_ssl($self)) {
|
||||||
$self->log(LOGINFO, "fail, unable to establish SSL");
|
$self->log(LOGINFO, "fail, unable to establish SSL");
|
||||||
return (DENY_DISCONNECT, "Cannot establish SSL session");
|
return DENY_DISCONNECT, "Cannot establish SSL session";
|
||||||
}
|
}
|
||||||
$self->log(LOGINFO, "pass, connect via SMTPS");
|
$self->log(LOGINFO, "pass, connect via SMTPS");
|
||||||
return DECLINED;
|
return DECLINED;
|
||||||
|
@ -248,7 +248,7 @@ sub evaluate {
|
|||||||
my $v =
|
my $v =
|
||||||
(($1 & 0xff) << 24) | (($2 & 0xff) << 16) | (($3 & 0xff) << 8) |
|
(($1 & 0xff) << 24) | (($2 & 0xff) << 16) | (($3 & 0xff) << 8) |
|
||||||
($4 & 0xff);
|
($4 & 0xff);
|
||||||
return ($v & $mask);
|
return $v & $mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub lookup_start {
|
sub lookup_start {
|
||||||
@ -502,7 +502,7 @@ sub collect_results {
|
|||||||
sub hook_data {
|
sub hook_data {
|
||||||
my ($self, $transaction) = @_;
|
my ($self, $transaction) = @_;
|
||||||
|
|
||||||
return (DECLINED) if $self->is_immune();
|
return DECLINED if $self->is_immune();
|
||||||
|
|
||||||
my $queries = $self->lookup_start(
|
my $queries = $self->lookup_start(
|
||||||
$transaction,
|
$transaction,
|
||||||
@ -524,10 +524,10 @@ sub hook_data {
|
|||||||
$transaction->header->add('X-URIBL-Match', $_->{desc}, 0);
|
$transaction->header->add('X-URIBL-Match', $_->{desc}, 0);
|
||||||
}
|
}
|
||||||
elsif ($_->{action} eq 'deny') {
|
elsif ($_->{action} eq 'deny') {
|
||||||
return (DENY, $_->{desc});
|
return DENY, $_->{desc};
|
||||||
}
|
}
|
||||||
elsif ($_->{action} eq 'denysoft') {
|
elsif ($_->{action} eq 'denysoft') {
|
||||||
return (DENYSOFT, $_->{desc});
|
return DENYSOFT, $_->{desc};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return DECLINED;
|
return DECLINED;
|
||||||
|
@ -161,7 +161,7 @@ sub hook_data_post {
|
|||||||
# check if something went wrong
|
# check if something went wrong
|
||||||
if ($signal) {
|
if ($signal) {
|
||||||
$self->log(LOGERROR, "kavscanner exited with signal: $signal");
|
$self->log(LOGERROR, "kavscanner exited with signal: $signal");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
# either we found a virus or something went wrong
|
# either we found a virus or something went wrong
|
||||||
@ -174,7 +174,7 @@ sub hook_data_post {
|
|||||||
$self->log(LOGWARN, "Virus found! ($description)");
|
$self->log(LOGWARN, "Virus found! ($description)");
|
||||||
|
|
||||||
# we don't want to be disturbed be these, so block mail and DENY connection
|
# we don't want to be disturbed be these, so block mail and DENY connection
|
||||||
return (DENY, "Virus found: $description");
|
return DENY, "Virus found: $description";
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -188,17 +188,17 @@ sub hook_data_post {
|
|||||||
"aveserver: some of the required parameters are missing from the command line."
|
"aveserver: some of the required parameters are missing from the command line."
|
||||||
)
|
)
|
||||||
if ($result =~ /^9$/);
|
if ($result =~ /^9$/);
|
||||||
return (DENY,
|
if ( $self->{_blockonerror} ) {
|
||||||
|
return DENY,
|
||||||
"Unable to scan for virus, please contact admin of "
|
"Unable to scan for virus, please contact admin of "
|
||||||
. $self->qp->config("me")
|
. $self->qp->config("me")
|
||||||
. ", if you feel this is an error!"
|
. ", if you feel this is an error!"
|
||||||
)
|
}
|
||||||
if $self->{_blockonerror};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "kavscanner results: $description");
|
$self->log(LOGINFO, "kavscanner results: $description");
|
||||||
$transaction->header->add('X-Virus-Checked',
|
$transaction->header->add('X-Virus-Checked',
|
||||||
'Checked by Kaspersky on ' . $self->qp->config("me"));
|
'Checked by Kaspersky on ' . $self->qp->config("me"));
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ sub hook_data_post {
|
|||||||
. $transaction->data_size . " vs "
|
. $transaction->data_size . " vs "
|
||||||
. $self->{"_bitd"}->{"max_size"} . ")"
|
. $self->{"_bitd"}->{"max_size"} . ")"
|
||||||
);
|
);
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ignore non-multipart emails
|
# Ignore non-multipart emails
|
||||||
@ -123,10 +123,10 @@ sub hook_data_post {
|
|||||||
if ($output) {
|
if ($output) {
|
||||||
$self->log(LOGINFO, "Virus(es) found: $output");
|
$self->log(LOGINFO, "Virus(es) found: $output");
|
||||||
if ($self->{"_bitd"}->{"deny_viruses"} eq "yes") {
|
if ($self->{"_bitd"}->{"deny_viruses"} eq "yes") {
|
||||||
return (DENY, "Virus Found: $output");
|
return DENY, "Virus Found: $output";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ sub hook_data_post {
|
|||||||
. $transaction->data_size
|
. $transaction->data_size
|
||||||
. " vs $self->{_max_size})"
|
. " vs $self->{_max_size})"
|
||||||
);
|
);
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $filename = $transaction->body_filename;
|
my $filename = $transaction->body_filename;
|
||||||
@ -211,8 +211,8 @@ sub hook_data_post {
|
|||||||
|
|
||||||
if ($signal) {
|
if ($signal) {
|
||||||
$self->log(LOGINFO, "clamscan exited with signal: $signal");
|
$self->log(LOGINFO, "clamscan exited with signal: $signal");
|
||||||
return (DENYSOFT) if (!$self->{_declined_on_fail});
|
return DENYSOFT if !$self->{_declined_on_fail};
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
if ($result == 1) {
|
if ($result == 1) {
|
||||||
$self->log(LOGINFO, "Virus(es) found: $output");
|
$self->log(LOGINFO, "Virus(es) found: $output");
|
||||||
@ -221,17 +221,17 @@ sub hook_data_post {
|
|||||||
$transaction->header->add('X-Virus-Details', $output);
|
$transaction->header->add('X-Virus-Details', $output);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return (DENY, "Virus Found: $output");
|
return DENY, "Virus Found: $output";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif ($result) {
|
elsif ($result) {
|
||||||
$self->log(LOGERROR, "ClamAV error: $cmd: $result\n");
|
$self->log(LOGERROR, "ClamAV error: $cmd: $result\n");
|
||||||
return (DENYSOFT) if (!$self->{_declined_on_fail});
|
return DENYSOFT if !$self->{_declined_on_fail};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$transaction->header->add('X-Virus-Checked',
|
$transaction->header->add('X-Virus-Checked',
|
||||||
"Checked by ClamAV on " . $self->qp->config("me"));
|
"Checked by ClamAV on " . $self->qp->config("me"));
|
||||||
}
|
}
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ sub hook_data_post {
|
|||||||
my $filename = $transaction->body_filename;
|
my $filename = $transaction->body_filename;
|
||||||
unless (defined $filename) {
|
unless (defined $filename) {
|
||||||
$self->log(LOGWARN, "didn't get a file name");
|
$self->log(LOGWARN, "didn't get a file name");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Now do the actual scanning!
|
# Now do the actual scanning!
|
||||||
@ -105,14 +105,14 @@ sub hook_data_post {
|
|||||||
|
|
||||||
if ($signal) {
|
if ($signal) {
|
||||||
$self->log(LOGWARN, "scanner exited with signal: $signal");
|
$self->log(LOGWARN, "scanner exited with signal: $signal");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
my $output = join(", ", @virii);
|
my $output = join(", ", @virii);
|
||||||
$output = substr($output, 0, 60);
|
$output = substr($output, 0, 60);
|
||||||
if ($result == 1 || $result == 3) {
|
if ($result == 1 || $result == 3) {
|
||||||
$self->log(LOGWARN, "Virus(es) found: $output");
|
$self->log(LOGWARN, "Virus(es) found: $output");
|
||||||
|
|
||||||
# return (DENY, "Virus Found: $output");
|
# return DENY, "Virus Found: $output";
|
||||||
# $transaction->header->add('X-Virus-Found', 'Yes', 0);
|
# $transaction->header->add('X-Virus-Found', 'Yes', 0);
|
||||||
# $transaction->header->add('X-Virus-Details', $output, 0);
|
# $transaction->header->add('X-Virus-Details', $output, 0);
|
||||||
$transaction->header->add('X-H+BEDV-Virus-Found', 'Yes', 0);
|
$transaction->header->add('X-H+BEDV-Virus-Found', 'Yes', 0);
|
||||||
@ -137,21 +137,20 @@ sub hook_data_post {
|
|||||||
|
|
||||||
# $transaction->header->add('X-Virus-Checked', 'Checked', 0);
|
# $transaction->header->add('X-Virus-Checked', 'Checked', 0);
|
||||||
$transaction->header->add('X-H+BEDV-Virus-Checked', 'Checked', 0);
|
$transaction->header->add('X-H+BEDV-Virus-Checked', 'Checked', 0);
|
||||||
return (DECLINED) unless $result;
|
return DECLINED if !$result;
|
||||||
|
|
||||||
if (@virii) {
|
if (@virii) {
|
||||||
return (DENY, "Virus found: $output")
|
return DENY, "Virus found: $output" if !$self->qp->config("hbedv_deny");
|
||||||
unless $self->qp->config("hbedv_deny");
|
|
||||||
foreach my $d ($self->qp->config("hbedv_deny")) {
|
foreach my $d ($self->qp->config("hbedv_deny")) {
|
||||||
foreach my $v (@virii) {
|
foreach my $v (@virii) {
|
||||||
if ($v =~ /^$d$/i) {
|
if ($v =~ /^$d$/i) {
|
||||||
$self->log(LOGWARN, "Denying mail with virus '$v'");
|
$self->log(LOGWARN, "Denying mail with virus '$v'");
|
||||||
return (DENY, "Virus found: $output");
|
return DENY, "Virus found: $output";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub unique {
|
sub unique {
|
||||||
|
@ -110,7 +110,7 @@ sub hook_data_post {
|
|||||||
|
|
||||||
if ($signal) {
|
if ($signal) {
|
||||||
$self->log(LOGWARN, "kavscanner exited with signal: $signal");
|
$self->log(LOGWARN, "kavscanner exited with signal: $signal");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $description = 'clean';
|
my $description = 'clean';
|
||||||
@ -187,6 +187,6 @@ sub hook_data_post {
|
|||||||
|
|
||||||
$transaction->header->add('X-Virus-Checked',
|
$transaction->header->add('X-Virus-Checked',
|
||||||
'Checked by ' . $self->qp->config("me"));
|
'Checked by ' . $self->qp->config("me"));
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,7 @@ sub hook_data_post {
|
|||||||
my ($self, $transaction) = @_;
|
my ($self, $transaction) = @_;
|
||||||
|
|
||||||
# klez files are always sorta big .. how big? Dunno.
|
# klez files are always sorta big .. how big? Dunno.
|
||||||
return (DECLINED)
|
return DECLINED if $transaction->data_size < 60_000;
|
||||||
if $transaction->data_size < 60_000;
|
|
||||||
|
|
||||||
# 220k was too little, so let's just disable the "big size check"
|
# 220k was too little, so let's just disable the "big size check"
|
||||||
# or $transaction->data_size > 1_000_000;
|
# or $transaction->data_size > 1_000_000;
|
||||||
@ -26,11 +25,11 @@ sub hook_data_post {
|
|||||||
and ++$seen_klez_signature
|
and ++$seen_klez_signature
|
||||||
and next;
|
and next;
|
||||||
|
|
||||||
return (DENY, "Klez Virus Detected")
|
return DENY, "Klez Virus Detected"
|
||||||
if $seen_klez_signature
|
if $seen_klez_signature
|
||||||
and m!^TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQA!;
|
and m!^TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQA!;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ sub hook_data_post {
|
|||||||
|
|
||||||
if ($transaction->data_size > $self->{"_sophie"}->{"max_size"} * 1024) {
|
if ($transaction->data_size > $self->{"_sophie"}->{"max_size"} * 1024) {
|
||||||
$self->log(LOGNOTICE, "Declining due to data_size");
|
$self->log(LOGNOTICE, "Declining due to data_size");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ignore non-multipart emails
|
# Ignore non-multipart emails
|
||||||
@ -34,7 +34,7 @@ sub hook_data_post {
|
|||||||
my $filename = $transaction->body_filename;
|
my $filename = $transaction->body_filename;
|
||||||
unless ($filename) {
|
unless ($filename) {
|
||||||
$self->log(LOGWARN, "Cannot process due to lack of filename");
|
$self->log(LOGWARN, "Cannot process due to lack of filename");
|
||||||
return (DECLINED); # unless $filename;
|
return DECLINED; # unless $filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $mode = (stat($self->spool_dir()))[2];
|
my $mode = (stat($self->spool_dir()))[2];
|
||||||
@ -61,20 +61,19 @@ sub hook_data_post {
|
|||||||
$self->log(LOGERROR, "One or more virus(es) found: $virus");
|
$self->log(LOGERROR, "One or more virus(es) found: $virus");
|
||||||
|
|
||||||
if (lc($self->{"_sophie"}->{"deny_viruses"}) eq "yes") {
|
if (lc($self->{"_sophie"}->{"deny_viruses"}) eq "yes") {
|
||||||
return (DENY,
|
return DENY,"Virus" . ($virus =~ /,/ ? "es " : " ") . "Found: $virus";
|
||||||
"Virus" . ($virus =~ /,/ ? "es " : " ") . "Found: $virus");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$transaction->header->add('X-Virus-Found', 'Yes');
|
$transaction->header->add('X-Virus-Found', 'Yes');
|
||||||
$transaction->header->add('X-Virus-Details', $virus);
|
$transaction->header->add('X-Virus-Details', $virus);
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$transaction->header->add('X-Virus-Checked',
|
$transaction->header->add('X-Virus-Checked',
|
||||||
"Checked by SOPHIE on " . $self->qp->config("me"));
|
"Checked by SOPHIE on " . $self->qp->config("me"));
|
||||||
|
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
=head1 NAME
|
=head1 NAME
|
||||||
|
@ -55,7 +55,7 @@ sub register {
|
|||||||
sub hook_data_post {
|
sub hook_data_post {
|
||||||
my ($self, $transaction) = @_;
|
my ($self, $transaction) = @_;
|
||||||
|
|
||||||
return (DECLINED)
|
return DECLINED
|
||||||
if $transaction->data_size > 250_000;
|
if $transaction->data_size > 250_000;
|
||||||
|
|
||||||
# Ignore non-multipart emails
|
# Ignore non-multipart emails
|
||||||
@ -69,7 +69,7 @@ sub hook_data_post {
|
|||||||
}
|
}
|
||||||
|
|
||||||
my $filename = $transaction->body_filename;
|
my $filename = $transaction->body_filename;
|
||||||
return (DECLINED) unless $filename;
|
return DECLINED if !$filename;
|
||||||
|
|
||||||
# Now do the actual scanning!
|
# Now do the actual scanning!
|
||||||
my @cmd = (
|
my @cmd = (
|
||||||
@ -92,28 +92,28 @@ sub hook_data_post {
|
|||||||
$virus = $1;
|
$virus = $1;
|
||||||
}
|
}
|
||||||
if ($output && $output =~ m/password-protected/m) {
|
if ($output && $output =~ m/password-protected/m) {
|
||||||
return (DENY, 'We do not accept password-protected zip files!');
|
return DENY, 'We do not accept password-protected zip files!';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($signal) {
|
if ($signal) {
|
||||||
$self->log(LOGWARN, "uvscan exited with signal: $signal");
|
$self->log(LOGWARN, "uvscan exited with signal: $signal");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
if ($result == 2) {
|
if ($result == 2) {
|
||||||
$self->log(LOGERROR, "Integrity check for a DAT file failed.");
|
$self->log(LOGERROR, "Integrity check for a DAT file failed.");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
elsif ($result == 6) {
|
elsif ($result == 6) {
|
||||||
$self->log(LOGERROR, "A general problem has occurred.");
|
$self->log(LOGERROR, "A general problem has occurred.");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
elsif ($result == 8) {
|
elsif ($result == 8) {
|
||||||
$self->log(LOGERROR, "The program could not find a DAT file.");
|
$self->log(LOGERROR, "The program could not find a DAT file.");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
elsif ($result == 15) {
|
elsif ($result == 15) {
|
||||||
$self->log(LOGERROR, "The program self-check failed");
|
$self->log(LOGERROR, "The program self-check failed");
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
elsif ($result) { # all of the possible virus returns
|
elsif ($result) { # all of the possible virus returns
|
||||||
if ($result == 12) {
|
if ($result == 12) {
|
||||||
@ -128,15 +128,15 @@ sub hook_data_post {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lc($self->{"_uvscan"}->{"deny_viruses"}) eq "yes") {
|
if (lc($self->{"_uvscan"}->{"deny_viruses"}) eq "yes") {
|
||||||
return (DENY, "Virus Found: $virus");
|
return DENY, "Virus Found: $virus";
|
||||||
}
|
}
|
||||||
$transaction->header->add('X-Virus-Found', 'Yes');
|
$transaction->header->add('X-Virus-Found', 'Yes');
|
||||||
$transaction->header->add('X-Virus-Details', $virus);
|
$transaction->header->add('X-Virus-Details', $virus);
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
$transaction->header->add('X-Virus-Checked',
|
$transaction->header->add('X-Virus-Checked',
|
||||||
"Checked by McAfee uvscan on " . $self->qp->config("me"));
|
"Checked by McAfee uvscan on " . $self->qp->config("me"));
|
||||||
|
|
||||||
return (DECLINED);
|
return DECLINED;
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ sub register {
|
|||||||
|
|
||||||
sub check_host {
|
sub check_host {
|
||||||
my ($self, $transaction, $rcpt) = @_;
|
my ($self, $transaction, $rcpt) = @_;
|
||||||
my $ip = $self->qp->connection->remote_ip || return (DECLINED);
|
my $ip = $self->qp->connection->remote_ip or return DECLINED;
|
||||||
|
|
||||||
# From tcpserver
|
# From tcpserver
|
||||||
if (exists $ENV{WHITELISTCLIENT}) {
|
if (exists $ENV{WHITELISTCLIENT}) {
|
||||||
|
@ -410,7 +410,7 @@ sub block_signal {
|
|||||||
sigprocmask(SIG_BLOCK, $blockset, $sigset)
|
sigprocmask(SIG_BLOCK, $blockset, $sigset)
|
||||||
or die "Could not block @signal signals: $!\n";
|
or die "Could not block @signal signals: $!\n";
|
||||||
|
|
||||||
return ($sigset);
|
return $sigset;
|
||||||
}
|
}
|
||||||
|
|
||||||
# unblock_signal: unblock/reset and receive pending signals
|
# unblock_signal: unblock/reset and receive pending signals
|
||||||
@ -531,7 +531,7 @@ sub qpsmtpd_instance {
|
|||||||
$qpsmtpd->spool_dir;
|
$qpsmtpd->spool_dir;
|
||||||
$qpsmtpd->size_threshold;
|
$qpsmtpd->size_threshold;
|
||||||
|
|
||||||
return ($qpsmtpd);
|
return $qpsmtpd;
|
||||||
}
|
}
|
||||||
|
|
||||||
# shmem: tie to shared memory hash
|
# shmem: tie to shared memory hash
|
||||||
@ -559,7 +559,7 @@ sub shmem {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (\%shmem_hash);
|
return \%shmem_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
# shmem_opt: connect to shared memory and perform options
|
# shmem_opt: connect to shared memory and perform options
|
||||||
@ -649,7 +649,7 @@ sub shmem_opt {
|
|||||||
warn("$@");
|
warn("$@");
|
||||||
}
|
}
|
||||||
|
|
||||||
return ($chld_busy);
|
return $chld_busy;
|
||||||
}
|
}
|
||||||
|
|
||||||
# info: write info
|
# info: write info
|
||||||
|
@ -48,40 +48,40 @@ sub validate_password {
|
|||||||
|
|
||||||
if (!$src_crypt && !$src_clear) {
|
if (!$src_crypt && !$src_clear) {
|
||||||
$self->log(LOGINFO, "fail: missing password");
|
$self->log(LOGINFO, "fail: missing password");
|
||||||
return ($deny, "$file - no such user");
|
return $deny, "$file - no such user";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$src_clear && $method =~ /CRAM-MD5/i) {
|
if (!$src_clear && $method =~ /CRAM-MD5/i) {
|
||||||
$self->log(LOGINFO, "skip: cram-md5 not supported w/o clear pass");
|
$self->log(LOGINFO, "skip: cram-md5 not supported w/o clear pass");
|
||||||
return (DECLINED, $file);
|
return DECLINED, $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defined $attempt_clear) {
|
if (defined $attempt_clear) {
|
||||||
if ($src_clear && $src_clear eq $attempt_clear) {
|
if ($src_clear && $src_clear eq $attempt_clear) {
|
||||||
$self->log(LOGINFO, "pass: clear match");
|
$self->log(LOGINFO, "pass: clear match");
|
||||||
return (OK, $file);
|
return OK, $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($src_crypt && $src_crypt eq crypt($attempt_clear, $src_crypt)) {
|
if ($src_crypt && $src_crypt eq crypt($attempt_clear, $src_crypt)) {
|
||||||
$self->log(LOGINFO, "pass: crypt match");
|
$self->log(LOGINFO, "pass: crypt match");
|
||||||
return (OK, $file);
|
return OK, $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (defined $attempt_hash && $src_clear) {
|
if (defined $attempt_hash && $src_clear) {
|
||||||
if (!$ticket) {
|
if (!$ticket) {
|
||||||
$self->log(LOGERROR, "skip: missing ticket");
|
$self->log(LOGERROR, "skip: missing ticket");
|
||||||
return (DECLINED, $file);
|
return DECLINED, $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($attempt_hash eq hmac_md5_hex($ticket, $src_clear)) {
|
if ($attempt_hash eq hmac_md5_hex($ticket, $src_clear)) {
|
||||||
$self->log(LOGINFO, "pass: hash match");
|
$self->log(LOGINFO, "pass: hash match");
|
||||||
return (OK, $file);
|
return OK, $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->log(LOGINFO, "fail: wrong password");
|
$self->log(LOGINFO, "fail: wrong password");
|
||||||
return ($deny, "$file - wrong password");
|
return $deny, "$file - wrong password";
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
Loading…
Reference in New Issue
Block a user