Hi all,
I have the following patch available to be used with the default qmail-scanner-1.24 distribution which adds the following funcionality:
+ File::Scan
Configure autodetects if File::Scan is installed and makes this the first scanner used to scan emails. Because its *really* fast, this should not affect most people, but if you have different preferences, you can manually edit the @scanner_array.
+ sub-filescan.pl
This includes a _recursive_ file generator which should be portable across implementations: sub get_file_list(); its only argument being a directory, returning and array of fully qualified filenames (including path), which can potentially be used with perlscanner to do a recursive scan.... (my todo list)
+ sub reject_email() has been added to sub-log_msg.pl
This procedure can be used to reject the email after during the SMTP conversation by sending a permanent error code to the client after receiving the message with the DATA command. Although this will not save bandwidth, the rejected message will not make it into qmail's queues.
+ sub-clamdscan.pl sub-clamscan.pl sub-spamassassin.pl sub-filescan.pl
These have been modified to reject email.
SpamAssassin can reject mail if $score > $sa_reject_score (global variable) is set to a value > 0.
This applies cleanly _only_ to stock qmail-scanner-1.24.tar.gz
-- Jorge Valdes Intercom El Salvador [EMAIL PROTECTED] voz: ++(503) 278-5068 fax: ++(503) 265-7025
diff -rubN qmail-scanner-1.24-orig/configure qmail-scanner-1.24/configure
--- qmail-scanner-1.24-orig/configure Mon Oct 18 18:26:55 2004
+++ qmail-scanner-1.24/configure Tue Nov 9 14:06:00 2004
@@ -38,7 +38,7 @@
VERSION=`grep '^# Version: ' qmail-scanner-queue.template`
VERSION=`echo $VERSION|awk '{print $NF}'`
-SUPPORTED_SCANNERS="clamscan,clamdscan,sweep,sophie,vscan,trophie,uvscan,csav,antivir,kavscanner,AvpLinux,kavdaemon,AvpDaemonClient,fsav,fprot,inocucmd,vexira,bitdefender,nod32,verbose_spamassassin,fast_spamassassin"
+SUPPORTED_SCANNERS="filescan,clamscan,clamdscan,sweep,sophie,vscan,trophie,uvscan,csav,antivir,kavscanner,AvpLinux,kavdaemon,AvpDaemonClient,fsav,fprot,inocucmd,vexira,bitdefender,nod32,verbose_spamassassin,fast_spamassassin"
SILENT_VIRUSES='klez,bugbear,hybris,yaha,braid,nimda,tanatos,sobig,winevar,palyh,fizzer,gibe,cailont,lovelorn,swen,dumaru,sober,hawawi,holar-i,mimail,poffer,bagle,worm.galil,mydoom,worm.sco,tanx,novarg,[EMAIL
PROTECTED]'
@@ -97,6 +97,7 @@
QS_USER="qscand"
SKIP_SETUID_TEST=""
MAX_ZIP_SIZE="1000000000"
+USE_FILE_SCAN=""
while [ -n "$1" ]
do
@@ -133,156 +134,166 @@
*) cat <<EOF >&2
valid options:
- --qs-user <username> User that Qmail-Scanner runs as (default: $QS_USER)
- --qmaildir <top of qmail> defaults to $QMAILDIR/
- --spooldir <spooldir> defaults to $AS_QQ/
- --bindir <installdir> where to install qmail-scanner-queue.pl
+ --qs-user <username>
+ User that Qmail-Scanner runs as (default: $QS_USER)
+
+ --qmaildir <top of qmail>
+ defaults to $QMAILDIR/
+
+ --spooldir <spooldir>
+ defaults to $AS_QQ/
+
+ --bindir <installdir>
+ where to install qmail-scanner-queue.pl
Defaults to /var/qmail/bin/
- --admin <username> user to Email alerts to (default: $USERNAME)
- --domain <domain name> "user"@"domain" makes up Email address
- to Email alerts to.
- --scanners <list of installed content scanners>
- Defaults to "auto" - will use
- whatever scanners are found on system.
- Use this option to override "auto" - set
- to one or more of the following:
-auto,none,$SUPPORTED_SCANNERS
+ --admin <username>
+ user to Email alerts to (default: $USERNAME)
- Note the special-case "none". This
- will disable all but the internal
+ --domain <domain name>
+ "user"@"domain" makes up Email address to Email alerts to.
+
+ --scanners <list of installed content scanners>
+ Defaults to "auto" - will use whatever scanners are found on system.
+ Use this option to override "auto" - set to one or more of the
+ following:
+ auto,none,$SUPPORTED_SCANNERS
+ Note the special-case "none". This will disable all but the internal
perlscanner module.
- --skip-text-msgs [yes|no] Defaults to "yes" - Q-S will skip
- running any anti-virus scanners on
- any messages it works out are text-only.
- i.e. don't have any attachments.
- Set to "no" if you want them to be scanned
- anyway.
-
- --notify "none|sender|recips|precips|admin|nmladm|nmlvadm|all" Defaults to
"$NOTIFY_ADDRESSES".
- Comma-separated list (no spaces!)
- of addresses to which alerts should
- be sent to. "nmladm" means only
- notify admin for "user infections",
- i.e. non-mailing-list mail.
- "nmlvadm" is the same as nmladm - except
- that it also doesn't notify for viral
e-mails.
- i.e. just "policy" quarantines get
e-mails. This allows you to
- still notify people when an e-mail is
blocked due to
- a policy decision (such as blocking
password-protected
- zip files), but a message tagged as viral
by an AV system
- will *not* trigger notification.
+ --skip-text-msgs [yes|no]
+ Defaults to "yes" - Q-S will skip running any anti-virus scanners on
+ any messages it works out are text-only. i.e. don't have any attachments.
+ Set to "no" if you want them to be scanned anyway.
+
+ --notify "none|sender|recips|precips|admin|nmladm|nmlvadm|all"
+ Defaults to "$NOTIFY_ADDRESSES". Comma-separated list (no spaces!)
+ of addresses to which alerts should be sent to. "nmladm" means only
+ notify admin for "user infections", i.e. non-mailing-list mail.
+ "nmlvadm" is the same as nmladm - except that it also doesn't notify for
+ viral e-mails. i.e. just "policy" quarantines get e-mails. This allows
+ you to still notify people when an e-mail is blocked due to a policy
+ decision (such as blocking password-protected zip files), but a message
+ tagged as viral by an AV system will *not* trigger notification.
Similarly, "psender"/"precips" means
notify the sender/recips only
if their e-mail was blocked for policy
reasons. i.e. if an AV system
found a virus, then don't notify the
sender/recip as the address was
probably forged.
- --local-domains "one.domain,two.domain" Defaults to the
- value of the "--domain" setting.
- Comma-separated list (no spaces!)
- of domains that are classified as
- "local". This is needed to ensure
- alerts are only sent to local users
- and not remote when '--notify "*recips"'
- is chosen. This will dramatically
- reduce the chance of alerts being
- sent to mailing-lists.
- --silent-viruses "virus1,virus2" Defaults to "auto".
- This option allows you to tell
- Qmail-Scanner *not* to notify
- senders when it quarantines one
- of these viruses. Viruses such
- as Klez alter the sender address
- so that it has no relation to the
- actual sender - so there's no point
- in responding to Klez messages - it
- just confuses people. The admin and
- recips will still be notified as set
- by "--notify".
- Use this option to override "auto".
- By default this is set to:
- $SILENT_VIRUSES
+
+ --local-domains "one.domain,two.domain"
+ Defaults to the value of the "--domain" setting.
+ Comma-separated list (no spaces!) of domains that are classified as
+ "local". This is needed to ensure alerts are only sent to local users
+ and not remote when '--notify "*recips"' is chosen. This will dramatically
+ reduce the chance of alerts being sent to mailing-lists.
+
+ --silent-viruses "virus1,virus2"
+ Defaults to "auto". This option allows you to tell Qmail-Scanner *not*
+ to notify senders when it quarantines one of these viruses. Viruses such
+ as Klez alter the sender address so that it has no relation to the actual
+ sender - so there's no point in responding to Klez messages - it just
+ confuses people. The admin and recips will still be notified as set by
+ "--notify". Use this option to override "auto". By default this is set
+ to: $SILENT_VIRUSES
+
--lang "$LANGUAGES"
Defaults to $QSLANG.
- --archive [yes|no|regex] Defaults to "no". Whether to archive mail after
- it as been processed. If "yes", all copies of
- processed mail will be moved into the maildir
- "$AS_QQ/$ARCHIVEDIR/". Any other string besides
- "yes" and "no" will be treated as a REGEX. Only mail
- from or to an address that contains that regex will
- be archived. e.g. "jhaar|harry" or "[EMAIL
PROTECTED]".
- Be careful with this option, a badly written regex
- will cause Qmail-Scanner to crash.
- --redundant [yes|no] Defaults to "yes". Whether or not to let the
scanners
- also scan any zip files and the original "raw" Email
- file.
- --log-details [yes|syslog|no] Whether or not to log to mailstats.csv/via
- syslog the attachment structure of every Email
- message. Logs to "syslog" by default.
- --log-crypto [yes|no] Defaults to "no". Whether or not to log the presence
- of cryptographic (both signing and encrypting)
- technologies in the "log-details". Q-S can flag
- PGP, S/MIME and password-protected zip files. This
- is informational logging only.
- --fix-mime [yes|no|num] Defaults to "yes". Whether or not to attempt to
- "fix" broken MIME messages before doing anything
- else. Should be safe, but *may* break some
- strange, old mailers (none known yet). If you see
blocks
- occurring due to this setting, try "--fix-mime 1"
first
- before "--fix-mime no".
- --ignore-eol-check [yes|no] Defaults to "no". Making this "yes" stops
Qmail-Scanner
- from treating "\r" or "\0" chars in the headers of
- MIME mail messages as being suspicious enough to
quarantine
- mail over. Some sites receive so much broken e-mail
that this
- option has been created so that they can still
receive such
- messages without having to be as drastic as to
"--fix-mime no"
- - which disables all sorts of other good stuff. Use
only if you
- have to.
-
- --add-dscr-hdrs [yes|no|all] Defaults to "no". This adds the now old-fashion
- X-Qmail-Scanner headers to the message. "all" adds
- the "rcpt to" headers too - this is a privacy hole.
- --debug [yes|no] Whether or not debugging is turned on. On (yes)
- by default. Can be also set to a number. Numbers
- over 100 cause Q-S to not cleanup working files
+
+ --archive [yes|no|regex]
+ Defaults to "no". Whether to archive mail after it as been processed.
+ If "yes", all copies of processed mail will be moved into the maildir
+ "$AS_QQ/$ARCHIVEDIR/". Any other string besides "yes" and "no"
+ will be treated as a REGEX. Only mail from or to an address that contains
+ that regex will be archived. e.g. "jhaar|harry" or "[EMAIL PROTECTED]". Be
+ careful with this option, a badly written regex will cause Qmail-Scanner
+ to crash.
+
+ --redundant [yes|no]
+ Defaults to "yes". Whether or not to let the scanners also scan any zip
+ files and the original "raw" Email file.
+
+ --log-details [yes|syslog|no]
+ Whether or not to log to mailstats.csv/via syslog the attachment structure
+ of every Email message. Logs to "syslog" by default.
+
+ --log-crypto [yes|no]
+ Defaults to "no". Whether or not to log the presence of cryptographic
+ (both signing and encrypting) technologies in the "log-details". Q-S can
+ flag PGP, S/MIME and password-protected zip files. This is informational
+ logging only.
+
+ --fix-mime [yes|no|num]
+ Defaults to "yes". Whether or not to attempt to "fix" broken MIME messages
+ before doing anything else. Should be safe, but *may* break some strange,
+ old mailers (none known yet). If you see blocks occurring due to this
+ setting, try "--fix-mime 1" first before "--fix-mime no".
+
+ --ignore-eol-check [yes|no]
+ Defaults to "no". Making this "yes" stops Qmail-Scanner from treating "\r"
+ or "\0" chars in the headers of MIME mail messages as being suspicious
+ enough to quarantine mail over. Some sites receive so much broken e-mail
+ that this option has been created so that they can still receive such
+ messages without having to be as drastic as to "--fix-mime no" - which
+ disables all sorts of other good stuff. Use only if you have to.
+
+ --add-dscr-hdrs [yes|no|all]
+ Defaults to "no". This adds the now old-fashion X-Qmail-Scanner headers
+ to the message. "all" adds the "rcpt to" headers too - this is a privacy
+ hole.
+
+ --debug [yes|no]
+ Whether or not debugging is turned on. On (yes) by default. Can be also
+ set to a number. Numbers over 100 cause Q-S to not cleanup working files
- thus allowing for offline debugging...
- --unzip [yes|no] Whether or not to forcibly unzip all zip files. Off
- by default as most AV's do unzip'ping themselves.
- --max-zip-size [number] Defaults to 1 Gbytes.
- This setting allows you to control the maximum size
you
- are willing to allow zip file attachments to unpack
to.
- This is to enable you to limit DoS attacks against
your
- Qmail-Scanner installation (someone could send you a
small zip
- file that unpacks to Gbytes of useless files -
filling your harddisk).
- Set to whatever value you think is appropriate for
your system. The
- default value of 1Gb is set so large so as not to
assume anything about
- your system - YOU WILL NEED TO SET THIS VALUE IN
ORDER TO GAIN ANY
- PROTECTION. Something like "100000000" (100 Mb) might
be appropriate.
- --block-password-protected [yes|no] Defaults to "no". Setting this to "yes"
allows
- you to quarantine any incoming zip files that are
password
- protected. This is primarily to stop viruses such as
Bagle which
- arrive within a password-protected zip file.
- --batch Do not confirm configure information (mainly for
scripting)
- --install Create directory paths, install perl script,
- and change ownerships to match.
- --mime-unpacker "reformime" Defaults to reformime.
+
+ --unzip [yes|no]
+ Whether or not to forcibly unzip all zip files. Off by default as most
+ AV's do unzip'ping themselves.
+
+ --max-zip-size [number]
+ Defaults to 1 Gbytes. This setting allows you to control the maximum
+ size you are willing to allow zip file attachments to unpack to. This
+ is to enable you to limit DoS attacks against your Qmail-Scanner
+ installation (someone could send you a small zip file that unpacks to
+ Gbytes of useless files - filling your harddisk). Set to whatever
+ value you think is appropriate for your system. The default value of
+ 1Gb is set so large so as not to assume anything about your system -
+ YOU WILL NEED TO SET THIS VALUE IN ORDER TO GAIN ANY PROTECTION.
+ Something like "100000000" (100 Mb) might be appropriate.
+
+ --block-password-protected [yes|no]
+ Defaults to "no". Setting this to "yes" allows you to quarantine any
+ incoming zip files that are password protected. This is primarily to
+ stop viruses such as Bagle which arrive within a password-protected
+ zip file.
+
+ --batch
+ Do not confirm configure information (mainly for scripting)
+
+ --install
+ Create directory paths, install perl script, and change ownerships to
+ match.
+
+ --mime-unpacker "reformime"
+ Defaults to reformime.
****************
Rarely Used
****************
- --no-QQ-check Do not check that the QMAILQUEUE patch is installed.
- This explicitly disables any "--install" reference
- as that is NOT POSSIBLE with a manual install.
- Use ONLY IF YOU MUST. The QMAILQUEUE patch is REALLY
- a GOOD THING!!!!
-
- --skip-setuid-test don't test for setuid perl. Only of use for those
wanting
- to run the C-wrapper version.
-
- --qmail-queue-binary Set this to the FULL PATH to the Qmail qmail-queue
- binary. This is only EVER set when doing a manual
- install.
+ --no-QQ-check
+ Do not check that the QMAILQUEUE patch is installed. This explicitly
+ disables any "--install" reference as that is NOT POSSIBLE with a manual
+ install. Use ONLY IF YOU MUST. The QMAILQUEUE patch is REALLY a GOOD
+ THING!!!!
+
+ --skip-setuid-test
+ don't test for setuid perl. Only of use for those wanting to run the
+ C-wrapper version.
+
+ --qmail-queue-binary
+ Set this to the FULL PATH to the Qmail qmail-queue binary. This is only
+ EVER set when doing a manual install.
This script must be run as root so it can detect problems with setuid
@@ -997,6 +1008,14 @@
fi
done
+DD=`$PERL5 -e 'use File::Scan;' 2>&1`
+if [ "$?" == "0" ]; then
+ USE_FILE_SCAN='use File::Scan;'
+ SCANNER_ARRAY="\"filescan_scanner\""
+ INSTALLED_SCANNERS="$INSTALLED_SCANNERS
+filescan"
+fi
+
if [ "$FIND_SILENT_VIRUSES" = "$SILENT_VIRUSES" ]; then
SILENT_VIRUSES="auto"
fi
@@ -1619,6 +1638,7 @@
s?BITDEFENDER?$BITDEFENDER?g;
s?CLAMSCAN?$CLAMSCAN?g;
s?CLAMDSCAN?$CLAMDSCAN?g;
+s?USE_FILE_SCAN?$USE_FILE_SCAN?g;
s?SPAMASSASSIN_BINARY?$SPAMASSASSIN_BINARY?g;
s?SPAMC_BINARY?$SPAMC_BINARY?g;
s?SPAMC_OPTIONS?$SPAMC_OPTIONS?g;
diff -rubN qmail-scanner-1.24-orig/qmail-scanner-queue.template
qmail-scanner-1.24/qmail-scanner-queue.template
--- qmail-scanner-1.24-orig/qmail-scanner-queue.template Tue Oct 19
19:49:33 2004
+++ qmail-scanner-1.24/qmail-scanner-queue.template Tue Nov 9 12:03:29 2004
@@ -221,8 +221,10 @@
my $spamc_subject='SPAMC_SUBJECT';
my $spamassassin_binary='SPAMASSASSIN_BINARY';
my ($sa_comment,$sa_level);
-my $sa_symbol='+';
-my ($tag_score)="";
+my $sa_symbol='*';
+my $sa_reject_score=0;
+my $sa_warn_score=0;
+my $tag_score="";
my
$SNEAKY_WINDOWS_EXTENSIONS="exe|com|pps|w[pm][szd]|vcf|nws|cmd|bat|pif|sc[rt]|dll|ocx|do[ct]|xl[swt]|p[po]t|rtf|vb[se]?|hta|p[lm]|sh[bs]|hlp|chm|eml|ws[cfh]|ad[ep]|jse?|md[abew]|ms[ip]|reg|as[dfx]|cil|cpl";
my
$VALID_WINDOWS_EXTENSIONS="sav|htm|html|pst|ost|txt|gif|jpeg|mpeg|jpg|png|mny|wav|tif|$SNEAKY_WINDOWS_EXTENSIONS";
@@ -268,6 +270,7 @@
#Want microsec times for debugging
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
use POSIX;
+USE_FILE_SCAN
use vars qw/ $opt_v $opt_h $opt_g $opt_r $opt_z/;
@@ -297,7 +300,6 @@
exit;
}
-
if ( $opt_g || $opt_r) {
&generate_quarantine_db;
exit 0;
@@ -324,15 +326,12 @@
$ENV{'TMP'} = $ENV{'TMPDIR'} = "$scandir/tmp/$file_id";
#$ENV{'QMAILSUSER'} = $ENV{'QMAILSHOST'} = '';
-
-
if ($mimeunpacker_binary =~ /reformime/) {
$mimeunpacker_binary .= " -x$ENV{'TMPDIR'}/";
} elsif ($mimeunpacker_binary =~ /ripmime/) {
$mimeunpacker_binary .= " --unique_names -i - -d $ENV{'TMPDIR'}/";
}
-
#Get current timestamp for logs
my ($sec,$min,$hour,$mday,$mon,$year,$nowtime);
($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
@@ -359,10 +358,8 @@
exit 0;
}
-
&scanner_info;
-
if ($ENV{'TCPREMOTEIP'}) {
$smtp_sender="via SMTP from $ENV{'TCPREMOTEIP'}";
$remote_smtp_ip=$ENV{'TCPREMOTEIP'};
@@ -454,7 +451,6 @@
}
}
-
#Msg has been delivered now, so don't want hangs in this part
#to affect delivery
@@ -1047,8 +1043,6 @@
&debug("p_s: starting scan of directory \"$ENV{'TMPDIR'}\"...");
use DB_File;
-
-
tie (%array, 'DB_File', "$db_filename.db", O_RDONLY, 0600) ||
&error_condition("cannot open $db_filename.db - $!");
if (!$quarantine_event && $illegal_mime && $headers{'mime-version'} &&
$BAD_MIME_CHECKS) {
@@ -1319,7 +1313,6 @@
$still_headers=0 if (/^(\r|\r\n|\n)$/);
#Insert Subject: line if e-mail dosn't contain one but must be tagged
print QMQ "Subject: $spamc_subject\n" if ((!$still_headers) &&
($sa_comment =~ /^yes/i) && (!$altered_subject) && $spamc_subject ne "" );
-
}
print QMQ;
}
@@ -1482,7 +1475,6 @@
}
}
system("$rm_binary -rf $ENV{'TMPDIR'}/ $scandir/$wmaildir/new/$file_id") if
($DEBUG < 100 && $file_id ne "");
-
}
@@ -1695,9 +1687,9 @@
while (<CLAMS>) {
chomp;
if (/ersion ([0-9\.\-a-z]+)/i) {
- $SCANINFO .="clamdscan: $1. ";
+ $SCANINFO .="clamdscan: $1; ";
} elsif (/^ClamAV ([^\/]+)\/([^\/]+)\//) {
- $SCANINFO .="clamdscan: $1/$2. ";
+ $SCANINFO .="clamdscan: $1/$2; ";
}
}
close(CLAMS);
@@ -1712,7 +1704,11 @@
}
}
close(SPAS);
- $SCANINFO .= "spamassassin: $spamassassin_eng. ";
+ $SCANINFO .= "spamassassin: $spamassassin_eng; ";
+ } elsif ($scanner eq 'filescan') {
+ my $fs = File::Scan->new();
+ my $fv = $fs->VERSION;
+ $SCANINFO .= "File::Scan $fv; ";
} else {
#Catch-all for other ones
$SCANINFO .= "$scanner: ???. ";
@@ -1830,9 +1826,6 @@
}
}
-
-
-
sub show_version {
my ($scanner);
&scanner_info;
diff -rubN qmail-scanner-1.24-orig/sub-clamdscan.pl
qmail-scanner-1.24/sub-clamdscan.pl
--- qmail-scanner-1.24-orig/sub-clamdscan.pl Sun Oct 17 19:40:36 2004
+++ qmail-scanner-1.24/sub-clamdscan.pl Tue Nov 9 08:36:58 2004
@@ -5,6 +5,7 @@
my ($start_clamdscan_time)=[gettimeofday];
my
($DD,$clamdscan_status,$eclamdscan_status,$stop_clamdscan_time,$clamdscan_time);
my ($clamdscan_verbose);
+ my $has_virus = 0;
$clamdscan_verbose="-v" if ($DEBUG);
&debug("run $clamdscan_binary $clamdscan_options $ENV{'TMPDIR'} 2>&1");
@@ -17,7 +18,7 @@
if ( $eclamdscan_status > 0) {
if ($eclamdscan_status == 1 && $DD =~ /\:\s(.*)\sFOUND$/m) {
- $quarantine_description=$+;
+ $quarantine_description=$+; $has_virus++;
&debug("There be a virus! ($quarantine_description)");
($quarantine_event=$quarantine_description)=~s/\s/_/g;
$quarantine_event="CLAMDSCAN:".substr($quarantine_event,0,$QE_LEN);
@@ -48,4 +49,7 @@
$stop_clamdscan_time=[gettimeofday];
$clamdscan_time = tv_interval ($start_clamdscan_time, $stop_clamdscan_time);
&debug("clamdscan: finished scan of dir \"$ENV{'TMPDIR'}\" in
$clamdscan_time secs");
+ if ($has_virus) {
+ &reject_email("Rejected VIRUS ",$quarantine_description,33);
+ }
}
diff -rubN qmail-scanner-1.24-orig/sub-clamscan.pl
qmail-scanner-1.24/sub-clamscan.pl
--- qmail-scanner-1.24-orig/sub-clamscan.pl Mon Apr 19 22:04:15 2004
+++ qmail-scanner-1.24/sub-clamscan.pl Tue Nov 9 08:37:57 2004
@@ -5,6 +5,7 @@
my ($start_clamscan_time)=[gettimeofday];
my ($DD,$clamscan_status,$stop_clamscan_time,$clamscan_time);
my ($clamscan_verbose,$eclamscan_status);
+ my $has_virus=0;
$clamscan_verbose="-v" if ($DEBUG);
&debug("run $clamscan_binary $clamscan_options $ENV{'TMPDIR'} 2>&1");
@@ -17,7 +18,7 @@
if ( $eclamscan_status > 0 ) {
if ($eclamscan_status == 1 && $DD =~ /\:\s(.*)\sFOUND$/m) {
- $quarantine_description=$+;
+ $quarantine_description=$+; $has_virus++;
&debug("There be a virus! ($quarantine_description)");
($quarantine_event=$quarantine_description)=~s/\s/_/g;
$quarantine_event="CLAMSCAN:".substr($quarantine_event,0,$QE_LEN);
@@ -41,4 +42,7 @@
$stop_clamscan_time=[gettimeofday];
$clamscan_time = tv_interval ($start_clamscan_time, $stop_clamscan_time);
&debug("clamscan: finished scan of dir \"$ENV{'TMPDIR'}\" in $clamscan_time
secs");
+ if ($has_virus) {
+ &reject_email("Rejected VIRUS ",$quarantine_description,33);
+ }
}
diff -rubN qmail-scanner-1.24-orig/sub-filescan.pl
qmail-scanner-1.24/sub-filescan.pl
--- qmail-scanner-1.24-orig/sub-filescan.pl Wed Dec 31 18:00:00 1969
+++ qmail-scanner-1.24/sub-filescan.pl Tue Nov 9 00:30:55 2004
@@ -0,0 +1,63 @@
+###############################
+#
+## Recursively generates a file-list
+##
+###############################
+sub get_file_list {
+ my @dfiles;
+ my @ufiles;
+ my $wdire = shift || return @ufiles;
+ opendir(DIRE, $wdire) || return @ufiles;
+ while (defined(my $file=readdir(DIRE))) {
+ next if $file eq '.';
+ next if $file eq '..';
+ my $full = join('/',$wdire,$file);
+ if (-d $full) {
+ push @dfiles,$full;
+ } else {
+ push @ufiles,$full;
+ }
+ }
+ closedir(DIRE);
+ foreach my $dd (@dfiles) {
+ my @fl = &get_file_list($dd);
+ foreach my $ff (@fl) {
+ push @ufiles,$ff;
+ }
+ }
+ return @ufiles;
+}
+
+sub filescan_scanner {
+ #File::Scan scanner
+ &debug("filescan: starting scan of directory \"$ENV{'TMPDIR'}\"...");
+
+ my ($start_filescan_time)=[gettimeofday];
+ my $filescanner = File::Scan->new();
+ my $has_virus = 0;
+
+ my @fl = &get_file_list($ENV{'TMPDIR'});
+
+ foreach my $file (@fl) {
+ &debug("filescan: scanning $file...");
+ if (my $vv = $filescanner->scan("$file")) {
+ &debug("filescan: There be a virus! ($vv)");
+ $quarantine_description=$vv; $has_virus++;
+ $quarantine_event="FileScan:$vv";
+ $description .= "\n--- File::Scan results --\n$vv FOUND";
+ last;
+ } elsif ( my $ee = $filescanner->error()) {
+ &debug("File::Scan [Error] = $ee");
+ &error_condition("FileScan: Error: $ee");
+ last;
+ } elsif ( my $ss = $filescanner->suspicious()) {
+ &debug("File::Scan [suspicious]");
+ last;
+ }
+ }
+ my ($filescan_time) = tv_interval ($start_filescan_time, [gettimeofday]);
+ &debug("filescan: finished scan of dir \"$ENV{'TMPDIR'}\" in $filescan_time
secs");
+ if ($has_virus) {
+ &reject_email("Rejected VIRUS ",$quarantine_description,33);
+ }
+}
diff -rubN qmail-scanner-1.24-orig/sub-log_msg.pl
qmail-scanner-1.24/sub-log_msg.pl
--- qmail-scanner-1.24-orig/sub-log_msg.pl Thu Sep 9 15:07:51 2004
+++ qmail-scanner-1.24/sub-log_msg.pl Tue Nov 9 08:39:25 2004
@@ -2,9 +2,7 @@
my($msgtype,$status,$elapsed_time,$msgsize,$frm,$recips,$subj,$msgid,$attachs)[EMAIL
PROTECTED];
my ($msg,$file);
-
my $syslogtype='mail|info';
-
if ($log_details eq "syslog") {
$msgtype =~ s/\s/_/g;
@@ -84,4 +82,30 @@
&debug("$msgtype: $msg");
}
+sub reject_email {
+ my ($exit_string,$exit_info,$exit_code)[EMAIL PROTECTED];
+ $exit_code=111 if (!$exit_code);
+
+ # st: tell qmail-smtpd why the message is rejected,
+ # so it can be written to the log
+ warn "$V_HEADER-$VERSION: $exit_string $exit_info from $$ $remote_smtp_ip\n";
+ &debug("r_e: $V_HEADER-$VERSION: $exit_string $exit_info");
+ my $reason;
+ if ($exit_code == 32) {
+ $reason = "Spam";
+ }
+ elsif ($exit_code == 33) {
+ $reason = "Virus:$exit_info";
+ }
+ else {
+ $reason = "Policy";
+ }
+ if ($tag_score !~ m/^:/) { $reason .= ':'; }
+ $reason .= $tag_score;
+ $elapsed_time = tv_interval ($start_time, [gettimeofday]);
+ &log_msg('qmail-scanner',$reason,$elapsed_time,$msg_size,$returnpath,
+ $recip,$headers{'subject'},$headers{$qsmsgid},'');
+ &cleanup;
+ exit $exit_code;
+}
diff -rubN qmail-scanner-1.24-orig/sub-spamassassin.pl
qmail-scanner-1.24/sub-spamassassin.pl
--- qmail-scanner-1.24-orig/sub-spamassassin.pl Mon Oct 18 18:58:17 2004
+++ qmail-scanner-1.24/sub-spamassassin.pl Tue Nov 9 16:21:01 2004
@@ -5,6 +5,11 @@
&debug("spamassassin: don't scan as RELAYCLIENT implies this was sent by a
local user");
return;
}
+ #Only run SA for real users
+ if ($returnpath eq "" && $headers{'from'} =~ m/mailer-daemon|postmaster/i) {
+ &debug("spamassassin: skipping message from POSTMASTER");
+ return;
+ }
#SpamAssassin client scanner
my ($spamassassin_found,$spamassassin_status);
my ($start_spamassassin_time)=[gettimeofday];
@@ -53,6 +58,7 @@
$sa_tag++;
$sa_status=1 if ($1 eq "Yes");
$sa_score=$3;$sa_max=$4;
+ last;
}
}
}
@@ -67,10 +73,15 @@
} else {
unlink("$scandir/$wmaildir/new/$file_id.spamc");
}
- if ($sa_max > $sa_score || ($sa_score == 0)) {
+ if ($sa_score == 0) {
+ $tag_score .= "SA:0($sa_score/$sa_max):";
+ }
+ elsif ($sa_max > $sa_score) {
$tag_score .= "SA:0($sa_score/$sa_max):";
$sa_comment = "No, hits=$sa_score required=$sa_max" if ($sa_fast);
- } else {
+ &debug("SA: ham message with $sa_score/$sa_max hits");
+ }
+ else {
$tag_score .= "SA:1($sa_score/$sa_max):";
$sa_comment = "Yes, hits=$sa_score required=$sa_max" if ($sa_fast);
&debug("SA: yup, this smells like SPAM");
@@ -90,6 +101,21 @@
$stop_spamassassin_time=[gettimeofday];
$spamassassin_time = tv_interval ($start_spamassassin_time,
$stop_spamassassin_time);
&debug("spamassassin: finished scan of dir \"$ENV{'TMPDIR'}\" in
$spamassassin_time secs");
+ if ($sa_reject_score && ($sa_score > $sa_reject_score)) {
+ &debug("SA: rejecting message with $sa_score hits");
+ &reject_email("Rejected SPAM",sprintf("%.2f/%.2f",$sa_score,$sa_max),32);
+ }
+ else {
+ my $tag = sprintf "%.3f/%.1f",$sa_score,$sa_max;
+ $spamc_subject=sprintf("[SPAM][%s]",$tag);
+ if ($sa_score > $sa_max) {
+ &debug("SA: spam message accepted with $tag");
+ warn "$V_HEADER-$VERSION: Accepted SPAM $tag from $$ $remote_smtp_ip\n";
+ } else {
+ &debug("SA: ham message accepted with $tag");
+ warn "$V_HEADER-$VERSION: Accepted HAM $tag from $$ $remote_smtp_ip\n";
+ }
+ }
}
