Remove a ton of 'return ()', and a few other minor readability tweaks.

This commit is contained in:
Jonathan Hall 2014-09-17 20:28:51 -05:00
parent 26b1d0bb62
commit 897a1fd8aa
72 changed files with 370 additions and 386 deletions

View File

@ -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");
} }

View File

@ -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,

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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); }

View File

@ -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 {

View File

@ -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 >

View File

@ -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() {

View File

@ -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) {

View File

@ -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 {

View File

@ -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 {

View File

@ -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";
} }

View File

@ -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)";
} }

View File

@ -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);

View File

@ -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";
} }

View File

@ -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
} }

View File

@ -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

View File

@ -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;

View File

@ -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";
} }

View File

@ -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 {

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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";
} }

View File

@ -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?";
);
} }

View File

@ -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 {

View File

@ -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");

View File

@ -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 {

View File

@ -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 {

View File

@ -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;
} }

View File

@ -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");

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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;
} }
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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 {

View File

@ -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 {

View File

@ -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');

View File

@ -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;
} }

View File

@ -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:

View File

@ -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;
} }
} }

View File

@ -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++;

View File

@ -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!";
} }

View File

@ -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 {

View File

@ -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)";
} }

View File

@ -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) {

View File

@ -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 {

View File

@ -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;

View File

@ -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 {

View File

@ -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}};

View File

@ -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...

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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");

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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 {

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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

View File

@ -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;
} }

View File

@ -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}) {

View File

@ -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

View File

@ -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;