#!/bin/sh
#
#     tiger - A UN*X security checking system
#     Copyright (C) 2000, 2001 Javier Fernandez-Sanguino Peña
#
#    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_listeningprocs - 08/23/2001
#
# check_listeningprocs - 08/23/2001 - jfs 
#             Removed netstat (the Linux file has it) since the different
#             UNIX implementations do not shared command line parameters
#             (lsof does)
# check_listeningprocs - 04/17/2003 - jfs 
#             Use safe delete() instead of RM
# check_listeningprocs - 08/08/2003 - jfs 
#             Improved temporary file creation.
# check_listeningprocs - 09/19/2003 - jfs 
#             Allow empty okprocess and okprocessuser with the patch
#            provided by Nicolas François
#
# TODO: 
# - provide a way (based on the Linux version) to work with Netstat's
# output (in Solaris -t or -u does not work and -p does not show processes
# but net tables)
# - the 'case' statements probably need to be introduced into an 'eval'
# (this bug was reported for Debian GNU/Linux) in order for multiple
# ValidUsers/ValidProcs to work ok. Check systems/Linux/2/check_listeningprocs
# (once it has been tested it will be included here too)
#
# NOTES:
#
# - there are know problems related to services open TCP/UDP ports spuriously
# to contact the outside world. Tiger cannot distinguish these from 
# normal servers. These usually happens with servers (DNS, Samba, Squid, 
# Qmail) that open UDP listeners to receive DNS requests (this is Debian
# bug #136991)
#
# To avoid these false positives you can either:
#   1.- add these processes to the list of valid processes in the tigerrc
#       configuration file (Tiger_Listening_ValidProcs)
#
#   2.- use the ignore mechanism (new in 3.2), for example, if you get reports
#        like  this one:
# WARN The process `X' is listening on socket 35477 (UDP) on every interface.
#        with the number of the socket varying everytime add an ignore 
#        entry in the tiger.ignore configuration file with:
# 'The process `X' is listening on socket [0-9]+ (UDP) on every interface.'
#
#-----------------------------------------------------------------------------
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 CAT CUT GREP AWK SORT UNIQ LSOF || exit 1
# Lsof is needed for this program since netstat does not work
# the same across all Unix platforms
  haveallfiles BASEDIR WORKDIR || exit 1
  haveallvars TESTLINK HOSTNAME
  
  message CONFIG init003c "" "$0: Configuration ok..."
  exit 0
}

#------------------------------------------------------------------------
echo
echo "# Checking listening processes "

haveallcmds CAT LSOF GREP CUT AWK SORT UNIQ || exit 1
haveallfiles BASEDIR WORKDIR || exit 1

okprocessusers=${Tiger_Listening_ValidUsers-"root"}
okprocess=${Tiger_Listening_ValidProcs-""}

safe_temp "$WORKDIR/procs.$$" "$WORKDIR/openprocs.$$"
trap 'delete $WORKDIR/procs.$$ $WORKDIR/openprocs.$$  ; exit 1' 1 2 3 15

check_socket()
{
	proc=$1
	user=$2
	type=$3
	asocket=$4
	socket=`echo $asocket |  $CUT -f 2 -d : | $SED -e 's/-.*$//'`
	[ "$type" = "raw" ] && socket="(hex) $socket"
	address=`echo $asocket | $CUT -f 1 -d :`
	[ "$address" = "127.0.0.1" ] && address="loopback"
	[ "$address" = "0.0.0.0" -o "$address" = "00000000" -o "$address" = "*" ] && address="every"
# Should address = 127.0.0.1 be considered harmful?
# TODO: This could be an option
	case $proc in
	$okprocess)
	;;
	*)
		case $user in
		$okprocessuser) 
		[ "$address" = "every" -a "$Tiger_Listening_Every" != "N" ] && \
		message WARN lin002i "" "The process \`$proc' is listening on socket $socket ($type) on $address interface." || \
		message INFO lin002i "" "The process \`$proc' is listening on socket $socket ($type) on $address interface." 
		;;
		*) 
		[ "$address" != "127.0.0.1" ]  && {
			message WARN lin003w "" "The process \`$proc' is listening on socket $socket ($type on $address interface) is run by $user."
		} 
		;;
		esac
	;;
	esac
}

$LSOF -n > $WORKDIR/procs.$$
$CAT $WORKDIR/procs.$$ | $GREP "IPv" | 
	$GREP -v "\->" |
	$AWK '{printf("%s %s %s %s\n", $1, $3, $7, $8)}' >> $WORKDIR/openprocs.$$
# Now check for raw sockets (some trojans use them too)
$CAT $WORKDIR/procs.$$ | $GREP "raw" |
        $AWK '{printf("%s %s %s %s\n", $1, $3, $5, $7)}' >> $WORKDIR/openprocs.$$

$CAT $WORKDIR/openprocs.$$ |
$SORT | $UNIQ |
while read proc user type asocket 
do
	check_socket $proc $user $type $asocket

done 

delete $WORKDIR/procs.$$ $WORKDIR/openprocs.$$
exit 0 
