McAfee uvscan 6.0.0 - patches provided

Michael Miller mmlist at mjmm.org
Thu Apr 15 10:50:41 IST 2010


Hi,

Attached are a set of patches to add support for the McAfee uvscan
v6.0.0 command line scanner. The v5 and v4 versions of uvscan are no
longer receiving updates from McAfee and should be viewed as retired.
During the testing Phil and I noticed that uvscan sometimes outputs "...
Found " or "... Found: " when a virus is found - please be sure to test,
at a minimum, with an eicar signature to ensure your copy of uvscan v6
is parsed correctly.

I have updated the following files:
etc/virus.scanners.conf
lib/MailScanner/SweepViruses.pm
lib/mcafee-autoupdate
lib/mcafee-wrapper

I have added the following files:
lib/mcafee6-autoupdate
lib/mcafee6-wrapper

(Note that mcafee-autoupdate and mcafee6-autoupdate are identical, so
after patching mcafee-autoupdate, you need to copy the resulting file to
mcafee6-autoupdate)

Thanks to Phil Randal for testing and troubleshooting my initial versions!

If the patches don't come through correctly, please let me know and I
can send as attachments.

Regards,
Mike

Patches against MailScanner-4.79.11-1 below:
#########################################################################
# diff -u etc/virus.scanners.conf.47911 etc/virus.scanners.conf
--- etc/virus.scanners.conf.47911       2010-04-11 00:14:02.000000000 +0100
+++ etc/virus.scanners.conf     2010-04-15 10:36:18.000000000 +0100
@@ -37,6 +37,7 @@
 kaspersky      /opt/MailScanner/lib/kaspersky-wrapper  /opt/AVP
 kavdaemonclient        /opt/MailScanner/lib/kavdaemonclient-wrapper
/usr/local
 mcafee         /opt/MailScanner/lib/mcafee-wrapper     /usr/local/uvscan
+mcafee6                /opt/MailScanner/lib/mcafee6-wrapper   
/usr/local/uvscan
 # Now updated to handle nod32 2.01 and upwards
 #nod32-1.99    /opt/MailScanner/lib/nod32-wrapper      /usr/local/nod32
 nod32-1.99     /opt/MailScanner/lib/nod32-wrapper      /usr/sbin


# diff -u lib/MailScanner/SweepViruses.pm.47911
lib/MailScanner/SweepViruses.pm
--- lib/MailScanner/SweepViruses.pm.47911       2010-04-10
23:26:06.000000000 +0100
+++ lib/MailScanner/SweepViruses.pm     2010-04-13 16:14:52.000000000 +0100
@@ -127,6 +127,18 @@
     SupportScanning    => $S_SUPPORTED,
     SupportDisinfect   => $S_SUPPORTED,
   },
+  mcafee6              => {
+    Name               => 'McAfee6',
+    Lock               => 'mcafee6Busy.lock',
+    CommonOptions      => '--recursive --ignore-links --analyze --mime ' .
+                           '--secure --noboot',
+    DisinfectOptions   => '--clean',
+    ScanOptions                => '',
+    InitParser         => \&InitMcAfee6Parser,
+    ProcessOutput      => \&ProcessMcAfee6Output,
+    SupportScanning    => $S_SUPPORTED,
+    SupportDisinfect   => $S_SUPPORTED,
+  },
   command              => {
     Name               => 'Command',
     Lock               => 'commandBusy.lock',
@@ -1379,6 +1391,11 @@
   $currentline = '';
 }

