#!/bin/bash #echo First entry into mason-decide! #Copyright 1999-2000, William Stearns . #Given ipchains rules on stdin, allow the user to decide what to do with the rule. #- Script shouldn't care about the source of the rules. mgt feeds it a copy of newrules, then starts learning. #- Originally put in place with same newrulepolicy #- Feed mason output to this app. stderr? fed to this app or not? #stdin: rule input #stdout: send to user #&10: user terminal input #&11: accepted rules output #&12: postponed rules output #&13: mason's flag file output for exit (this script feeds !!EXIT!! to that file when user chooses quit. #cat indata | ./mason-decide 10<&1 11>accepted 12>postponed 13>flagfile #FIXME - ignore line w/ only whitespace #FIXME - should we be loading MASONLIB/CONF/running checksys, etc? almost certainly yes. #FIXME - use wrap? #Last YYYY code used: 0004, use 0005 next MASONDIR=${MASONDIR:-"/var/lib/mason/"} MASONCONF=${MASONCONF:-"/etc/masonrc"} MASONLIB=${MASONLIB:-"${MASONDIR}masonlib"} #MASONLIB=${MASONLIB:-"${MASONDIR}masonlib"} #My editor of choice (mcedit) gets quoting backwards if there is an odd number of these. if [ -f $MASONLIB ]; then . $MASONLIB else #Can't use wrap here - no library to load it from. 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 sleep 10 exit 1 fi EOFREACHED='' mdcleanup () { #FIXME - this doesn't seem to catch before we get at least one rule... EXITNOW="YES" showstate 'mason-decide: exiting' if [ -n "$CURRLINE" ]; then echo "$CURRLINE" >&12 fi echo '!!EXIT!!' >&13 if type -path logger >/dev/null ; then #Give something in /var/log/messages to give Mason a kick through the last rule... logger 'Mason-decide exiting' fi COMMITTED="YES" if [ "$EOFREACHED" != "YES" ]; then while read INLINE ; do #postpone the rest echo "$INLINE" >&12 done EOFREACHED="YES" fi echo echo $0 done! IFS="$ORIGIFS" exit 0 } catchall trap mdcleanup SIGINT #Ctrl-C generates this #Problems: #Doesn't honor commentchar setting. #Doesn't deal with a mix of ipchains/ipfwadm. #Doesn't handle iptables at all. #Rules added by $0 - type header >>&11 ? #Add port to /etc/services and delete for rescan menu () { echo $ENH "Modify choices:" echo $ENH " ${KEY}E${NORM}dit manually ${KEY}E${NORM}dit the rule" echo $ENH " ${KEY}J${NORM}ot ${KEY}J${NORM}ot a note at the end of the rule" #append to the end with comment character echo $ENH " ${KEY}A${NORM}ccept change policy to ${KEY}A${NORM}ccept and commit" #place these three in baserules echo $ENH " ${KEY}D${NORM}eny change policy to ${KEY}D${NORM}eny and commit" echo $ENH " ${KEY}M${NORM}asq change policy to ${KEY}M${NORM}asquerade and commit" echo $ENH " ${KEY}R${NORM}eject change policy to ${KEY}R${NORM}eject and commit" echo $ENH "Commit choices:" echo $ENH " ${KEY}P${NORM}ostpone ${KEY}P${NORM}ostpone choice" #Append to newrules echo $ENH " ${KEY}T${NORM}hrow away ${KEY}T${NORM}hrow away line" echo $ENH " ${KEY}B${NORM}lockedhost make this host a ${KEY}B${NORM}LOCKEDHOST and delete the rule" echo $ENH " ${KEY}N${NORM}oincoming make this port a ${KEY}N${NORM}OINCOMING port and delete the rule" echo $ENH " ${KEY}C${NORM}ommit ${KEY}C${NORM}ommit to the permanent firewall set" echo $ENH " ${KEY}Q${NORM}uit postpone any remaining rules and ${KEY}Q${NORM}uit" #Feed !!EXIT!! to flag file, postpone rest of the rules #Postpone everything without exiting? #Original - go back to original version echo } #End of menu reppolicy () { #Replace the policy in CURRLINE with $1 if [ -n "$CURRLINE" ]; then case "$1" in [Aa]*) CURRLINE=`echo "$CURRLINE" | \ sed -e 's/\(.*\)ipchains\(.*\)-j [A-Z]*\(\W.*\)/\1ipchains\2-j ACCEPT\3/' \ -e 's/\(.*\)iptables\(.*\)-j [A-Z]*\(\W.*\)/\1iptables\2-j ACCEPT\3/' \ -e 's/\(.*\)ipfwadm\(.*\)-a [a-z]*\(\W.*\)/\1ipfwadm\2-a accept\3/' \ -e 's/\(.*\)ipfwadm\(.*\)\W-m\(\W.*\)/\1ipfwadm\2\3/'` ;; [Dd]*) CURRLINE=`echo "$CURRLINE" | \ sed -e 's/\(.*\)ipchains\(.*\)-j [A-Z]*\(\W.*\)/\1ipchains\2-j DENY\3/' \ -e 's/\(.*\)iptables\(.*\)-j [A-Z]*\(\W.*\)/\1iptables\2-j DROP\3/' \ -e 's/\(.*\)ipfwadm\(.*\)-a [a-z]*\(\W.*\)/\1ipfwadm\2-a deny\3/' \ -e 's/\(.*\)ipfwadm\(.*\)\W-m\(\W.*\)/\1ipfwadm\2\3/'` ;; [Mm]*) CURRLINE=`echo "$CURRLINE" | \ sed -e 's/\(.*\)ipchains\(.*\)-j [A-Z]*\(\W.*\)/\1ipchains\2-j MASQ\3/' \ -e 's/\(.*\)iptables\(\W*-[AI]\)\W*[A-Za-z0-9]*\(.*\)-j [A-Z]*\(\W.*\)/\1iptables\2 POSTROUTING -t nat\3-j MASQUERADE\4/' \ -e 's/\(.*\)ipfwadm\(.*\)\W-m\(\W.*\)/\1ipfwadm\2\3/' \ -e 's/\(.*\)ipfwadm\(.*\)-a [a-z]*\(\W.*\)/\1ipfwadm\2-a accept -m\3/'` ;; [Rr]*) CURRLINE=`echo "$CURRLINE" | \ sed -e 's/\(.*\)ipchains\(.*\)-j [A-Z]*\(\W.*\)/\1ipchains\2-j REJECT\3/' \ -e 's/\(.*\)iptables\(.*\)-j [A-Z]*\(\W.*\)/\1iptables\2-j REJECT\3/' \ -e 's/\(.*\)ipfwadm\(.*\)-a [a-z]*\(\W.*\)/\1ipfwadm\2-a reject\3/' \ -e 's/\(.*\)ipfwadm\(.*\)\W-m\(\W.*\)/\1ipfwadm\2\3/'` ;; esac fi #CURRLINE="$CURRLINE #$1" } #End of reppolicy if [ -f $MASONCONF ]; then #The entire loadconf function is not required . $MASONCONF fi #checksys #Disabled as we've already done this at least once in mason or mason-gui-text checkconf ORIGIFS="$IFS" IFS='' EXITNOW='' echo #FIXME - null CURRLINE when committed; check for null CURRLINE. echo $ENH Waiting for new rule, press ${KEY}Ctrl-C${NORM} to abort... showstate 'mason-decide: waiting for new rule' while [ "$EXITNOW" != "YES" ] && read INLINE ; do showstate 'mason-decide: processing rule' CURRLINE="$INLINE" #Check to see if the line is a firewall rule #Loop until some commit choice made. COMMITTED='' clear echo $ENH "${HEADER}-----------${NORM}" echo "$CURRLINE" echo $ENH "${HEADER}-----------${NORM}" menu while [ "$COMMITTED" != "YES" ] && read CHOICE <&10 ; do case "$CHOICE" in [Ee]*) echo Manually editing the rule. showstate 'mason-decide: editing rule' if ! type -path mktemp >/dev/null 2>/dev/null ; then TMPFILE="/var/lib/mason/manualedit" #FIXME - || RETVAL=$? ? likewise below. touch $TMPFILE else TMPFILE=`mktemp -q /tmp/mason-edit.XXXXXX` fi if [ $? -ne 0 ]; then echo $ENH "${WARN}$0: Can't create temp file.${NORM}" else echo "$CURRLINE" >$TMPFILE $EDITOR $TMPFILE <&10 CURRLINE=`cat $TMPFILE` rm -f $TMPFILE || : fi ;; [Jj]*) echo Jot a note at the end of the rule, append to end with comment character echo $ENH Please enter a comment. Just press ${KEY}Enter${NORM} if you changed your mind. read NEWCOMMENT <&10 if [ -n "$NEWCOMMENT" ]; then CURRLINE="$CURRLINE $CMNT$NEWCOMMENT" fi ;; [Aa]*) echo Change policy to Accept and commit to baserules reppolicy 'Accept' echo "$CURRLINE" >&11 COMMITTED="YES" ;; [Dd]*) echo Change policy to Deny and commit to baserules reppolicy 'Deny' echo "$CURRLINE" >&11 COMMITTED="YES" ;; [Mm]*) echo Change policy to Masq and commit to baserules reppolicy 'Masq' echo "$CURRLINE" >&11 COMMITTED="YES" ;; [Rr]*) echo Change policy to Reject and commit to baserules reppolicy 'Reject' echo "$CURRLINE" >&11 COMMITTED="YES" ;; [Pp]*) echo Postpone choice, append to newrules echo "$CURRLINE" >&12 COMMITTED="YES" ;; [Tt]*) echo Throw away line CURRLINE='' COMMITTED="YES" ;; [Bb]*) echo make this host a BLOCKEDHOST and delete the rule echo Please enter the host or network to block. echo Just press enter if you changed your mind. read TOBLOCK <&10 if [ -n "$TOBLOCK" ]; then echo "BLOCKEDHOSTS=\"\${BLOCKEDHOSTS} $TOBLOCK\"" >>/etc/masonrc #Block right now. dorule i input '' '' '' "$TOBLOCK" '' '' '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO mason-decide: YYYY 0001 dorule i output '' '' '' "$TOBLOCK" '' '' '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO mason-decide: YYYY 0002 dorule i input '' '' '' '' '' "$TOBLOCK" '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO mason-decide: YYYY 0003 dorule i output '' '' '' '' '' "$TOBLOCK" '' '' '' deny '' "$LOGBLOCKS" '' || logfail $LINENO mason-decide: YYYY 0004 CURRLINE='' COMMITTED="YES" fi ;; [Nn]*) echo make port a NOINCOMING port and delete the rule echo Please enter the port to make noincoming. echo Use the format \"portnumber/protocol\", such as echo \"telnet/tcp\" or \"23/tcp\". echo Just press enter if you changed your mind. read TONOINCOMING <&10 if [ -n "$TONOINCOMING" ]; then echo "NOINCOMING=\"\${NOINCOMING} $TONOINCOMING\"" >>/etc/masonrc #BLOCK right now for OUTSIDEIF in $INCOMINGINTERFACES ; do oneblockproto $TONOINCOMING $OUTSIDEIF done CURRLINE='' COMMITTED="YES" fi ;; [Cc]*) echo Commit to the permanent firewall set echo "$CURRLINE" >&11 COMMITTED="YES" ;; [Qq]*) echo Quit. When we exit the loop, any additional rules will be postponed EXITNOW="YES" if [ -n "$CURRLINE" ]; then echo "$CURRLINE" >&12 #Save current rule to postpone set fi echo '!!EXIT!!' >&13 COMMITTED="YES" ;; esac if [ "$COMMITTED" != "YES" ]; then clear echo '-----------' echo "$CURRLINE" echo '-----------' menu fi done #If not committed and read choice echo $ENH Waiting for new rule, press ${KEY}Ctrl-C${NORM} to abort... if [ "`echo $INLINE | sed -e 's/#.*//' -e 's/ //g'`" != "`echo $CURRLINE | sed -e 's/#.*//' -e 's/ //g'`" ]; then #If changed, remove old line and install new echo -n Rule changed, removing old rule... #REMOVEME #echo eval `echo $INLINE | sed -e "s/\(.*\)ipchains\(.*\)-[AI]\(\W*[A-Za-z0-9]*\)\(\W.*\)/\1ipchains\2-D\3$NOLOGSUFFIX\4/" \ # -e "s/\(.*\)iptables\(.*\)-[AI]\(\W*[A-Za-z0-9]*\)\(\W.*\)/\1iptables\2-D\3$NOLOGSUFFIX\4/" \ # -e 's/\(.*\)ipfwadm\(.*\)-[ai]\(\W.*\)/\1ipfwadm\2-d\3/'` eval `echo $INLINE | sed -e "s/\(.*\)ipchains\(.*\)-[AI]\(\W*[A-Za-z0-9]*\)\(\W.*\)/\1ipchains\2-D\3$NOLOGSUFFIX\4/" \ -e "s/\(.*\)iptables\(.*\)-[AI]\(\W*[A-Za-z0-9]*\)\(\W.*\)/\1iptables\2-D\3$NOLOGSUFFIX\4/" \ -e 's/\(.*\)ipfwadm\(.*\)-[ai]\(\W.*\)/\1ipfwadm\2-d\3/'` # || : ? Sigh. if [ -n "$CURRLINE" ]; then echo -n and installing new version... #the "N" after \3 on the iptables and ipchains lines was removed so the new rule will be added to the main chain and not the NOLOG chain. #echo eval `echo $CURRLINE | sed -e 's/\(.*\)ipchains\(.*\)-[AI]\(\W*[A-Za-z]*\)\(\W.*\)/\1ipchains\2-I\3\4/' \ # -e 's/\(.*\)iptables\(.*\)-[AI]\(\W*[A-Za-z]*\)\(\W.*\)/\1iptables\2-I\3\4/' \ # -e 's/\(.*\)ipfwadm\(.*\)-[ai]\(\W*[a-z]*\)\(\W.*\)/\1ipfwadm\2-i\3\4/'` eval `echo $CURRLINE | sed -e 's/\(.*\)ipchains\(.*\)-[AI]\(\W*[A-Za-z]*\)\(\W.*\)/\1ipchains\2-I\3\4/' \ -e 's/\(.*\)iptables\(.*\)-[AI]\(\W*[A-Za-z]*\)\(\W.*\)/\1iptables\2-I\3\4/' \ -e 's/\(.*\)ipfwadm\(.*\)-[ai]\(\W*[a-z]*\)\(\W.*\)/\1ipfwadm\2-i\3\4/'` fi echo done! fi CURRLINE='' showstate 'mason-decide: waiting for new rule' done #not EXITNOW and read INLINE if [ "$EXITNOW" != "YES" ]; then EOFREACHED="YES" fi if [ "$EOFREACHED" != "YES" ]; then while read INLINE ; do #postpone the rest echo "$INLINE" >&12 done fi echo echo $0 done! showstate '' IFS="$ORIGIFS"