#!/bin/bash
#Copyright 2002, 2003 William Stearns <wstearns@pobox.com>
#Released under the GPL.

FBLibVer='0.3.7'

#-------------------------------------------------------------------------
#Find some crucial binaries, set some needed variables.
#-------------------------------------------------------------------------

if [ -z "$IptablesBin" -a -n "`which iptables 2>/dev/null`" ]; then
	IptablesBin=`which iptables 2>/dev/null`
fi
if [ -z "$IptablesBin" -o ! -x "$IptablesBin" ]; then
	echo "The iptables binary isn't in your path or isn't executable.  Please fix and restart.  Exiting." >&2
	exit 1
fi

[ -n "`which sudo 2>/dev/null`" ] && IptablesBin="`which sudo 2>/dev/null` $IptablesBin"
[ -z "$FBLibDir" ] && FBLibDir='/usr/lib/firebricks/'
[ -z "$FBData" ] && FBData='/var/lib/firebricks/'


#-------------------------------------------------------------------------
#If the chain exists, flush it, otherwise create it.
#-------------------------------------------------------------------------
FlushOrNewChain () {
	if [ -n "$1" ]; then
#if iptables -L -n >/dev/null 2>&1 ; then echo iptables successful ; fi
		if $IptablesBin -L $1 -n >/dev/null 2>&1 ; then	#If chain exists
			$IptablesBin -F $1 >/dev/null 2>&1
		else
			$IptablesBin -N $1 >/dev/null 2>&1
		fi
	fi
} #End of flushornewchain


#-------------------------------------------------------------------------
#If the chain exists, remove it.
#-------------------------------------------------------------------------
DestroyChain () {
	if [ -n "$1" ]; then
#if iptables -L -n >/dev/null 2>&1 ; then echo iptables successful ; fi
		if $IptablesBin -L $1 -n >/dev/null 2>&1 ; then	#If chain exists
			$IptablesBin -F $1 >/dev/null 2>&1
			$IptablesBin -X $1 >/dev/null 2>&1
		fi
	fi
} #End of flushornewchain


#-------------------------------------------------------------------------
#List which iptables modules are needed for this brick
#-------------------------------------------------------------------------
ModuleList () {
	cat $0 | grep -- '-m ' | while read OneLine ; do
		set -- $OneLine
		while [ -n "$1" ]; do
			if [ "z$1" = "z-m" -a -n "$2" ]; then
				echo $2
			fi
			shift
		done
	done | sort | uniq
}


#-------------------------------------------------------------------------
#Print some default help text to precede the module specific text.
#-------------------------------------------------------------------------
DefaultHelp () {
	cat <<EOTEXT >&2

	Quick start: use
$Me start LOG
	to simply log suspicious packets, or
$Me start DROP
	to drop them.

	The common command line parameters are:
DROP	Implement drop rules; the packet is discarded with no error message
REJECT	Drop the packet and return the default error
REJECT-host-unreach  Drop the packet and force a particular error
LOG	Log the packet to syslog.
start	Create the rule chain and link it into INPUT/OUTPUT/FORWARD
stop	Delete the rule chain and remove references in I/O/F.
replace	Replace the rules in $Me with a fresh copy, with no gaps in security.

	The less commonly used options are:
--dry-run   Just show what rules would be run, do not make any actual changes.
NONE	Implement rules with no target, i.e., accounting rules
help	Show this help text
create	Create the chain and rules, but make no references to it.
destroy Delete the rules in chain, but do not affect anything in I/O/F.
link	Just put the jumps from I/O/F.
unlink	Just remove the jumps from I/O/F.
status	Show whether the chain is in place or not.
version show module version.
insert	Put the I/O/F links at the top of those chains.
append	Put the I/O/F links at the bottom of those chains.
{other}	Anything else is treated as a -j action (another chain or target)

	All of the above can be mixed on the command line.  They are 
executed in order specified (with the exception that LOG rules are
placed before other rule types).

EOTEXT
Modules="`ModuleList`"
if [ -n "$Modules" ]; then
	echo '==== Iptables modules required ====' $Modules
fi
echo '==== Brick specific help ===='
}


