Subversion Repositories livecd

Rev

Rev 169 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

#!/bin/bash
#
################################################################
#
# Simple Virus Scanner GUI for 
#
# - f-prot 
# - uvscan (McAfee)
# - clamscan
#
################################################################
#
# Urs Beyerle, PSI
#
# (some parts taken from f-prot_gui.sh by Fabian Franz)
#
################################################################
#
  MyVersion=0.3.1
#
################################################################

clean_exit()
{
  rm -rf /tmp/virusscan.$$
}

trap "clean_exit" EXIT

### ------------------------------------------------------------
### definitions
### ------------------------------------------------------------

### set path
PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin"

### title
TITLE="Virus Scanner GUI $MyVersion"
MENU_TITLE="Virus Scanner GUI $MyVersion"

### scan engine list
ENGINE_LIST=""

### fprot
FPROT=$(which f-prot 2>/dev/null)
if [ $FPROT ]; then
    FPROT_NAME="F-Prot"
    FPROT_OPT="-all -ai -archive -dumb -packed -list"
    FPROT_CHECKUPDATES=/usr/local/f-prot/tools/check-updates.pl
    FPROT_ON="1"
    ENGINE_LIST="$ENGINE_LIST $FPROT_NAME $FPROT On"
    echo "f-prot found."
fi

### uvscan (McAfee)
UVSCAN=$(which uvscan 2>/dev/null)
if [ $UVSCAN ]; then
    UVSCAN_NAME="McAfee"
    UVSCAN_OPT="--secure -v -r --summary"
    UVSCAN_CHECKUPDATES=/usr/local/uvscan/update-dat
    UVSCAN_ON="1"
    ENGINE_LIST="$ENGINE_LIST $UVSCAN_NAME $UVSCAN On"
    echo "uvscan found."
fi

### clamscan (Clam)
CLAM=$(which clamscan 2>/dev/null)
if [ $CLAM ]; then
    CLAM_NAME="Clam"
    CLAM_OPT="-r"
    if [ -x /usr/bin/psi-freshclam ]; then
        CLAM_CHECKUPDATES=/usr/bin/psi-freshclam
    else
        CLAM_CHECKUPDATES="/etc/init.d/clamd status || /etc/init.d/clamd start && /usr/bin/freshclam"
    fi
    CLAM_ON="1"
    ENGINE_LIST="$ENGINE_LIST $CLAM_NAME $CLAM On"
    echo "clamscan found."
fi

### tmpdir
TMPDIR=/tmp/virusscanner.$$
TMP=$TMPDIR/dialog
mkdir -p $TMPDIR

### report dir
REPORT_DIR="/var/log/virusscanner"
mkdir -p /var/log/virusscanner

### dialog or xdialog?
DIALOG="dialog"
XDIALOG_HIGH_DIALOG_COMPAT=1
export XDIALOG_HIGH_DIALOG_COMPAT
[ -n "$DISPLAY" ] && [ -x /usr/bin/Xdialog ] && DIALOG="Xdialog"; XDIALOG="yes"

### do we have a virus scanner?
if [ ! $FPROT ] && [ ! $UVSCAN ] && [ ! $CLAM ]; then
    MESSAGE0="Please install a virus scan engine: F-prot, McAfee or clamav!"
    $DIALOG --title "$TITLE" --msgbox "$MESSAGE0" 0 0
    exit 1
fi

### need root rights!
if [ "$UID" -ne "0" ]; then
    MESSAGE0="To use this program, you need to be root"
    $DIALOG --title "$TITLE" --msgbox "$MESSAGE0" 0 0
    exit 1
fi


### ------------------------------------------------------------
### functions
### ------------------------------------------------------------


