raised default max msg size in clamdscan from 128k

added max_size on config, so it's likely to get noticed, since even 1M is probably too low for most sites. This should likely default to the same as databytes?
This commit is contained in:
Matt Simerson 2013-04-29 22:06:47 -04:00
parent 1731542647
commit cc6ab49474
7 changed files with 104 additions and 30 deletions

View File

@ -91,9 +91,9 @@ spamassassin reject 12
# dspam must run after spamassassin for the learn_from_sa feature to work # dspam must run after spamassassin for the learn_from_sa feature to work
dspam autolearn spamassassin reject 0.95 dspam autolearn spamassassin reject 0.95
# run the clamav virus checking plugin # run the clamav virus checking plugin (max size in Kb)
# virus/clamav # virus/clamav
# virus/clamdscan deny_viruses yes scan_all 1 # virus/clamdscan deny_viruses yes max_size 1024
naughty reject data naughty reject data

View File

@ -64,7 +64,9 @@ https://github.com/qpsmtpd-dev/qpsmtpd-dev/wiki/DMARC-FAQ
=head1 TODO =head1 TODO
2. provide dmarc feedback to domains that request it provide dmarc feedback to domains that request it
reject messages with multiple From: headers
=head1 AUTHORS =head1 AUTHORS

View File

@ -26,6 +26,7 @@ sub hook_mail_pre {
unless ($addr =~ /^<.*>$/) { unless ($addr =~ /^<.*>$/) {
$self->log(LOGINFO, "added MAIL angle brackets"); $self->log(LOGINFO, "added MAIL angle brackets");
$addr = '<' . $addr . '>'; $addr = '<' . $addr . '>';
$self->adjust_karma(-1);
} }
return (OK, $addr); return (OK, $addr);
} }
@ -35,6 +36,7 @@ sub hook_rcpt_pre {
unless ($addr =~ /^<.*>$/) { unless ($addr =~ /^<.*>$/) {
$self->log(LOGINFO, "added RCPT angle brackets"); $self->log(LOGINFO, "added RCPT angle brackets");
$addr = '<' . $addr . '>'; $addr = '<' . $addr . '>';
$self->adjust_karma(-1);
} }
return (OK, $addr); return (OK, $addr);
} }

View File

