#!/bin/sh
#
# /secure/trip_host.sh					Boran, 01.3.01
#
# Function: Run tripwire on $target & check if files have been changed.
#           If there were changes AND auto_update is set, then update
#           the tripwire DB so that only new changes will be reported
#           next time this is run.
#           Results are printed to stdout
# Problems: ripwire will core dump on systems with large number of files.
#
# Typically another script would call this script for each remote machine
# that needs to be monitored, gather the results and send them via email
# to the sysadmin. It assumes that the following files are in $workdir:
#   tripwire.$os.$hw Tripwire binary for target, e.g. tripwire.Linux.sparc
#   tw.config.$os    Tripwire config for target, e.g. tw.config.Linux
#   tw.db_$target    Tripwire database for $target (for '-check' mode)
#
# History:   
#  12.7.00 sb <2> Check for filenames with metacharacters to stop an attacker
#             executing commands on our host with appropriate file name.
#             Thanks: Ralf Laue [ralf.laue@virbus.de]
#  26.4.00 sb Old script resurrected, fixed and tested on 
#             Solaris7+8/sparc, RH6.1/sparc, OpenBSD2.6/sparc.
#####################################################################

##---------- initialise variables -------
workdir='/secure/tripwire'
twdb='/secure/tw/databases';
#quiet='-q'
quiet=''
config="tw.config"
arg1="$1";
arg2="$2";
auto_update='YES';
scp="/usr/local/bin/scp -pq"
ssh="/usr/local/bin/ssh -n -q -x"
tripwire="./tripwire -i 2"
temp=$0.$$;
errs=$0.err.$$;

USAGE="USAGE: $0  [-h | -help | -initialise | -check] TARGET_HOST";

if [ "$arg2" != "" ] ; then
    target="$arg2";
else
    echo $USAGE
    exit 1;
fi

if   [ "$arg1" = "-initialise" ]  ; then mode="-initialise";
elif [ "$arg1" = "-init" ]        ; then mode="-initialise";
elif [ "$arg1" = "-check" ]       ; then mode="-check";
elif [ "$arg1" = "-help" ]        ; then echo $USAGE; exit 1;
elif [ "$arg1" = "-h" ]           ; then echo $USAGE; exit 1;
else
    echo "Your must select an option -initialise or -check."
    echo $USAGE
    exit 1;
fi

##---------- functions -------
check_err () {
    if [ $* -ne 0 ] ; then
    	echo "SCRIPT $0 ABORTED: error."
    	exit 1;
    fi
}

# Check connection to $target
$ssh $target date >/dev/null
if [ $? -ne 0 ] ; then
    echo "  ==> SCRIPT $0 ABORTED: cannot execute remote commands on $target."
    exit 1;
fi

cd $workdir;

##------ copy necessary files to $target, including 
##------ appropriate binary
$ssh $target "mkdir /secure; mkdir /secure/tw; mkdir $twdb;" >/dev/null 2>&1
os=`$ssh $target uname -s`
hw=`$ssh $target uname -m`
$scp tripwire.$os.$hw $config.$os $target:/secure/tw
check_err "$?";
$ssh $target "cd /secure/tw; mv tripwire.$os.$hw tripwire; mv $config.$os $config"
check_err "$?";

if [ "$mode" = "-initialise" ] ; then
  ## Initialise, upload db & wipe on target
  $ssh $target "cd /secure/tw; $tripwire -c $config $quiet -initialise" 2>$errs
  myerr=$?;
  ## Inform of all errors except missing files (since we use
  ## a general config for several machines)
  if [ -f $errs ] ; then cat $errs |egrep -v "No such file"; rm $errs; fi
  check_err "$myerr";
  $scp $target:$twdb/tw.db_$target .    ; check_err "$?";
  $ssh $target "rm -rf $twdb /secure/tw"; check_err "$?";

elif [ "$mode" = "-check" ] ; then
  ##--- Checking: Download db, check for changes, update,
  ##--- upload new db and wipe binaries/db on target

  ## Download db
  $scp tw.db_$target $target:$twdb        ; check_err "$?";
  ## Run tripwire
  #$ssh $target "cd /secure/tw; $tripwire $quiet -c $config -d $twdb/tw.db_$target" |tee $temp
  $ssh $target "cd /secure/tw; $tripwire $quiet -c $config -d $twdb/tw.db_$target" 2>$errs |tee $temp
  ## Inform of all errors except missing files (since we use
  ## a general config for several machines)
  if [ -f $errs ] ; then cat $errs |egrep -v "No such file"; rm $errs; fi

  ## If any changes were reported, detect then and reinitialise:
  if [ "$auto_update" = "YES" ] ; then
    num_changes=`egrep 'changed|added|deleted' $temp|wc -l |awk '{print $1}'`;
    if [ $num_changes -gt 0 ] ; then
      ## reinit with $temp contents
      list=`egrep 'changed|added|deleted' $temp |awk '{print $9}' |tr '\n' ' '`; 
      ## <2> check for dangerous file names
      echo "$list" | egrep '(\&|\||\;|\(|\))'
      if [ $? -eq 0 ] ; then 
        echo " "; 
        echo ">>>> SECURITY ERROR <<<<<<<< "; 
        echo "Shell metacharacters in a filename for update, stopped!"; 
        echo " "; 
        exit 1; 
      fi
      echo "Updating $num_changes files: $list ...";
      $ssh $target "cd /secure/tw; $tripwire  -c $config -d $twdb/tw.db_$target -update $list" 2>$errs
      if [ -f $errs ] ; then cat $errs |egrep -v "No such file"; rm $errs; fi
      echo "Saving changed database...\c"
      $scp $target:$twdb/tw.db_$target .  ; check_err "$?";
      echo "done"
    fi
  fi
  rm $temp;
  # Cleanup remote host
  $ssh $target "rm -rf $twdb /secure/tw"  ; check_err "$?";

else
  echo "Error: $0 bug: invalid mode."
  exit 1;
fi

## End 
