#!/usr/bin/perl
#++
#   $Id: scanq.pl,v 1.4 2005/05/14 00:21:40 az Exp $
# 
#   File:		scanq.pl
#   Date:		Sun Feb  1 21:39:42 2004
#   Author:		Alexander Zangerl (az)
# 
#   Abstract:
#	sendmail queue scanner, predigests mime for clamav 
#
#   Modifications:
#	$Log: scanq.pl,v $
#	Revision 1.4  2005/05/14 00:21:40  az
#	fucking idiots don't honor their own --quiet switch
#
#	Revision 1.3  2005/04/15 12:23:09  az
#	fixed, checked, removed the scan/noscan reporting
#
#	Revision 1.2  2005/04/15 11:58:00  az
#	second version, which bypasses known local machines
#
#--
# (c) Alexander Zangerl 2004. 
# License: GPL 2. 

use strict;
use MIME::Parser;
use File::Temp qw/ tempfile tempdir /;
use IO::Handle;

my $inq="/var/spool/mqueue.in/";
my $outq="/var/spool/mqueue/";
my $qdir="/var/spool/quarantine";

opendir(D,$inq) or die "cant open $inq: $!\n";
my @all=readdir(D);
closedir (D);

my $tempdir=tempdir(CLEANUP=>1);
my $parser=MIME::Parser->new;
$parser->output_dir($tempdir);

foreach my $fn (@all)
{
    next if ($fn!~/^qf(.+)$/);
    my $key=$1;
    next if (! -r "$inq/df$key");
    next if (-f "$inq/.$key");
    open(F,">$inq/.$key") or die "can't open $inq/.$key: $!\n";
    print F "$$\n";
    close F;
    
    # take in queue file, feed headers to mimeparser
    open(F,"$inq/$fn") or die "can't open $inq/$fn: $!\n";
    my ($headfh, $headfn) = tempfile();
    die "can't create header file: $!\n" if (!$headfn);
    my ($seenfirstreceived,$h,$dontscan);
    while (<F>)
    {
	/^H\?[^\?]*\?(.+)$/ and print $headfh ($h=$1)."\n";
	/^\s.+/ and print $headfh $_;
	# if this is known good: don't scan it.
	if (!$seenfirstreceived 
	    and $h=~/^Received:/)
	{
	    $seenfirstreceived=1;
	    # don't scan 127.0.0.1 and 192.168.x.x
	    $dontscan=($h=~/^Received:\s+from\s+\S+\s+\(\S+\s+\[(\d+\.\d+\.\d+\.\d+)\]\)/ and ($1 eq "127.0.0.1" or $1=~/^192\.168\./));
	}
    }
    print $headfh "\n";
    close F;
    close $headfh;

    # now fire up parser
    # fixme: too lazy to check for exception here.
    $parser->parse_two($headfn,"$inq/df$key");
    unlink($headfn);

    # scan temp files 
    my $res;			# stays zero -> fine.
    if (!$dontscan)
    {
	$res=0xffff && system("clamscan --recursive --unzip --tgz "
			      ."--quiet --log=$qdir/clamav.$key "
			      ."--disable-summary $tempdir >>$qdir/clamav.$key 2>&1");
    }
    if ($res)
    {
	# move junk to quarantine queue
	system("mv $inq/qf$key $inq/df$key $qdir");
    }
    else
    {
	# move mail to real queue, get rid of empty clamav report
	system("mv $inq/qf$key $inq/df$key $outq");
	unlink("$qdir/clamav.$key");
    }

    # and clean up after yourself
    unlink("$inq/.$key");
    $parser->filer->purge;
}

