qpsmtpd/plugins/virus/hbedv
Matt Simerson dbaa9dbd6c POD corrections, additional tests, plugin consistency
on files in plugins dir:
  fixed a number of POD errors

  formatted some # comments into POD

  removed bare 1;  (these are plugins, not perl modules)
    most instances of this were copy/pasted from a previous plugin that had it

  removed instances of # vim ts=N ...
    they weren't consistent, many didn't match .perltidyrc

  on modules that failed perl -c tests, added 'use Qpsmtpd::Constants;'

Conflicts:

	plugins/async/check_earlytalker
	plugins/async/dns_whitelist_soft
	plugins/async/dnsbl
	plugins/async/queue/smtp-forward
	plugins/async/require_resolvable_fromhost
	plugins/async/rhsbl
	plugins/async/uribl
	plugins/auth/auth_checkpassword
	plugins/auth/auth_cvm_unix_local
	plugins/auth/auth_flat_file
	plugins/auth/auth_ldap_bind
	plugins/auth/auth_vpopmail
	plugins/auth/auth_vpopmail_sql
	plugins/auth/authdeny
	plugins/check_badmailfromto
	plugins/check_badrcptto_patterns
	plugins/check_bogus_bounce
	plugins/check_earlytalker
	plugins/check_norelay
	plugins/check_spamhelo
	plugins/connection_time
	plugins/dns_whitelist_soft
	plugins/dnsbl
	plugins/domainkeys
	plugins/greylisting
	plugins/hosts_allow
	plugins/http_config
	plugins/logging/adaptive
	plugins/logging/apache
	plugins/logging/connection_id
	plugins/logging/transaction_id
	plugins/logging/warn
	plugins/milter
	plugins/queue/exim-bsmtp
	plugins/queue/maildir
	plugins/queue/postfix-queue
	plugins/queue/smtp-forward
	plugins/quit_fortune
	plugins/random_error
	plugins/rcpt_map
	plugins/rcpt_regexp
	plugins/relay_only
	plugins/require_resolvable_fromhost
	plugins/rhsbl
	plugins/sender_permitted_from
	plugins/spamassassin
	plugins/tls
	plugins/tls_cert
	plugins/uribl
	plugins/virus/aveclient
	plugins/virus/bitdefender
	plugins/virus/clamav
	plugins/virus/clamdscan
	plugins/virus/hbedv
	plugins/virus/kavscanner
	plugins/virus/klez_filter
	plugins/virus/sophie
	plugins/virus/uvscan
2012-04-29 00:00:10 -07:00

159 lines
4.2 KiB
Perl

#!perl -Tw
# H+B EDV-AV plugin.
=head1 NAME
hbedv - plugin for qpsmtpd which calls the H+BEDV anti virus scanner
=head1 DESCRIPTION
The B<hbedv> plugin checks a mail for viruses with the H+BEDV anti virus
scanner (see L<http://www.antivir.de/> for info). It can deny mails if a
virus was found with a configurable deny list.
=head1 VERSION
this is B<hbedv> version 1.1
=head1 CONFIGURATION
Add (perl-)regexps to the F<hbedv_deny> configuration file, one per line for the
virii you want to block, e.g.:
Worm\/Sober\..*
Worm\/NetSky\..*
or just
.*
to block any virus ;)
Set the location of the binary with
hbedv hbedvscanner /path/to/antivir
in the plugin config if qpsmtpd, the location defaults to I</usr/bin/antivir>.
=head1 NOTES
If the hbedv_deny config file is empty or could not be found, any virus
will be blocked.
This plugin started life as a copy of the B<clamav> plugin.
=head1 LICENCE
Written by Hanno Hecker E<lt>hah@uu-x.deE<gt>.
The B<hbedv> plugin is published under the same licence as qpsmtpd itself.
=cut
sub register {
my ($self, $qp, @args) = @_;
if (@args % 2) {
$self->log(LOGERROR, "FATAL ERROR: odd number of arguments");
exit 3;
}
my %args = @args;
if (!exists $args{hbedvscanner}) {
$self->{_hbedvscan_loc} = "/usr/bin/antivir";
} else {
if ($args{hbedvscanner} =~ /^(\/[\/\-\_\.a-z0-9A-Z]*)$/) {
$self->{_hbedvscan_loc} = $1;
} else {
$self->log(LOGERROR, "FATAL ERROR: Unexpected characters in hbedvscanner argument");
exit 3;
}
}
}
sub hook_data_post {
my ($self, $transaction) = @_;
my $filename = $transaction->body_filename;
unless (defined $filename) {
$self->log(LOGWARN, "didn't get a file name");
return (DECLINED);
}
# Now do the actual scanning!
my $cmd = $self->{_hbedvscan_loc}." --archive-max-recursion=50 --alltypes -z -noboot -nombr -rs $filename 2>&1";
$self->log(LOGDEBUG, "Running: $cmd");
my @output = `$cmd`;
my $result = ($? >> 8);
my $signal = ($? & 127);
chomp(@output);
my @virii = ();
foreach my $line (@output) {
next unless $line =~ /^ALERT: \[([^\]]+)\s+(\w+)?\]/; # $2 =~ /^(virus|worm)$/;
push @virii, $1;
}
@virii = unique(@virii);
$self->log(LOGDEBUG, "results: ".join("//",@output));
if ($signal) {
$self->log(LOGWARN, "scanner exited with signal: $signal");
return (DECLINED);
}
my $output = join(", ", @virii);
$output = substr($output, 0, 60);
if ($result == 1 || $result == 3) {
$self->log(LOGWARN, "Virus(es) found: $output");
# return (DENY, "Virus Found: $output");
# $transaction->header->add('X-Virus-Found', 'Yes', 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-Details', $output, 0);
}
elsif ($result == 200) {
$self->log(LOGWARN, "Program aborted, not enough memory available");
}
elsif ($result == 211) {
$self->log(LOGWARN, "Programm aborted, because the self check failed");
}
elsif ($result == 214) {
$self->log(LOGWARN, "License key not found");
}
elsif ($result) {
$self->log(LOGWARN, "Error: $result, look for exit codes in the output of '"
.$self->{_hbedvscan_loc}." --help' for more info\n");
}
# $transaction->header->add('X-Virus-Checked', 'Checked', 0);
$transaction->header->add('X-H+BEDV-Virus-Checked', 'Checked', 0);
return (DECLINED) unless $result;
if (@virii) {
return(DENY, "Virus found: $output")
unless $self->qp->config("hbedv_deny");
foreach my $d ($self->qp->config("hbedv_deny")) {
foreach my $v (@virii) {
if ($v =~ /^$d$/i) {
$self->log(LOGWARN, "Denying mail with virus '$v'");
return(DENY, "Virus found: $output");
}
}
}
}
return (DECLINED);
}
sub unique {
## This is the short version, I haven't tried if any warnings
## are generated by perl if you use just this... if you need
## every cpu cycle, try this:
## my %h;foreach (@_) { ++$h{$_}; }; return keys(%h);
my @list = @_;
my %hash;
foreach my $item (@list) {
exists $hash{$item} || ($hash{$item} = 1);
}
return keys(%hash)
}