### ------------------------------------------------------------
welcome_message()
{
    WELCOME_MESSAGE=$( cat <<EOF
-------------------------------------------\n
 Welcome to $TITLE\n
-------------------------------------------\n
PLEASE NOTE: No files will be delete.\n
\n
Press OK to continue\n
EOF)
    [ $XDIALOG ] && echo $TITLE
    $DIALOG --title "$TITLE" --infobox "$WELCOME_MESSAGE" 0 0 8
    [ $? -ne 0 ] && exit
}


### ------------------------------------------------------------
find_partitions()
{
    PART_ALL=$(LC_ALL=C fdisk -l | sed 's/*//g' | egrep -v "swap|Extended|Ext." | awk '{ print $1 }' | grep "/dev/")
    PART_LIST=$(LC_ALL=C fdisk -l | sed 's/*//g' | egrep -v "swap|Extended|Ext." | awk '{ printf("%s %s-Partition off\n",$1,$6 $7 $8 $9) }' | grep "/dev/")
    # add "Select all"
    PART_LIST="$PART_LIST Select All off"
}


### ------------------------------------------------------------
choose_parts()
{
    MESSAGE2="Found partitions"
    $DIALOG --title "$TITLE" --checklist "$MESSAGE2" 0 0 0 $PART_LIST 2>$TMP
    PARTS=$(sed 's,",,g;s,//, /,g' $TMP)
    # all selected ?
    grep -q "Select" $TMP
    if [ "$?" = "0" ]; then
        PARTS=$PART_ALL
    fi
    [ $XDIALOG ] && echo "Partition(s) selected:"
    [ $XDIALOG ] && echo $PARTS
    [ -n "$PARTS" ] && FILES=""
}


### ------------------------------------------------------------
choose_dirfile()
{ 
    $DIALOG --title $TITLE --fselect "$(pwd)/" 0 0 2>$TMP
    FILES=$(cat $TMP)
    [ -n "$FILES" ] && PARTS=""
}


### ------------------------------------------------------------
choose_engine()
{
    MESSAGE_ENGINE="Available Virus Scan Engine(s)"
    $DIALOG --title "$TITLE" --checklist "$MESSAGE_ENGINE" 0 0 4 $ENGINE_LIST 2>$TMP
    # create new engine list
    ENGINE_LIST=""

    # deselect f-prot ?
    if [ $FPROT_NAME ]; then
        grep -q $FPROT_NAME $TMP
        if [ "$?" = "0" ]; then
            ENGINE_LIST="$ENGINE_LIST $FPROT_NAME $FPROT On";  FPROT_ON="1"
        else
            ENGINE_LIST="$ENGINE_LIST $FPROT_NAME $FPROT Off"; FPROT_ON=""
        fi
    fi

    # deselect uvscan ?
    if [ $UVSCAN_NAME ]; then
        grep -q $UVSCAN_NAME $TMP
        if [ "$?" = "0" ]; then
            ENGINE_LIST="$ENGINE_LIST $UVSCAN_NAME $UVSCAN On";  UVSCAN_ON="1"
        else
            ENGINE_LIST="$ENGINE_LIST $UVSCAN_NAME $UVSCAN Off"; UVSCAN_ON=""
        fi
    fi

    # deselect clamscan ?
    if [ $CLAM_NAME ]; then
        grep -q $CLAM_NAME $TMP
        if [ "$?" = "0" ]; then
            ENGINE_LIST="$ENGINE_LIST $CLAM_NAME $CLAM On";  CLAM_ON="1"
        else
            ENGINE_LIST="$ENGINE_LIST $CLAM_NAME $CLAM Off"; CLAM_ON=""
        fi
    fi
}

