
#-----------------------------------------------------------------------
# Copyright (C) 2000-2001, Jean-Sebastien Morisset <jsmoriss@mvlan.net>
#-----------------------------------------------------------------------
# $Id: security_check.sh,v 1.5 2001/09/17 21:42:37 jsmoriss Exp $
#-----------------------------------------------------------------------
#  $RCSfile: security_check.sh,v $
#   $Author: jsmoriss $
# $Revision: 1.5 $
#     $Date: 2001/09/17 21:42:37 $
#   $Locker:  $ 
#     $Name:  $
#-----------------------------------------------------------------------
#
# 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 <http://www.gnu.org/copyleft/gpl.txt>.
# 
# 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 (LICENSE file in archive) for more details.
#
#-----------------------------------------------------------------------
# README
#-----------------------------------------------------------------------
#
# A bourne shell function used by rcf; a very secure, fast, and complete
# firewall for linux <http://jsmoriss.mvlan.net/linux/rcf.html>.
#
#-----------------------------------------------------------------------
# FUNCTION
#-----------------------------------------------------------------------

Security_Check () {

	uid="0"
	gid="0"

	# Before calling this function, the PATH was prefixed with the 
	# standard binary directories. This minimizes the chance of finding
	# a bad grep or sed which are used here.
	#
	echo -n "Checking PATH for relative directories... "
	fixed_path="`echo $ORIGINAL_PATH|sed -e 's/^[^\/][^:]*//' -e 's/:[^\/][^:]*//g' -e 's/^://' -e 's/:$//'`"
	if [ "$ORIGINAL_PATH" != "$fixed_path" ]
	then
		echo "failed": failed="path"
		echo "    Your PATH variable contains relative directories (doesn't start with '/')."
		echo "    For security reasons, you should remove these directories from your PATH"
		echo "    variable permanently (usually set in /etc/profile or ~/.profile)."
		
		echo "    Original PATH=$ORIGINAL_PATH"
		echo "       Fixed PATH=$fixed_path"

		PATH="${PATH_PREFIX}:${fixed_path}"
		export PATH
	else
		echo "ok"
	fi
	unset fixed_path

	# Now that we've potentially broken the PATH variable <smile>, make
	# sure we can still get at all the binaries we'll need.
	#
	echo -n "Checking for essential binaries... "
	if [ ! "`which which 2>/dev/null`" ]
	then
		echo "failed"; failed="bin"
		echo "    Unable to locate 'which' in any PATH directory!"
	else
		# If we have a 'which', continue checking...
		#
		for bin in \
			chmod \
			cp \
			expr \
			find \
			grep \
			insmod \
			ipchains \
			ls \
			lsmod \
			mv \
			netstat \
			sed \
			sort \
			xargs
		do
			if [ ! "`which $bin 2>/dev/null`" ]
			then
				# only print failed once
				[ "$failed" != "bin" ] && echo "failed"; failed="bin"
				echo "    Unable to locate '$bin' in any PATH directory!"
			fi
		done
		unset bin

		# Easier on the brain if we use an else. :-)
		if [ "`which ip 2>/dev/null`" -o \( "`which ifconfig 2>/dev/null`" -a "`which route 2>/dev/null`" \) ]
		then
			:
		else
			# only print failed once
			[ "$failed" != "bin" ] && echo "failed"; failed="bin"
			echo "    Unable to locate 'ip' or 'ifconfig' & 'route' in any PATH directory!"
		fi
		[ "$failed" != "bin" ] && echo "ok"
	fi

	# Skip the file permission tests if we're missing binaries, etc.
	if [ "$failed" != "bin" ]
	then
		# If we have a grep, make sure it's functioning.
		echo -n "Checking for working grep... "
		if [ "`echo 'a b c' | grep '\(z\|b\) c' 2>/dev/null`" = 'a b c' ]
		then
			echo "ok"
		else
			echo "failed"; failed="bin"
		fi

		echo -n "Checking for working find... "
		find_help="`find --help 2>/dev/null`"
		if [ "`echo $find_help|sed -ne '/-uid /p'`" -a "`echo $find_help|sed -ne '/-gid /p'`" \
			-a "`echo $find_help|sed -ne '/-perm /p'`" -a "`echo $find_help|sed -ne '/-type /p'`" \
			-a "`echo $find_help|sed -ne '/-follow/p'`" ]
		then
			echo "ok"
			find_type="complete"
		else
			echo "basic (slow security file check)"
			find_type="basic"
		fi

		# If we have a sort, make sure it's functioning (older LRP distros don't have a working sort).
		echo -n "Checking for working sort... "
		if [ "`echo 'b
a' | sort 2>/dev/null | sed -n '1p'`" != "a" ]
		then
			echo "failed"; failed="bin"
			echo "    '`which sort 2>/dev/null`' is unable to sort a simple list!"
		else
			echo "ok"
		fi

		echo -n "Checking file permissions and owners"
		[ "$find_type" = "basic" -a "$SECURITY_FILE_CHECK" = "yes" ] && echo -n " (use -nsfc to skip)"
		echo -n "..."

		if [ "$SECURITY_FILE_CHECK" = "no" ]
		then
			echo " skipped"
		else
			if [ "$find_type" = "complete" ]
			then
				for file_dir in $0 $CONF ${CONF}.bak ${GROUP_DIR} ${MODULE_DIR} ${FUNCTION_DIR}
				do
					dir_perm="0700"
					case $file_dir in
						$0)	file_perm="0700" ;;
						*)	file_perm="0600" ;;
					esac
					
					[ -d "$file_dir" ] \
						&& for file in `find "$file_dir" -follow -type d \
						\( ! -uid "$uid" -o ! -gid "$gid" -o ! -perm $dir_perm \)`
					do
						[ "$failed" != "files" ] && {
							echo "failed"; failed="files"
							echo "    The owners and/or permissions of these files are incorrect."
							echo "    Please execute the following commands:"
						}
						echo "        chmod $dir_perm $file" >>/dev/stderr
						echo "        chown ${uid}:${gid} $file" >>/dev/stderr
					done

					[ -d "$file_dir" -o -f "$file_dir" ] \
						&& for file in `find "$file_dir" -follow -type f \
						\( ! -uid "$uid" -o ! -gid "$gid" -o ! -perm $file_perm \)`
					do
						[ "$failed" != "files" ] && {
							echo "failed"; failed="files"
							echo "    The owners and/or permissions of these files are incorrect."
							echo "    Please execute the following commands:"
						}
						echo "        chmod $file_perm $file" >>/dev/stderr
						echo "        chown ${uid}:${gid} $file" >>/dev/stderr
					done
				done
			else
				file_num="0"
				for file_dir in $0 $CONF ${CONF}.bak ${GROUP_DIR} ${MODULE_DIR} ${FUNCTION_DIR}
				do
					[ -d "$file_dir" -o -f "$file_dir" ] \
						&& for file in `find "$file_dir"`
					do
						file_num="`expr $file_num + 1`"
						[ "$failed" != "files" -a "$file_num" -gt "10" ] && { file_num="0"; echo -n "."; }
	
						case $file_dir in
							$0)	correct_perm="-rwx------"; chmod_perm="0700" ;;
							*)	if [ -d "$file" ]; then correct_perm="drwx------"; chmod_perm="0700";
								else correct_perm="-rw-------"; chmod_perm="0600"; fi
							;;
						esac
	
						if [ "`ls -dLln \"$file\"|\
							sed -n -e 's/^\([^ ]*\)  *[^ ]* \([^ ]*\)  *\([^ ]*\) .*$/\1 \2 \3/p'`" \
								!= "$correct_perm $uid $gid" ]
						then
							[ "$failed" != "files" ] && {
								echo "failed"; failed="files"
								echo "    The owners and/or permissions of these files are incorrect."
								echo "    Please execute the following commands:"
							}
							echo "        chmod $chmod_perm $file" >>/dev/stderr
							echo "        chown ${uid}:${gid} $file" >>/dev/stderr
						fi
					done
					unset file correct_perm chmod_perm
				done
				unset file_num
			fi
			unset file_dir
			[ "$failed" != "files" ] && echo " ok" || echo ""
		fi
	fi

	# If we've detected any error, exit here.
	if [ "$failed" ]
	then
		echo ""
		echo "These problems must be addressed before running `Sed_Basename $0` again."
		echo ""
		exit 1
	fi

	unset uid gid
}