#-------------------------------------------------------------------------
#Parse command line options
#-------------------------------------------------------------------------
while [ -n "$1" ]; do
	case "$1" in
	NONE)				Actions="$Actions NONE"		;;
	[Dd][Rr][Oo][Pp])		Actions="$Actions DROP"		;;
	[Rr][Ee][Jj][Ee][Cc][Tt])	Actions="$Actions REJECT"	;;
	[Rr][Ee][Jj][Ee][Cc][Tt]*)	Actions="$Actions $1"		;;
	[Ll][Oo][Gg])			Actions="LOG $Actions"		;;
	[Hh][Ee][Ll][Pp])		Tasks="$Tasks help"		;;
	[Ll][Ii][Nn][Kk])		Tasks="$Tasks link"		;;
	[Uu][Nn][Ll][Ii][Nn][Kk])	Tasks="$Tasks unlink"		;;
	[Cc][Rr][Ee][Aa][Tt][Ee])	Tasks="$Tasks create"		;;
	[Dd][Ee][Ss][Tt][Rr][Oo][Yy])	Tasks="$Tasks destroy"		;;
	[Ss][Tt][Aa][Rr][Tt])		Tasks="$Tasks create link"	;;
	[Ss][Tt][Oo][Pp])		Tasks="$Tasks unlink destroy"	;;
	[Rr][Ee][Pp][Ll][Aa][Cc][Ee])	Tasks="$Tasks renamechain create replacelinks" ;;
	[Ss][Tt][Aa][Tt][Uu][Ss])	Tasks="$Tasks status"		;;
	[Vv][Ee][Rr][Ss][Ii][Oo][Nn])	Tasks="$Tasks version"		;;
	[Aa][Pp][Ee][Nn][Dd])		AppIn=' -A '			;;
	[Ii][Nn][Ss][Ee][Rr][Tt])	AppIn=' -I '			;;
	--[Dd][Rr][Yy]-[Rr][Uu][Nn])	IptablesBin="echo $IptablesBin"	;;
	*)
		echo "Unknown action $1, treating it as a target."
		Actions="$Actions $1"
		;;
	esac
	shift
done


#-------------------------------------------------------------------------
#Set up looping variables needed to take multiple user-specifiable actions
#-------------------------------------------------------------------------
Ipt='eval for OneAction in $Actions ; do '"$IptablesBin"
Tail='`case "$OneAction" in NONE) : ;; LOG) echo "-j LOG"; [ -n "$LogAs" ] && echo "--log-prefix ${LogAs}_" ;; *) echo -j "$OneAction" | sed -e "s/REJECT-/REJECT --reject-with /" ;; esac` ; done'

#Defaults, both can be changed for a given rule by preceding it with Action='...' and/or LogAs='...'
#Actions="LOG DROP REJECT-host-unreach REJECT-host-prohib"
#LogAs='defaultlogstring'
#
#Sample usage of Ipt and Tail:
#LogAs='badstuff'	$Ipt AA BB CC $Tail
#			$Ipt DD EE FF $Tail
#Actions='NONE DROP'	$Ipt GG HH II $Tail
#Actions='NONE'		$Ipt JJ KK LL $Tail
#Leave off iptables binary at the beginning, "-j TARGET" at the end;
#Ipt and Tail handle these.


#-------------------------------------------------------------------------
#Set defaults if not already set by command line or config files.
#-------------------------------------------------------------------------
[ -z "$Actions" ] && Actions=${DefaultActions:-'NONE'}
[ -z "$AppIn" ] && AppIn=' -A '
[ -z "$Tasks" ] && Tasks='create link'
[ -z "$LogAs" ] && LogAs="FB-$Me"