### ------------------------------------------------------------
define_report()
{
    DATE=$(date +"%Y-%m-%d")
    DIVIDER="------------------------------------------------------------------------------------------"
    DOTS=".........\n.........\n........."

    ### where to report
    REPORT_TMP=$REPORT_DIR/report.tmp
    rm -rf $REPORT_TMP
    touch $REPORT_TMP
    NR=$(ls $REPORT_DIR/$PREFIX* 2>/dev/null | wc -l | tr -d " ")

    if [ $FPROT_ON ]; then
        FPROT_REPORT="$REPORT_DIR/report_fprot-$DATE-$NR.txt"
        FPROT_REPORT_MIN="$REPORT_DIR/report_fprot-$DATE-$NR.min.txt"
        echo $DIVIDER > $FPROT_REPORT
        echo "F-Prot Report:" >> $FPROT_REPORT
        cat $FPROT_REPORT > $FPROT_REPORT_MIN   
    fi
    
    if [ $UVSCAN_ON ]; then
        UVSCAN_REPORT="$REPORT_DIR/report_mcafee-$DATE-$NR.txt"
        UVSCAN_REPORT_MIN="$REPORT_DIR/report_mcafee-$DATE-$NR.min.txt"
        echo $DIVIDER > $UVSCAN_REPORT
        echo "McAfee Report:" >> $UVSCAN_REPORT
        echo $DIVIDER >> $UVSCAN_REPORT
        $UVSCAN --version >> $UVSCAN_REPORT
        cat $UVSCAN_REPORT > $UVSCAN_REPORT_MIN 
    fi

    if [ $CLAM_ON ]; then
        CLAM_REPORT="$REPORT_DIR/report_clam-$DATE-$NR.txt"
        CLAM_REPORT_MIN="$REPORT_DIR/report_clam-$DATE-$NR.min.txt"
        echo $DIVIDER > $CLAM_REPORT
        echo "Clam Report:" >> $CLAM_REPORT
        echo $DIVIDER >> $CLAM_REPORT
        $CLAM --version >> $CLAM_REPORT
        cat $CLAM_REPORT > $CLAM_REPORT_MIN     
    fi
}


### ------------------------------------------------------------
report_fprot()
{
    [ $XDIALOG ] && echo -n "Creating F-Prot report... "

    # create report (normal and min)
    # normal report
    echo $DIVIDER >> $FPROT_REPORT
    echo $PART_TOSCAN >> $FPROT_REPORT
    echo $DIVIDER >> $FPROT_REPORT
    cat $REPORT_TMP >> $FPROT_REPORT
    echo $DIVIDER >> $FPROT_REPORT
    echo >> $FPROT_REPORT

    # min report
    echo $DIVIDER >> $FPROT_REPORT_MIN
    echo $PART_TOSCAN >> $FPROT_REPORT_MIN
    echo $DIVIDER >> $FPROT_REPORT_MIN
    head -n 25 $REPORT_TMP >> $FPROT_REPORT_MIN
    echo -e $DOTS >> $FPROT_REPORT_MIN
    tail -n 20 $REPORT_TMP >> $FPROT_REPORT_MIN       
    echo $DIVIDER >> $FPROT_REPORT_MIN
    grep " Infection: " $REPORT_TMP >> $FPROT_REPORT_MIN
    grep " Infection: " $REPORT_TMP
    if [ "$?" = "0" ]; then
        echo "VIRUS INFECTION FOUND !!!" >> $FPROT_REPORT_MIN
        [ $XDIALOG ] && echo "VIRUS INFECTION FOUND !!!"
        echo $DIVIDER >> $FPROT_REPORT_MIN
    fi 
    echo >> $FPROT_REPORT_MIN

    rm -f $REPORT_TMP
    touch $REPORT_TMP

    [ $XDIALOG ] && echo " done."
}


