File-Scan
view release on metacpan or search on metacpan
examples/procmail/scanvirus.pl view on Meta::CPAN
output_dir => $tmp_dir,
check_content_type => 1,
decode_subject => 1,
exclude_types => ["image/gif", "image/jpeg"],
);
my $headers = {};
my $line_from = <STDIN>;
my ($from) = ($line_from =~ /^From +([^ ]+) +/o);
eval {
alarm($timeout);
open(OUTPUT, ">$tmp_dir/$id.tmp") or exit_script("Can't open '$tmp_dir/$id.tmp': $!");
$headers = $explode->parse(\*STDIN, \*OUTPUT);
close(OUTPUT);
alarm(0);
};
my %attachs = ();
for my $msg (keys(%{$headers})) {
if(exists($headers->{$msg}->{'content-disposition'}) &&
exists($headers->{$msg}->{'content-disposition'}->{'filepath'})) {
my $file = $headers->{$msg}->{'content-disposition'}->{'filepath'};
$attachs{$file} = 0;
}
}
my $result = scalar(keys(%attachs)) ? &init_scan($tmp_dir, \%attachs, $from, $ENV{LOGNAME}) : 0;
if($result && $quarantine) {
unless(-d $quarantine) { mkdir($quarantine, 0755) or exit_script("$!"); }
&deliver_msg("$tmp_dir/$id.tmp", $line_from, $ENV{LOGNAME}, $quarantine);
}
unless($preserve) {
if(my $res = &clean_dir($tmp_dir)) { &logs("error.log", "$res"); }
}
exit($result);
}
#---extract_file----------------------------------------------------------
sub extract_file {
my $fh = shift;
my $size = shift;
my $buff = shift;
my $file = shift;
open(NEWFILE, ">$file") or return("Can't open $file: $!");
flock(NEWFILE, LOCK_EX);
binmode(NEWFILE);
print NEWFILE $buff;
while(read($fh, $buff, $size)) { print NEWFILE $buff; }
flock(NEWFILE, LOCK_UN);
close(NEWFILE);
return("");
}
#---decode_b64_file---------------------------------------------------------
sub decode_b64_file {
my $files = shift;
my $tmp_dir = shift;
my $file = shift;
my ($filename) = ($file =~ /\/?([^\/]+)$/);
my $decoded = join("/", $tmp_dir, "$filename\.eml");
open(ENCFILE, "<$file") or return("Can't open $file: $!\n");
open(DECFILE, join("", ">$decoded")) or return("Can't open $decoded: $!\n");
binmode(DECFILE);
while(<ENCFILE>) { print DECFILE rfc822_base64($_); }
close(DECFILE);
close(ENCFILE);
$files->{$decoded} = "";
return("");
}
#---mhtml_exploit---------------------------------------------------------
sub mhtml_exploit {
my $files = shift;
my $tmp_dir = shift;
my $file = shift;
my ($error, $buff, $filename, $size) = ("", "", "", 1024);
open(FILE, "<$file") or return("Can't open $file: $!");
binmode(FILE);
while(read(FILE, $buff, $size)) {
$buff =~ s{^MIME-Version: 1.0\x0aContent-Location: *File://([^\x0a]+)\x0aContent-Transfer-Encoding: binary\x0a\x0a}{}o or last;
if($filename = join("/", $tmp_dir, $1)) {
unless($error = &extract_file(\*FILE, $size, $buff, $filename)) {
$files->{$filename} = "";
}
last;
}
}
close(FILE);
return($error);
}
#---unzip_file------------------------------------------------------------
sub unzip_file {
my $files = shift;
my $program = shift;
my $tmp_dir = shift;
my $file = shift;
my $pid = open(UNZIP, "-|");
defined($pid) or return("Cannot fork: $!");
if($pid) {
while(<UNZIP>) {
if(my ($f) = (/$pattern/)[1]) {
$f =~ s/ +$//g;
$files->{$f} = "";
}
}
close(UNZIP) or return("Unzip error: kid exited $?");
} else {
my @args = ("-P", "''", "-d", $tmp_dir, "-j", "-n");
exec($program, @args, $file) or return("Can't exec program: $!");
}
return("");
}
#---init_scan-------------------------------------------------------------
sub init_scan {
my $tmp_dir = shift;
my $files = shift;
my $from = shift || "unknown";
my $user = shift || "unknown";
( run in 0.912 second using v1.01-cache-2.11-cpan-2398b32b56e )