Mini Shell

Direktori : /proc/thread-self/root/proc/self/root/proc/thread-self/root/opt/maldetect/
Upload File :
Current File : //proc/thread-self/root/proc/self/root/proc/thread-self/root/opt/maldetect/maldet

#!/bin/bash
#
##
# Linux Malware Detect v1.4.1
#             (C) 2002-2011, R-fx Networks <proj@r-fx.org>
#             (C) 2011, Ryan MacDonald <ryan@r-fx.org>
# inotifywait (C) 2007, Rohan McGovern <rohan@mcgovern.id.au>
# This program may be freely redistributed under the terms of the GNU GPL v2
##
#

ver=1.4.1

inspath=/opt/maldetect
cnf=$inspath/conf.maldet
intcnf=$inspath/internals.conf
datestamp=`date +"%m%d%y-%H%M"`


pub=1
user=`whoami`
userdir="$(cat /etc/passwd | grep "^$user:" | cut -d: -f6)"
quardir="$userdir/quarantine"

sessdir="$userdir/tmp/maldet/session"
tmpdir="$userdir/tmp/maldet/tmp"
hex_fifo="$userdir/tmp/maldet/hexfifo"
logf="$userdir/tmp/maldet/event_log"

header() {
	echo "Linux Malware Detect v$ver"
	echo "            (C) 2002-2011, R-fx Networks <proj@r-fx.org>"
	echo "            (C) 2011, Ryan MacDonald <ryan@r-fx.org>"
    echo "inotifywait (C) 2007, Rohan McGovern <rohan@mcgovern.id.au>"
	echo "This program may be freely redistributed under the terms of the GNU GPL v2"
	echo ""
}


if [ -f "$cnf" ] && [ ! "$cnf" == "" ]; then
   source $cnf
else
   header
   echo "maldet($user:$$): {glob} $cnf not found, aborting."
   exit 1
fi

if [ -f "$intcnf" ] && [ ! "$intcnf" == "" ]; then
   source $intcnf
else
   header
   echo "maldet($user:$$): {glob} $intcnf not found, aborting."
   exit 1
fi

if [ "$(whoami)" == "root" ] && [ ! "$1" == "--update" ]; then
  
  echo "scanning as the root user is currently disabled."
  exit 1
  
fi


mkdir -p $quardir >> /dev/null 2>&1
mkdir -p $sessdir >> /dev/null 2>&1
mkdir -p $tmpdir >> /dev/null 2>&1
mkdir -p $cldir >> /dev/null 2>&1
touch $logf

# commented out to avoid tripwire alarms
#echo $ver > $lmd_verf

# we don't strictly NEED wget to do a scan - commented this check out
#if [ -z "$wget" ]; then
#	header
#	echo "could not find required binary wget, aborting."
#	exit 1	
#fi

if [ -z "$md5sum" ]; then
	header
	echo "could not find required binary md5sum, aborting."
	exit 1	
fi

if [ -z "$od" ]; then
	header
	echo "could not find required binary od, aborting."
	exit 1	
fi

if [ -z "$find" ]; then
	header
	echo "could not find required binary find, aborting."
	exit 1	
fi

if [ -z "$perl" ]; then
	header
	echo "could not find required binary perl, aborting."
	exit 1	
fi


if [ -z "$EDITOR" ]; then
	defedit=`which nano 2> /dev/null`
	if [ -z "$defedit" ]; then
		EDITOR=vi
	else
		EDITOR=nano
	fi
fi

if [ "$hex_fifo_scan" == "1" ]; then
 mkfifo=`which mkfifo 2> /dev/null`
 if [ -f "$mkfifo" ] && [ ! -p "$hex_fifo" ]; then
	$mkfifo -m 666 $hex_fifo
 fi
fi

usage_short() {
cat <<EOF
signature set: $def_ver
usage maldet [-h|--help] [-l|--log] [-e|--report] [-p|--purge] [-c|--checkout]
[-b|--background] [-m|--monitor] [-k|--kill-monitor] [-a|--scan-all] [-r|--scan-recent]
[-q|--quarantine] [-s|--restore] [-n|--clean] [-u|--update] [-d|--update-ver]
EOF
}

usage_long() {
cat<<EOF
signature set: $def_ver
usage $0 [ OPTION ]
    -b, --background
      Execute operations in the background, ideal for large scans
      e.g: maldet -b -r /home/?/public_html 7
	
    -r, --scan-recent PATH DAYS
       Scan files created/modified in the last X days (default: 7d, wildcard: ?)
       e.g: maldet -r /home/?/public_html 2

    -a, --scan-all PATH
       Scan all files in path (default: /home, wildcard: ?)
       e.g: maldet -a /home/?/public_html

    -l, --log
       View maldet log file events

    -e, --report SCANID email
       View scan report of most recent scan or of a specific SCANID and optionally
       e-mail the report to a supplied e-mail address
       e.g: maldet --report
       e.g: maldet --report list
       e.g: maldet --report 050910-1534.21135
       e.g: maldet --report SCANID user@domain.com

    -s, --restore FILE|SCANID
       Restore file from quarantine queue to orginal path or restore all items from
       a specific SCANID
       e.g: maldet --restore /opt/maldetect/quarantine/config.php.23754
       e.g: maldet --restore 050910-1534.21135

    -q, --quarantine SCANID
       Quarantine all malware from report SCANID
       e.g: maldet --quarantine 050910-1534.21135

    -n, --clean SCANID
       Try to clean & restore malware hits from report SCANID
       e.g: maldet --clean 050910-1534.21135

    -co, --config-option VAR1=VALUE,VAR2=VALUE,VAR3=VALUE
       Set or redefine the value of conf.maldet config options
       e.g: maldet --config-option email_addr=you@domain.com,quar_hits=1

    -p, --purge
       Clear logs, quarantine queue, session and temporary data.
EOF
}

eout() {
arg=$1
stdout=$2
appn=maldet
	if [ ! -f "$logf" ]; then
		touch $logf
	fi
	logf_size=`$wc -l $logf | awk '{print$1}'`
	if [ "$logf_size" -ge "20000" ]; then
                trim=1000
                printf "%s\n" "$trim,${logf_size}d" w | ed -s $logf
	fi
        if [ ! "$arg" == "" ]; then
                echo "$(date +"%b %d %H:%M:%S") $(hostname -s) $appn($$): $arg" >> $logf
		if [ ! -z "$stdout" ]; then
			echo "$appn($$): $arg"
		fi
        fi
}

trap_exit() {
	if [ "$svc" == "m" ]; then
		echo
		eout "{glob} monitor interrupt by user, sending kill." 1
		monitor_kill
		exit
	elif [ "$svc" == "a" ] || [ "$sv" == "r" ]; then
		echo
		gen_report
		if [ ! "$tot_hit" == "0" ]; then
                    if [ "$suppress_cleanhit" == "1" ] && [ ! "$tot_hit" == "$cl_hit" ]; then
                       alert file $nsess
                    elif [ "$suppress_cleanhit" == "0" ]; then
                       alert file $nsess
                    fi
		fi
		mv $scan_session $nsess_hits
		rm -f $find_results $scan_session
		eout "{glob} scan interrupt by user, aborting scan..." 1
		eout "{scan} scan report saved, to view run: mal-scan $user --report $datestamp.$$" 1
		if [ "$quar_hits" == "0" ] && [ ! "$tot_hit" == "0" ]; then
		  eout "{glob} quarantine is disabled! set quar_hits=1 in conf.maldet or to quarantine results run: mal-scan $user -q $datestamp.$$" 1
		fi
		exit
	fi
}

