#!/bin/sh
#
#     tiger - A UN*X security checking system
#     Copyright (C) 2000, 2001 Javier Fernandez-Sanguino Pea
#
#    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, 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.
#
#     Please see the file `COPYING' for the complete copyright notice.
#
# Linux/deb_checkmd5sums - 24/08/2001
#
# 09/19/2003 - jfs - Add patches provided by Nicolas Franois to 
#      greatly improve the speed and add support for diversions 
#      (Debian Bug #162589).
#      Also added some minor changes so the package in question
#      is printed when files don't match and avoid printing
#      errors related to conffiles (Debian Bug #211329)
#      
#
# TODO:
# - Consider using a single file instead of calling MD5sum
#   each time.
# - Add an option to Tiger so some directories might be excluded from this
#   check.
#
#-----------------------------------------------------------------------------
TigerInstallDir='.'


#
# Set default base directory.
# Order or preference:
#      -B option
#      TIGERHOMEDIR environment variable
#      TigerInstallDir installed location
#
basedir=${TIGERHOMEDIR:=$TigerInstallDir}

for parm
do
   case $parm in
   -B) basedir=$2; break;;
   esac
done

#
# Verify that a config file exists there, and if it does
# source it.
#
[ ! -r $basedir/config ] && {
  echo "--ERROR-- [init002e] No 'config' file in \`$basedir'."
  exit 1
}

. $basedir/config

. $BASEDIR/initdefs

#
# If run in test mode (-t) this will verify that all required
# elements are set.
#
[ "$Tiger_TESTMODE" = 'Y' ] && {
  haveallcmds MD5SUM CAT CUT SED GREP BASENAME || exit 1
  haveallfiles BASEDIR WORKDIR || exit 1
  haveallvars TESTLINK HOSTNAME
  
  message CONFIG init003c "" "$0: Configuration ok..."
  exit 0
}

#------------------------------------------------------------------------
echo
echo "# Checking md5sums of installed files"

haveallcmds MD5SUM CAT CUT SED GREP BASENAME || exit 1

# From the localepurge binary:
LOCALEDIR=/usr/share/locale
MANDIR=/usr/share/man
LOCALEPURGE=/etc/locale.nopurge
if [ -f "$LOCALEPURGE" ]
then
  LOCALENOPURGED=`for l in $($GREP ^[a-z] $LOCALEPURGE); do echo -n "$l\|"; done; echo -n "[^a-z].*"`
  SED_REMOVE_LOCALES_PURGED="/  usr\/share\/locale\/\($LOCALENOPURGED\)\//p;/  usr\/share\/locale/d"
fi
DIVERSIONS="/var/lib/dpkg/diversions"

if [ -d /var/lib/dpkg/info ] 
then
for md5file in /var/lib/dpkg/info/*md5sums
do
[ -f $md5file ] && [ ! -L $md5file  ] && {
# Note: We  do not check things in  /usr/share/doc
# to speed things up
	$GREP -v "/share/doc" "$md5file" |
# Also don't check purged locales
        $SED -e "$SED_REMOVE_LOCALES_PURGED" |
	$SED -e "s/^\(.*\)  \(.*\)/\1  \/\2/" |
	$MD5SUM -c 2>&1 | $SED -e "s/^.*md5sum: MD5 check failed for '\(.*\)'/DIFF \1/; s/^.*md5sum: can't open \(.*\)/ERR \1/" | {
		while read err file
		do
			package=`echo "$md5file" | $CUT -f 1 -d "."`
			package=`$BASENAME $package`
			case $err in
			DIFF)
				# don't check diverted now
				[ -z `$GREP -x "$file" $DIVERSIONS` ] &&
				# and conffiles should not be checked either
				[ -z `$GREP -sx "$file" /var/lib/dpkg/info/$package.conffiles` ] &&
					message ERROR lin005e "" "Installed file \`$file' checksum differs from installed package '$package'."
# TODO: Consider including the MD5sum to this message
# notice that some integrity checkers might do this already too.
				;;
			ERR)
					message ERROR lin006e "" "Cannot check file \"$file\" provided by \"$package\" since it does not exist"
				;;
			esac
		done 
	}
}
done
# check diversions
/usr/sbin/dpkg-divert --list |
# extract the file diverted, the backup file and the diverter package
$SED -e 's/diversion of \(\/.*\) to \(\/.*\) by \(.*\)$/\1;\2;\3/' | {
  saveIFS=$IFS
  IFS=";"
  while read file tofile bypackage
  do
    IFS=":" ; set X `$DPKG -S "$file" | $GREP -v "^diversion by "`
    IFS=", " ; set X $2
    while [ "$2" != "" ]
    do
      if [ "$2" = "$bypackage" ]
      then
        currentfile=$file
      else
        currentfile=$tofile
      fi
      [ -f "/var/lib/dpkg/info/$2.md5sums" ] && {
        md5pck=`$GREP "$(echo "$file\$"|$CUT -c2-)" /var/lib/dpkg/info/$2.md5sums | $CUT -f 1 -d " "`
        [ -n "$md5pck" ] && {
          if [ -f $currentfile ]
          then
            md5sum=`$MD5SUM "$currentfile" | $CUT -f 1 -d " "`
            [ "$md5pck" != "$md5sum" ] &&
              message ERROR lin005e "" "Installed file \`$currentfile' checksum differs from installed packages."
          else
            message ERROR lin006e "" "Cannot check file \"$currentfile\" provided by \"$2\" since it does not exist"
          fi
        }
      }
      shift
    done
    IFS=";"
  done

  # restore IFS
  IFS=$saveIFS
}

else
	message WARN lin006w "" "This check cannot be done since we seem not to be running on a Debian GNU/Linux system"
fi
