### 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: allowptp.template,v 1.13 1999-09-14 21:55:14-07 jhardin Exp $


proc allowptp {} {
    # Allow / Services (Point-to-Point)

    Desc "Point-to-Point Services Allowed"

    ShortDesc "Point-to-Point Services Allowed"

    Header head1 -text "Point-to-Point Services Allowed"\
	    -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."\
	    "\n\nUse point-to-point rules for controlling one particular local-network computer's"\
	    "access to one particular Internet computer, or vice-versa."

    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)."\
	    "\nWARNING: 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."

    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."\
	    "\nWARNING: If you select \"0: 0.0.0.0\" then this rule will apply to *all* hosts on the Internet."

    Entry localhostIP -text "Local Host"\
            -help "The unique IP address of a computer on the local network."

    global ServiceList
    ComboBox allowservice -text "Service to allow"\
	    -count 10\
	    -help "Select a service from the list, or enter one in the form port#(:port#)/\[tcp|udp\]."\
	      "For example, to allow 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."\
            -entries $ServiceList

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

    # allow point-to-point masquerade on internal firewalls
    # this likely won't be set up with diald, so we won't do the sl0 rules...
    CheckBox masquerade -text "Masquerade" \
           -default 0 \
           -help "You may want to masquerade certain outbound traffic"\
                 "on the internal firewall of your boundary network,"\
                 "for example if you wish someone on your private network"\
                 "to be able to retrieve mail via POP from a system on the Internet."\
                 "Check this checkbox to masquerade this traffic."\
                 "\n\nNote: this can introduce security holes. Use with caution."

    Line line1

    Frame frame1 -entries {hostIP hostnetmask}
    Frame frame2 -entries {allowservice direction masquerade}
    Frame frame3 -entries {frame1 localhostIP frame2 line1} -orient top

    ExtEntry allowedhosts -entries frame3 -count 5

    ShowPage {
      global FirewallInKernel
      global MasqInKernel
      if {$FirewallInKernel == 0} {
	set label1 "is not"
	Disable allowedhosts
      } else {
	set label1 "is"
	Enable allowedhosts
        # If internet or boundary firewall and if not directly on internet
        # then allow ptp masquerade without killing regular forwarding.
        # This lets you allow users on the corporate network to poll their ISP's POP server, for example
        if {$MasqInKernel != 0 && ${isp@on_internet} != 0 && ${isp@internal_firewall} != 0} {
          forevery allowedhosts {
	    if {$direction(index) == 0} {	# inbound (specified host is SOURCE)
              # only for outbound traffic
              set masquerade 0
              Disable masquerade
            } else {
              Enable masquerade
            }
          }
        } else {
          forevery allowedhosts {
            set masquerade 0
            Disable masquerade
          }
        }
      }
    }

    Change {
      global FirewallInKernel
      global MasqInKernel
      if {$FirewallInKernel == 0} {
	set label1 "is not"
	Disable allowedhosts
      } else {
	set label1 "is"
	Enable allowedhosts
        # If internet or boundary firewall and if not directly on internet
        # then allow ptp masquerade without killing regular forwarding.
        # This lets you allow users on the corporate network to poll their ISP's POP server, for example
        if {$MasqInKernel != 0 && ${isp@on_internet} != 0 && ${isp@internal_firewall} != 0} {
          forevery allowedhosts {
	    if {$direction(index) == 0} {	# inbound (specified host is SOURCE)
              # only for outbound traffic
              set masquerade 0
              Disable masquerade
            } else {
              Enable masquerade
            }
          }
        } else {
          forevery allowedhosts {
            set masquerade 0
            Disable masquerade
          }
        }
      }
    }

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

        forevery allowedhosts {

          # 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_ALLOW"
              print
              print "# process P-t-P Internet host permissions from file $hostIP"
              print "if \[ -s $hostIP ]"
              print "then"
              print "  $PERL -n -e '$ParseIP' $hostIP | \\"
              print "  while read IP_TO_ALLOW"
              print "  do"
            } else {
              print
              print "# perl not found - cannot set P-t-P 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 $allowservice
          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 "# Allow ICMP message $port$descr from Internet host/network $host to local host $localhostIP"
                print $IPFWADM "-I -a accept \$INET -P $prot -S $host $port -D $localhostIP/32"
                if {${isp@on_internet}} {
                  if {$LocalNetIP != "" && ${masq@masquerade} == 0} {
                    print $IPFWADM "-F -a accept \$LETH -P $prot -S $host $port -D $localhostIP/32"
                    print $IPFWADM "-O -a accept \$LETH -P $prot -S $host $port -D $localhostIP/32"
                  }
                }
              } else {
                # TCP or UDP
                print "# Allow Internet host/network $host to request $prot port $port$descr from local host $localhostIP"
                print $IPFWADM "-I -a accept \$INET -P $prot -S $host -D $localhostIP/32 $port"
                print $IPFWADM "-O -a accept \$INET -P $prot$ACK -D $host -S $localhostIP/32 $port"
                if {${isp@on_internet}} {
                  if {$LocalNetIP != "" && ${masq@masquerade} == 0} {
                    print $IPFWADM "-F -a accept \$LETH -P $prot -S $host -D $localhostIP/32 $port"
                    print $IPFWADM "-O -a accept \$LETH -P $prot -S $host -D $localhostIP/32 $port"
                    print $IPFWADM "-I -a accept \$LETH -P $prot$ACK -D $host -S $localhostIP/32 $port"
                    print $IPFWADM "-F -a accept \$INET -P $prot$ACK -D $host -S $localhostIP/32 $port"
                  }
                }
              }
            } else {	# outbound (specified host is DEST)
              if {$prot == "icmp"} {
                if {$masquerade == 0} {
                  print "# Allow local host $localhostIP to send ICMP message $port$descr to Internet host/network $host"
                  print $IPFWADM "-O -a accept \$INET -P $prot -S $localhostIP/32 $port -D $host"
                  if {${isp@on_internet}} {
                    if {$LocalNetIP != "" && ${masq@masquerade} == 0} {
                      print $IPFWADM "-I -a accept \$LETH -P $prot -S $localhostIP/32 $port -D $host"
                      print $IPFWADM "-F -a accept \$INET -P $prot -S $localhostIP/32 $port -D $host"
                    }
                  }
                } else {
                  print "# Warning: cannot masquerade P-t-P ICMP traffic (local host $localhostIP, Internet host/net $hostIP, message $port)"
                }
              } else {
                # TCP or UDP
                print "# Allow local host $localhostIP to request $prot port $port$descr from Internet host/network $host"
                if {$masquerade == 0} {
                  print $IPFWADM "-O -a accept \$INET -P $prot -S $localhostIP/32 -D $host $port"
                  print $IPFWADM "-I -a accept \$INET -P $prot$ACK -D $localhostIP/32 -S $host $port"
                  if {${isp@on_internet}} {
                    if {$LocalNetIP != "" && ${masq@masquerade} == 0} {
                      print $IPFWADM "-I -a accept \$LETH -P $prot -S $localhostIP/32 -D $host $port"
                      print $IPFWADM "-F -a accept \$INET -P $prot -S $localhostIP/32 -D $host $port"
                      print $IPFWADM "-F -a accept \$LETH -P $prot$ACK -D $localhostIP/32 -S $host $port"
                      print $IPFWADM "-O -a accept \$LETH -P $prot$ACK -D $localhostIP/32 -S $host $port"
                    }
                  }
                } else {
                  if {$InetIPValid == 0} {
                    print "# Warning: Internet interface IP address not known - this may not work reliably."
                  } 
                  print "# Security Warning:"
                  print "# This allows ANY process running on the firewall to request the service from the Internet host"

                  print $IPFWADM "-O -a accept \$INET -P $prot -S \$INET_IP -D $host $port"
                  print $IPFWADM "-I -a accept \$INET -P $prot$ACK -D \$INET_IP -S $host $port"
                  if {${isp@on_internet}} {
                    if {$LocalNetIP != "" && ${masq@masquerade} == 0} {
                      print $IPFWADM "-I -a accept \$LETH -P $prot -S $localhostIP/32 -D $host $port"
                      print $IPFWADM "-F -a -m accept \$INET -P $prot -S $localhostIP/32 -D $host $port"
                      print $IPFWADM "-F -a accept \$LETH -P $prot$ACK -D $localhostIP/32 -S $host $port"
                      print $IPFWADM "-O -a accept \$LETH -P $prot$ACK -D $localhostIP/32 -S $host $port"
                    }
                  }
                }
              }
            }

            if {$prot == "tcp" && $port == "21"} {
              # ftp service...
              # add special handling for ftp-data "reverse connection"
              # with type-of-service adjustment for bulk data
              print "#  The previous was an FTP control channel - permit the FTP data channel,"
              print "#  with Type-of-Service set to bulk data"
              if {$direction(index) == 0} {	# inbound (specified host is SOURCE)
                print $IPFWADM "-O -a accept \$INET -P $prot -S $localhostIP/32 20 -D $host 1025:65535 -t 0xE1 0x08"
                print $IPFWADM "-I -a accept \$INET -P $prot$ACK -D $localhostIP/32 20 -S $host 1025:65535 -t 0xE1 0x08"
                if {${isp@on_internet}} {
                  if {$LocalNetIP != "" && ${masq@masquerade} == 0} {
                    print $IPFWADM "-I -a accept \$LETH -P $prot -S $localhostIP/32 20 -D $host 1025:65535 -t 0xE1 0x08"
                    print $IPFWADM "-F -a accept \$INET -P $prot -S $localhostIP/32 20 -D $host 1025:65535"
                    print $IPFWADM "-F -a accept \$LETH -P $prot$ACK -D $localhostIP/32 20 -S $host 1025:65535"
                    print $IPFWADM "-O -a accept \$LETH -P $prot$ACK -D $localhostIP/32 20 -S $host 1025:65535"
                  }
                }
              } else {	# outbound (specified host is DEST)
                if {$masquerade == 0} {
                  print $IPFWADM "-I -a accept \$INET -P $prot -S $host 20 -D $localhostIP/32 1025:65535 -t 0xE1 0x08"
                  print $IPFWADM "-O -a accept \$INET -P $prot$ACK -D $host 20 -S $localhostIP/32 1025:65535 -t 0xE1 0x08"
                  if {${isp@on_internet}} {
                    if {$LocalNetIP != "" && ${masq@masquerade} == 0} {
                      print $IPFWADM "-I -a accept \$INET -P $prot -S $host 20 -D $localhostIP/32 1025:65535 -t 0xE1 0x08"
                      print $IPFWADM "-F -a accept \$LETH -P $prot -S $host 20 -D $localhostIP/32 1025:65535"
                      print $IPFWADM "-O -a accept \$LETH -P $prot -S $host 20 -D $localhostIP/32 1025:65535"
                      print $IPFWADM "-I -a accept \$LETH -P $prot$ACK -D $host 20 -S $localhostIP/32 1025:65535 -t 0xE1 0x08"
                      print $IPFWADM "-F -a accept \$INET -P $prot$ACK -D $host 20 -S $localhostIP/32 1025:65535"
                      print $IPFWADM "-O -a accept \$INET -P $prot$ACK -D $host 20 -S $localhostIP/32 1025:65535"
                    }
                  }
                } else {
                  print $IPFWADM "-I -a accept \$INET -P $prot -S $host 20 -D \$INET_IP 1025:65535 -t 0xE1 0x08"
                  print $IPFWADM "-O -a accept \$INET -P $prot$ACK -D $host 20 -S \$INET_IP 1025:65535 -t 0xE1 0x08"
                  # forwarding is taken care of by the FTP masquerade module...
                  global MODPROBE
                  if {$MODPROBE != ""} {
                    print $MODPROBE "ip_masq_ftp"
                  } else {
                    print "# Warning: couldn't locate modprobe - masqueraded FTP will be unreliable."
                  }
                }
              }
            }

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

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