clean() {
file="$1"
hitname="$2"
v="$3"
sh_hitname=`echo $hitname | sed -e 's/{HEX}//' -e 's/{MD5}//' | tr '.' ' ' | awk '{print$1"."$2"."$3}'`
if [ -d "$cldir" ] && [ "$quar_clean" == "1" ] && [ -f "$file" ]; then
	if [ -f "$cldir/$sh_hitname" ] && [ -f "$file.info" ]; then
	        file_path=`cat $file.info | awk '{print$4}'`
		eout "{clean} restoring $file for cleaning attempt" $v
		restore "$file" >> /dev/null 2>&1
		eout "{clean} trying to clean $file_path with $sh_hitname rule" $v
		$(cat $cldir/$sh_hitname) $file_path
		eout "{clean} rescanning $file_path for malware hits" $v
		cleanst="1"
		scan_stage1 "$file_path" >> /dev/null 2>&1
		unset cleanst
		if [ -f "$file_path" ]; then
			echo "$file_path" >> $sessdir/clean.$$
			echo "$file_path" >> $tmpdir/.clean.alltime
			eout "{clean} clean successful on $file_path" $v
		else
			eout "{clean} clean failed on $file_path and returned to quarantine" $v
		fi
	elif [ -f "$cldir/$sh_hitname" ] && [ -f "$file" ]; then
	        file_path="$file"
		eout "{clean} trying to clean $file with $sh_hitname rule" $v
		$(cat $cldir/$sh_hitname) $file_path
		eout "{clean} scanning $file for malware hits" $v
		cleanst="1"
		unset clean_failed
		scan_stage1 "$file_path" 1 >> /dev/null 2>&1
		unset cleanst
		if [ "$clean_failed" == "1" ]; then
			eout "{clean} clean failed on $file" $v
		else
			echo "$file" >> $sessdir/clean.$$
			echo "$file_path" >> $tmpdir/.clean.alltime
			eout "{clean} clean successful on $file" $v
		fi
	fi
else
	eout "file path error on $file, aborting." $v
	exit
fi
}

restore() {
 file="$1"
 fname=`basename $file`
 if [ -f "$quardir/$file" ] && [ -f "$quardir/$file.info" ]; then
	file_owner=`cat $quardir/$file.info | awk '{print$1}'`
	file_group=`cat $quardir/$file.info | awk '{print$2}'`
	file_mode=`cat $quardir/$file.info | awk '{print$3}'`
	file_path=`cat $quardir/$file.info | awk '{print$4}'`
	chown $file_owner.$file_group "$quardir/$file" >> /dev/null 2>&1
	chmod $file_mode "$quardir/$file" >> /dev/null 2>&1
	mv -f "$quardir/$file" "$file_path"
	eout "{restore} quarantined file $file restored to $file_path" 1
 elif [ -f "$file" ] && [ -f "$file.info" ]; then
        file_owner=`cat $file.info | awk '{print$1}'`
        file_group=`cat $file.info | awk '{print$2}'`
        file_mode=`cat $file.info | awk '{print$3}'`
        file_path=`cat $file.info | awk '{print$4}'`
        chown $file_owner.$file_group "$file" >> /dev/null 2>&1
        chmod $file_mode "$file" >> /dev/null 2>&1
        mv -f "$file" "$file_path"
        eout "{restore} quarantined file $file restored to $file_path" 1
 else
	eout "{restore} invalid file or could not be found" 1
 fi
}

restore_hitlist() {
hitlist="$sessdir/session.hits.$1"
if [ -f "$hitlist" ]; then
 val_aquar=`tail -n1 $hitlist | awk '{print$5}'`
 val_mquar=`tail -n1 $hitlist | awk '{print$3}'`
 if [ "$val_aquar" ]; then
  for file in `cat $hitlist | awk '{print$5}'`; do
        if [ -f "$file" ]; then
                restore $file
        fi
  done
 elif [ "$val_mquar" ]; then
  for file in `cat $hitlist | awk '{print$3}'`; do
        quar_file=`cat $logf | grep -w "$file" | tail -n1 | awk '{print$12}' | tr -d "'"`
        restore $quar_file
  done
 else
	eout "{restore} could not find a valid hit list to restore." 1
 fi
fi
}

clean_hitlist() {
hitlist="$sessdir/session.hits.$1"
if [ -f "$hitlist" ]; then
 for file in `cat $hitlist | awk '{print$3}'`; do
	if [ -f "$file" ]; then
          hitname=`cat $hitlist | grep $file | awk '{print$1}'`
	  clean "$file" "$hitname" "$1"
	else
          hitname=`cat $hitlist | grep $file | awk '{print$1}'`
	  quarfile=`cat $hitlist | grep $file | awk '{print$5}'`
	  clean "$quarfile" "$hitname" "$1"
	fi
 done
else
	eout "{clean} invalid SCANID, aborting." 1
	exit
fi
}

quar_hitlist() {
hitlist="$sessdir/session.hits.$1"
if [ -f "$hitlist" ]; then
 for file in `cat $hitlist | awk '{print$3}'`; do
  if [ -f "$file" ]; then
	file_owner=`stat -c "%U" "$file"`
	file_group=`stat -c "%G" "$file"`
	file_mode=`stat -c "%a" "$file"`
	if [ "$pub" == "1" ]; then
		chattr -ia "$file" >> /dev/null 2>&1
		chmod 400 "$file"
	else
		chattr -ia "$file"
		chmod 000 "$file"
	fi
	file_name=`basename "$file"`
	file_namewc=`echo $file_name | $wc -m`
	rnd="$RANDOM"
	mv "$file" "$quardir/$file_name.$rnd"
	echo "$file_owner $file_group $file_mode $file" > $quardir/$file_name.$rnd.info
	eout "{quar} malware quarantined from '$file' to '$quardir/$file_name.$rnd'" 1
	echo "$file => $quardir/$file_name.$rnd" >> $tmpdir/.quar.alltime    
	if [ "$quar_susp" == "1" ]; then
		quar_susp "$file"
	fi
	if [ "$quar_clean" == "1" ] && [ ! "$cleanst" == "1" ]; then
		unset cleanst
		hitname=`cat $hitlist | grep $file | awk '{print$1}'`
		clean "$quardir/$file_name.$rnd" "$hitname" 1
	fi

  fi
 done
else
	echo "{quar} invalid quarantine hit list, aborting."
	exit
fi
}

view_report() {
 rid="$1"
 if [ "$rid" == "list" ]; then
	eout "Available Reports:"
	for file in `ls /opt/maldetect/sess/session.[0-9]* 2> /dev/null`; do
		SCANID=`cat $file | grep "SCAN ID"`
		TIME=`cat $file | grep "TIME"`
		if [ ! -z "$SCANID" ] && [ ! -z "$TIME" ]; then
			echo "$TIME | $SCANID"
		fi
	done
	exit
 fi
 if [ -f "$sessdir/session.$rid" ] && [ ! -z "$(echo $2 | grep '\@')" ]; then
	cat $sessdir/session.$rid | mail -s "$email_subj" $2
	eout "{report} report ID $rid sent to $2" 1
	exit
 fi
 if [ "$rid" == "" ] && [ -f "$sessdir/session.last" ]; then
	rid=`cat $sessdir/session.last`
	$EDITOR $sessdir/session.$rid
 elif [ -f "$sessdir/session.$rid" ]; then
	$EDITOR $sessdir/session.$rid
 else
	echo "{report} no report found, aborting."
	exit
 fi
}

view() {
	echo "Viewing last 50 lines from $logf:"
	tail -n 50 $logf
}