### ------------------------------------------------------------
report_uvscan()
{
    [ $XDIALOG ] && echo -n "Creating McAfee report... "
    
    # create report (normal and min)
    # normal report
    echo $DIVIDER >> $UVSCAN_REPORT
    echo $PART_TOSCAN >> $UVSCAN_REPORT
    echo $DIVIDER >> $UVSCAN_REPORT
    cat $REPORT_TMP >> $UVSCAN_REPORT
    echo $DIVIDER >> $UVSCAN_REPORT
    echo >> $UVSCAN_REPORT

    # min report
    echo $DIVIDER >> $UVSCAN_REPORT_MIN
    echo $PART_TOSCAN >> $UVSCAN_REPORT_MIN
    echo $DIVIDER >> $UVSCAN_REPORT_MIN
    head -n 10 $REPORT_TMP >> $UVSCAN_REPORT_MIN
    echo -e $DOTS >> $UVSCAN_REPORT_MIN
    tail -n 12 $REPORT_TMP >> $UVSCAN_REPORT_MIN              
    echo $DIVIDER >> $UVSCAN_REPORT_MIN
    grep " Found: " $REPORT_TMP >> $UVSCAN_REPORT_MIN
    grep " Found: " $REPORT_TMP
    if [ "$?" = "0" ]; then
        echo "VIRUS INFECTION FOUND !!!" >> $UVSCAN_REPORT_MIN
        [ $XDIALOG ] && echo "VIRUS INFECTION FOUND !!!"
        echo $DIVIDER >> $UVSCAN_REPORT_MIN
    fi 
    echo >> $UVSCAN_REPORT_MIN

    rm -f $REPORT_TMP
    touch $REPORT_TMP

    [ $XDIALOG ] && echo " done."
}


### ------------------------------------------------------------
report_clam()
{
    [ $XDIALOG ] && echo -n "Creating Clam report... "

    # create report (normal and min)
    # normal report
    echo $DIVIDER >> $CLAM_REPORT
    echo $PART_TOSCAN >> $CLAM_REPORT
    echo $DIVIDER >> $CLAM_REPORT
    cat $REPORT_TMP >> $CLAM_REPORT
    echo $DIVIDER >> $CLAM_REPORT
    echo >> $CLAM_REPORT

    # min report
    echo $DIVIDER >> $CLAM_REPORT_MIN
    echo $PART_TOSCAN >> $CLAM_REPORT_MIN
    echo $DIVIDER >> $CLAM_REPORT_MIN
    head -n 5 $REPORT_TMP >> $CLAM_REPORT_MIN
    echo -e $DOTS >> $CLAM_REPORT_MIN
    tail -n 15 $REPORT_TMP >> $CLAM_REPORT_MIN        
    echo $DIVIDER >> $CLAM_REPORT_MIN
    grep " FOUND$" $REPORT_TMP >> $CLAM_REPORT_MIN
    grep " FOUND$" $REPORT_TMP
    if [ "$?" = "0" ]; then
        echo "VIRUS INFECTION FOUND !!!" >> $CLAM_REPORT_MIN
        [ $XDIALOG ] && echo "VIRUS INFECTION FOUND !!!"
        echo $DIVIDER >> $CLAM_REPORT_MIN
    fi 
    echo >> $CLAM_REPORT_MIN

    rm -f $REPORT_TMP
    touch $REPORT_TMP

    [ $XDIALOG ] && echo " done."
}


### ------------------------------------------------------------
show_reports()
{
    ### show report 
    [ $FPROT_ON ]  && $DIALOG  --title "$TITLE: F-Prot Small Report" \
                           --textbox $FPROT_REPORT_MIN 0 0
    [ $UVSCAN_ON ] && $DIALOG --title "$TITLE: McAfee Small Report" \
                           --textbox $UVSCAN_REPORT_MIN 0 0
    [ $CLAM_ON ]   && $DIALOG --title "$TITLE: Clam Small Report" \
                           --textbox $CLAM_REPORT_MIN 0 0

    ### info about report files
    REPORT_MESSAGE="\nVirus Scan Reports can be found in $REPORT_DIR\n"
    $DIALOG --title "$TITLE" --no-close --infobox "$REPORT_MESSAGE" 0 0 5
    [ $XDIALOG ] && echo -e "$REPORT_MESSAGE"

}


