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.
|
Mail::Address does RFC822 addresses, we need SMTP addresses.
|
||||||
Replace Mail::Address with Peter J. Holzer's Qpsmtpd::Address module.
|
Replace Mail::Address with Peter J. Holzer's Qpsmtpd::Address module.
|
||||||
|
|
||||||
|
Add "plugin/virus/uvscan" - McAfee commandline virus scanner
|
||||||
|
|
||||||
|
|
||||||
0.28 - 2004/06/05
|
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