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";
+    }
+  }
 }
 

Reply via email to