### ------------------------------------------------------------
scan()
{
    if [ -z "$PARTS" -a -z "$FILES" ]; then
        MESSAGE3="Please select partition(s) or directory/file first."
        $DIALOG --title "$TITLE" --msgbox "$MESSAGE3" 0 0
        return
    fi

    if [ -z "$SCAN_WITH" ]; then
        MESSAGE_SORRY="Sorry, either no scan engine selected or available."
        $DIALOG --title "$TITLE" --msgbox "$MESSAGE_SORRY" 0 0
        return
    fi
    
    ### mount partitions
    TOSCAN=""
    for i in $PARTS; do
        mkdir -p /mnt/${i/\/dev\//}
        # already mounted?
        df $i | cut -d" " -f1 | grep -q "$i"
        if [ $? != "0" ]; then
            mount -o "ro" $i /mnt/${i/\/dev\//}
            if [ "$?" != "0" ]; then
                MESSAGE_UMOUNT="Partiton $i could not be mounted."
                $DIALOG --title "$TITLE" --msgbox "$MESSAGE_UMOUNT" 0 0
            else
                TOSCAN="$TOSCAN /mnt/${i/\/dev\//}"
            fi   
        else
            mountpoint=$( df $i | grep "$i" | awk '{ print $6 }' )
            echo "$i is already mounted at $mountpoint"
            TOSCAN="$TOSCAN $mountpoint"
        fi
    done
    TOSCAN="$TOSCAN $FILES"

    MESSAGE4="Scanning files on"
    MESSAGE5="Searching for files, that will be scanned ..."

    ### define where to report
    define_report

    ### watch $REPORT_TMP
    if [ $XDIALOG ]; then 
        # is there already a tail -F running?
        ps wwaux | grep tail | grep "$REPORT_TMP" | grep -q -v grep
        if [ "$?" != "0" ]; then
            xterm -sb -title "tail -F $REPORT_TMP" -e tail -F $REPORT_TMP &
        fi
    fi

    ### scan each partition
    for PART_TOSCAN in $TOSCAN; do

        [ $XDIALOG ] && echo "Scanning $PART_TOSCAN... "

        ### scan with FPROT
        if [ $FPROT_ON ]; then

            {   max=$(find $PART_TOSCAN -type f | wc -l )
                echo -e "XXX\nF-Prot: $MESSAGE4: $PART_TOSCAN\nXXX"
                $FPROT $FPROT_OPT -report=$REPORT_TMP $PART_TOSCAN | grep "^$PART_TOSCAN" | sed 's/->.*//g' | uniq | while read a; do count=$[count+1]; echo $[count*100/max]; done 
            } | $DIALOG --title "$TITLE" --gauge "$MESSAGE5 $PART_TOSCAN" 10 40

            report_fprot
        fi

        ### scan with UVSCAN (McAfee)
        if [ $UVSCAN_ON ]; then

            {   max=$(find $PART_TOSCAN | wc -l )
                echo -e "XXX\nMcAfee: $MESSAGE4: $PART_TOSCAN\nXXX"
                $UVSCAN $UVSCAN_OPT $PART_TOSCAN 2>/dev/null | tee $REPORT_TMP 2>/dev/null | grep "^Scanning" | grep -v "\.zip" | grep -v "\.tar" | grep -v ".\tgz" | while read a; do count=$[count+1]; echo $[count*100/max]; done 
            } | $DIALOG --title "$TITLE" --gauge "$MESSAGE5 $PART_TOSCAN" 10 40
            
            report_uvscan
        fi

        ### scan clamscan (Clam)
        if [ $CLAM_ON ]; then

            {   max=$(find $PART_TOSCAN -type f | wc -l )
                echo -e "XXX\nClam: $MESSAGE4: $PART_TOSCAN\nXXX"
                $CLAM $CLAM_OPT $PART_TOSCAN 2>/dev/null | tee $REPORT_TMP 2>/dev/null | grep "^$PART_TOSCAN" | while read a; do count=$[count+1]; echo $[count*100/max]; done 
            } | $DIALOG --title "$TITLE" --gauge "$MESSAGE5 $PART_TOSCAN" 10 40
            
            report_clam
        fi

    done

    ### unmount partitions
    for i in $PARTS; do
        umount /mnt/${i/\/dev\//} 2>/dev/null
    done

    ### show reports
    show_reports

}


### ------------------------------------------------------------
shutdown () 
{
    $DIALOG --title "$TITLE" --radiolist "Reboot or shutdown the PC?" 0 0 3 poweroff "" on reboot "" off 2>$TMP
    ACTION=$(cat $TMP)
    if [ $ACTION ]; then
        $ACTION
        exit 1
    fi
}


### ------------------------------------------------------------
quit () 
{

    # kill all tails to log files
    ps wwaux | grep tail | grep "$REPORT_TMP" | grep -v grep | awk '{ print $2 }' | while read pid; do 
        kill $pid 2>/dev/null
    done
    echo "Exit."

}


### ------------------------------------------------------------
online_update ()
{
    echo "Run online update "
    # remove old temporary dir
    rm -rf /var/tmp/f-prot
    # clamd running?
    [ -x /etc/init.d/clamd ] && /etc/init.d/clamd status >/dev/null && CALMD_WAS_RUNNING="true"
    # which update commands
    CHECKUPDATES=""
    [ "$FPROT_CHECKUPDATES" ]  && CHECKUPDATES="$CHECKUPDATES $FPROT_CHECKUPDATES ;"
    [ "$UVSCAN_CHECKUPDATES" ] && CHECKUPDATES="$CHECKUPDATES $UVSCAN_CHECKUPDATES ;"
    [ "$CLAM_CHECKUPDATES" ] && CHECKUPDATES="$CHECKUPDATES $CLAM_CHECKUPDATES ;"

    if [ -n "$DISPLAY" ]; then
        xterm -sb -e "$CHECKUPDATES echo 'Press a key to continue ...'; read -n1"
    else
        $CHECKUPDATES echo 'Press a key to continue ...'; read -n1
    fi
    # clean up
    rm -rf /var/tmp/f-prot
    [ -x /etc/init.d/clamd ] && [ ! $CALMD_WAS_RUNNING ] && /etc/init.d/clamd stop >/dev/null
}

### ------------------------------------------------------------
### Main Program
### ------------------------------------------------------------

### find partitons
find_partitions

### print welcome message
welcome_message

### menu
### ------------------------------------------------------------

MENU_1="Select partition(s)"
MENU_2="(or: Select a directory/file)"
MENU_3="Choose Scan Engine(s)"
MENU_4="Do Online-Update"
MENU_5="Start Scanning"
MENU_6="Reboot/Shutdown"
MENU_7="Quit"

while true; do

    SCAN_WITH=""
    [ $FPROT_ON ]  && SCAN_WITH=" $FPROT_NAME"
    [ $UVSCAN_ON ] && SCAN_WITH="$SCAN_WITH $UVSCAN_NAME"
    [ $CLAM_ON ] && SCAN_WITH="$SCAN_WITH $CLAM_NAME"

    $DIALOG --title "$TITLE" \
        --menu "$MENU_TITLE" 0 0 7\
        1 "$MENU_1"\
        2 "$MENU_2"\
        3 "$MENU_3" \
        4 "$MENU_4" \
        5 "$MENU_5 (with$SCAN_WITH)" \
        6 "$MENU_6" \
        7 "$MENU_7" \
        2> $TMP

    [ $? -ne 0 ] && break

    CHOICE=$(cat $TMP)

    case "$CHOICE" in
     1)
      choose_parts
      ;;
     2)
      choose_dirfile
      ;;
     3)
      choose_engine
      ;;
     4)
      online_update
      ;;
     5)
      scan
      ;;
     6)
      shutdown || break
      ;;
     7)
      break
      ;;
    esac
done

# clean up and quit
quit