+# Initialise any state variables the McAfee6 output parser uses
+sub InitMcAfee6Parser {
+  ;
+}
+
 # Initialise any state variables the Command (CSAV) output parser uses
 sub InitCommandParser {
   ;
@@ -1837,7 +1854,7 @@
   $logout = $report;
   $logout =~ s/%/%%/g;
   $logout =~ s/\s{20,}/ /g;
-  # note: '$dot' does not become '.'
+  # note: '$dot' does not become '.', but blank for rootdir
   ($dot, $id, $part, @rest) = split(/\//, $lastline);
   my $notype = substr($part,1);
   $logout =~ s/\Q$part\E/$notype/;
@@ -1858,6 +1875,64 @@
   return 1;
 }

+sub ProcessMcAfee6Output {
+  my($line, $infections, $types, $BaseDir, $Name) = @_;
+
+  my($report, $dot, $id, $part, @rest);
+  my($logout);
+  my($filename, $virusname);
+
+  chomp $line;
+
+  #MailScanner::Log::InfoLog("McAfee6 said \"$line\"");
+
+  # Should we worry about any warnings/errors?
+  return 0 unless $line =~ /Found/;
+
+  # McAfee prints the whole path including
+  # ./message/part so make it the same
+  # eg: /var/spool/MailScanner/incoming/4118/./o3B07pUD004176/eicar.com
+  #
+  # strip off leading BaseDir
+  $line =~ s/^$BaseDir//;
+  # and then remaining /. (which may be removed in future as per v5 uvscan)
+  $line =~ s/^\/\.//;
+  # and put the leading . back in place
+  $line =~ s/^/\./;
+
+  $filename = $line;
+  $filename =~ s/ \.\.\. Found.*$//;
+
+  #get the virus name - not used currently
+  #$virusname = $line;
+  #$virusname =~ s/^.* \.\.\. Found.?//;
+
+  $report = $line;
+  $logout = $line;
+  $logout =~ s/%/%%/g;
+  $logout =~ s/\s{20,}/ /g;
+  # note: '$dot' does become '.'
+  ($dot, $id, $part, @rest) = split(/\//, $filename);
+  my $notype = substr($part,1);
+  $logout =~ s/\Q$part\E/$notype/;
+  $report =~ s/\Q$part\E/$notype/;
+  $report =~ s/ \.\.\. Found/ Found/;
+  MailScanner::Log::InfoLog($logout);
+
+  $report = $Name . ': ' . $report if $Name;
+
+  # Infections found in the header must be handled specially here
+  if ($id =~ /\.(?:header|message)/) {
+    # The attachment name is "" ==> infection is whole messsage
+    $part = "";
+    # Correct the message id by deleting all from .header onwards
+    $id =~ s/\.(?:header|message).*$//;
+  }
+  $infections->{"$id"}{"$part"} .= $report . "\n";
+  $types->{"$id"}{"$part"} .= "v";
+  return 1;
+}
+
 # This next function originally contributed in its entirety by
 # "Richard Brookhuis" <brookhuis at busschers.nl>
 #



#########################################################################
# diff -u lib/mcafee-autoupdate.47911 lib/mcafee-autoupdate
--- lib/mcafee-autoupdate.47911 2010-04-10 20:02:56.000000000 +0100
+++ lib/mcafee-autoupdate       2010-04-15 10:19:51.000000000 +0100
@@ -2,7 +2,15 @@
 #
 # Update the McAfee data files.
 #
+# As at 2010/04/10 the mcafee6-autoupdate and mcafee6-autoupdate scripts
+# are identical. The logic to differentiate between versions is built in
+# to the script to enable only one version of the script to be maintained.
+#
+# based on:
+#
 # $Cambridge: hermes/conf/build/bin/uvscan-update,v 1.52 2004/08/18
19:12:02 fanf2 Exp $
+# and patch from:
+#
http://lists.mailscanner.info/pipermail/mailscanner/2009-November/094019.html

 # $PREFIX is the directory where the uvscan binary is (NOT a symlink to
 # the binary), which is where it looks for its dat files. You may run
@@ -17,13 +25,36 @@
 # the subdirectory via a current link. The current link is updated
 # without locking on the assumption that this is sufficiently unlikely
 # to cause a problem.
+#
+
+# As of Apr 2010, McAfee is no longer publishing V1 DATs, and is only
+# publishing V2 DATs:
+#
+#   https://kc.mcafee.com/corporate/index?page=content&id=KB60404
+#   https://kc.mcafee.com/corporate/index?page=content&id=KB60772
+#
+# Version 6 of McAfee VirusScan Command Line Scanner for Unix uses V2 DATs.
+# Version 5, which uses V1 DATs, is EoL and no longer receives DAT updates.
+#
+# If this script detects taht we are running VirusScan CLI version 6, we
+# extract the DATs from the V2 DAT zip archive (avvdat-XXXX.zip).
+# Otherwise, we log an error about EoL scanner and no available updates.
+#
+# As V1 DATs are no longer published, support for them has been removed
+# from this update script.

 # defaults
 OPTS="-d"
 PREFIX=/opt/uvscan
-FTPDIR=http://download.nai.com/products/datfiles/4.x/nai
+FTPDIR=http://update.nai.com/products/commonupdater
 RETRIES=1
 INTERVAL=300
+CLIVERSION=6
+
+wgetverbosity="--no-verbose"
+tarverbosity=""
+unzipverbosity="-q"
+unzipopts="-o"

 # handle the command line
 usage () {
@@ -61,7 +92,7 @@
                ;;
         /*)     PREFIX=$arg
                 ;;
-        http:)  ftp_proxy=$arg
+        http://*)  ftp_proxy=$arg
                 http_proxy=$arg
                 export ftp_proxy
                 export http_proxy
@@ -90,20 +121,32 @@
 option v VERBOSE
 case $FORCE in
 yes)    VERBOSE=yes
+       wgetverbosity=""
+       tarverbosity="v"
+       unzipverbosity=""
 esac

-# look for binaries and libraris in plausible places
+# look for binaries and libraries in plausible places
 PATH=$PREFIX:/usr/local/bin:/usr/bin:/bin
 # this is only necessary for broken setups
 LD_LIBRARY_PATH=$PREFIX
 export PATH LD_LIBRARY_PATH

+#setup sane umask, just in case...
+umask 022
+
 # where this script finds things
 DATDIR=$PREFIX/datfiles
-DATFILES="clean.dat extra.dat internet.dat names.dat scan.dat"
+
+# These are for CLI v6+:
+# Note that runtime.dat is not distributed; it is generated by uvscan the
+# first time it runs (including with "uvscan --version").
+DATFILES6="avvclean.dat avvnames.dat avvscan.dat runtime.dat extra.dat"
+
 LINKNAME=current
 LINKREL=datfiles/$LINKNAME

+
 # wrapper functions for echo etc.
 timestamp () {
         case $TIME in
@@ -143,7 +186,11 @@
 say PREFIX=$PREFIX

 # check directory setup is correct
-for link in $LINKREL $DATFILES
+# At this point we do not know whether this is a CLI version 6 or version 5
+# installation, and more particularly what the filenames for the DAT files
+# are.
+#for link in $LINKREL $DATFILES
+for link in $LINKREL
 do
         if ! is -h $PREFIX/$link
         then
@@ -181,12 +228,59 @@
         run rm -f $out $err
 }

+#this parses an ini file for the occurence of a value in the specified
section
+#parseini INIFILE SECTION ITEM
+parseini () {
+  myINIFILE="$1"
+  mySECTION="$2"
+  myITEM="$3"
+  if [ ! -s "${myINIFILE}" ]
+  then
+    echo "UNKNOWN"
+    return 1
+  fi
+
+  myINSEC="no"
+  while read line
+  do
+    #just incase input is in DOS format... (Is the case for avvdat.ini)
+    line="`echo $line|sed 's/\r//'`"
+
+    if [ "${line}" = "[${mySECTION}]" ]
+    then
+      myINSEC="yes"
+      continue
+    fi
+    if [ "`echo ${line}|cut -c1`"  = "[" ]
+    then
+      myINSEC="no"
+      continue
+    fi
+    [ "${myINSEC}" = "yes" ] || continue
+    if [ "`echo ${line}|cut -d= -f1`" = "${myITEM}" ]
+    then
+      echo "`echo ${line}|sed 's/^'"${myITEM}="'//'`"
+      return 0
+    fi
+  done < ${myINIFILE}
+  echo "UNKNOWN"
+  return 1
+}
+
 # work out latest dat version
 try=$RETRIES
 while :
-do      getver "wget --tries=$try --waitretry=$INTERVAL --passive-ftp
$FTPDIR/update.ini" update.ini "DATVersion="
-        VERSION=$VER
-        case $VERSION in
+do
+        rm -f avvdat.ini
+        if is $? != 0
+        then
+          say "Error deleting avvdat.init... update may not be successful."
+        fi
+
+        run wget --tries=$try --waitretry=$INTERVAL --passive-ftp
$FTPDIR/avvdat.ini
+       NEWVER=`parseini avvdat.ini AVV-ZIP DATVersion`
+say New version is $NEWVER
+        case $NEWVER in
         UNKNOWN)
                 if ! try=`expr $try - 1`
                 then break
@@ -201,40 +295,75 @@
 done

 # work out installed dat version
-getver "uvscan --version" version.err "Virus data file v"
+# CLI v5 is EoL so no point in checking for it first,
+# as no one should still be using it
+getver "uvscan --version" version.err "Dat set version: "
+if is $VER = UNKNOWN
+then
+       # Might be CLI pre-v6:
+       getver "uvscan --version" version.err "Virus data file v"
+        if is $VER != UNKNOWN
+        then
+          VERBOSE=yes
+         say "uvscan earlier than v6 found. No DATs available. ABORTING."
+          say "Please upgrade uvscan to at least v6.0.0"
+          if is $VER != 5937
+          then
+            say ""
+            say "You are not running the last released v1 DAT."
+            say "Please manually upgrade to DAT v5937 if possible."
+          fi
+          run exit 1
+        fi
+fi
 PREVIOUS=$VER

 case $FORCE in
 yes)    say Forced update from $PREVIOUS
         PREVIOUS=0000
         ;;
-*)      if is $VERSION -eq $PREVIOUS
-        then    say Already have $VERSION
+*)      if is $NEWVER -eq $PREVIOUS
+        then    say Already have $NEWVER
                 run exit 0
         fi
 esac

+# select appropriate archive name and DAT filenames
+# if this is CLI v6, we use V2 DAT archive
+if is $CLIVERSION = 6
+then
+        DISTARC=avvdat-$NEWVER.zip
+        DATFILES="$DATFILES6"
+else
+        say "Fatal Error. Unsupported CLI version found..."
+        exit 1
+fi
+
 VERBOSE=yes

+# We are performing an update, so be chatty (as opposed to explicitly
+# verbose as requested)
+CHATTY=yes
+
 say Installed dat file is $PREVIOUS
-say Latest dat file is $VERSION
+say Latest dat file is $NEWVER

-if is $VERSION = UNKNOWN
+if is $NEWVER = UNKNOWN
 then    say Problem with McAfee datfile update from $FTPDIR
         run exit 1
-elif is $VERSION -lt $PREVIOUS
+elif is $NEWVER -lt $PREVIOUS
 then    say Remote version $VERSION older than installed version $PREVIOUS
         run exit 1
-elif is -d $VERSION
-then    say Cleaning away $VERSION directory
-        run rm -rf $VERSION
+elif is -d $NEWVER
+then    say Cleaning away $NEWVER directory
+        run rm -rf $NEWVER
 fi

 retry () {
         echo "$OUT"
         say Fetch or test failed -- removing bad McAfee data files
         run cd $DATDIR
-        run rm -rf $VERSION
+        run rm -rf $NEWVER
         if ! try=`expr $try - 1`
         then    say Giving up
                 run exit 1
@@ -248,19 +377,25 @@
 while :
 do
         # fetch and extract dat files
-        TARFILE=dat-$VERSION.tar
-        run mkdir $VERSION
-        run cd $VERSION
+        run mkdir $NEWVER
+        run cd $NEWVER
         run chmod 700 .
-        if ! run wget --tries=$try --waitretry=$INTERVAL --passive-ftp
--progress=dot:mega $FTPDIR/$TARFILE
+        if ! run wget $wgetverbosity --tries=$try --waitretry=$INTERVAL
--passive-ftp --progress=dot:mega $FTPDIR/$DISTARC
         then retry
         fi
-        run tar xvf $TARFILE
+       if is ! $CLIVERSION 6
+       then
+               run tar x${tarverbosity}f $DISTARC
+       else
+               run unzip $unzipverbosity $unzipopts $DISTARC
+       fi
         run chmod 644 *
         run chmod 755 .

         # verify the contents
-        CMD="uvscan --version --dat ."
+       # this will create runtime.dat too
+        # we use --decompress to speed up future runs...
+        CMD="uvscan --version --dat . --decompress"
         say "> $CMD"
         if ! OUT=`$CMD 2>&1`
         then    retry
@@ -280,21 +415,19 @@
                 s/^/# /;/@MM/s/$/ <--/' readme.txt
 esac
 # remove some crap
-run rm -f *.diz *.exe *.ini *.lst *.tar *.txt
+run rm -f *.diz *.exe *.ini *.lst *.tar *.txt *.zip

-# do remaining part of initial setup
-case $INIT in
-yes)    for file in $DATFILES
-        do
-                run rm -f $PREFIX/$file
-                run ln -s $LINKREL/$file $PREFIX/$file
-        done
-esac
+# Make sure symlinks are in place
+for file in $DATFILES
+do
+       run rm -f $PREFIX/$file
+       run ln -s $LINKREL/$file $PREFIX/$file
+done

 # update the current version link
 run cd $DATDIR
-run ln -s $VERSION $VERSION/$LINKNAME
-run mv $VERSION/$LINKNAME .
+run ln -s $NEWVER $NEWVER/$LINKNAME
+run mv $NEWVER/$LINKNAME .

 # maybe delete old dat files
 case $DELETE in


##############################################################################
# diff -u lib/mcafee-wrapper.47911 lib/mcafee-wrapper
--- lib/mcafee-wrapper.47911    2010-04-15 10:33:07.000000000 +0100
+++ lib/mcafee-wrapper  2010-04-10 23:23:36.000000000 +0100
@@ -33,6 +33,7 @@
 # Then tweaked for heron by JKF again
 # Then tweaked for McAfee by JKF
 # Modified (badly!) by SEP398 to work with the update script
+# Modified by MJMM to exclude uvscan v6 (different output parsing required)

 PackageDir=$1
 shift
@@ -43,7 +44,14 @@
 export LD_LIBRARY_PATH

 if [ "x$1" = "x-IsItInstalled" ]; then
-  [ -x ${PackageDir}/$prog ] && exit 0
+
+  #first check if the excutable exists...
+  [ -x ${PackageDir}/$prog ] || exit 1
+
+  #second check if it is pre-v6 (using different output string)
+  ${PackageDir}/$prog --version | grep "Virus data file v" > /dev/null
+  [ $? = 0 ] && exit 0
+
   exit 1
 fi




#####################################################################################
New file: lib/mcafee6-wrapper
# cat lib/mcafee6-wrapper
#!/bin/sh

#   MailScanner - SMTP E-Mail Virus Scanner
#   Copyright (C) 2001  Julian Field
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
02111-1307  USA
#
#   The author, Julian Field, can be contacted by email at
#      Jules at JulianField.net
#   or by paper mail at
#      Julian Field
#      Dept of Electronics & Computer Science
#      University of Southampton
#      Southampton
#      SO17 1BJ
#      United Kingdom
#

# JKF Wrapper Sophos programs with the correct LD_LIBRARY_PATH
# Modified for solaris by CJG
# Then tweaked for heron by JKF again
# Then tweaked for McAfee by JKF
# Modified (badly!) by SEP398 to work with the update script
#
# MJMM Copied as mcafee6-wrapper for handle uvscan v6.0+
# MJMM Updated to detect v6 (different output parsing required)

PackageDir=$1
shift
prog=uvscan # `basename $0`
datDIR=$PackageDir

LD_LIBRARY_PATH=$PackageDir
export LD_LIBRARY_PATH

if [ "x$1" = "x-IsItInstalled" ]; then

  #first check if the excutable exists...
  [ -x ${PackageDir}/$prog ] || exit 1

  #second check if it is v6 (using different output string)
  ${PackageDir}/$prog --version | grep "Dat set version: " > /dev/null
  [ $? = 0 ] && exit 0

  exit 1
fi

if [ -f ${PackageDir}/datfiles/current/extra.dat ]; then
  exec ${PackageDir}/$prog -d $datDIR --extra
${PackageDir}/datfiles/current/extra.dat "$@"
else
  if [ -f ${PackageDir}/extra.dat ]; then
    exec ${PackageDir}/$prog -d $datDIR --extra ${PackageDir}/extra.dat "$@"
  fi
  exec ${PackageDir}/$prog -d $datDIR "$@"
fi








Michael Miller wrote:
> Hi
>
> I was wondering if there was a date when we can expect MailScanner to
> natively support the updated McAfee uvscan anti virus scanner? uvscan
> v5.3 is now EoL as DATs are no longer being released.
>
> I see a few patches were posted a few months back but they don't appear
> to have been merged into MailScanner itself. Does anyone have any more
> recent patches for uvscan 6.0.0?
>
> If there is interest in this, I can set about testing the patches and
> consolidating the parsing and the updating patches and reposting if they
> will be useful.
>
> Regards,
> Mike
>
>   


More information about the MailScanner mailing list