@ -77,6 +77,12 @@ Default: perm
Adjust the quantity of logging for this plugin. See docs/logging.pod Adjust the quantity of logging for this plugin. See docs/logging.pod
=head1 TODO
=head1 SEE ALSO
https://tools.ietf.org/html/rfc5322
=head1 AUTHOR =head1 AUTHOR
2012 - Matt Simerson 2012 - Matt Simerson
@ -130,36 +136,59 @@ sub hook_data_post {
return $self->get_reject("Headers are missing", "missing headers"); return $self->get_reject("Headers are missing", "missing headers");
}; };
return (DECLINED, "immune") if $self->is_immune(); return DECLINED if $self->is_immune();
foreach my $h (@required_headers) { my $errors = $self->has_required_headers( $header );
next if $header->get($h); $errors += $self->has_singular_headers( $header );
$self->adjust_karma(-1);
return $self->get_reject("We require a valid $h header",
"no $h header");
}
foreach my $h (@singular_headers) {
next if !$header->get($h); # doesn't exist
my @qty = $header->get($h);
next if @qty == 1; # only 1 header
$self->adjust_karma(-1);
return
$self->get_reject(
"Only one $h header allowed. See RFC 5322, Section 3.6",
"too many $h headers",);
}
my $err_msg = $self->invalid_date_range(); my $err_msg = $self->invalid_date_range();
if ($err_msg) { if ($err_msg) {
$self->adjust_karma(-1);
return $self->get_reject($err_msg, $err_msg); return $self->get_reject($err_msg, $err_msg);
} }
if ( $errors ) {
return $self->get_reject($self->get_reject_type(),
"RFC 5322 validation errors" );
};
$self->log(LOGINFO, 'pass'); $self->log(LOGINFO, 'pass');
return (DECLINED); return (DECLINED);
} }
sub has_required_headers {
my ($self, $header) = @_;
my $errors;
foreach my $h (@required_headers) {
next if $header->get($h);
$errors++;
$self->adjust_karma(-1);
$self->is_naughty(1) if $self->{args}{reject};
$self->store_deferred_reject("We require a valid $h header");
$self->log(LOGINFO, "fail, no $h header" );
}
return $errors;
};
sub has_singular_headers {
my ($self, $header) = @_;
my $errors;
foreach my $h (@singular_headers) {
next if !$header->get($h); # doesn't exist
my @qty = $header->get($h);
next if @qty == 1; # only 1 header
$errors++;
$self->adjust_karma(-1);
$self->is_naughty(1) if $self->{args}{reject};
$self->store_deferred_reject(
"Only one $h header allowed. See RFC 5322, Section 3.6",
);
$self->log(LOGINFO, "fail, too many $h headers" );
}
return $errors;
};
sub invalid_date_range { sub invalid_date_range {
my $self = shift; my $self = shift;
@ -175,12 +204,14 @@ sub invalid_date_range {
my $past = $self->{_args}{past}; my $past = $self->{_args}{past};
if ($past && $ts < time - ($past * 24 * 3600)) { if ($past && $ts < time - ($past * 24 * 3600)) {
$self->log(LOGINFO, "fail, date too old ($date)"); $self->log(LOGINFO, "fail, date too old ($date)");
$self->adjust_karma(-1);
return "The Date header is too far in the past"; return "The Date header is too far in the past";
} }
my $future = $self->{_args}{future}; my $future = $self->{_args}{future};
if ($future && $ts > time + ($future * 24 * 3600)) { if ($future && $ts > time + ($future * 24 * 3600)) {
$self->log(LOGINFO, "fail, date in future ($date)"); $self->log(LOGINFO, "fail, date in future ($date)");
$self->adjust_karma(-1);
return "The Date header is too far in the future"; return "The Date header is too far in the future";
} }

View File

@ -203,6 +203,12 @@ this prohibition applies to the matching of the parameter to its IP
address only; see Section 7.9 for a more extensive discussion of address only; see Section 7.9 for a more extensive discussion of
rejecting incoming connections or mail messages. rejecting incoming connections or mail messages.
=head1 TODO
is_forged_literal, if the forged IP is an internal IP, it's likely one
of our clients that should have authenticated. Perhaps when we check back
later in data_post, if they have added relay_client, then give back the
karma.
=head1 AUTHOR =head1 AUTHOR

View File

@ -244,6 +244,7 @@ sub register {
#$self->prune_db(); # keep the DB compact #$self->prune_db(); # keep the DB compact
$self->register_hook('connect', 'connect_handler'); $self->register_hook('connect', 'connect_handler');
$self->register_hook('mail_pre', 'from_handler');
$self->register_hook('rcpt_pre', 'rcpt_handler'); $self->register_hook('rcpt_pre', 'rcpt_handler');
$self->register_hook('data', 'data_handler'); $self->register_hook('data', 'data_handler');
$self->register_hook('data_post', 'data_handler'); $self->register_hook('data_post', 'data_handler');
@ -271,7 +272,7 @@ sub hook_pre_connection {
} }
my ($penalty_start_ts, $naughty, $nice, $connects) = my ($penalty_start_ts, $naughty, $nice, $connects) =
$self->parse_value($tied->{$key}); $self->parse_db_record($tied->{$key});
$self->calc_karma($naughty, $nice); $self->calc_karma($naughty, $nice);
return $self->cleanup_and_return($tied, $lock); return $self->cleanup_and_return($tied, $lock);
} }
@ -297,7 +298,7 @@ sub connect_handler {
} }
my ($penalty_start_ts, $naughty, $nice, $connects) = my ($penalty_start_ts, $naughty, $nice, $connects) =
$self->parse_value($tied->{$key}); $self->parse_db_record($tied->{$key});
my $summary = "$naughty naughty, $nice nice, $connects connects"; my $summary = "$naughty naughty, $nice nice, $connects connects";
my $karma = $self->calc_karma($naughty, $nice); my $karma = $self->calc_karma($naughty, $nice);
@ -321,25 +322,47 @@ sub connect_handler {
return $self->get_reject($mess, $karma); return $self->get_reject($mess, $karma);
} }
sub from_handler {
my ($self, $transaction, $addr) = @_;
# test if sender has placed an illegal (RFC (2)821) space in envelope from
my $full_from = $self->connection->notes('envelope_from');
$self->illegal_envelope_format( $full_from );
return DECLINED;
};
sub rcpt_handler { sub rcpt_handler {
my ($self, $transaction, $addr) = @_; my ($self, $transaction, $addr) = @_;
$self->illegal_envelope_format(
$self->connection->notes('envelope_rcpt'),
);
my $count = $self->connection->notes('recipient_count') || 0;
$count++;
if ( $count > 1 ) {
$self->log(LOGINFO, "recipients c: $count ($addr)");
$self->connection->notes('recipient_count', $count);
};
return DECLINED if $self->is_immune(); return DECLINED if $self->is_immune();
my $recipients = scalar $self->transaction->recipients or do { my $recipients = scalar $self->transaction->recipients or do {
$self->log(LOGDEBUG, "info, no recipient count"); $self->log(LOGDEBUG, "info, no recipient count");
return DECLINED; return DECLINED;
}; };
$self->log(LOGINFO, "recipients t: $recipients ($addr)");
my $history = $self->connection->notes('karma_history'); my $history = $self->connection->notes('karma_history');
if ( $history > 0 ) { if ( $history > 0 ) {
$self->log(LOGDEBUG, "info, good history"); $self->log(LOGINFO, "info, good history");
return DECLINED; return DECLINED;
}; };
my $karma = $self->connection->notes('karma'); my $karma = $self->connection->notes('karma');
if ( $karma > 0 ) { if ( $karma > 0 ) {
$self->log(LOGDEBUG, "info, good connection"); $self->log(LOGINFO, "info, good connection");
return DECLINED; return DECLINED;
}; };
@ -376,7 +399,7 @@ sub disconnect_handler {
my $key = $self->get_db_key(); my $key = $self->get_db_key();
my ($penalty_start_ts, $naughty, $nice, $connects) = my ($penalty_start_ts, $naughty, $nice, $connects) =
$self->parse_value($tied->{$key}); $self->parse_db_record($tied->{$key});
my $history = ($nice || 0) - $naughty; my $history = ($nice || 0) - $naughty;
my $log_mess = ''; my $log_mess = '';
@ -410,7 +433,17 @@ sub disconnect_handler {
return $self->cleanup_and_return($tied, $lock); return $self->cleanup_and_return($tied, $lock);
} }
sub parse_value { sub illegal_envelope_format {
my ($self, $addr) = @_;
# test if envelope address has an illegal (RFC (2)821) space
if ( uc substr($addr,0,6) ne 'FROM:<' && uc substr($addr,0,4) ne 'TO:<' ) {
$self->log(LOGINFO, "illegal envelope address format: $addr" );
$self->adjust_karma(-1);
};
};
sub parse_db_record {
my ($self, $value) = @_; my ($self, $value) = @_;
my $penalty_start_ts = my $naughty = my $nice = my $connects = 0; my $penalty_start_ts = my $naughty = my $nice = my $connects = 0;

View File

@ -123,8 +123,8 @@ sub register {
# Set some sensible defaults # Set some sensible defaults
$self->{'_args'}{'deny_viruses'} ||= 'yes'; $self->{'_args'}{'deny_viruses'} ||= 'yes';
$self->{'_args'}{'max_size'} ||= 128; $self->{'_args'}{'max_size'} ||= 1024;
$self->{'_args'}{'scan_all'} ||= 0; $self->{'_args'}{'scan_all'} ||= 1;
for my $setting ('deny_viruses', 'defer_on_error') { for my $setting ('deny_viruses', 'defer_on_error') {
next unless $self->{'_args'}{$setting}; next unless $self->{'_args'}{$setting};
if (lc $self->{'_args'}{$setting} eq 'no') { if (lc $self->{'_args'}{$setting} eq 'no') {