#!/bin/bash
#Copyright (c) 1999, William L. Stearns <wstearns@pobox.com>
#See top of Mason script for copyright and licensing information.

MASONDIR=${MASONDIR:-"/var/lib/mason/"}
MASONCONF=${MASONCONF:-"/etc/masonrc"}
MASONLIB=${MASONLIB:-"${MASONDIR}masonlib"}
if [ -f $MASONLIB ]; then
	. $MASONLIB
else
	echo Missing $MASONLIB library file.  Please get a complete copy of Mason from >/dev/stderr
	echo http://www.pobox.com/~wstearns/mason/ .  Exiting. >/dev/stderr
	exit
fi
if [ -f $MASONCONF ]; then
	. $MASONCONF
fi
checksys
checkconf


EXITCONTROL="NO"
ISLEARNING="NO"
while [ ! "${EXITCONTROL}" = "YES" ]; do
	clear
	echo "---- Mason firewall builder for Linux                         ----"
	echo "---- Learning shell for Mason.                                ----"
	echo "---- see http://www.pobox.com/~wstearns/mason/ for more info. ----"
	echo "---- William Stearns <wstearns@pobox.com>                     ----"
#FIXME - use a /var/run file to hold status
	if [ "$ISLEARNING" = "YES" ]; then
		echo Mason is currently in learn mode.
	else
		echo Mason IS NOT currently learning.
	fi
	echo
	echo BL: Begin Learning.
	echo EL: End Learning.
	echo EB: Edit Base firewall rule file.	#=> end learn
	echo EN: Edit New firewall rule file.	#=> end learn, ask to merge rulefiles when done
	echo MR: Merge Rules from new to base.
	echo CS: Change Mason settings.			#=> sigusr1 mason when done
	echo LC: Lock this terminal and display new rules.
	echo Q: Quit.
	read CHOICE
	case `echo $CHOICE |tr A-Z a-z` in
	bl)	
		echo Begin Learning.
		echo 
		flushfirewall
		runlearnfirewall
		nohup tail -f --lines=0 $PACKETLOGFILE | $MASONEXE >>$NEWRULEFILE &
		ISLEARNING="YES"
		echo Mason is now running in the background.  I will be showing the log 
		echo output.  Press Ctrl-C when you want to return to the main menu - Mason
		echo will continue to run in the background until you choose \"EL\" from the
		echo main menu.
		tail -f --lines=0 $PACKETLOGFILE $NEWRULEFILE &
		echo Press ENTER to return to the main menu
		read JUNK
		kill -9 $!
																;;
	el)
		echo End Learning.
		killall -9 tail
		killall -HUP mason
		ISLEARNING="NO"
		flushfirewall
		runstandardfirewall
																;;
	eb)
		echo Edit Base rule file.
		cp -pf $BASERULEFILE ${BASERULEFILE}.bak
		$EDITOR $BASERULEFILE
		if diff $BASERULEFILE ${BASERULEFILE}.bak >/dev/null ; then
			echo No changes made.
		else
			echo Changes made, restarting firewall
			flushfirewall
			if [ "$ISLEARNING" = "YES" ]; then
				runlearnfirewall
			else
				runstandardfirewall
			fi
		fi
																;;
	en)		
		echo Edit the new rule file.
		if [ "$ISLEARNING" = "YES" ]; then
			echo Ending the learn process.
			killall -9 tail
			killall -HUP mason
			ISLEARNING="NO"
		fi
		cp -pf $NEWRULEFILE ${NEWRULEFILE}.bak
		cat $NEWRULEFILE | sort -t '#' +1 | uniq >${NEWRULEFILE}.sorted
		cat ${NEWRULEFILE}.sorted >${NEWRULEFILE}			#This preserves the permissions of fwrules
		rm -f ${NEWRULEFILE}.sorted
		$EDITOR $NEWRULEFILE
		if diff $NEWRULEFILE ${NEWRULEFILE}.bak >/dev/null ; then
			echo No changes made.
		else
			if [ "$ISLEARNING" = "YES" ]; then
				echo Changes made, restarting firewall
				flushfirewall
				runlearnfirewall
			else
				echo Changes made, but no need to restart firewall.
			fi
		fi
																;;
	mr)
		echo Do you want to merge some, all, or none of the rules in this file
		echo to the base rule file?  Enter \"some\", \"all\", or \"none\".
		read WHATTOMERGE
		case $WHATTOMERGE in
		all)
			cp -pf $BASERULEFILE ${BASERULEFILE}.bak
			cp -pf $NEWRULEFILE ${NEWRULEFILE}.bak
			cat $NEWRULEFILE | sort -t '#' +1 | uniq >${NEWRULEFILE}.sorted
			cat ${NEWRULEFILE}.sorted >${NEWRULEFILE}			#This preserves the permissions of fwrules
			rm -f ${NEWRULEFILE}.sorted
			echo "#Rules merged from the new rule file:"	>>$BASERULEFILE
			#cat $NEWRULEFILE | sed -e 's/^/#/'				>>$BASERULEFILE #Use this version if you want to force them commented
			cat $NEWRULEFILE								>>$BASERULEFILE
			cat /dev/null >$NEWRULEFILE
			echo You will probably want to edit the base rule file next.
																	;;
		some)
			echo What string identifies the rules to merge?
			read MERGEID
			echo There are `cat $NEWRULEFILE | grep "$MERGEID" | wc -l` rules with that ID, and
			echo `cat $NEWRULEFILE | grep -v "$MERGEID" | wc -l` lines without it, `cat $NEWRULEFILE | wc -l` total.
			echo Do you want to continue \(yes/no\)?
			read YESNO
			case $YESNO in
			yes|YES|y|Y)
				cp -pf $BASERULEFILE ${BASERULEFILE}.bak
				cp -pf $NEWRULEFILE ${NEWRULEFILE}.bak
				cat $NEWRULEFILE | sort -t '#' +1 | uniq >${NEWRULEFILE}.sorted
				cat ${NEWRULEFILE}.sorted >${NEWRULEFILE}			#This preserves the permissions of fwrules
				rm -f ${NEWRULEFILE}.sorted
				echo "#Rules merged from the new rule file:"	>>$BASERULEFILE
				#cat $NEWRULEFILE | grep "$MERGEID" | sed -e 's/^/#/'	>>$BASERULEFILE
				cat $NEWRULEFILE | grep "$MERGEID"						>>$BASERULEFILE
				cat $NEWRULEFILE | grep -v "$MERGEID" >${NEWRULEFILE}.tmp
				cat ${NEWRULEFILE}.tmp >$NEWRULEFILE
				rm -f ${NEWRULEFILE}.tmp
				echo You will probably want to edit the base rule file next.
																		;;
			*)	echo Aborting merge.									;;
			esac
																	;;
		esac
																;;
	cs)
		echo Here are the non-comment lines in ${MASONCONF}:
		echo
		cat ${MASONCONF} | sed -e 's/#.*//' | grep -v '^$' | uniq
		echo
		echo Press enter to edit this file
		read JUNK
		cp -pf $MASONCONF ${MASONCONF}.bak
		$EDITOR $MASONCONF
		if diff $MASONCONF ${MASONCONF}.bak >/dev/null ; then
			echo No changes made.
		else
			if [ "$ISLEARNING" = "YES" ]; then
				echo Changes made, ignalling mason to reread configuration.
				killall -USR1 mason
			else
				echo Changes made.
			fi
		fi
																;;
	lc)
		if [ "$ISLEARNING" = "YES" ]; then
			tail -f --lines=0 $PACKETLOGFILE $NEWRULEFILE &
		fi	
		vlock
		if [ "$ISLEARNING" = "YES" ]; then
			kill -9 $!
		fi
																;;
	q)
		EXITCONTROL="YES"
		echo Exiting.  Returning to the standard firewall.
		flushfirewall
		runstandardfirewall
																;;
	*)	echo Unknown choice.  Please enter the one or two character code.
																;;
	esac

done


