mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-09 18:45:54 +02:00
* Kleiner Tux im Webinterface für den eXciter und den Benne :) Geändert: * time.cgi überarbeitet und Funktion verbessert. * index.cgi - noch ein Paar Fehler behoben oder was hinzugefügt. * FLASH-Eintrag aus der crontab gelöscht. * Online-Hilfe-Rettungsringe (die hässlichen) aus den CGIs entfernt. * Logger von ipcop nach ipfire umgestellt. Gelöscht: * Nicht benötigte Reste vom IPCop entfernt. git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@160 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8
1178 lines
40 KiB
Perl
1178 lines
40 KiB
Perl
#!/usr/bin/perl
|
|
#
|
|
# SmoothWall CGIs
|
|
#
|
|
# This code is distributed under the terms of the GPL
|
|
#
|
|
# (c) The SmoothWall Team
|
|
# Copyright (c) 2002/04/13 Steve Bootes - Add source IP support
|
|
#
|
|
# $Id: portfw.cgi,v 1.5.2.18 2005/05/02 16:19:49 eoberlander Exp $
|
|
#
|
|
#
|
|
# Darren Critchley February 2003 - I added the multiple external access rules for each port forward
|
|
# A couple of things to remember when reading the code
|
|
# There are two kinds of records in the config file, those with a number in the first field, and then 0,
|
|
# these are port forward rules, these records will have a 0 or 0.0.0.0 in position 9 (ORIG_IP)
|
|
# If there is a 0, it means that there are external access rules, otherwise the port is open to ALL.
|
|
# The second type of record is a number followed by a number which indicates that it is an external access
|
|
# rule. The first number indicates which Portfw rule it belongs to, and the second is just a unique key.
|
|
#
|
|
# Darren Critchley - March 5, 2003 - if you come along after me and work on this page, please comment your
|
|
# work. Put your name, and date and then your comment - it helps the person that comes along after you
|
|
# to figure out why and how things have changed, and it is considered good coding practice
|
|
# Thanks . . .
|
|
#
|
|
|
|
use strict;
|
|
|
|
# enable only the following on debugging purpose
|
|
#use warnings;
|
|
#use CGI::Carp 'fatalsToBrowser';
|
|
|
|
require 'CONFIG_ROOT/general-functions.pl';
|
|
require "${General::swroot}/lang.pl";
|
|
require "${General::swroot}/header.pl";
|
|
|
|
#workaround to suppress a warning when a variable is used only once
|
|
my @dummy = ( ${Header::colouryellow} );
|
|
undef (@dummy);
|
|
|
|
my %cgiparams=();
|
|
my %selected=();
|
|
my %checked=();
|
|
my $prtrange1=0;
|
|
my $prtrange2=0;
|
|
my $errormessage = '';
|
|
my $filename = "${General::swroot}/portfw/config";
|
|
my $aliasfile = "${General::swroot}/ethernet/aliases";
|
|
|
|
&Header::showhttpheaders();
|
|
|
|
$cgiparams{'ENABLED'} = 'off';
|
|
$cgiparams{'KEY1'} = '0';
|
|
$cgiparams{'KEY2'} = '0';
|
|
$cgiparams{'PROTOCOL'} = '';
|
|
$cgiparams{'SRC_PORT'} = '';
|
|
$cgiparams{'DEST_IP'} = '';
|
|
$cgiparams{'DEST_PORT'} = '';
|
|
$cgiparams{'SRC_IP'} = '';
|
|
$cgiparams{'ORIG_IP'} = '';
|
|
$cgiparams{'REMARK'} = '';
|
|
$cgiparams{'OVERRIDE'} = 'off';
|
|
$cgiparams{'ACTION'} = '';
|
|
|
|
&Header::getcgihash(\%cgiparams);
|
|
|
|
my $disable_all = "0";
|
|
my $enable_all = "0";
|
|
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'add'})
|
|
{
|
|
&valaddupdate();
|
|
|
|
# Darren Critchley - if there is an error, don't waste any more time processing
|
|
if ($errormessage) { goto ERROR; }
|
|
|
|
open(FILE, $filename) or die 'Unable to open config file.';
|
|
my @current = <FILE>;
|
|
close(FILE);
|
|
my $key1 = 0; # used for finding last sequence number used
|
|
foreach my $line (@current)
|
|
{
|
|
my @temp = split(/\,/,$line);
|
|
|
|
chomp ($temp[8]);
|
|
if ($cgiparams{'KEY2'} eq "0"){ # if key2 is 0 then it is a portfw addition
|
|
if ( $cgiparams{'SRC_PORT'} eq $temp[3] &&
|
|
$cgiparams{'PROTOCOL'} eq $temp[2] &&
|
|
$cgiparams{'SRC_IP'} eq $temp[7])
|
|
{
|
|
$errormessage =
|
|
"$Lang::tr{'source port in use'} $cgiparams{'SRC_PORT'}";
|
|
}
|
|
# Check if key2 = 0, if it is then it is a port forward entry and we want the sequence number
|
|
if ( $temp[1] eq "0") {
|
|
$key1=$temp[0];
|
|
}
|
|
# Darren Critchley - Duplicate or overlapping Port range check
|
|
if ($temp[1] eq "0" &&
|
|
$cgiparams{'PROTOCOL'} eq $temp[2] &&
|
|
$cgiparams{'SRC_IP'} eq $temp[7] &&
|
|
$errormessage eq '')
|
|
{
|
|
&portchecks($temp[3], $temp[5]);
|
|
}
|
|
} else {
|
|
if ( $cgiparams{'KEY1'} eq $temp[0] &&
|
|
$cgiparams{'ORIG_IP'} eq $temp[8])
|
|
{
|
|
$errormessage =
|
|
"$Lang::tr{'source ip in use'} $cgiparams{'ORIG_IP'}";
|
|
}
|
|
}
|
|
}
|
|
|
|
ERROR:
|
|
unless ($errormessage)
|
|
{
|
|
# Darren Critchley - we only want to store ranges with Colons
|
|
$cgiparams{'SRC_PORT'} =~ tr/-/:/;
|
|
$cgiparams{'DEST_PORT'} =~ tr/-/:/;
|
|
|
|
if ($cgiparams{'KEY1'} eq "0") { # 0 in KEY1 indicates it is a portfw add
|
|
$key1++; # Add one to last sequence number
|
|
open(FILE,">>$filename") or die 'Unable to open config file.';
|
|
flock FILE, 2;
|
|
if ($cgiparams{'ORIG_IP'} eq '0.0.0.0/0') {
|
|
# if the default/all is taken, then write it to the rule
|
|
print FILE "$key1,0,$cgiparams{'PROTOCOL'},$cgiparams{'SRC_PORT'},$cgiparams{'DEST_IP'},$cgiparams{'DEST_PORT'},$cgiparams{'ENABLED'},$cgiparams{'SRC_IP'},$cgiparams{'ORIG_IP'},$cgiparams{'REMARK'}\n";
|
|
} else { # else create an extra record so it shows up
|
|
print FILE "$key1,0,$cgiparams{'PROTOCOL'},$cgiparams{'SRC_PORT'},$cgiparams{'DEST_IP'},$cgiparams{'DEST_PORT'},$cgiparams{'ENABLED'},$cgiparams{'SRC_IP'},0,$cgiparams{'REMARK'}\n";
|
|
print FILE "$key1,1,$cgiparams{'PROTOCOL'},0,$cgiparams{'DEST_IP'},$cgiparams{'DEST_PORT'},$cgiparams{'ENABLED'},0,$cgiparams{'ORIG_IP'},$cgiparams{'REMARK'}\n";
|
|
}
|
|
close(FILE);
|
|
undef %cgiparams;
|
|
&General::log($Lang::tr{'forwarding rule added'});
|
|
system('/usr/local/bin/setportfw');
|
|
} else { # else key1 eq 0
|
|
my $insertpoint = ($cgiparams{'KEY2'} - 1);
|
|
open(FILE, ">$filename") or die 'Unable to open config file.';
|
|
flock FILE, 2;
|
|
foreach my $line (@current) {
|
|
chomp($line);
|
|
my @temp = split(/\,/,$line);
|
|
if ($cgiparams{'KEY1'} eq $temp[0] && $insertpoint eq $temp[1]) {
|
|
if ($temp[1] eq "0") { # this is the first xtaccess rule, therefore modify the portfw rule
|
|
$temp[8] = '0';
|
|
}
|
|
print FILE "$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6],$temp[7],$temp[8],$temp[9]\n";
|
|
print FILE "$cgiparams{'KEY1'},$cgiparams{'KEY2'},$cgiparams{'PROTOCOL'},0,$cgiparams{'DEST_IP'},$cgiparams{'DEST_PORT'},$cgiparams{'ENABLED'},0,$cgiparams{'ORIG_IP'},$cgiparams{'REMARK'}\n";
|
|
} else {
|
|
print FILE "$line\n";
|
|
}
|
|
}
|
|
close(FILE);
|
|
undef %cgiparams;
|
|
&General::log($Lang::tr{'external access rule added'});
|
|
system('/usr/local/bin/setportfw');
|
|
} # end if if KEY1 eq 0
|
|
} # end unless($errormessage)
|
|
}
|
|
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'update'})
|
|
{
|
|
&valaddupdate();
|
|
|
|
# Darren Critchley - If there is an error don't waste any more processing time
|
|
if ($errormessage) { $cgiparams{'ACTION'} = $Lang::tr{'edit'}; goto UPD_ERROR; }
|
|
|
|
open(FILE, $filename) or die 'Unable to open config file.';
|
|
my @current = <FILE>;
|
|
close(FILE);
|
|
my $disabledpfw = '0';
|
|
my $lastpfw = '';
|
|
my $xtaccessdel = '0';
|
|
|
|
foreach my $line (@current)
|
|
{
|
|
my @temp = split(/\,/,$line);
|
|
if ( $temp[1] eq "0" ) { # keep track of the last portfw and if it is enabled
|
|
$disabledpfw = $temp[6];
|
|
$lastpfw = $temp[0];
|
|
}
|
|
chomp ($temp[8]);
|
|
if ( $cgiparams{'SRC_PORT'} eq $temp[3] &&
|
|
$cgiparams{'PROTOCOL'} eq $temp[2] &&
|
|
$cgiparams{'SRC_IP'} eq $temp[7])
|
|
{
|
|
if ($cgiparams{'KEY1'} ne $temp[0] && $cgiparams{'KEY2'} eq "0")
|
|
{
|
|
$errormessage =
|
|
"$Lang::tr{'source port in use'} $cgiparams{'SRC_PORT'}";
|
|
}
|
|
}
|
|
if ($cgiparams{'ORIG_IP'} eq $temp[8])
|
|
{
|
|
if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} ne $temp[1])
|
|
# If we have the same source ip within a portfw group, then we have a problem!
|
|
{
|
|
$errormessage = "$Lang::tr{'source ip in use'} $cgiparams{'ORIG_IP'}";
|
|
$cgiparams{'ACTION'} = $Lang::tr{'edit'};
|
|
}
|
|
}
|
|
|
|
# Darren Critchley - Flag when a user disables an xtaccess
|
|
if ($cgiparams{'KEY1'} eq $temp[0] &&
|
|
$cgiparams{'KEY2'} eq $temp[1] &&
|
|
$cgiparams{'KEY2'} ne "0" && # if KEY2 is 0 then it is a portfw
|
|
$cgiparams{'ENABLED'} eq "off" &&
|
|
$temp[6] eq "on") { # we have determined that someone has turned an xtaccess off
|
|
$xtaccessdel = "1";
|
|
}
|
|
|
|
# Darren Critchley - Portfw enabled, then enable xtaccess for all associated xtaccess records
|
|
if ($cgiparams{'ENABLED'} eq "on" && $cgiparams{'KEY2'} eq "0" && $cgiparams{'ENABLED'} ne $temp[6])
|
|
{
|
|
$enable_all = "1";
|
|
} else {
|
|
$enable_all = "0";
|
|
}
|
|
# Darren Critchley - Portfw disabled, then disable xtaccess for all associated xtaccess records
|
|
if ($cgiparams{'ENABLED'} eq "off" && $cgiparams{'KEY2'} eq "0")
|
|
{
|
|
$disable_all = "1";
|
|
} else {
|
|
$disable_all = "0";
|
|
}
|
|
|
|
# Darren Critchley - if we are enabling an xtaccess, only allow if the associated Portfw is enabled
|
|
if ($cgiparams{'KEY1'} eq $lastpfw && $cgiparams{'KEY2'} ne "0") { # identifies an xtaccess record in the group
|
|
if ($cgiparams{'ENABLED'} eq "on" && $cgiparams{'ENABLED'} ne $temp[6] ){ # a change has been made
|
|
if ($disabledpfw eq "off")
|
|
{
|
|
$errormessage = "$Lang::tr{'cant enable xtaccess'}";
|
|
$cgiparams{'ACTION'} = $Lang::tr{'edit'};
|
|
}
|
|
}
|
|
}
|
|
|
|
# Darren Critchley - rule to stop someone from entering ALL into a external access rule,
|
|
# the portfw is the only place that ALL can be specified
|
|
if ($cgiparams{'KEY2'} ne "0" && $cgiparams{'ORIG_IP'} eq "0.0.0.0/0") {
|
|
$errormessage = "$Lang::tr{'xtaccess all error'}";
|
|
$cgiparams{'ACTION'} = $Lang::tr{'edit'};
|
|
}
|
|
|
|
# Darren Critchley - Duplicate or overlapping Port range check
|
|
if ($temp[1] eq "0" &&
|
|
$cgiparams{'KEY1'} ne $temp[0] &&
|
|
$cgiparams{'PROTOCOL'} eq $temp[2] &&
|
|
$cgiparams{'SRC_IP'} eq $temp[7] &&
|
|
$errormessage eq '')
|
|
{
|
|
&portchecks($temp[3], $temp[5]);
|
|
} # end port testing
|
|
|
|
}
|
|
|
|
# Darren Critchley - if an xtaccess was disabled, now we need to check to see if it was the only xtaccess
|
|
if($xtaccessdel eq "1") {
|
|
my $xctr = 0;
|
|
foreach my $line (@current)
|
|
{
|
|
my @temp = split(/\,/,$line);
|
|
if($temp[0] eq $cgiparams{'KEY1'} &&
|
|
$temp[6] eq "on") { # we only want to count the enabled xtaccess's
|
|
$xctr++;
|
|
}
|
|
}
|
|
if ($xctr == 2){
|
|
$disable_all = "1";
|
|
}
|
|
}
|
|
|
|
UPD_ERROR:
|
|
unless ($errormessage)
|
|
{
|
|
# Darren Critchley - we only want to store ranges with Colons
|
|
$cgiparams{'SRC_PORT'} =~ tr/-/:/;
|
|
$cgiparams{'DEST_PORT'} =~ tr/-/:/;
|
|
|
|
open(FILE, ">$filename") or die 'Unable to open config file.';
|
|
flock FILE, 2;
|
|
foreach my $line (@current) {
|
|
chomp($line);
|
|
my @temp = split(/\,/,$line);
|
|
if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1]) {
|
|
print FILE "$cgiparams{'KEY1'},$cgiparams{'KEY2'},$cgiparams{'PROTOCOL'},$cgiparams{'SRC_PORT'},$cgiparams{'DEST_IP'},$cgiparams{'DEST_PORT'},$cgiparams{'ENABLED'},$cgiparams{'SRC_IP'},$cgiparams{'ORIG_IP'},$cgiparams{'REMARK'}\n";
|
|
} else {
|
|
# Darren Critchley - If it is a port forward record, then chances are good that a change was made to
|
|
# Destination Ip or Port, and we need to update all the associated external access records
|
|
if ($cgiparams{'KEY2'} eq "0" && $cgiparams{'KEY1'} eq $temp[0]) {
|
|
$temp[4] = $cgiparams{'DEST_IP'};
|
|
$temp[5] = $cgiparams{'DEST_PORT'};
|
|
$temp[2] = $cgiparams{'PROTOCOL'};
|
|
}
|
|
|
|
# Darren Critchley - If a Portfw has been disabled, then set all associated xtaccess as disabled
|
|
if ( $disable_all eq "1" && $cgiparams{'KEY1'} eq $temp[0] ) {
|
|
$temp[6] = 'off';
|
|
}
|
|
if ( $enable_all eq "1" && $cgiparams{'KEY1'} eq $temp[0] ) {
|
|
$temp[6] = 'on';
|
|
}
|
|
# Darren Critchley - Deal with the override to allow ALL
|
|
if ( $cgiparams{'OVERRIDE'} eq "on" && $temp[1] ne "0" && $cgiparams{'KEY1'} eq $temp[0] ) {
|
|
$temp[6] = 'off';
|
|
}
|
|
print FILE "$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6],$temp[7],$temp[8],$temp[9]\n";
|
|
}
|
|
}
|
|
close(FILE);
|
|
undef %cgiparams;
|
|
&General::log($Lang::tr{'forwarding rule updated'});
|
|
system('/usr/local/bin/setportfw');
|
|
}
|
|
if ($errormessage) {
|
|
$cgiparams{'ACTION'} = $Lang::tr{'edit'};
|
|
}
|
|
}
|
|
|
|
# Darren Critchley - Allows rules to be enabled and disabled
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'toggle enable disable'})
|
|
{
|
|
open(FILE, $filename) or die 'Unable to open config file.';
|
|
my @current = <FILE>;
|
|
close(FILE);
|
|
my $disabledpfw = '0';
|
|
my $lastpfw = '';
|
|
my $xtaccessdel = '0';
|
|
|
|
foreach my $line (@current)
|
|
{
|
|
my @temp = split(/\,/,$line);
|
|
if ( $temp[1] eq "0" ) { # keep track of the last portfw and if it is enabled
|
|
$disabledpfw = $temp[6];
|
|
$lastpfw = $temp[0];
|
|
}
|
|
# Darren Critchley - Flag when a user disables an xtaccess
|
|
if ($cgiparams{'KEY1'} eq $temp[0] &&
|
|
$cgiparams{'KEY2'} eq $temp[1] &&
|
|
$cgiparams{'KEY2'} ne "0" && # if KEY2 is 0 then it is a portfw
|
|
$cgiparams{'ENABLED'} eq "off" &&
|
|
$temp[6] eq "on") { # we have determined that someone has turned an xtaccess off
|
|
$xtaccessdel = "1";
|
|
}
|
|
|
|
# Darren Critchley - Portfw enabled, then enable xtaccess for all associated xtaccess records
|
|
if ($cgiparams{'ENABLED'} eq "on" && $cgiparams{'KEY2'} eq "0" && $cgiparams{'ENABLED'} ne $temp[6])
|
|
{
|
|
$enable_all = "1";
|
|
} else {
|
|
$enable_all = "0";
|
|
}
|
|
# Darren Critchley - Portfw disabled, then disable xtaccess for all associated xtaccess records
|
|
if ($cgiparams{'ENABLED'} eq "off" && $cgiparams{'KEY2'} eq "0")
|
|
{
|
|
$disable_all = "1";
|
|
} else {
|
|
$disable_all = "0";
|
|
}
|
|
|
|
# Darren Critchley - if we are enabling an xtaccess, only allow if the associated Portfw is enabled
|
|
if ($cgiparams{'KEY1'} eq $lastpfw && $cgiparams{'KEY2'} ne "0") { # identifies an xtaccess record in the group
|
|
if ($cgiparams{'ENABLED'} eq "on" && $cgiparams{'ENABLED'} ne $temp[6] ){ # a change has been made
|
|
if ($disabledpfw eq "off")
|
|
{
|
|
$errormessage = "$Lang::tr{'cant enable xtaccess'}";
|
|
goto TOGGLEEXIT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Darren Critchley - if an xtaccess was disabled, now we need to check to see if it was the only xtaccess
|
|
if($xtaccessdel eq "1") {
|
|
my $xctr = 0;
|
|
foreach my $line (@current)
|
|
{
|
|
my @temp = split(/\,/,$line);
|
|
if($temp[0] eq $cgiparams{'KEY1'} &&
|
|
$temp[6] eq "on") { # we only want to count the enabled xtaccess's
|
|
$xctr++;
|
|
}
|
|
}
|
|
if ($xctr == 2){
|
|
$disable_all = "1";
|
|
}
|
|
}
|
|
|
|
open(FILE, ">$filename") or die 'Unable to open config file.';
|
|
flock FILE, 2;
|
|
foreach my $line (@current) {
|
|
chomp($line);
|
|
my @temp = split(/\,/,$line);
|
|
if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1]) {
|
|
print FILE "$cgiparams{'KEY1'},$cgiparams{'KEY2'},$temp[2],$temp[3],$temp[4],$temp[5],$cgiparams{'ENABLED'},$temp[7],$temp[8],$temp[9]\n";
|
|
} else {
|
|
# Darren Critchley - If a Portfw has been disabled, then set all associated xtaccess as disabled
|
|
if ( $disable_all eq "1" && $cgiparams{'KEY1'} eq $temp[0] ) {
|
|
$temp[6] = 'off';
|
|
}
|
|
if ( $enable_all eq "1" && $cgiparams{'KEY1'} eq $temp[0] ) {
|
|
$temp[6] = 'on';
|
|
}
|
|
print FILE "$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6],$temp[7],$temp[8],$temp[9]\n";
|
|
}
|
|
}
|
|
close(FILE);
|
|
&General::log($Lang::tr{'forwarding rule updated'});
|
|
system('/usr/local/bin/setportfw');
|
|
TOGGLEEXIT:
|
|
undef %cgiparams;
|
|
}
|
|
|
|
|
|
# Darren Critchley - broke out Edit routine from the delete routine - Edit routine now just puts values in fields
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'})
|
|
{
|
|
open(FILE, "$filename") or die 'Unable to open config file.';
|
|
my @current = <FILE>;
|
|
close(FILE);
|
|
|
|
unless ($errormessage)
|
|
{
|
|
foreach my $line (@current)
|
|
{
|
|
chomp($line);
|
|
my @temp = split(/\,/,$line);
|
|
if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1] ) {
|
|
$cgiparams{'PROTOCOL'} = $temp[2];
|
|
$cgiparams{'SRC_PORT'} = $temp[3];
|
|
$cgiparams{'DEST_IP'} = $temp[4];
|
|
$cgiparams{'DEST_PORT'} = $temp[5];
|
|
$cgiparams{'ENABLED'} = $temp[6];
|
|
$cgiparams{'SRC_IP'} = $temp[7];
|
|
$cgiparams{'ORIG_IP'} = $temp[8];
|
|
$cgiparams{'REMARK'} = $temp[9];
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
# Darren Critchley - broke out Remove routine as the logic is getting too complex to be combined with the Edit
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'remove'})
|
|
{
|
|
open(FILE, "$filename") or die 'Unable to open config file.';
|
|
my @current = <FILE>;
|
|
close(FILE);
|
|
|
|
# If the record being deleted is an xtaccess record, and it is the only one for a portfw record
|
|
# then we need to adjust the portfw record to be open to ALL ip addressess or an error will occur
|
|
# in setportfw.c
|
|
my $fixportfw = '0';
|
|
if ($cgiparams{'KEY2'} ne "0") {
|
|
my $counter = 0;
|
|
foreach my $line (@current)
|
|
{
|
|
chomp($line);
|
|
my @temp = split(/\,/,$line);
|
|
if ($temp[0] eq $cgiparams{'KEY1'}) {
|
|
$counter++;
|
|
}
|
|
}
|
|
if ($counter eq 2) {
|
|
$fixportfw = '1';
|
|
}
|
|
}
|
|
|
|
unless ($errormessage)
|
|
{
|
|
open(FILE, ">$filename") or die 'Unable to open config file.';
|
|
flock FILE, 2;
|
|
my $linedeleted = 0;
|
|
foreach my $line (@current)
|
|
{
|
|
chomp($line);
|
|
my @temp = split(/\,/,$line);
|
|
|
|
if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1] ||
|
|
$cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq "0" )
|
|
{
|
|
$linedeleted = 1;
|
|
} else {
|
|
if ($temp[0] eq $cgiparams{'KEY1'} && $temp[1] eq "0" && $fixportfw eq "1") {
|
|
$temp[8] = '0.0.0.0/0';
|
|
}
|
|
print FILE "$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6],$temp[7],$temp[8],$temp[9]\n";
|
|
# print FILE "$line\n";
|
|
}
|
|
}
|
|
close(FILE);
|
|
if ($linedeleted == 1) {
|
|
&General::log($Lang::tr{'forwarding rule removed'});
|
|
undef %cgiparams;
|
|
}
|
|
system('/usr/local/bin/setportfw');
|
|
}
|
|
}
|
|
|
|
# Darren Critchley - Added routine to allow external access rules to be added
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'add xtaccess'})
|
|
{
|
|
open(FILE, $filename) or die 'Unable to open config file.';
|
|
my @current = <FILE>;
|
|
close(FILE);
|
|
my $key = 0; # used for finding last sequence number used
|
|
foreach my $line (@current)
|
|
{
|
|
my @temp = split(/\,/,$line);
|
|
if ($temp[0] eq $cgiparams{'KEY1'}) {
|
|
$key = $temp[1]
|
|
}
|
|
if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1] ) {
|
|
$cgiparams{'PROTOCOL'} = $temp[2];
|
|
$cgiparams{'SRC_PORT'} = $temp[3];
|
|
$cgiparams{'DEST_IP'} = $temp[4];
|
|
$cgiparams{'DEST_PORT'} = $temp[5];
|
|
$cgiparams{'ENABLED'} = $temp[6];
|
|
$cgiparams{'SRC_IP'} = $temp[7];
|
|
$cgiparams{'ORIG_IP'} = '';
|
|
$cgiparams{'REMARK'} = $temp[9];
|
|
}
|
|
}
|
|
$key++;
|
|
$cgiparams{'KEY2'} = $key;
|
|
# Until the ADD button is hit, there needs to be no change to portfw rules
|
|
}
|
|
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'reset'})
|
|
{
|
|
undef %cgiparams;
|
|
}
|
|
|
|
if ($cgiparams{'ACTION'} eq '')
|
|
{
|
|
$cgiparams{'PROTOCOL'} = 'tcp';
|
|
$cgiparams{'ENABLED'} = 'on';
|
|
$cgiparams{'SRC_IP'} = '0.0.0.0';
|
|
}
|
|
|
|
$selected{'PROTOCOL'}{'udp'} = '';
|
|
$selected{'PROTOCOL'}{'tcp'} = '';
|
|
$selected{'PROTOCOL'}{'gre'} = '';
|
|
$selected{'PROTOCOL'}{$cgiparams{'PROTOCOL'}} = "selected='selected'";
|
|
|
|
$selected{'SRC_IP'}{$cgiparams{'SRC_IP'}} = "selected='selected'";
|
|
|
|
$checked{'ENABLED'}{'off'} = '';
|
|
$checked{'ENABLED'}{'on'} = '';
|
|
$checked{'ENABLED'}{$cgiparams{'ENABLED'}} = "checked='checked'";
|
|
|
|
&Header::openpage($Lang::tr{'port forwarding configuration'}, 1, '');
|
|
|
|
&Header::openbigbox('100%', 'left', '', $errormessage);
|
|
|
|
if ($errormessage) {
|
|
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
|
print "<class name='base'><font color='${Header::colourred}'>$errormessage\n</font>";
|
|
print " </class>\n";
|
|
&Header::closebox();
|
|
}
|
|
|
|
print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>\n";
|
|
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'}){
|
|
&Header::openbox('100%', 'left', $Lang::tr{'edit a rule'});
|
|
} else {
|
|
&Header::openbox('100%', 'left', $Lang::tr{'add a new rule'});
|
|
}
|
|
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'} && $cgiparams{'KEY2'} ne "0" || $cgiparams{'ACTION'} eq $Lang::tr{'add xtaccess'}){
|
|
# if it is not a port forward record, don't validate as the fields are disabled
|
|
my $PROT = "\U$cgiparams{'PROTOCOL'}\E";
|
|
# Darren Critchley - Format the source and destination ports
|
|
my $dstprt = $cgiparams{'DEST_PORT'};
|
|
$dstprt =~ s/-/ - /;
|
|
$dstprt =~ s/:/ - /;
|
|
|
|
print <<END
|
|
<table>
|
|
<tr>
|
|
<td class='base'>$Lang::tr{'protocol'}: <b>$PROT</b></td>
|
|
<td width='20'> </td>
|
|
<td class='base' align='right'>$Lang::tr{'destination ip'}: </td>
|
|
<td><b>$cgiparams{'DEST_IP'}</b></td>
|
|
<td width='20'> </td>
|
|
<td class='base' align='right'>$Lang::tr{'destination port'}: </td>
|
|
<td><b>$dstprt</b></td>
|
|
</tr>
|
|
</table>
|
|
|
|
<input type='hidden' name='PROTOCOL' value='$cgiparams{'PROTOCOL'}' />
|
|
<input type='hidden' name='SRC_IP' value='$cgiparams{'SRC_IP'}' />
|
|
<input type='hidden' name='SRC_PORT' value='$cgiparams{'SRC_PORT'}' />
|
|
<input type='hidden' name='DEST_IP' value='$cgiparams{'DEST_IP'}' />
|
|
<input type='hidden' name='DEST_PORT' value='$cgiparams{'DEST_PORT'}' />
|
|
END
|
|
;
|
|
} else {
|
|
print <<END
|
|
<table width='100%'>
|
|
<tr>
|
|
<td width='10%'>$Lang::tr{'protocol'}: </td>
|
|
<td width='15%'>
|
|
<select name='PROTOCOL'>
|
|
<option value='tcp' $selected{'PROTOCOL'}{'tcp'}>TCP</option>
|
|
<option value='udp' $selected{'PROTOCOL'}{'udp'}>UDP</option>
|
|
<option value='gre' $selected{'PROTOCOL'}{'gre'}>GRE</option>
|
|
</select>
|
|
</td>
|
|
<td class='base' width='20%'><font color='${Header::colourred}'>$Lang::tr{'alias ip'}:</font></td>
|
|
<td>
|
|
<select name='SRC_IP'>
|
|
<option value='0.0.0.0' $selected{'SRC_IP'}{'0.0.0.0'}>DEFAULT IP</option>
|
|
END
|
|
;
|
|
open(ALIASES, "$aliasfile") or die 'Unable to open aliases file.';
|
|
while (<ALIASES>)
|
|
{
|
|
chomp($_);
|
|
my @temp = split(/\,/,$_);
|
|
if ($temp[1] eq 'on') {
|
|
print "<option value='$temp[0]' $selected{'SRC_IP'}{$temp[0]}>$temp[0]";
|
|
if (defined $temp[2] and ($temp[2] ne '')) { print " ($temp[2])"; }
|
|
print "</option>\n";
|
|
}
|
|
}
|
|
close(ALIASES);
|
|
print <<END
|
|
</select>
|
|
</td>
|
|
<td class='base' width='20%'><font color='${Header::colourred}'>$Lang::tr{'source port'}:</font></td>
|
|
<td width='10%'><input type='text' name='SRC_PORT' value='$cgiparams{'SRC_PORT'}' size='8' /></td>
|
|
</tr>
|
|
<tr>
|
|
<td class='base'> </td>
|
|
<td> </td>
|
|
<td class='base'>$Lang::tr{'destination ip'}:</td>
|
|
<td><input type='text' name='DEST_IP' value='$cgiparams{'DEST_IP'}' size='15' /></td>
|
|
<td class='base'>$Lang::tr{'destination port'}:</td>
|
|
<td><input type='text' name='DEST_PORT' value='$cgiparams{'DEST_PORT'}' size='8' /></td>
|
|
</tr>
|
|
</table>
|
|
END
|
|
;
|
|
}
|
|
|
|
print <<END
|
|
<table>
|
|
<tr>
|
|
<td class='base'>$Lang::tr{'remark title'} <img src='/blob.gif' alt='*' /> </td>
|
|
<td><input type='text' name='REMARK' value='$cgiparams{'REMARK'}' size='55' maxlength='50' /></td>
|
|
END
|
|
;
|
|
unless ($cgiparams{'ACTION'} eq $Lang::tr{'add xtaccess'} && $cgiparams{'ENABLED'} eq "off") {
|
|
print "<td width='20'> </td>";
|
|
print "<td>$Lang::tr{'enabled'} </td><td><input type='checkbox' name='ENABLED' $checked{'ENABLED'}{'on'} /></td>\n";
|
|
}
|
|
print <<END
|
|
</tr>
|
|
</table>
|
|
END
|
|
;
|
|
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'} && $cgiparams{'KEY2'} eq "0" && ($cgiparams{'ORIG_IP'} eq "0" || $cgiparams{'ORIG_IP'} eq "0.0.0.0/0")){
|
|
# if it is a port forward rule with a 0 in the orig_port field, this means there are xtaccess records, and we
|
|
# don't want to allow a person to change the orig_ip field as it will mess other logic up
|
|
print "<input type='hidden' name='ORIG_IP' value='$cgiparams{'ORIG_IP'}' />\n";
|
|
} else {
|
|
print <<END
|
|
<table>
|
|
<tr>
|
|
<td class='base'><font class='boldbase' color='${Header::colourred}'>$Lang::tr{'source network'}</font> <img src='/blob.gif' alt='*' /> </td>
|
|
<td><input type='text' name='ORIG_IP' value='$cgiparams{'ORIG_IP'}' size='15' /></td>
|
|
</tr>
|
|
</table>
|
|
END
|
|
;
|
|
}
|
|
|
|
print <<END
|
|
<table width='100%'>
|
|
<hr />
|
|
<tr>
|
|
<td class='base' width='25%'><img src='/blob.gif' alt ='*' align='top' /> <font class='base'>$Lang::tr{'this field may be blank'}</font></td>
|
|
END
|
|
;
|
|
|
|
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'}){
|
|
if($cgiparams{'KEY2'} eq "0"){
|
|
print "<td width='35%' align='right'>$Lang::tr{'open to all'}: </td><td width='5%'><input type='checkbox' name='OVERRIDE' $checked{'OVERRIDE'}{'on'} /></td>\n";
|
|
} else {
|
|
print "<td width='40%'> </td>\n";
|
|
}
|
|
print "<td align='center' width='15%'><input type='submit' name='ACTION' value='$Lang::tr{'update'}' />";
|
|
print "<input type='hidden' name='KEY1' value='$cgiparams{'KEY1'}' />";
|
|
print "<input type='hidden' name='KEY2' value='$cgiparams{'KEY2'}' /></TD>";
|
|
print "<td align='center' width='15%'><input type='submit' name='ACTION' value='$Lang::tr{'reset'}' /></td>";
|
|
# on an edit and an xtaccess add, for some reason the "Reset" button stops working, so I make it a submit button
|
|
} else {
|
|
print "<td width='30%'> </td>\n";
|
|
print "<td align='center' width='15%'><input type='submit' name='ACTION' value='$Lang::tr{'add'}' /></td>";
|
|
if ($cgiparams{'ACTION'} eq $Lang::tr{'add xtaccess'}) {
|
|
print "<td align='center' width='15%'><input type='hidden' name='KEY1' value='$cgiparams{'KEY1'}' />";
|
|
print "<input type='hidden' name='KEY2' value='$cgiparams{'KEY2'}' />";
|
|
print "<input type='submit' name='ACTION' value='$Lang::tr{'reset'}' /></td>";
|
|
} elsif ($errormessage ne '') {
|
|
print "<td align='center' width='15%'><input type='submit' name='ACTION' value='$Lang::tr{'reset'}' /></td>";
|
|
} else {
|
|
print "<td align='center' width='15%'><input type='reset' name='ACTION' value='$Lang::tr{'reset'}' /></td>";
|
|
}
|
|
}
|
|
print <<END
|
|
<td width='5%' align='right'> </td>
|
|
</tr>
|
|
</table>
|
|
END
|
|
;
|
|
&Header::closebox();
|
|
|
|
print "</form>\n";
|
|
|
|
&Header::openbox('100%', 'left', $Lang::tr{'current rules'});
|
|
print <<END
|
|
<table width='100%'>
|
|
<tr>
|
|
<td width='7%' class='boldbase' align='center'><b>$Lang::tr{'proto'}</b></td>
|
|
<td width='31%' class='boldbase' align='center'><b>$Lang::tr{'source'}</b></td>
|
|
<td width='2%' class='boldbase' align='center'> </td>
|
|
<td width='31%' class='boldbase' align='center'><b>$Lang::tr{'destination'}</b></td>
|
|
<td width='24%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b></td>
|
|
<td width='4%' class='boldbase' colspan='4' align='center'><b>$Lang::tr{'action'}</b></td>
|
|
</tr>
|
|
END
|
|
;
|
|
|
|
my $id = 0;
|
|
my $xtaccesscolor = '#F6F4F4';
|
|
open(RULES, "$filename") or die 'Unable to open config file.';
|
|
while (<RULES>)
|
|
{
|
|
my $protocol = '';
|
|
my $gif = '';
|
|
my $gdesc = '';
|
|
my $toggle = '';
|
|
chomp($_);
|
|
my @temp = split(/\,/,$_);
|
|
$temp[9] ='' unless defined $temp[9];# Glles ESpinasse : suppress warning on page init
|
|
if ($temp[2] eq 'udp') {
|
|
$protocol = 'UDP'; }
|
|
elsif ($temp[2] eq 'gre') {
|
|
$protocol = 'GRE' }
|
|
else {
|
|
$protocol = 'TCP' }
|
|
# Change bgcolor when a new portfw rule is added
|
|
if ($temp[1] eq "0"){
|
|
$id++;
|
|
}
|
|
# Darren Critchley highlight the row we are editing
|
|
if ( $cgiparams{'ACTION'} eq $Lang::tr{'edit'} && $cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1] ) {
|
|
print "<tr bgcolor='${Header::colouryellow}'>\n";
|
|
} else {
|
|
if ($id % 2) {
|
|
print "<tr bgcolor='${Header::table1colour}'>\n";
|
|
}
|
|
else {
|
|
print "<tr bgcolor='${Header::table2colour}'>\n";
|
|
}
|
|
}
|
|
|
|
if ($temp[6] eq 'on') { $gif = 'on.gif'; $toggle='off'; $gdesc=$Lang::tr{'click to disable'};}
|
|
else { $gif = 'off.gif'; $toggle='on'; $gdesc=$Lang::tr{'click to enable'}; }
|
|
|
|
# Darren Critchley - this code no longer works - should we remove?
|
|
# catch for 'old-style' rules file - assume default ip if
|
|
# none exists
|
|
if (!&General::validip($temp[7]) || $temp[7] eq '0.0.0.0') {
|
|
$temp[7] = 'DEFAULT IP'; }
|
|
if ($temp[1] eq '0') { # Port forwarding entry
|
|
|
|
# Darren Critchley - Format the source and destintation ports
|
|
my $srcprt = $temp[3];
|
|
$srcprt =~ s/-/ - /;
|
|
$srcprt =~ s/:/ - /;
|
|
my $dstprt = $temp[5];
|
|
$dstprt =~ s/-/ - /;
|
|
$dstprt =~ s/:/ - /;
|
|
|
|
# Darren Critchley - Get Port Service Name if we can - code borrowed from firewalllog.dat
|
|
$_=$temp[3];
|
|
if (/^\d+$/) {
|
|
my $servi = uc(getservbyport($temp[3], lc($temp[2])));
|
|
if ($servi ne '' && $temp[3] < 1024) {
|
|
$srcprt = "$srcprt($servi)"; }
|
|
}
|
|
$_=$temp[5];
|
|
if (/^\d+$/) {
|
|
my $servi = uc(getservbyport($temp[5], lc($temp[2])));
|
|
if ($servi ne '' && $temp[5] < 1024) {
|
|
$dstprt = "$dstprt($servi)"; }
|
|
}
|
|
|
|
# Darren Critchley - If the line is too long, wrap the port numbers
|
|
my $srcaddr = "$temp[7] : $srcprt";
|
|
if (length($srcaddr) > 22) {
|
|
$srcaddr = "$temp[7] :<br /> $srcprt";
|
|
}
|
|
my $dstaddr = "$temp[4] : $dstprt";
|
|
if (length($dstaddr) > 26) {
|
|
$dstaddr = "$temp[4] :<br /> $dstprt";
|
|
}
|
|
print <<END
|
|
<td align='center'>$protocol</td>
|
|
<td align='center'>$srcaddr</td>
|
|
<td align='center'><img src='/images/forward.gif' alt='=>' /></td>
|
|
<td align='center'>$dstaddr</td>
|
|
<td align='left'> $temp[9]</td>
|
|
<td align='center'>
|
|
<form method='post' name='frm$temp[0]c' action='$ENV{'SCRIPT_NAME'}'>
|
|
<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
|
|
<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
|
|
<input type='hidden' name='KEY1' value='$temp[0]' />
|
|
<input type='hidden' name='KEY2' value='$temp[1]' />
|
|
<input type='hidden' name='ENABLED' value='$toggle' />
|
|
</form>
|
|
</td>
|
|
|
|
<td align='center'>
|
|
<form method='post' name='frm$temp[0]' action='$ENV{'SCRIPT_NAME'}'>
|
|
<input type='hidden' name='ACTION' value='$Lang::tr{'add xtaccess'}' />
|
|
<input type='image' name='$Lang::tr{'add xtaccess'}' src='/images/add.gif' alt='$Lang::tr{'add xtaccess'}' title='$Lang::tr{'add xtaccess'}' />
|
|
<input type='hidden' name='KEY1' value='$temp[0]' />
|
|
<input type='hidden' name='KEY2' value='$temp[1]' />
|
|
</form>
|
|
</td>
|
|
|
|
<td align='center'>
|
|
<form method='post' name='frm$temp[0]' action='$ENV{'SCRIPT_NAME'}'>
|
|
<input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
|
|
<input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
|
|
<input type='hidden' name='KEY1' value='$temp[0]' />
|
|
<input type='hidden' name='KEY2' value='$temp[1]' />
|
|
</form>
|
|
</td>
|
|
|
|
<td align='center'>
|
|
<form method='post' name='frm$temp[0]b' action='$ENV{'SCRIPT_NAME'}'>
|
|
<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
|
|
<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
|
|
<input type='hidden' name='KEY1' value='$temp[0]' />
|
|
<input type='hidden' name='KEY2' value='$temp[1]' />
|
|
</form>
|
|
</td>
|
|
|
|
</tr>
|
|
END
|
|
;
|
|
} else { # external access entry
|
|
print <<END
|
|
<td align='center'> </td>
|
|
|
|
<td align='left' colspan='4'> <font color='${Header::colourred}'>$Lang::tr{'access allowed'}</font> $temp[8] ($temp[9])</td>
|
|
|
|
<td align='center'>
|
|
<form method='post' name='frm$temp[0]$temp[1]t' action='$ENV{'SCRIPT_NAME'}'>
|
|
<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$Lang::tr{'toggle enable disable'}' title='$Lang::tr{'toggle enable disable'}' />
|
|
<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
|
|
<input type='hidden' name='KEY1' value='$temp[0]' />
|
|
<input type='hidden' name='KEY2' value='$temp[1]' />
|
|
<input type='hidden' name='ENABLED' value='$toggle' />
|
|
</form>
|
|
</td>
|
|
|
|
<td align='center'> </td>
|
|
|
|
<td align='center'>
|
|
<form method='post' name='frm$temp[0]$temp[1]' action='$ENV{'SCRIPT_NAME'}'>
|
|
<input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
|
|
<input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
|
|
<input type='hidden' name='KEY1' value='$temp[0]' />
|
|
<input type='hidden' name='KEY2' value='$temp[1]' />
|
|
</form>
|
|
</td>
|
|
|
|
<td align='center'>
|
|
<form method='post' name='frm$temp[0]b$temp[1]b' action='$ENV{'SCRIPT_NAME'}'>
|
|
<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
|
|
<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
|
|
<input type='hidden' name='KEY1' value='$temp[0]' />
|
|
<input type='hidden' name='KEY2' value='$temp[1]' />
|
|
</form>
|
|
</td>
|
|
|
|
</tr>
|
|
END
|
|
;
|
|
}
|
|
}
|
|
|
|
close(RULES);
|
|
|
|
print "</table>";
|
|
|
|
# If the fixed lease file contains entries, print Key to action icons
|
|
if ( ! -z "$filename") {
|
|
print <<END
|
|
<table>
|
|
<tr>
|
|
<td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td>
|
|
<td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
|
|
<td class='base'>$Lang::tr{'click to disable'}</td>
|
|
<td> </td>
|
|
<td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
|
|
<td class='base'>$Lang::tr{'click to enable'}</td>
|
|
<td> </td>
|
|
<td><img src='/images/add.gif' alt='$Lang::tr{'add xtaccess'}' /></td>
|
|
<td class='base'>$Lang::tr{'add xtaccess'}</td>
|
|
<td> </td>
|
|
<td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
|
|
<td class='base'>$Lang::tr{'edit'}</td>
|
|
<td> </td>
|
|
<td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
|
|
<td class='base'>$Lang::tr{'remove'}</td>
|
|
</tr>
|
|
</table>
|
|
END
|
|
;
|
|
}
|
|
|
|
&Header::closebox();
|
|
|
|
&Header::closebigbox();
|
|
|
|
&Header::closepage();
|
|
|
|
# Validate Field Entries
|
|
sub validateparams
|
|
{
|
|
# Darren Critchley - Get rid of dashes in port ranges
|
|
$cgiparams{'DEST_PORT'}=~ tr/-/:/;
|
|
$cgiparams{'SRC_PORT'}=~ tr/-/:/;
|
|
|
|
# Darren Critchley - code to substitue wildcards
|
|
if ($cgiparams{'SRC_PORT'} eq "*") {
|
|
$cgiparams{'SRC_PORT'} = "1:65535";
|
|
}
|
|
if ($cgiparams{'SRC_PORT'} =~ /^(\D)\:(\d+)$/) {
|
|
$cgiparams{'SRC_PORT'} = "1:$2";
|
|
}
|
|
if ($cgiparams{'SRC_PORT'} =~ /^(\d+)\:(\D)$/) {
|
|
$cgiparams{'SRC_PORT'} = "$1:65535";
|
|
}
|
|
if ($cgiparams{'DEST_PORT'} eq "*") {
|
|
$cgiparams{'DEST_PORT'} = "1:65535";
|
|
}
|
|
if ($cgiparams{'DEST_PORT'} =~ /^(\D)\:(\d+)$/) {
|
|
$cgiparams{'DEST_PORT'} = "1:$2";
|
|
}
|
|
if ($cgiparams{'DEST_PORT'} =~ /^(\d+)\:(\D)$/) {
|
|
$cgiparams{'DEST_PORT'} = "$1:65535";
|
|
}
|
|
|
|
# Darren Critchley - Add code for GRE protocol - we want to ignore ports, but we need a place holder
|
|
if ($cgiparams{'PROTOCOL'} eq 'gre') {
|
|
$cgiparams{'SRC_PORT'} = "GRE";
|
|
$cgiparams{'DEST_PORT'} = "GRE";
|
|
}
|
|
|
|
unless($cgiparams{'PROTOCOL'} =~ /^(tcp|udp|gre)$/) { $errormessage = $Lang::tr{'invalid input'}; }
|
|
# Darren Critchley - Changed how the error routine works a bit - for the validportrange check, we need to
|
|
# pass in src or dest to determine which side we are working with.
|
|
# the routine returns the complete error or ''
|
|
if ($cgiparams{'PROTOCOL'} ne 'gre') {
|
|
$errormessage = &General::validportrange($cgiparams{'SRC_PORT'}, 'src');
|
|
}
|
|
if( ($cgiparams{'ORIG_IP'} ne "0" && $cgiparams{'KEY2'} ne "0") || $cgiparams{'ACTION'} eq $Lang::tr{'add'}) {
|
|
# if it is a port forward record with 0 in orig_ip then ignore checking this field
|
|
unless(&General::validipormask($cgiparams{'ORIG_IP'}))
|
|
{
|
|
if ($cgiparams{'ORIG_IP'} ne '') {
|
|
$errormessage = $Lang::tr{'source ip bad'}; }
|
|
else {
|
|
$cgiparams{'ORIG_IP'} = '0.0.0.0/0'; }
|
|
}
|
|
}
|
|
# Darren Critchey - New rule that sets destination same as source if dest_port is blank.
|
|
if ($cgiparams{'DEST_PORT'} eq ''){
|
|
$cgiparams{'DEST_PORT'} = $cgiparams{'SRC_PORT'};
|
|
}
|
|
# Darren Critchey - Just in case error message is already set, this routine would wipe it out if
|
|
# we don't do a test here
|
|
if ($cgiparams{'PROTOCOL'} ne 'gre') {
|
|
unless($errormessage) {$errormessage = &General::validportrange($cgiparams{'DEST_PORT'}, 'dest');}
|
|
}
|
|
unless(&General::validip($cgiparams{'DEST_IP'})) { $errormessage = $Lang::tr{'destination ip bad'}; }
|
|
return;
|
|
}
|
|
|
|
# Darren Critchley - we want to make sure that a port range does not overlap another port range
|
|
sub checkportoverlap
|
|
{
|
|
my $portrange1 = $_[0]; # New port range
|
|
my $portrange2 = $_[1]; # existing port range
|
|
my @tempr1 = split(/\:/,$portrange1);
|
|
my @tempr2 = split(/\:/,$portrange2);
|
|
|
|
unless (&checkportinc($tempr1[0], $portrange2)){ return 0;}
|
|
unless (&checkportinc($tempr1[1], $portrange2)){ return 0;}
|
|
|
|
unless (&checkportinc($tempr2[0], $portrange1)){ return 0;}
|
|
unless (&checkportinc($tempr2[1], $portrange1)){ return 0;}
|
|
|
|
return 1; # Everything checks out!
|
|
}
|
|
|
|
# Darren Critchley - we want to make sure that a port entry is not within an already existing range
|
|
sub checkportinc
|
|
{
|
|
my $port1 = $_[0]; # Port
|
|
my $portrange2 = $_[1]; # Port range
|
|
my @tempr1 = split(/\:/,$portrange2);
|
|
|
|
if ($port1 < $tempr1[0] || $port1 > $tempr1[1]) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
# Darren Critchley - certain ports are reserved for Ipcop
|
|
# TCP 67,68,81,222,445
|
|
# UDP 67,68
|
|
# Params passed in -> port, rangeyn, protocol
|
|
sub disallowreserved
|
|
{
|
|
# port 67 and 68 same for tcp and udp, don't bother putting in an array
|
|
my $msg = "";
|
|
my @tcp_reserved = (81,222,444);
|
|
my $prt = $_[0]; # the port or range
|
|
my $ryn = $_[1]; # tells us whether or not it is a port range
|
|
my $prot = $_[2]; # protocol
|
|
my $srcdst = $_[3]; # source or destination
|
|
|
|
if ($ryn) { # disect port range
|
|
if ($srcdst eq "src") {
|
|
$msg = "$Lang::tr{'rsvd src port overlap'}";
|
|
} else {
|
|
$msg = "$Lang::tr{'rsvd dst port overlap'}";
|
|
}
|
|
my @tmprng = split(/\:/,$prt);
|
|
unless (67 < $tmprng[0] || 67 > $tmprng[1]) { $errormessage="$msg 67"; return; }
|
|
unless (68 < $tmprng[0] || 68 > $tmprng[1]) { $errormessage="$msg 68"; return; }
|
|
if ($prot eq "tcp") {
|
|
foreach my $prange (@tcp_reserved) {
|
|
unless ($prange < $tmprng[0] || $prange > $tmprng[1]) { $errormessage="$msg $prange"; return; }
|
|
}
|
|
}
|
|
} else {
|
|
if ($srcdst eq "src") {
|
|
$msg = "$Lang::tr{'reserved src port'}";
|
|
} else {
|
|
$msg = "$Lang::tr{'reserved dst port'}";
|
|
}
|
|
if ($prt == 67) { $errormessage="$msg 67"; return; }
|
|
if ($prt == 68) { $errormessage="$msg 68"; return; }
|
|
if ($prot eq "tcp") {
|
|
foreach my $prange (@tcp_reserved) {
|
|
if ($prange == $prt) { $errormessage="$msg $prange"; return; }
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
# Darren Critchley - Attempt to combine Add/Update validation as they are almost the same
|
|
sub valaddupdate
|
|
{
|
|
if ($cgiparams{'KEY2'} eq "0"){ # if it is a port forward rule, then validate properly
|
|
&validateparams();
|
|
} else { # it is an xtaccess rule, just check for a valid ip
|
|
unless(&General::validipormask($cgiparams{'ORIG_IP'}))
|
|
{
|
|
if ($cgiparams{'ORIG_IP'} ne '') {
|
|
$errormessage = $Lang::tr{'source ip bad'}; }
|
|
else { # this rule stops someone from adding an ALL xtaccess record
|
|
$errormessage = $Lang::tr{'xtaccess all error'};
|
|
$cgiparams{'ACTION'} = $Lang::tr{'add xtaccess'};
|
|
}
|
|
}
|
|
# Darren Critchley - check for 0.0.0.0/0 - not allowed for xtaccess
|
|
if ($cgiparams{'ORIG_IP'} eq "0.0.0.0/0" || $cgiparams{'ORIG_IP'} eq "0.0.0.0") {
|
|
$errormessage = $Lang::tr{'xtaccess all error'};
|
|
$cgiparams{'ACTION'} = $Lang::tr{'add xtaccess'};
|
|
}
|
|
}
|
|
# Darren Critchley - Remove commas from remarks
|
|
$cgiparams{'REMARK'} = &Header::cleanhtml($cgiparams{'REMARK'});
|
|
|
|
# Darren Critchley - Check to see if we are working with port ranges
|
|
our ($prtrange1, $prtrange2);
|
|
$_ = $cgiparams{'SRC_PORT'};
|
|
if ($cgiparams{'KEY2'} eq "0" && m/:/){
|
|
$prtrange1 = 1;
|
|
}
|
|
if ($cgiparams{'SRC_IP'} eq '0.0.0.0') { # Dave Roberts - only check if using DEFAULT IP
|
|
if ($prtrange1 == 1){ # check for source ports reserved for Ipcop
|
|
&disallowreserved($cgiparams{'SRC_PORT'},1,$cgiparams{'PROTOCOL'},"src");
|
|
if ($errormessage) { goto EXITSUB; }
|
|
} else { # check for source port reserved for Ipcop
|
|
&disallowreserved($cgiparams{'SRC_PORT'},0,$cgiparams{'PROTOCOL'},"src");
|
|
if ($errormessage) { goto EXITSUB; }
|
|
}
|
|
}
|
|
|
|
$_ = $cgiparams{'DEST_PORT'};
|
|
if ($cgiparams{'KEY2'} eq "0" && m/:/){
|
|
$prtrange2 = 1;
|
|
}
|
|
if ($cgiparams{'SRC_IP'} eq '0.0.0.0') { # Dave Roberts - only check if using DEFAULT IP
|
|
if ($prtrange2 == 1){ # check for destination ports reserved for IPFire
|
|
&disallowreserved($cgiparams{'DEST_PORT'},1,$cgiparams{'PROTOCOL'},"dst");
|
|
if ($errormessage) { goto EXITSUB; }
|
|
} else { # check for destination port reserved for IPFire
|
|
&disallowreserved($cgiparams{'DEST_PORT'},0,$cgiparams{'PROTOCOL'},"dst");
|
|
if ($errormessage) { goto EXITSUB; }
|
|
}
|
|
}
|
|
|
|
|
|
EXITSUB:
|
|
return;
|
|
}
|
|
|
|
# Darren Critchley - Duplicate or overlapping Port range check
|
|
sub portchecks
|
|
{
|
|
$_ = $_[0];
|
|
our ($prtrange1, $prtrange2);
|
|
if (m/:/ && $prtrange1 == 1) { # comparing two port ranges
|
|
unless (&checkportoverlap($cgiparams{'SRC_PORT'},$_[0])) {
|
|
$errormessage = "$Lang::tr{'source port overlaps'} $_[0]";
|
|
}
|
|
}
|
|
if (m/:/ && $prtrange1 == 0 && $errormessage eq '') { # compare one port to a range
|
|
unless (&checkportinc($cgiparams{'SRC_PORT'}, $_[0])) {
|
|
$errormessage = "$Lang::tr{'srcprt within existing'} $_[0]";
|
|
}
|
|
}
|
|
if (! m/:/ && $prtrange1 == 1 && $errormessage eq '') { # compare one port to a range
|
|
unless (&checkportinc($_[0], $cgiparams{'SRC_PORT'})) {
|
|
$errormessage = "$Lang::tr{'srcprt range overlaps'} $_[0]";
|
|
}
|
|
}
|
|
|
|
if ($errormessage eq ''){
|
|
$_ = $_[1];
|
|
if (m/:/ && $prtrange2 == 1) { # if true then there is a port range
|
|
unless (&checkportoverlap($cgiparams{'DEST_PORT'},$_[1])) {
|
|
$errormessage = "$Lang::tr{'destination port overlaps'} $_[1]";
|
|
}
|
|
}
|
|
if (m/:/ && $prtrange2 == 0 && $errormessage eq '') { # compare one port to a range
|
|
unless (&checkportinc($cgiparams{'DEST_PORT'}, $_[1])) {
|
|
$errormessage = "$Lang::tr{'dstprt within existing'} $_[1]";
|
|
}
|
|
}
|
|
if (! m/:/ && $prtrange2 == 1 && $errormessage eq '') { # compare one port to a range
|
|
unless (&checkportinc($_[1], $cgiparams{'DEST_PORT'})) {
|
|
$errormessage = "$Lang::tr{'dstprt range overlaps'} $_[1]";
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|