#!/bin/sh
#
#     tiger - A UN*X security checking system
#
#     Copyright (C) 2002 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.
#
# check_tcpd - 26/05/2002
#
# Tests for the existance of tcp-wrappers and changes in their configuration 
# it also determines which services are running wrapped in tcp-wrappers.
# (based on check_inetd)
#
# check_tcpd - 10/07/2003 - jfs - Remove temporary files
# check_tcpd - 08/11/2003 - jfs
#     Check for the availability of TCPD and only run the checks on inetd
#     if TCPD is available. Preliminary code for XINETD. Also check for
#     the hosts.allow and hosts.deny file permissions.
# check_tcpd - 08/08/2003 - jfs
#     Improved temporary file creation.
# check_tcpd - 06/26/2003 - jfs
#     Fixed calls to test ([]) it worked in Linux but not in other OS due
#     to -n not being implicit.
# check_tcpd - 04/23/2003 - jfs
#     Fixed requirements
# check_tcpd - 08/09/2002 - jfs
#     Added RM to dependancies.
# check_tcpd - 07/25/2002 - jfs
#     Changed TigerInstallDir to .
#
#-----------------------------------------------------------------------------
# TODO: 
#
# - This check should include checks on the _content_ of hosts.allow,
#   and hosts.deny (notice that hosts.equiv is checked for in check_rhosts)
# - it is not currently able to determine services which are compiled
# against libwrap (many in Debian GNU/Linux) and tell the user that they
# are protected this way.
# - it only uses inetd (through GEN_INETD_SETS) but could be improved to 
#   use GEN_XINETD_SETS if available.
#
#-----------------------------------------------------------------------------
#
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 SED AWK CAT GEN_INETD_SETS GREP JOIN LS SORT UNIQ RM || exit 1
  haveallfiles BASEDIR WORKDIR INETDFILE || exit 1
  
  echo "--CONFIG-- [init003c] $0: Configuration ok..."
  exit 0
}

#------------------------------------------------------------------------
echo
echo "# Performing check of services with tcp wrappers..."

haveallcmds SED AWK CAT GEN_INETD_SETS GREP JOIN LS SORT UNIQ RM || exit 1
haveallfiles BASEDIR WORKDIR INETDFILE || exit 1

saveifs=$IFS

tmpservices=$WORKDIR/sec.$$ts
tmpinetd=$WORKDIR/sec.$$in
safe_temp $tmpservices $tmpinetd

trap 'delete $tmpservices $tmpinetd; exit 1' 1 2 3 15
checkinetd ()
{
  infile=$1

  $JOIN -o 1.1 2.6 1.6 1.7 $infile $INETDFILE > $WORKDIR/cinetd.$$

# TODO: This is not used (what do we need it for?) - jfs
  __xx="`$LS -id \`$AWK '{print $3}' $WORKDIR/cinetd.$$ |
           $GREP -v internal
          \` 2>/dev/null |
         $SORT |
         $UNIQ -c |
         $SORT -rn |
         $SED -e '1q'`"
  set x $__xx
	 
  count="$2"
  size="$3"
#  tcpdpath="$4"
# Tcp-wrappers patch is configured in the systems configuration files
  tcpdpath=$TCPD

#  [ "$count" -lt 2 ] && tcpdpath=
    
  $GREP -v '^#' $infile | grep -v '^$' |
  while read currservice s p t user currbinary parm1 parms
  do
      if [ "$currbinary" = "$tcpdpath" ] ; then
       message INFO inet015i "" "Service $currservice is using tcp wrappers."
      fi
  done

  $CAT $WORKDIR/cinetd.$$ |
  while read service exppath currpath callpath
  do
    if [ -n "`echo $currpath | $GREP '?'`" ]; then
     currpath=`echo $currpath | $SED -e "s/\?//"`
    fi
    if [ -n "`echo $exppath | $GREP '?'`" ]; then
     exppath=`echo $exppath | $SED -e "s/\?//"`
    fi

    if [ "$currpath" = "$tcpdpath" -a "$currpath" != "$exppath" ] ; then
       message INFO inet014i "" "Service $service has been modified to run under tcp wrappers."
    fi

    if [ "$currpath" != "$exppath" -a  "$exppath" != "$tcpath" ]; then
	message FAIL inet016f "" "Service $service which was previously protected by tcpwrappers is now using $currpath (instead of $exppath)."
    fi
  done 
  
  delete $WORKDIR/cinetd.$$
}

check_hfileperm()
{
 for __file
 do
    getpermit $__file |
    while read _namefile _owner _group ur uw ux gr gw gx or ow ox suid sgid stk
    do
     [ "$gw" != '0' ] && \
         message WARN inet023w "" "The file $__file can be written by any user of the group $_group."
     [ "$ow" != '0' ] && \
         message FAIL inet024f "" "The file $__file can be written by any user."
     [ "$_owner" != 'root' ] && \
         message FAIL inet025f "" "The file $__file is not owned by root (owned by $owner)."
    done
 done
}

realpath="$REALPATH -d"

[ ! -n "$REALPATH" -o ! $TESTEXEC "$REALPATH" ] && realpath="echo"

[ -z "$TCPD" -o ! -e "$TCPD" ] && \
	message FAIL inet021f "" "Tcp wrappers does not seem to be installed in this system."

if [ -z "$HOSTALLOW" -o ! -e "$HOSTALLOW" ] ; then
	message FAIL inet022f "" "The hosts.allow file used by Tcp wrappers does not seem to be present in this system"
else
	check_hfileperm $HOSTALLOW
fi

if [ -z "$HOSTDENY" -o ! -e "$HOSTDENY" ] ; then
	message FAIL inet022f "" "The hosts.deny file used by Tcp wrappers does not seem to be present in this system"
else
	check_hfileperm $HOSTDENY
fi

# This piece of code compares the current inetd configuration with the
# configuration under $OS/$REL/$ARCH/inetd file (which is also generated
# with gen_inetd_sets)
haveallcmds GEN_INETD_SETS UNIQ &&
haveallfiles INETDFILE && {
    $GEN_INETD_SETS |
    while read inetd_set
    do
      inetdsrc=`$CAT $inetd_set.src`
      echo "# Analysing inetd entries from $inetdsrc"

      checkinetd $inetd_set

      delete $inetd_set $inetd_set.src
    done
  }

# Enable when GEN_XINETD_SETS is available
#
#haveallcmds GEN_XINETD_SETS UNIQ TCPD &&
#haveallfiles XINETDFILE && {
#    $GEN_XINETD_SETS |
#    while read xinetd_set
#   do
#     inetdsrc=`$CAT $xinetd_set.src`
#      echo "# Analysing xinetd entries from $xinetdsrc"
#
#      checkinetd $xinetd_set
#      delete $xinetd_set $xinetd_set.src
#    done
#  }

delete $tmpservices $tmpinetd

exit 0
