### Copyright (C) 1997 John D. Hardin
### 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 of the License, 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.
###
### You should have received a copy of the GNU General Public License
### along with this program; if not, write to the Free Software
### Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

### $Id: denyhost.template,v 2.14 1998-09-14 17:06:18-07 jhardin Exp $


proc denyhosts {} {
    # Deny / Services (Per-Host, Internet Hosts)

    Desc "Per-Internet-Host Service Blocking"

    ShortDesc "Per-Internet-Host Service Blocking"

    Header head1 -text "Per-Internet-Host Service Blocking"\
	    -background gray\
	    -help "Services are things like Telnet for logins, SMTP for email, FTP for file transfer,"\
	    "HTTP for Webs, and so forth. Certain services you may want to provide even if your default"\
	    "policy is \"deny\", for example, HTTP to serve web pages."\

    Label label1 -text "Firewall support"\
            -textafter "compiled into the kernel."\
	    -default "is"\
	    -packFrame:anchor center \
	    -help "Firewall support must be compiled into the kernel. If it is not,"\
	    "then you must configure and build a new kernel; see the Kernel HOWTO for"\
	    "instructions."

    Entry hostIP -text "Internet Host"\
            -help "The name or unique IP address of a computer on the Internet,"\
	    "or a network address (to match all hosts on a particular network).\n"\
	    "WARNING: If you enter a name then that name should probably be in your /etc/hosts file."\
	    "If you access the Internet via dialup there is no guarantee that the ipfwadm"\
            "command will be able to look up the name using DNS."\
            "\n\nIf you provide a file name here, the IP addresses and netmasks will be retrieved"\
            "from that file at the time the firewall script is run. This allows you to modify the"\
            "list of Internet hosts permitted to access your local network without having to"\
            "regenerate the firewall script; simply edit the IP address file and re-run the"\
            "generated firewall script."

    global MaskList
    ComboBox hostnetmask -text "Network Mask"\
	    -count 8 -noedit 1\
            -entries $MaskList\
	    -help "If you entered the IP address or name for a specific host, select \"32: 255.255.255.255\" -"\
	    "this means that the address must match exactly for the packet to be accepted.\n"\
	    "If you entered a network address, or if you entered a host IP or name and want to match all of the"\
	    "hosts on the same network as that host, select the appropriate netmask for that network.\n"\
	    "WARNING: If you select \"0: 0.0.0.0\" then this rule will apply to *all* hosts on the Internet."

    global ServiceList
    ComboBox denyservice -text "Service to deny"\
	    -count 10\
	    -help "Select a service from the list, or enter one in the form port#(:port#)/\[tcp|udp\]."\
	      "For example, to deny HTTP requests, enter \"80/tcp\". See the file"\
	      "/etc/services (from which this list was generated) for a list of services with some comments,"\
	      "or consult your ISP.\n\n"\
              "Leave blank to block all tcp and udp traffic in the selected direction."\
            -entries $ServiceList

    Radio direction -defaultIndex 0\
	    -entryhelp {\
	    "Inbound" "Service requests coming in from host(s) on the Intenet."\
	    "Outbound" "Service requests going out to host(s) on the Internet."\
	    }

    Line line1

    Frame frame1 -entries {hostIP hostnetmask}
    Frame frame2 -entries {denyservice direction}
    Frame frame3 -entries {frame1 frame2 line1} -orient top

    ExtEntry deniedhosts -entries frame3 -count 5

    CheckBox UseHTTPBlockList -text "Use HTTP Block List"\
	    -default 0\
	    -help "Rather than entering HTTP sites to block in this screen individually and regenerating"\
            "your firewall file every time you change the list, you can put the list of addresses in a separate"\
            "file and have the firewall process that file every time it runs.\n\n"\
            "Outgoing HTTP requests to each IP address in that file will be blocked.\n\n"\
            "You can use this to easily block those irritating ad-banner sites, pornography sites, or whatever."
    
    Entry HTTPBlockListFile -text "HTTP Block List filename"\
            -default "/etc/HTTP-blocklist"\
            -help "The name of a file containing a list of IP addresses of computers or networks"\
            "on the Internet where outgoing HTTP requests are to be blocked.\n\n"\
            "IP addresses should be of the form xxx.xxx.xxx.xxx/nnn.nnn.nnn.nnn"\
            "where nnn.nnn.nnn.nnn is the netmask, or xxx.xxx.xxx.xxx/nn where nn is the number of mask bits."\
            "See the \"Network Mask\" combo box for details.\n\n"\
            "Only enter one IP address per line."

    Frame frame4 -entries {UseHTTPBlockList HTTPBlockListFile} \
	    -packFrame:anchor center

    CheckBox UseSMTPBlockList -text "Use SMTP Block List"\
	    -default 0\
	    -help "Rather than entering SMTP sites to block in this screen individually and regenerating"\
            "your firewall file every time you change the list, you can put the list of addresses in a separate"\
            "file and have the firewall process that file every time it runs.\n\n"\
            "Incoming SMTP requests from each IP address in that file will be blocked.\n\n"\
            "You can use this to block those irritating spammers and spamhavens."
    
    Entry SMTPBlockListFile -text "SMTP Block List filename"\
            -default "/etc/SMTP-blocklist"\
            -help "The name of a file containing a list of IP addresses of computers or networks"\
            "on the Internet where incoming SMTP requests are to be blocked.\n\n"\
            "IP addresses should be of the form xxx.xxx.xxx.xxx/nnn.nnn.nnn.nnn"\
            "where nnn.nnn.nnn.nnn is the netmask, or xxx.xxx.xxx.xxx/nn where nn is the number of mask bits."\
            "See the \"Network Mask\" combo box for details.\n\n"\
            "Only enter one IP address per line."

    Frame frame5 -entries {UseSMTPBlockList SMTPBlockListFile} \
	    -packFrame:anchor center

    ShowPage {
      global FirewallInKernel
      if {$FirewallInKernel == 0} {
	set label1 "is not"
	Disable deniedhosts
      } else {
	set label1 "is"
	Enable deniedhosts
      }
      if {$UseHTTPBlockList} {
        Enable HTTPBlockListFile
      } else {
        Disable HTTPBlockListFile
      }
      if {$UseSMTPBlockList} {
        Enable SMTPBlockListFile
      } else {
        Disable SMTPBlockListFile
      }
    }

    Change {
      if {$UseHTTPBlockList} {
        Enable HTTPBlockListFile
      } else {
        Disable HTTPBlockListFile
      }
      if {$UseSMTPBlockList} {
        Enable SMTPBlockListFile
      } else {
        Disable SMTPBlockListFile
      }
    }

    Save {
      global IPFWADM
      global ISPPort
      global LocalNetIP
      global LocalNetMask
      global PERL
      global ParseIP
      global MatchService
      global MatchPort
      if {$IPFWADM == "" || $ISPPort == ""} {
        # nothing
      } else {

        forevery deniedhosts {

          # If host IP is actually a filename, then parse the IP addresses from the file
          set fromfile 0
          if {[file exists $hostIP]} {
            if {$PERL != ""} {
              set fromfile 1
              set host "\$IP_TO_BLOCK"
              print
              print "# process Internet host permissions from file $hostIP"
              print "if \[ -s $hostIP ]"
              print "then"
              print "  $PERL -n -e '$ParseIP' $hostIP | \\"
              print "  while read IP_TO_BLOCK"
              print "  do"
            } else {
              print
              print "# perl not found - cannot set Internet host rules from $hostIP."
              print "# Install perl, then regenerate the firewall file."
              # generate do-nothing rules
              set host "0.0.0.0/32"
            }
          } else {
            # get the net mask for the host
            regexp {([0-9]+): } $hostnetmask junk maskbits
            set host "$hostIP/$maskbits"
          }

          set service $denyservice
          if {[regexp "$MatchPort" $service junk port junk prot]} {
            set ACK [pick {$prot == "tcp"} " \$ConnEstablished" ""]
            # if there's a description before or after the port spec, retrieve it.
            set descr ""
            if {![regexp "^(\[ A-Za-z0-9\\-_\]+)\[ \t\]+" $service junk descr]} {
              # not before. try after.
              regexp "\[ \t(\]+(\[ A-Za-z0-9\\-_\]+)" $service junk descr
            }
            if {$descr != ""} {
              set descr " ($descr)"
            }

            if {$direction(index) == 0} {	# inbound (specified host is SOURCE)
              if {$prot == "icmp"} {
                print "# Block ICMP message $port$descr from Internet host/network $host to anyone on the local net"
                print $IPFWADM "-I -a deny -o \$INET -P $prot -S $host $port -D \$ANY"
              } else {
                if {$prot == "tcp"} {
                  print "# Allow established $prot port $port$descr traffic from Internet network/host $host"
                  print $IPFWADM "-I -a accept \$INET -P $prot \$ConnEstablished -S $host -D \$ANY $port"
                }
                print "# Block new $prot port $port$descr traffic from Internet network/host $host"
                print $IPFWADM "-I -a deny -o \$INET -P $prot -S $hostIP/$maskbits -D \$ANY $port"
              }
            } else {				# outbound (specified host is DEST)
              if {$prot == "icmp"} {
                print "# Block ICMP message $port$descr to Internet network/host $host"
                print $IPFWADM "-O -a reject \$INET -P $prot -S \$ANY $port -D $host"
              } else {
                if {$prot == "tcp"} {
                  print "# Allow established $prot port $port$descr traffic to Internet network/host $host"
                  print $IPFWADM "-O -a accept \$INET -P $prot \$ConnEstablished -S \$ANY -D $host $port"
                }
                print "# Block new $prot port $port$descr traffic to Internet network/host $host"
                print $IPFWADM "-O -a reject \$INET -P $prot -S \$ANY -D $host $port"
              }
            }

          } else {
            print "# Syntax error on host $host: service \"$denyservice\" unparseable."
            tk_dialog .warning "Warning" "Syntax error on host $host: service \"$denyservice\" unparseable." info 0 OK
          }

          if {$fromfile != 0} {
            # finish up the shell script loop
            print "  done"
            print "fi"
            print
          }
        }
      }
      

      if {$PERL != "" && $UseHTTPBlockList} {
        if {[file exists $HTTPBlockListFile]} {
          print
          print "# process the HTTP Block List file"
          print "if \[ -s $HTTPBlockListFile ]"
          print "then"
          print "  $PERL -n -e '$ParseIP' $HTTPBlockListFile | \\"
          print "  while read IP_TO_BLOCK"
          print "  do"
          print "    # Allow established HTTP traffic to Internet network/host"
          print "    $IPFWADM -O -a accept \$INET -P tcp \$ConnEstablished -S \$ANY -D \$IP_TO_BLOCK 80"
          print "    # Block new HTTP traffic to Internet network/host"
          print "    $IPFWADM -O -a reject \$INET -P tcp -S \$ANY -D \$IP_TO_BLOCK 80"
          print "  done"
          print "fi"
        } else {
          print
          print "# HTTP Block List file $HTTPBlockListFile not found."
          print "# Create it, then regenerate the firewall file."
          tk_dialog .warning "Warning" "HTTP Block List file \"$HTTPBlockListFile\" not found." info 0 OK
        }
      }


      if {$PERL != "" && $UseSMTPBlockList} {
        if {[file exists $SMTPBlockListFile]} {
          print
          print "# process the SMTP Block List file"
          print "if \[ -s $SMTPBlockListFile ]"
          print "then"
          print "  $PERL -n -e '$ParseIP' $SMTPBlockListFile | \\"
          print "  while read IP_TO_BLOCK"
          print "  do"
          print "    # Allow established SMTP traffic from Internet network/host"
          print "    $IPFWADM -I -a accept \$INET -P tcp \$ConnEstablished -S \$IP_TO_BLOCK -D \$ANY 25"
          print "    # Block new SMTP traffic from Internet network/host"
          print "    $IPFWADM -I -a deny -o \$INET -P tcp -S \$IP_TO_BLOCK -D \$ANY 25"
          print "  done"
          print "fi"
        } else {
          print
          print "# SMTP Block List file $SMTPBlockListFile not found."
          print "# Create it, then regenerate the firewall file."
          tk_dialog .warning "Warning" "SMTP Block List file \"$SMTPBlockListFile\" not found." info 0 OK
        }
      }
    }
}
