#!/bin/bash # ################################################################ # # Simple Virus Scanner GUI for # # - f-prot # - uvscan (McAfee) # - clamscan # ################################################################ # # Urs Beyerle # # (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