purge() {
	:> $logf
	rm -f $tmpdir/* $quardir/* $sessdir/*
	eout "{glob} logs and quarantine data cleared by user request (-p)" 1
}


quar_susp() {
file="$1"
user=`stat -c "%U" "$file"`
user_id=`id -u $user`
if [ ! "$user" == "" ] && [ "$user_id" -ge "$quar_susp_minuid" ]; then
	if [ -f "/scripts/suspendacct" ]; then
		if [ ! -f "/var/cpanel/suspended/$user" ]; then
		 /scripts/suspendacct $user "mal-scan $user --report $datestamp.$$" >> /dev/null 2>&1
		 eout "{quar} account $user cpanel suspended" 1
		 echo "$user" >> $sessdir/suspend.users.$$
                 echo "$user" >> $tmpdir/.susp.alltime
		fi
	else
		if [ "$(grep $user /etc/passwd | cut -d':' -f7 | grep /bin/false)" == "" ]; then
		 /usr/sbin/usermod -s /bin/false $user >> /dev/null 2>&1
		 eout "{quar} account $user suspended; set 'usermod -s /bin/false'"
                 echo "$user" >> $sessdir/suspend.users.$$
                 echo "$user" >> $tmpdir/.susp.alltime
		fi
	fi	
fi
}

quar() {
file="$1"
hitname="$2"
if [ -f "$file" ] && [ -d "$quardir" ]; then
 if [ "$quar_hits" == "1" ]; then
  file_owner=`stat -c "%U" "$file"`
  file_group=`stat -c "%G" "$file"`
  file_mode=`stat -c "%a" "$file"`
  file_name=`basename "$file"`
  file_namewc=`echo $file_name | $wc -m`
  rnd="$RANDOM"
  if [ "$quar_susp" == "1" ]; then
   quar_susp "$file"
  fi
  chattr -ia "$file"
  mv "$file" "$quardir/$file_name.$rnd"
  if [ "$pub" == "1" ]; then
   chmod 400 "$quardir/$file_name.$rnd"
  else
   chmod 000 "$quardir/$file_name.$rnd"
   chown root.root "$quardir/$file_name.$rnd"
  fi
  echo "$file_owner $file_group $file_mode $file" > $quardir/$file_name.$rnd.info
  eout "{quar} malware quarantined from '$file' to '$quardir/$file_name.$rnd'"
  echo "$file => $quardir/$file_name.$rnd" >> $tmpdir/.quar.alltime

  if [ ! -z "$scan_session" ]; then
   echo "$hitname : $file => $quardir/$file_name.$rnd" >> $scan_session
  fi

  if [ "$quar_clean" == "1" ] && [ ! "$cleanst" == "1" ]; then
   unset cleanst
   clean "$quardir/$file_name.$rnd" "$hitname"
  fi

 else
  if [ ! -z "$scan_session" ]; then
   echo "$hitname : $file" >> $scan_session
  fi
 fi
else
 eout "{quar} fatal error handling '$file'"
fi
}

scan() {
 spath="$1"
 spath=`echo $spath | tr '?' '*'`
 days=$2


 if [ ! -f "$find" ]; then
	eout "{scan} could not locate find command" 1
	exit
 fi
 if [ ! -f "$ignore_paths" ]; then
	touch $ignore_paths
	chmod 640 $ignore_paths
 elif [ ! -f "$ignore_sigs" ]; then
	touch $ignore_sigs
	chmod 640 $ignore_sigs
 fi

 if [ ! "$days" == "all" ]; then 
 val=`echo $days | grep "[[:alpha:]]"`
  if [ ! -z "$val" ]; then
	eout "{scan} days value must be numeric value in the range of 1 - 60, reverting to default (7)." 1
	days=7
  elif [ "$days" -gt "60" ]; then
	eout "{scan} days value must be numeric value in the range of 1 - 60, reverting to default (7)." 1
	days=7
  fi
 fi

 if [ ! -d $(echo $spath | tr '*' ' ' | awk '{print$1}') ] && [ ! -f $(echo $spath | tr '*' ' ' | awk '{print$1}') ]; then
	eout "{scan} invalid path $spath" 1
	exit
 fi

 scan_session=$tmpdir/.sess.$$
 find_results=$tmpdir/.find.$$
 touch $find_results
 touch $scan_session

 sigignore
 hex_sigs=`$wc -l $dat_hexstring | awk '{print$1}'`
 md5_sigs=`$wc -l $dat_md5hash | awk '{print$1}'`
 tot_sigs=$[md5_sigs+hex_sigs]
 if [ -z "$setmodsec" ]; then
	 eout "{scan} signatures loaded: $tot_sigs ($md5_sigs MD5 / $hex_sigs HEX)" 1
 fi

 if [ -f "$ignore_file_ext" ]; then
	if [ ! "$(cat $ignore_file_ext)" == "" ]; then
		for i in `cat $ignore_file_ext`; do
			if [ "$ignore_fext" == "" ]; then
				ignore_fext="! -iname *$i"
			else
				ignore_fext="$ignore_fext ! -iname *$i"
			fi
		done
	fi
 fi

 if [ "$days" == "all" ]; then
  if [ -z "$setmodsec" ]; then
	  eout "{scan} building file list for $spath, this might take awhile..." 1
  fi
  $find $spath -maxdepth $maxdepth -type f -size +${minfilesize}c -size -$maxfilesize $ignore_fext | grep -vf $ignore_paths > $find_results
 else
  if [ -z "$setmodsec" ]; then
	  eout "{scan} building file list for $spath of new/modified files from last $days days, this might take awhile..." 1
  fi
  $find $spath -maxdepth $maxdepth -type f -mtime -$days -size +${minfilesize}c -size -$maxfilesize $ignore_fext | grep -vf $ignore_paths > $find_results
 fi

 if [ ! -f "$find_results" ] || [ -z "$(cat $find_results)" ]; then
  if [ -z "$setmodsec" ]; then
	if [ "$days" == "all" ]; then
	 eout "{scan} scan returned zero results, please provide a new path." 1
	 exit
	else
	 eout "{scan} scan returned zero results, please increase days range or provide a new path." 1
	 exit
	fi
  fi
 fi

 res_col="1"
 move_to_col="echo -en \\033[${res_col}G"
 tot_files=`$wc -l $find_results | awk '{print$1}'`
 if [ -z "$setmodsec" ]; then
	 eout "{scan} file list completed, found $tot_files files..." 1
 fi
 touch $sessdir/clean.$$
 if [ ! -f "$scan_session" ]; then
      touch $scan_session
 fi

 if [ ! -z "$setmodsec" ]; then
	eout "{scan.modsec} scan of $spath in progress (id: $datestamp.$$)"
 fi
 cnt=0
 clamscan=`which clamscan 2> /dev/null`
 if [ -f "$clamscan" ] && [ "$clamav_scan" == "1" ]; then
	if [ -z "$setmodsec" ]; then
		eout "{scan} found ClamAV clamscan binary, using as scanner engine..." 1
	fi
	if [ "$string_length_scan" == "1" ]; then
		if [ -z "$setmodsec" ]; then
			eout "{scan} preprocessing file list for string length hits..." 1
			scan_strlen list "$find_results" >> /dev/null 2>&1
		fi
	fi
	if [ -d "/var/lib/clamav" ]; then
		clamav_db="-d /var/lib/clamav"
	elif [ -d "/var/clamav" ]; then
		clamav_db="-d /var/clamav"
	fi
        if [ -z "$setmodsec" ]; then
		eout "{scan} scan of $spath ($tot_files files) in progress..." 1
	fi
	for hit in `$clamscan -d $inspath/sigs/rfxn.ndb -d $inspath/sigs/rfxn.hdb $clamav_db -r --infected --no-summary -f $find_results 2> /dev/null | tr -d ':' | sed 's/.UNOFFICIAL//' | awk '{print$2":"$1}'`; do
		file=`echo $hit | tr ':' ' ' | awk '{print$2}'`
		signame=`echo $hit | tr ':' ' ' | awk '{print$1}'`
		clamsig=`echo $signame | grep -iE "HEX|MD5"`
		if [ -z "$clamsig" ]; then
			signame="{CAV}$signame"
		fi
		quar "$file" "$signame"
		if [ ! "$set_background" == "1" ]; then
        	  tot_hit=`$wc -l $scan_session | awk '{print$1}'`
	          cl_hit=`$wc -l $sessdir/clean.$$ | awk '{print$1}'`
		  if [ -z "$setmodsec" ]; then
	        	  $move_to_col && echo -n "maldet($user:$$): {scan} processing scan results for hits: $tot_hit hits $cl_hit cleaned"
		  fi
		  cnt=$tot_files
		fi
	done
 else
  for i in `cat $find_results | tr ' ' '%'`; do
   i=`echo $i | tr '%' ' '`
   cnt=$[cnt+1]
   if [ ! -f "$scan_session" ]; then
	touch $scan_session
   fi

  if [ -z "$setmodsec" ]; then
   if [ ! "$set_background" == "1" ]; then
	  tot_hit=`$wc -l $scan_session | awk '{print$1}'`
	  cl_hit=`$wc -l $sessdir/clean.$$ | awk '{print$1}'`
	  $move_to_col && echo -n "maldet($user:$$): {scan} $cnt/$tot_files files scanned: $tot_hit hits $cl_hit cleaned"
   fi
  fi
   if [ -f "$i" ]; then
    scan_stage1 "$i" >> /dev/null 2>&1
   fi
  done
 fi

  if [ -z "$setmodsec" ]; then
   echo
  fi
  tot_hit=`$wc -l $scan_session | awk '{print$1}'`
  cl_hit=`$wc -l $sessdir/clean.$$ | awk '{print$1}'`
  gen_report

  if [ ! -z "$setmodsec" ]; then
   if [ ! "$tot_hit" == "0" ]; then
	echo "0 maldet: $hitname $spath"
        eout "{scan.modsec} results returned FAIL hit found on $spath (id: $datestamp.$$)"
   else
	echo "1 maldet: OK"
        eout "{scan.modsec} results returned OK on $spath (id: $datestamp.$$)"
   fi
  else
   eout "{scan} scan completed on $spath: files $tot_files, malware hits $tot_hit, cleaned hits $cl_hit" 1
   eout "{scan} scan report saved, to view run: mal-scan $user --report $datestamp.$$" 1
   if [ "$quar_hits" == "0" ] && [ ! "$tot_hit" == "0" ]; then
    eout "{scan} quarantine is disabled! set quar_hits=1 in conf.maldet or to quarantine results run: mal-scan $user -q $datestamp.$$" 1
   fi
  fi

  if [ ! "$tot_hit" == "0" ]; then
        if [ "$suppress_cleanhit" == "1" ] && [ ! "$tot_hit" == "$cl_hit" ]; then
         alert file $nsess
        elif [ "$suppress_cleanhit" == "0" ]; then
         alert file $nsess
        fi
  fi
  mv $scan_session $nsess_hits
  rm -f $find_results $scan_session
}

scan_strlen() {
type=$1
file=$2
if [ "$string_length_scan" == "1" ] && [ "$type" == "file" ]; then
	flen=`$wc -L $file 2> /dev/null | awk '{print$1}'`
	if [ "$flen" -ge "$string_length" ]; then
		eout "{strlen} malware string length hit on $file"
		quar "$file" "{SA}stat.strlength"
	fi
elif [ "$string_length_scan" == "1" ] && [ "$type" == "list" ]; then
        list=$tmpdir/.strlen.flist.$$
        cp $file $list
        sed -i "s/'/\\\\'/g" $list
        cat $list | xargs wc -L 2> /dev/null | grep -vw total >> $list.strlen
        awk "{if (\$1>=$string_length) print\$2}" $list.strlen >> $list.hits
        for i in `cat $list.hits`; do
                if [ -f "$i" ]; then
                        eout "{strlen} malware string length hit on $i"
                        quar "$i" "{SA}stat.strlength"
                fi
        done
        rm -f $list.strlen $list.hits $list
fi
}

scan_stage1() {
 file="$1"
 clchk="$2"
 hash=`$md5sum "$file" | awk '{print$1}'`
 if  [ ! -z "$hash" ]; then
  val_hash=`grep -m1 $hash $dat_md5hash`
  if [ ! -z "$val_hash" ]; then
	md5_hit=$hash
	md5_hitname=`echo $val_hash | cut -d':' -f2`
	eout "{md5hash} malware hit $md5_hitname on $file"
	if [ "$clchk" == "1" ]; then
		clean_failed=1
	else
		quar "$file" "$md5_hitname"
	fi
	unset val_hash md5_hit md5_hitname
  else
	if [ -f "$file" ]; then
		scan_stage2 "$file" $clchk >> /dev/null 2>&1
	fi
	if [ -f "$file" ]; then
		scan_strlen file "$file" >> /dev/null 2>&1
	fi
  fi
 else
	eout "{scan} error could not read or hash $file, do we have permission?"
 fi
}

scan_stage2() {
 file="$1"
 clchk="$2"
 ftype=`file -b "$file" | egrep "core file|compressed data|archive data"`
 if [ -z "$ftype" ]; then
	if [ -p "$hex_fifo" ] && [ "$hex_fifo_scan" == "1" ]; then
                if [ "$OSTYPE" == "FreeBSD" ]; then
                        $od -v -N$hex_fifo_depth -tx1 "$file" | cut -c12-256 | tr -d ' \n' > $hex_fifo 2>&1 &
                else
                        $od -v -w64 -N$hex_fifo_depth -tx1 "$file" | cut -c9-256 | tr -d '\n ' > $hex_fifo 2>&1 &
                fi
	        val_hex=`$perl $hexmfifo_pl`
	else
                if [ "$OSTYPE" == "FreeBSD" ]; then
                        val_hex=`$perl $hexm_pl $($od -v -N$hexdepth -tx1 "$file" | cut -c12-256 | tr -d ' \n')`
                else
                        val_hex=`$perl $hexm_pl $($od -v -w$hexdepth -N$hexdepth -tx1 "$file" | tr -d '\n ')`
                fi
	fi
  if [ ! -z "$val_hex" ]; then
	hex_hit=`echo $val_hex | awk '{print$1}'`
	hex_hitname=`echo $val_hex | awk '{print$2}'`
	eout "{hexstring} malware hit $hex_hitname on $file"
        if [ "$clchk" == "1" ]; then
                clean_failed=1
	else
		quar "$file" "$hex_hitname"
	fi
	unset val_hex hex_hit hex_hitname
  fi
 fi
}

gen_report() {
if [ -f "$scan_session" ]; then
 tot_hit=`$wc -l $scan_session | awk '{print$1}'`
 nsess_hits=$sessdir/session.hits.$datestamp.$$
 echo "$datestamp.$$" > $sessdir/session.last
 nsess=$sessdir/session.$datestamp.$$
 cat >> $nsess <<EOF
malware detect scan report for $(hostname):
SCAN ID: $datestamp.$$
TIME: $(date +"%b %e %H:%M:%S %z")
PATH: $spath
EOF
if [ ! "$days" == "all" ]; then
cat >> $nsess <<EOF
RANGE: $days days
EOF
fi
cat >> $nsess <<EOF
TOTAL FILES: $tot_files
TOTAL HITS: $tot_hit
TOTAL CLEANED: $cl_hit

EOF
if [ "$quar_hits" == "0" ] && [ ! "$tot_hit" == "0" ]; then
cat >> $nsess <<EOF
NOTE: quarantine is disabled! set quar_hits=1 in conf.maldet or to quarantine results run: mal-scan $user -q $datestamp.$$
EOF
fi
 if [ "$quar_clean" -ne "0" ]; then
  if [ -f "$sessdir/clean.$$" ] && [ ! -z "$(cat $sessdir/clean.$$)" ]; then
cat >> $nsess <<EOF
CLEANED & RESTORED FILES:
$(cat $sessdir/clean.$$)

EOF
  fi
 fi
 if [ "$quar_susp" -ne "0" ]; then
   if [ -f "$sessdir/suspend.users.$$" ] && [ ! -z "$(cat $sessdir/suspend.users.$$)" ]; then
cat >> $nsess <<EOF
SUSPENDED ACCOUNTS:
$(cat $sessdir/suspend.users.$$)

EOF
   fi
 fi 
 if [ "$tot_hit" -ne "0" ]; then
  echo "FILE HIT LIST:" >> $nsess
  cat $scan_session >> $nsess
 fi
cat >> $nsess <<EOF
===============================================
Linux Malware Detect v$ver < proj@rfxn.com >
EOF
fi
}

trim_log() {
log=$1
logtrim=$2
if [ -f "$log" ]; then
  log_size=`$wc -l $log | awk '{print$1}'`
  if [ "$log_size" -gt "$logtrim" ]; then
    trim=$[logtrim/10]
    printf "%s\n" "$trim,${log_size}d" w | ed -s $log
  fi
fi
}

alert() {
type=$1
file="$2"

if [ "$email_alert" == "1" ]; then
 if [ "$type" == "file" ] && [ -f "$file" ]; then

  cat $file | $mail -s "$email_subj" $email_addr
  if [ ! "$(whoami)" == "root" ] && [ -z "$(echo $2 | grep '\@')" ]; then
	if [ -z "$setmodsec" ]; then
	  eout "{alert} sent scan report to config default $email_addr" 1
	  eout "{alert} send scan report to an alternate address with: mal-scan $user --report $datestamp.$$ you@domain.com" 1
	else
	  eout "{alert} sent scan report to config default $email_addr"
	fi
  else
	  eout "{alert} sent scan report to $email_addr" 1
  fi
 elif [ "$type" == "daily" ]; then
  rm -f $tmpdir/.daily.alert.hits $tmpdir/.daily.clean.hits $tmpdir/.daily.monitor.alert $tmpdir/.daily.susp.hits

  scan_session=`cat $sessdir/session.monitor.current`
  $tlog $scan_session daily.alert > $tmpdir/.daily.alert.hits
  $tlog $tmpdir/.clean.alltime daily.clean.alert > $tmpdir/.daily.clean.hits
  $tlog $tmpdir/.monitor.scanned.alltime daily.monitor.alert > $tmpdir/.daily.monitor.alert
  $tlog $tmpdir/.susp.alltime daily.susp.alert > $tmpdir/.daily.susp.hits

  tot_hits=`$wc -l $tmpdir/.daily.alert.hits | awk '{print$1}'`
  tot_cl=`$wc -l $tmpdir/.daily.clean.hits | awk '{print$1}'`
  tot_files=`$wc -l $tmpdir/.daily.monitor.alert | awk '{print$1}'`
  tot_susp=`$wc -l $tmpdir/.daily.susp.hits | awk '{print$1}'`

  trim_log $tmpdir/.monitor.scanned.alltime 5000
  trim_log $tmpdir/.clean.alltime 5000
  trim_log $tmpdir/.quar.alltime 5000
  trim_log $tmpdir/.susp.alltime 5000

  $tlog $sessdir/session.hits.$datestamp.$$ daily.alert >> /dev/null 2>&1
  $tlog $tmpdir/.clean.alltime daily.clean.alert >> /dev/null 2>&1
  $tlog $tmpdir/.monitor.scanned.alltime daily.monitor.alert >> /dev/null 2>&1
  $tlog $tmpdir/.susp.alltime daily.susp.alert >> /dev/null 2>&1

  if [ ! -z "$(cat $tmpdir/.daily.alert.hits)" ]; then
   tmpf=$tmpdir/.alert
   rm -f $tmpf
if [ "$tot_hits" -gt "$tot_files" ]; then
	tot_files=$tot_hits
fi
cat >> $tmpf <<EOF
malware detect $type monitor report for $(hostname):
SCAN ID: $datestamp.$$
TIME: $(date +"%b %e %H:%M:%S %z")
TOTAL FILES: $tot_files
TOTAL HITS: $tot_hits
TOTAL CLEANED: $tot_cl

EOF
if [ -f "$tmpdir/.daily.clean.hits" ] && [ ! "$tot_cl" == "0" ]; then
cat >> $tmpf <<EOF
CLEANED & RESTORED FILES:
$(cat $tmpdir/.daily.clean.hits)

EOF
fi
if [ -f "$tmpdir/.daily.susp.hits" ] && [ ! "$tot_susp" == "0" ]; then
cat >> $tmpf <<EOF
SUSPENDED ACCOUNTS:
$(cat $tmpdir/.daily.susp.hits)

EOF
fi

cat >> $tmpf <<EOF
FILE HIT LIST:
$(cat $tmpdir/.daily.alert.hits)
===============================================
Linux Malware Detect v$ver < proj@rfxn.com >
EOF
   cp $tmpf $sessdir/session.$datestamp.$$
   echo "$datestamp.$$" > $sessdir/session.last
   email_subj="$email_subj :: $type"
   cat $tmpf | $mail -s "$email_subj" $email_addr
   eout "{alert} sent $type alert to $email_addr"
   rm -f $tmpf $tmpdir/.daily.alert.hits $tmpdir/.daily.clean.hits $tmpdir/.daily.monitor.alert $tmpdir/.daily.susp.hits
  fi
 elif [ "$type" == "weekly" ]; then
  rm -f $tmpdir/.weekly.alert.hits $tmpdir/.weekly.clean.hits $tmpdir/.weekly.monitor.alert $tmpdir/.daily.susp.hits


  scan_session=`cat $sessdir/session.monitor.current`
  $tlog $scan_session weekly.alert > $tmpdir/.weekly.alert.hits
  $tlog $tmpdir/.clean.alltime weekly.clean.alert > $tmpdir/.weekly.clean.hits
  $tlog $tmpdir/.monitor.scanned.alltime weekly.monitor.alert > $tmpdir/.weekly.monitor.alert
  $tlog $tmpdir/.susp.alltime weekly.susp.alert > $tmpdir/.weekly.susp.hits

  tot_hits=`$wc -l $tmpdir/.weekly.alert.hits | awk '{print$1}'`
  tot_cl=`$wc -l $tmpdir/.weekly.clean.hits | awk '{print$1}'`
  tot_files=`$wc -l $tmpdir/.weekly.monitor.alert | awk '{print$1}'`
  tot_susp=`$wc -l $tmpdir/.weekly.susp.hits | awk '{print$1}'`

  trim_log $tmpdir/.monitor.scanned.alltime 5000
  trim_log $tmpdir/.clean.alltime 5000
  trim_log $tmpdir/.quar.alltime 5000
  trim_log $tmpdir/.susp.alltime 5000

  $tlog $sessdir/session.hits.$datestamp.$$ weekly.alert >> /dev/null 2>&1
  $tlog $tmpdir/.clean.alltime weekly.clean.alert >> /dev/null 2>&1
  $tlog $tmpdir/.monitor.scanned.alltime weekly.monitor.alert >> /dev/null 2>&1
  $tlog $tmpdir/.susp.alltime weekly.susp.alert >> /dev/null 2>&1

  if [ ! -z "$(cat $tmpdir/.weekly.alert.hits)" ]; then
   tmpf=$tmpdir/.alert
   rm -f $tmpf
if [ "$tot_hits" -gt "$tot_files" ]; then
	tot_files=$tot_hits
fi
cat >> $tmpf <<EOF
malware detect $type monitor report for $(hostname):
SCAN ID: $datestamp.$$
TIME: $(date +"%b %e %H:%M:%S %z")
TOTAL FILES: $tot_files
TOTAL HITS: $tot_hits
TOTAL CLEANED: $tot_cl

EOF
if [ -f "$tmpdir/.weekly.clean.hits" ] && [ ! "$tot_cl" == "0" ]; then
cat >> $tmpf <<EOF
CLEANED & RESTORED FILES:
$(cat $tmpdir/.weekly.clean.hits)

EOF
fi
if [ -f "$tmpdir/.weekly.susp.hits" ] && [ ! "$tot_susp" == "0" ]; then
cat >> $tmpf <<EOF
SUSPENDED ACCOUNTS:
$(cat $tmpdir/.weekly.susp.hits)

EOF
fi

cat >> $tmpf <<EOF
FILE HIT LIST:
$(cat $tmpdir/.weekly.alert.hits)
===============================================
Linux Malware Detect v$ver < proj@rfxn.com >
EOF
   echo "$datestamp.$$" > $sessdir/session.last
   cp $tmpf $sessdir/session.$datestamp.$$
   email_subj="$email_subj :: $type"
   cat $tmpf | $mail -s "$email_subj" $email_addr
   eout "{alert} sent $type alert to $email_addr"
   rm -f $tmpf $tmpdir/.weekly.alert.hits $tmpdir/.weekly.clean.hits $tmpdir/.weekly.monitor.alert $tmpdir/.weekly.susp.hits
  fi
 else
        eout "{alert} file input error, alert discarded."
 fi

fi
}

monitor_kill() {
	touch $tmpdir/stop_monitor
        inotify_pid=`pidof inotifywait`
	if [ -f "$tmpdir/monitor.pid" ]; then
	  monitor_pid=`cat $tmpdir/monitor.pid`
	fi
        kill -9 $inotify_pid $monitor_pid >> /dev/null 2>&1
        killall -9 inotifywait >> /dev/null 2>&1
        exit
}

monitor_cycle() {
 echo $$ > $tmpdir/monitor.pid
 if [ ! -f "$tmpdir/stop_monitor" ]; then
	 inotify_pid=`pidof inotifywait`
	 if [ -z "$inotify_pid" ]; then
	        eout "{mon} no inotify process found, exiting (are we a zombie process?)" 1
	        exit
	 fi
         log_size=`$wc -l $inotify_log | awk '{print$1}'`
         if [ "$log_size" -ge "$inotify_trim" ]; then
                trim=1000
                printf "%s\n" "$trim,${log_size}d" w | ed -s $inotify_log
                eout "{mon} inotify log file trimmed"
         fi
	 sleep $inotify_stime
	 monitor_check
 else
	rm -f $tmpdir/stop_monitor
	eout "{mon} monitoring terminated by user, inotify killed."
	exit
 fi
}

monitor_check() {
for file in `$tlog $inotify_log inotify | grep -E "CREATE|MODIFY|MOVED_FROM|MOVED_TO" | awk '{print$1}' | sort | uniq | tr ' ' '%'`; do
 file=`echo $file | tr '%' ' '`
 if [ -f "$file" ]; then
  sigignore 1
  echo "$file" >> $tmpdir/.monitor.scanned.alltime
  eout "{mon} inotify file scan $file"
  scan_stage1 "$file" >> /dev/null 2>&1
## CREATE,ISDIR: directory check for running inotifywait without -r
# elif [ -d "$file" ]; then
#  sigignore 1
#  eout "{mon} inotify directory scan $file"
#  find $file -maxdepth $maxdepth -type f -mmin -5 -size +${minfilesize}c -size -$maxfilesize > $tmpdir/.mmin.find.$$
#  for dirfile in `cat $tmpdir/.mmin.find.$$ | tr ' ' '%'`; do
#    dirfile=`echo $dirfile | tr '%' ' '`
#    echo "$dirfile" >> $tmpdir/.monitor.scanned.alltime
#    eout "{mon} inotify file scan $dirfile"
#    scan_stage1 "$dirfile" >> /dev/null 2>&1
#  done
#  rm -f $tmpdir/.mmin.find.$$
##
 fi
done
monitor_cycle
}

monitor_init() {
inopt="$1"
scan_session=$sessdir/session.hits.$datestamp.$$
touch $scan_session
echo "$scan_session" > $sessdir/session.monitor.current

if [ "$inopt" == "" ]; then
	eout "invalid usage of -m|--monitor, aborting." 1
	exit
fi

if [ ! -f "$inotify" ]; then
 eout "{mon} could not find inotify command" 1
 exit
fi

if [ -f "/boot/System.map-$(uname -r)" ]; then
	ksup=`grep -i inotify_ /boot/System.map-$(uname -r)`
	if [ -z "$ksup" ]; then
		eout "{mon} kernel does not support inotify(), aborting." 1
		exit
	fi
elif [ -f "/boot/config-$(uname -r)" ]; then
	ksup=`grep -m1 CONFIG_INOTIFY /boot/config-$(uname -r)`
	if [ -z "$ksup" ]; then
		eout "{mon} kernel does not support inotify(), aborting." 1
		exit
	fi
fi

inotify_pid=`pidof inotifywait`
if [ ! -z "$inotify_pid" ]; then
	eout "{mon} existing inotify process detected (try -k): $inotify_pid" 1
	exit
fi

rm -f $tmpdir/stop_monitor $tmpdir/inotifywait.pid

procs=`cat /proc/cpuinfo  | grep -c processor`
users_tot=`cat /etc/passwd | grep -ic home`
inotify_user_watches=$[inotify_base_watches*users_tot]
eout "{mon} set inotify max_user_instances to 128" 1
echo 128 > /proc/sys/fs/inotify/max_user_instances
eout "{mon} set inotify max_user_watches to $inotify_user_watches" 1
echo $inotify_user_watches > /proc/sys/fs/inotify/max_user_watches 

icnt=0
inotify_fpaths=$sessdir/inotify.paths.$$
rm -f $inotify_fpaths
touch $inotify_log
chmod 640 $inotify_log

if [ "$(echo $inopt | grep -E "users|user|USERS|USER")" ]; then
 for i in `cat /etc/passwd | cut -d':' -f1,3,6`; do
  user=`echo $i | cut -d':' -f1`
  user_id=`echo $i | cut -d':' -f2`
  user_home=`echo $i | cut -d':' -f3`
  icnt=$[icnt+1]

  if [ "$user_id" -ge "$inotify_minuid" ]; then
  if [ ! -z "$inotify_webdir" ] && [ -d "$user_home/$inotify_webdir" ]; then
	echo "$user_home/$inotify_webdir" >> $inotify_fpaths
	eout "{mon} added $user_home/$inotify_webdir to inotify monitoring array" 1
   elif [ -d "$user_home" ]; then
	echo "$user_home" >> $inotify_fpaths
	eout "{mon} added $user_home to inotify monitoring array" 1
   else
 	eout "{mon} could not find any suitable user home paths"
   fi
  fi
 done

 if [ -d "/dev/shm" ]; then
	echo "/dev/shm" >> $inotify_fpaths
	eout "{mon} added /dev/shm to inotify monitoring array" 1
 fi
 if [ -d "/var/tmp" ]; then
	echo "/var/tmp" >> $inotify_fpaths
	eout "{mon} added /var/tmp to inotify monitoring array" 1
 fi
 if [ -d "/tmp" ]; then
	echo "/tmp" >> $inotify_fpaths
	eout "{mon} added /tmp to inotify monitoring array" 1
 fi
elif [ -f "$inopt" ]; then
	tot_paths=`$wc -l $inotify_fpaths | awk '{print$1}'`
	if [ "$tot_paths" == "0" ]; then
		eout "{mon} no paths specified in $inopt, aborting." 1
		exit
	fi
        for i in `cat $inopt`; do
                if [ -d "$i" ]; then
                        eout "{mon} added $i to inotify monitoring array" 1
                        echo "$i" >> $inotify_fpaths
                else
                        eout "{mon} ignored invalid path $i" 1
                fi
        done

elif [ -d "$inopt" ] || [ "$(echo $inopt | grep -E ".*,.*")" ]; then
	for i in `echo $inopt | tr ',' '\n'`; do
		if [ -d "$i" ]; then
			eout "{mon} added $i to inotify monitoring array" 1
			echo "$i" >> $inotify_fpaths
		else
			eout "{mon} invalid path $i specified, ignoring." 1
		fi
	done
else
	eout "{mon} no valid option or invalid file/path provided, aborting." 1
	exit
fi

if [ -f "$ignore_inotify" ]; then
 cnt=`$wc -l $ignore_inotify | awk '{print$1}'`
 if [ "$cnt" > "0" ]; then
  for igfile in `cat $ignore_inotify`; do
    if [ "$igregexp" ]; then
	igregexp="$igregexp|$igfile"
    else
	igregexp="($igfile"
    fi
  done
  igregexp="$igregexp)"
  exclude="--exclude $igregexp"
 fi
fi

tot_paths=`$wc -l $inotify_fpaths | awk '{print$1}'`
eout "{mon} starting inotify process on $tot_paths paths, this might take awhile..." 1
$nice -n $inotify_nice $inotify -d -r -o $inotify_log --fromfile $inotify_fpaths $exclude --timefmt "%d %b %H:%M:%S" --format "%w%f %e %T" -m -e create,move,modify >> /dev/null 2>&1 &
sleep 2
inotify_pid=`pidof inotifywait`
if [ -z "$inotify_pid" ]; then
        eout "{mon} no inotify process found, check $inotify_log for errors." 1
	exit
else
        eout "{mon} inotify startup successful (pid: $inotify_pid)" 1
	eout "{mon} inotify monitoring log: $inotify_log" 1
        echo "$inotify_pid" > $tmpdir/inotifywait.pid
fi
monitor_cycle >> /dev/null 2>&1 &
}

checkout() { 
file="$1"
host=ftp.rfxn.com
user=anonymous
passwd=anonymous
upath=incoming

cfile="$(pwd)/$file"
if [ -f "$cfile" ]; then
	file=$cfile
fi

if [ -f "$file" ]; then

eout "{checkout} uploading $file to $host" 1

ftp -v -n -i $host << EOT
user $user@rfxn.com $passwd
prompt
cd $upath
lcd $lcd
binary
put "$file" "$RANDOM.$$.bin"
ascii
put "$file" "$RANDOM.$$.ascii"
bye
EOT

elif [ -d "$file" ]; then
	for i in `find $file -type f`; do
ftp -v -n -i $host << EOT
user $user $passwd
prompt
cd $upath
lcd $lcd
binary
put "$i" "$RANDOM.$$.bin"
ascii
put "$i" "$RANDOM.$$.ascii"
bye
EOT
	done
fi


}

sigignore() {
sil=$1
	chk=`$wc -l $ignore_sigs | awk '{print$1}'`
	if [ ! "$chk" == "0" ]; then
	   cat $dat_hexstring | grep -vf $ignore_sigs > $dat_hexstring.new
	   mv $dat_hexstring.new $dat_hexstring
	   cat $dat_md5hash | grep -vf $ignore_sigs > $dat_md5hash.new
	   mv $dat_md5hash.new $dat_md5hash
	   chmod 640 $dat_md5hash $dat_hexstring
	   if [ "$sil" == "1" ]; then
		   eout "{glob} processed $chk signature ignore entries"
	   else
		   eout "{glob} processed $chk signature ignore entries" 1
	   fi
        fi
}


lmdup() {
ofile=$tmpdir/.lmdup_vercheck.$$
tmp_inspath=/usr/local/lmd_update
rm -rf $tmp_inspath
rm -f $ofile

mkdir -p $tmp_inspath
chmod 750 $tmp_inspath

eout "{update} checking for available updates..." 1

$wget --referer="http://www.rfxn.com/LMD-$ver" -q -t5 -T5 "$lmdurl_ver" -O $ofile >> /dev/null 2>&1
if [ -s "$ofile" ]; then
	installed_ver=`echo $ver | tr -d '.'`
	current_ver=`cat $ofile | tr -d '.'`
	current_hver=`cat $ofile`
	if [ "$current_ver" -gt "$installed_ver" ]; then
		eout "{update} new version $current_hver found, updating..." 1
		$wget --referer="http://www.rfxn.com/LMD-$ver" -q -t5 -T5 "http://www.rfxn.com/downloads/maldetect-current.tar.gz" -O "$tmp_inspath/maldetect-current.tar.gz"
		if [ -f "$tmp_inspath/maldetect-current.tar.gz" ]; then
		 cd $tmp_inspath/
		 tar xfz maldetect-current.tar.gz
		 cd maldetect-*
		 chmod 750 install.sh
		 sh -c './install.sh' >> /dev/null 2>&1
		 eout "{update} completed update v$ver => v$current_hver, running signature updates..." 1
		 $inspath/maldet --update 1
		 eout "{update} update and config import completed." 1
		else
			eout "{update} could not download maldetect-current.tar.gz, please try again later." 1
			exit
		fi
	else
		eout "{update} hashing install files and checking against server..." 1
		md5sum $inspath/maldet $inspath/internals.conf $inspath/inotify/tlog $inspath/inotify/inotifywait $inspath/clean/* | awk '{print$1}' | tr '\n' ' ' | tr -d ' ' > $lmd_hashf
		ofile_hash=$tmpdir/.lmdup_hashcheck
		$wget --referer="http://www.rfxn.com/LMD-$ver" -q -t5 -T5 "$lmdurl_hash" -O $ofile_hash >> /dev/null 2>&1
		if [ -f "$ofile_hash" ]; then
			installed_hash=`cat $lmd_hashf`
			current_hash=`cat $ofile_hash`
			if [ ! "$installed_hash" == "$current_hash" ]; then
				eout "{update} version check shows latest but hash check failed, forcing update..." 1
		                $wget --referer="http://www.rfxn.com/LMD-$ver" -q -t5 -T5 "http://www.rfxn.com/downloads/maldetect-current.tar.gz" -O "$tmp_inspath/maldetect-current.tar.gz"
	        	        if [ -f "$tmp_inspath/maldetect-current.tar.gz" ]; then
	                	 cd $tmp_inspath/
	        	         tar xfz maldetect-current.tar.gz
		                 cd maldetect-*
        		         chmod 750 install.sh
		                 sh -c './install.sh' >> /dev/null 2>&1
        	        	 eout "{update} completed update v$ver => v$current_hver, running signature updates..." 1
        		         $inspath/maldet --update 1
	                	 eout "{update} update and config import completed." 1
                		else
        	                 eout "{update} could not download maldetect-current.tar.gz, please try again later." 1
	                         exit
				fi
			else
				eout "{update} latest version already installed." 1
			fi
		else
			eout "{update} latest version already installed." 1
		fi
	fi
else
	eout "{update} could not download version file from server, please try again later." 1
	exit
fi

rm -rf $tmp_inspath $ofile $ofile_hash
}

sigup() {
eout "{sigup} performing signature update check..." 1
if [ -z "$def_ver" ]; then
	eout "{sigup} could not determine signature version" 1
	def_ver=0
else
	eout "{sigup} local signature set is version $def_ver" 1
fi

if [ ! -f "$wget" ]; then
	eout "{sigup} could not locate wget command" 1
	exit
fi

tmpf="$tmpdir/.hver$$"
$wget --referer="http://www.rfxn.com/LMD-$ver" -t5 -T5 -q $defurl_ver -O $tmpf
if [ ! -f "$tmpf" ]; then
	eout "{sigup} could not download signature data from server, please try again later." 1
	exit
fi
if [ -z $(cat $tmpf) ]; then
	eout "{sigup} could not download signature data from server, please try again later." 1
	exit
fi

nver=`cat $tmpf`

if [ -f "$dat_md5hash" ]; then
	lines_md5=`cat $dat_md5hash | $wc -l | awk '{print$1}'`
else
	lines_md5=0
fi
if [ -f "$dat_hexstring" ]; then
	lines_hex=`cat $dat_hexstring | $wc -l | awk '{print$1}'`
else
	lines_hex="0"
fi

if [ ! -f "$dat_md5hash" ] || [ ! -f "$dat_hexstring" ]; then
	def_ver=2011041200000
	eout "{sigup} signature files missing or corrupted, forcing update..." 1
elif [ "$lines_md5" -lt "1000" ] || [ "$lines_hex" -lt "1000" ]; then
	def_ver=2011041200000
	eout "{sigup} signature files corrupted, forcing update..." 1
fi

if [ "$nver" != "$def_ver" ]; then
	eout "{sigup} new signature set ($nver) available" 1

	$wget --referer="http://www.rfxn.com/LMD-$ver" -t5 -T5 -q $defurl_md5hash -O $dat_md5hash
	eout "{sigup} downloaded $defurl_md5hash" 1

	$wget --referer="http://www.rfxn.com/LMD-$ver" -t5 -T5 -q $defurl_hex -O $dat_hexstring
	eout "{sigup} downloaded $defurl_hex" 1

	$wget --referer="http://www.rfxn.com/LMD-$ver" -t5 -T5 -q $defurl_hex_cav -O $dat_hex_cav
	eout "{sigup} downloaded $defurl_hex_cav" 1

	$wget --referer="http://www.rfxn.com/LMD-$ver" -t5 -T5 -q $defurl_md5_cav -O $dat_md5_cav
	eout "{sigup} downloaded $defurl_md5_cav" 1

	$wget --referer="http://www.rfxn.com/LMD-$ver" -t5 -T5 -q $defurl_cl -O $tmpdir/maldet-clean.tgz
	cd $tmpdir/
	tar xfz $tmpdir/maldet-clean.tgz
	cp -f $tmpdir/clean/* $cldir
	rm -rf $tmpdir/maldet-clean.tgz $tmpdir/clean
        eout "{sigup} downloaded $defurl_cl" 1

	cat $tmpf > $def_verf
	eout "{sigup} signature set update completed" 1
	sigignore
	hex_sigs=`$wc -l $dat_hexstring | awk '{print$1}'`
	md5_sigs=`$wc -l $dat_md5hash | awk '{print$1}'`
	tot_sigs=$[md5_sigs+hex_sigs]
	eout "{sigup} $tot_sigs signatures ($md5_sigs MD5 / $hex_sigs HEX)" 1

else
	eout "{sigup} latest signature set already installed" 1
fi

rm -f $tmpf
}

if [ -z "$1" ]; then
        header
        usage_short
else
 while [ -n "$1" ]; do
 case "$1" in
	#--mkpubpaths)
	#	if [ "$public_scan" == "1" ]; then
	#	chmod 711 $inspath/pub
	#	for user in `cat /etc/passwd | cut -d ':' -f1`; do
	#		uid=`id --user $user`
	#		if [ -z "$uid" ]; then 
	#			uid=9
	#		fi
	#		if [ -z "$pubuser_minuid" ]; then
	#			pubuser_minuid=10
	#		fi
	#		if [ "$uid" -ge "$pubuser_minuid" ] && [ ! -d "$inspath/pub/$user" ]; then
	#			mkdir -p $inspath/pub/$user/quar $inspath/pub/$user/sess $inspath/pub/$user/tmp >> /dev/null 2>&1
	#			touch $inspath/pub/$user/event_log >> /dev/null 2>&1
	#			chown -R $user.$user $inspath/pub/$user >> /dev/null 2>&1
	#			chmod 750 $inspath/pub/$user $inspath/pub/$user/quar $inspath/pub/$user/sess $inspath/pub/$user/tmp >> /dev/null 2>&1
	#			chmod 640 $inspath/pub/$user/event_log >> /dev/null 2>&1
	#			eout "{glob} created public scanning paths for user $user"
	#		fi
	#		unset uid user
	#	done
	#	exit
	#	else
	#		header
	#		echo "public scanning support not enabled in conf.maldet, aborting."
	#		exit
	#	fi
	#;;
	#--modsec)
	#	setmodsec=1
	#;;
	-co|--config-option)
		shift
		tmpco=$tmpdir/config.cli
		rm -f $tmpco
		touch $tmpco
		echo $1 | sed -e 's/--config-option //' -e 's/-co //' | tr -d ' ' | tr ',' '\n' > $tmpco
		. $tmpco
		rm -f $tmpco
	;;
	-qd)
		shift
		if [ -d "$1" ];  then
			eout "{scan} set quarantine path: $1" 1
			quardir="$1"
		fi
	;;
	-b|--background)
		set_background=1
	;;
#	--alert-daily)
#		alert daily
#	;;
#	--alert-weekly)
#		alert weekly
#	;;
#	-m|--monitor)
#		header
#		shift
#                if [ "$OSTYPE" == "FreeBSD" ]; then
#                        eout "{mon} not currently supported under FreeBSD" 1
#                else
#			svc=m
#			trap trap_exit 2
#			monitor_init "$1"
#		fi
#	;;
#	-k|--kill-monitor)
#		header
#		if [ "$OSTYPE" == "FreeBSD" ]; then
#			eout "{mon} not currently supported under FreeBSD" 1
#		else
#			eout "{mon} sent kill to monitor service" 1
#			monitor_kill
#		fi
#	;;
	-a|--scan-all)
		shift
		if [ -z "$setmodsec" ]; then
			header
		fi
		svc=a
		trap trap_exit 2
		spath="$1"
		if [ "$spath" == "" ]; then
			spath=/home
		fi
		if [ "$set_background" == "1" ]; then
			eout "{scan} launching scan of $spath to background, see $logf for progress" 1
                        scan "$spath" all >> /dev/null 2>&1 &
		else
		        scan "$spath" all
		fi
	;;
	-r|--scan-recent)
		header
		svc=r
		trap trap_exit 2
		shift
		spath="$1"
		shift
		days="$1"
		if [ -z "$spath" ]; then
			eout "{scan} no path defined" 1
			exit
		fi
		if [ -z "$days" ]; then
			days=7
		fi
                if [ "$set_background" == "1" ]; then
                        eout "{scan} launching scan of $spath changes in last ${days}d to background, see $logf for progress" 1
			scan "$spath" "$days" >> /dev/null 2>&1 &
		else
			scan "$spath" "$days"
		fi
	;;
	-l|--log)
		header
		view
	;;
	-e|--report)
		header
		shift
		view_report "$1" "$2"
	;;
	-p|--purge)
		header
		purge
	;;
	#-d|--update-ver|--update-version)
	#	header
	#	lmdup
	#;;
	-u|--update)
		shift
		if [ ! "$1" == "1" ]; then
			header
		fi
		sigup
	;;
	-s|--restore)
		header
		shift
		if [ -f "$sessdir/session.hits.$1" ]; then
			restore_hitlist "$1"
		else
			restore "$1"
		fi
	;;
	-q|--quarantine)
		header
		shift
		quar_hitlist "$1"
	;;
	-n|--clean)
		header
		shift
		clean_hitlist "$1"
	;;
	-h|--help)
		header
		usage_long
	;;
	*)
		header
		usage_short
	esac
	shift
	done
fi

Zerion Mini Shell 1.0