Add "plugin/virus/uvscan" - McAfee commandline virus scanner
git-svn-id: https://svn.perl.org/qpsmtpd/trunk@271 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
parent
b9dca51d2a
commit
96ec52d088
2
Changes
2
Changes
@ -5,6 +5,8 @@
|
||||
Mail::Address does RFC822 addresses, we need SMTP addresses.
|
||||
Replace Mail::Address with Peter J. Holzer's Qpsmtpd::Address module.
|
||||
|
||||
Add "plugin/virus/uvscan" - McAfee commandline virus scanner
|
||||
|
||||
|
||||
0.28 - 2004/06/05
|
||||
|
||||
|
124
plugins/virus/uvscan
Normal file
124
plugins/virus/uvscan
Normal file
@ -0,0 +1,124 @@
|
||||
#!/usr/bin/perl -w
|
||||
=head1 NAME
|
||||
|
||||
uvscan
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
A qpsmtpd plugin for the McAfee commandline virus scanner, uvscan.
|
||||
|
||||
=head1 INSTALL AND CONFIG
|
||||
|
||||
Place this plugin in the plugin/virus directory beneath the standard
|
||||
qpsmtpd installation. If you installed uvscan with the default path, you
|
||||
can use this plugin with default options (nothing specified):
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<uvscan_location>
|
||||
|
||||
Full path to the uvscan binary and all signature files; defaults to
|
||||
/usr/local/bin/uvscan.
|
||||
|
||||
=item B<deny_viruses>
|
||||
|
||||
Whether the scanner will automatically delete messages which have viruses.
|
||||
Takes either 'yes' or 'no' (defaults to 'yes').
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
John Peacock <jpeacock@cpan.org>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (c) 2004 John Peacock
|
||||
|
||||
Based heavily on the clamav plugin
|
||||
|
||||
This plugin is licensed under the same terms as the qpsmtpd package itself.
|
||||
Please see the LICENSE file included with qpsmtpd for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub register {
|
||||
my ($self, $qp, @args) = @_;
|
||||
$self->register_hook("data_post", "uvscan");
|
||||
|
||||
while (@args) {
|
||||
$self->{"_uvscan"}->{pop @args}=pop @args;
|
||||
}
|
||||
$self->{"_uvscan"}->{"uvscan_location"}||="/usr/local/bin/uvscan";
|
||||
}
|
||||
|
||||
sub uvscan {
|
||||
my ($self, $transaction) = @_;
|
||||
|
||||
return (DECLINED)
|
||||
if $transaction->body_size > 250_000;
|
||||
|
||||
my $filename = $transaction->body_filename;
|
||||
return (DECLINED) unless $filename;
|
||||
|
||||
# Now do the actual scanning!
|
||||
my @cmd =($self->{"_uvscan"}->{"uvscan_location"},
|
||||
'--mime', '--unzip', '--secure', '--noboot',
|
||||
$filename, '2>&1 |');
|
||||
$self->log(LOGINFO, "Running: ",join(' ', @cmd));
|
||||
open(FILE, join(' ', @cmd)); #perl 5.6 doesn't properly support the pipe
|
||||
# mode list form of open, but this is basically the same thing. This form
|
||||
# of exec is safe(ish).
|
||||
my $output;
|
||||
while (<FILE>) { $output.=$_; }
|
||||
close FILE;
|
||||
|
||||
my $result = ($? >> 8);
|
||||
my $signal = ($? & 127);
|
||||
|
||||
unlink($filename);
|
||||
|
||||
my $virus;
|
||||
if ($output && $output =~ m/.*\W+Found (.*)\n/m) {
|
||||
$virus=$1;
|
||||
}
|
||||
if ($output && $output =~ m/password-protected/m) {
|
||||
return (DENY, 'We do not accept password-protected zip files!');
|
||||
}
|
||||
|
||||
if ($signal) {
|
||||
$self->log(LOGWARN, "uvscan exited with signal: $signal");
|
||||
return (DECLINED);
|
||||
}
|
||||
if ($result == 2) {
|
||||
$self->log(LOGERROR, "Integrity check for a DAT file failed.");
|
||||
return (DECLINED);
|
||||
} elsif ($result == 6) {
|
||||
$self->log(LOGERROR, "A general problem has occurred.");
|
||||
return (DECLINED);
|
||||
} elsif ($result == 8) {
|
||||
$self->log(LOGERROR, "The program could not find a DAT file.");
|
||||
return (DECLINED);
|
||||
} elsif ($result == 15) {
|
||||
$self->log(LOGERROR, "The program self-check failed");
|
||||
return (DECLINED);
|
||||
} elsif ( $result ) { # all of the possible virus returns
|
||||
if ($result == 12) {
|
||||
$self->log(LOGERROR, "The program tried to clean a file but failed.");
|
||||
} elsif ($result == 13) {
|
||||
$self->log(LOGERROR, "One or more virus(es) found");
|
||||
} elsif ($result == 19) {
|
||||
$self->log(LOGERROR, "Successfully cleaned the file");
|
||||
}
|
||||
|
||||
if (lc($self->{"_uvscan"}->{"deny_viruses"}) eq "yes") {
|
||||
return (DENY, "Virus Found: $virus");
|
||||
}
|
||||
$transaction->header->add('X-Virus-Found', 'Yes');
|
||||
$transaction->header->add('X-Virus-Details', $virus);
|
||||
return (DECLINED);
|
||||
}
|
||||
|
||||
$transaction->header->add('X-Virus-Checked', 'Checked');
|
||||
return (DECLINED);
|
||||
}
|
Loading…
Reference in New Issue
Block a user