use strict;
use Sort::Naturally;
+use utf8;
+use feature 'unicode_strings';
+
no warnings 'uninitialized';
+
# enable only the following on debugging purpose
#use warnings;
#use CGI::Carp 'fatalsToBrowser';
&General::readhasharray("$configipsec", \%ipsecconf);
&Header::showhttpheaders();
&Header::getcgihash(\%fwdfwsettings);
-&Header::openpage($Lang::tr{'fwdfw menu'}, 1, '');
+&Header::openpage($Lang::tr{'firewall rules'}, 1, '');
&Header::openbigbox('100%', 'center',$errormessage);
#### JAVA SCRIPT ####
print<<END;
$errormessage=&checksource;
if(!$errormessage){&checktarget;}
if(!$errormessage){&checkrule;}
+
#check if manual ip (source) is orange network
if ($fwdfwsettings{'grp1'} eq 'src_addr'){
my ($sip,$scidr) = split("/",$fwdfwsettings{$fwdfwsettings{'grp1'}});
if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && !&validremark($fwdfwsettings{'ruleremark'})){
$errormessage=$Lang::tr{'fwdfw err remark'}."<br>";
}
+ if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && &validremark($fwdfwsettings{'ruleremark'})){
+ $errormessage='';
+ }
if ($fwdfwsettings{'oldruleremark'} eq $fwdfwsettings{'ruleremark'}){
$fwdfwsettings{'nosave'} = 'on';
}
if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && !&validremark($fwdfwsettings{'ruleremark'})){
$errormessage=$Lang::tr{'fwdfw err remark'}."<br>";
}
+ if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && &validremark($fwdfwsettings{'ruleremark'})){
+ $errormessage='';
+ }
if ($fwdfwsettings{'oldruleremark'} eq $fwdfwsettings{'ruleremark'}){
$fwdfwsettings{'nosave'} = 'on';
}
if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && !&validremark($fwdfwsettings{'ruleremark'})){
$errormessage=$Lang::tr{'fwdfw err remark'}."<br>";
}
+ if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && &validremark($fwdfwsettings{'ruleremark'})){
+ $errormessage='';
+ }
if ($fwdfwsettings{'oldruleremark'} eq $fwdfwsettings{'ruleremark'}){
$fwdfwsettings{'nosave'} = 'on';
}
return $errormessage;
}
}elsif($fwdfwsettings{'src_addr'} eq $fwdfwsettings{$fwdfwsettings{'grp1'}} && $fwdfwsettings{'src_addr'} eq ''){
- $errormessage.=$Lang::tr{'fwdfw err nosrcip'};
- return $errormessage;
+ $fwdfwsettings{'grp1'}='std_net_src';
+ $fwdfwsettings{$fwdfwsettings{'grp1'}} = 'ALL';
}
#check empty fields
}
}
}else{
- $errormessage=$Lang::tr{'fwdfw dnat error'}."<br>";
- return $errormessage;
+ if ($fwdfwsettings{'grp2'} ne 'ipfire'){
+ $errormessage=$Lang::tr{'fwdfw dnat error'}."<br>";
+ return $errormessage;
+ }
}
}
if ($fwdfwsettings{'tgt_addr'} eq $fwdfwsettings{$fwdfwsettings{'grp2'}} && $fwdfwsettings{'tgt_addr'} ne ''){
return $errormessage;
}
}elsif($fwdfwsettings{'tgt_addr'} eq $fwdfwsettings{$fwdfwsettings{'grp2'}} && $fwdfwsettings{'tgt_addr'} eq ''){
- $errormessage.=$Lang::tr{'fwdfw err notgtip'};
- return $errormessage;
+ $fwdfwsettings{'grp2'}='std_net_tgt';
+ $fwdfwsettings{$fwdfwsettings{'grp2'}} = 'ALL';
}
#check for mac in targetgroup
if ($fwdfwsettings{'grp2'} eq 'cust_grp_tgt'){
&base;
}
}
+sub del_double
+{
+ my %all=();
+ @all{@_}=1;
+ return (keys %all);
+}
sub disable_rule
{
my $key1=shift;
my $name=shift;
&General::readhasharray("$configsrv", \%customservice);
&General::readhasharray("$configsrvgrp", \%customservicegrp);
- my $tcp;
- my $udp;
- my $icmp;
@protocols=();
+ my @specprot=("IPIP","IPV6","IGMP","GRE","AH","ESP");
if($type eq 'service'){
foreach my $key (sort { ncmp($customservice{$a}[0],$customservice{$b}[0]) } keys %customservice){
if ($customservice{$key}[0] eq $name){
}elsif($type eq 'group'){
foreach my $key (sort { ncmp($customservicegrp{$a}[0],$customservicegrp{$b}[0]) } keys %customservicegrp){
if ($customservicegrp{$key}[0] eq $name){
- foreach my $key1 (sort { ncmp($customservice{$a}[0],$customservice{$b}[0]) } keys %customservice){
- if ($customservice{$key1}[0] eq $customservicegrp{$key}[2]){
- if($customservice{$key1}[2] eq 'TCP'){
- $tcp='TCP';
- }elsif($customservice{$key1}[2] eq 'ICMP'){
- $icmp='ICMP';
- }elsif($customservice{$key1}[2] eq 'UDP'){
- $udp='UDP';
+ if ($customservicegrp{$key}[2] ~~ @specprot){
+ push (@protocols," ".$customservicegrp{$key}[2]);
+ }else{
+ foreach my $key1 (sort { ncmp($customservice{$a}[0],$customservice{$b}[0]) } keys %customservice){
+ if ($customservice{$key1}[0] eq $customservicegrp{$key}[2]){
+ if (!grep(/$customservice{$key1}[2]/, @protocols)){
+ push (@protocols,$customservice{$key1}[2]);}
}
}
}
}
}
}
- if($tcp && $udp && $icmp){
- push (@protocols,"TCP,UDP, <br>ICMP");
- return @protocols;
- }
- if($tcp){
- push (@protocols,"TCP");
- }
- if($udp){
- push (@protocols,"UDP");
- }
- if($icmp){
- push (@protocols,"ICMP");
- }
+
+ # Sort protocols alphabetically.
+ @protocols = sort(@protocols);
+
return @protocols;
}
sub getcolor
my $val=shift;
my $hash=shift;
if($optionsfw{'SHOWCOLORS'} eq 'on'){
+ # Don't colourise MAC addresses
+ if (&General::validmac($val)) {
+ $tdcolor = "";
+ return;
+ }
+
#custom Hosts
if ($nettype eq 'cust_host_src' || $nettype eq 'cust_host_tgt'){
foreach my $key (sort keys %$hash){
return;
}elsif($val =~ /^(.*?)\/(.*?)$/){
my ($sip,$scidr) = split ("/",$val);
- if ( &General::IpInSubnet($sip,$netsettings{'ORANGE_ADDRESS'},$netsettings{'ORANGE_NETMASK'})){
+ if ( &Header::orange_used() && &General::IpInSubnet($sip,$netsettings{'ORANGE_ADDRESS'},$netsettings{'ORANGE_NETMASK'})){
$tdcolor="style='background-color: $Header::colourorange;color:white;'";
return;
}
$tdcolor="style='background-color: $Header::colourgreen;color:white;'";
return;
}
- if ( &General::IpInSubnet($sip,$netsettings{'BLUE_ADDRESS'},$netsettings{'BLUE_NETMASK'})){
+ if ( &Header::blue_used() && &General::IpInSubnet($sip,$netsettings{'BLUE_ADDRESS'},$netsettings{'BLUE_NETMASK'})){
$tdcolor="style='background-color: $Header::colourblue;color:white;'";
return;
}
}
#Check if IP is part of a IPsec N2N network
foreach my $key (sort keys %ipsecconf){
- my ($a,$b) = split("/",$ipsecconf{$key}[11]);
- $b=&General::iporsubtodec($b);
- if (&General::IpInSubnet($c,$a,$b)){
- $tdcolor="style='background-color: $Header::colourvpn;color:white;'";
- return;
+ if ($ipsecconf{$key}[11]){
+ my ($a,$b) = split("/",$ipsecconf{$key}[11]);
+ $b=&General::iporsubtodec($b);
+ if (&General::IpInSubnet($c,$a,$b)){
+ $tdcolor="style='background-color: $Header::colourvpn;color:white;'";
+ return;
+ }
}
}
}
$selected{'TIME_TO'}{$fwdfwsettings{'TIME_TO'}} = 'selected';
$selected{'ipfire'}{$fwdfwsettings{$fwdfwsettings{'grp2'}}} ='selected';
$selected{'ipfire_src'}{$fwdfwsettings{$fwdfwsettings{'grp1'}}} ='selected';
+ $selected{'dnat'}{$fwdfwsettings{'dnat'}} ='selected';
+ $selected{'snat'}{$fwdfwsettings{'snat'}} ='selected';
}
}
$fwdfwsettings{'oldgrp1a'}=$fwdfwsettings{'grp1'};
my ($sip,$scidr) = split("/",$fwdfwsettings{$fwdfwsettings{'grp1'}});
if ($scidr eq '32'){$fwdfwsettings{$fwdfwsettings{'grp1'}}=$sip;}
my ($dip,$dcidr) = split("/",$fwdfwsettings{$fwdfwsettings{'grp2'}});
- if ($scidr eq '32'){$fwdfwsettings{$fwdfwsettings{'grp2'}}=$dip;}
+ if ($dcidr eq '32'){$fwdfwsettings{$fwdfwsettings{'grp2'}}=$dip;}
&Header::openbox('100%', 'left', $Lang::tr{'fwdfw source'});
#------SOURCE-------------------------------------------------------
print "<form method='post'>";
if (! -z "${General::swroot}/ethernet/aliases"){
foreach my $alias (sort keys %aliases)
{
- print "<option value='$alias' $selected{'ipfire'}{$alias}>$alias</option>";
+ print "<option value='$alias' $selected{'ipfire_src'}{$alias}>$alias ($aliases{$alias}{'IPT'})</option>";
}
}
print<<END;
</td>
END
- if (%aliases) {
- print <<END;
+ print <<END;
<td width='25%' align='right'>$Lang::tr{'dnat address'}:</td>
<td width='30%'>
<select name='dnat' style='width: 100%;'>
- <option value='Default IP' $selected{'dnat'}{'Default IP'}>$Lang::tr{'default ip'} ($netsettings{'RED_ADDRESS'})</option>
+ <option value='AUTO' $selected{'dnat'}{'AUTO'}>- $Lang::tr{'automatic'} -</option>
+ <option value='Default IP' $selected{'dnat'}{'Default IP'}>$Lang::tr{'red1'} ($redip)</option>
END
+ if (%aliases) {
foreach my $alias (sort keys %aliases) {
print "<option value='$alias' $selected{'dnat'}{$alias}>$alias ($aliases{$alias}{'IPT'})</option>";
}
-
- print "</select>";
- } else {
- print <<END;
- <td colspan="2" width='55%'>
- <input type='hidden' name='dnat' value='Default IP'>
- </td>
-END
}
+ #DNAT Dropdown
+ foreach my $network (sort keys %defaultNetworks)
+ {
+ if ($defaultNetworks{$network}{'NAME'} eq 'BLUE'||$defaultNetworks{$network}{'NAME'} eq 'GREEN' ||$defaultNetworks{$network}{'NAME'} eq 'ORANGE'){
+ print "<option value='$defaultNetworks{$network}{'NAME'}'";
+ print " selected='selected'" if ($fwdfwsettings{'dnat'} eq $defaultNetworks{$network}{'NAME'});
+ print ">$network ($defaultNetworks{$network}{'NET'})</option>";
+ }
+ }
+ print "</select>";
print "</tr>";
#SNAT
foreach my $alias (sort keys %aliases) {
print "<option value='$alias' $selected{'snat'}{$alias}>$alias ($aliases{$alias}{'IPT'})</option>";
}
-
- # XXX this is composed in a very ugly fashion
+ # SNAT Dropdown
foreach my $network (sort keys %defaultNetworks) {
- next if($defaultNetworks{$network}{'NAME'} eq "IPFire");
- next if($defaultNetworks{$network}{'NAME'} eq "ALL");
- next if($defaultNetworks{$network}{'NAME'} =~ /OpenVPN/i);
- next if($defaultNetworks{$network}{'NAME'} =~ /IPsec/i);
-
- print "<option value='$defaultNetworks{$network}{'NAME'}'";
- print " selected='selected'" if ($fwdfwsettings{$fwdfwsettings{'nat'}} eq $defaultNetworks{$network}{'NAME'});
- print ">$network ($defaultNetworks{$network}{'NET'})</option>";
+ if ($defaultNetworks{$network}{'NAME'} eq 'BLUE'||$defaultNetworks{$network}{'NAME'} eq 'GREEN' ||$defaultNetworks{$network}{'NAME'} eq 'ORANGE'){
+ print "<option value='$defaultNetworks{$network}{'NAME'}'";
+ print " selected='selected'" if ($fwdfwsettings{'snat'} eq $defaultNetworks{$network}{'NAME'});
+ print ">$network ($defaultNetworks{$network}{'NET'})</option>";
+ }
}
-
print <<END;
</select>
</td>
if (! -z "${General::swroot}/ethernet/aliases"){
foreach my $alias (sort keys %aliases)
{
- print "<option value='$alias' $selected{'ipfire'}{$alias}>$alias</option>";
+ print "<option value='$alias' $selected{'ipfire'}{$alias}>$alias ($aliases{$alias}{'IPT'})</option>";
}
}
print<<END;
&changerule($configfwdfw);
#print"6";
}
+ $fwdfwsettings{'ruleremark'}=~ s/,/;/g;
+ utf8::decode($fwdfwsettings{'ruleremark'});
+ $fwdfwsettings{'ruleremark'}=&Header::escape($fwdfwsettings{'ruleremark'});
if ($fwdfwsettings{'updatefwrule'} ne 'on'){
my $key = &General::findhasharraykey ($hash);
$$hash{$key}[0] = $fwdfwsettings{'RULE_ACTION'};
sub validremark
{
# Checks a hostname against RFC1035
- my $remark = $_[0];
-
- # Each part should be at least two characters in length
- # but no more than 63 characters
- if (length ($remark) < 1 || length ($remark) > 255) {
- return 0;}
- # Only valid characters are a-z, A-Z, 0-9 and -
- if ($remark !~ /^[a-zäöüA-ZÖÄÜ0-9-.:;\|_()\/\s]*$/) {
- return 0;}
- # First character can only be a letter or a digit
- if (substr ($remark, 0, 1) !~ /^[a-zäöüA-ZÖÄÜ0-9(]*$/) {
- return 0;}
- # Last character can only be a letter or a digit
- if (substr ($remark, -1, 1) !~ /^[a-zöäüA-ZÖÄÜ0-9.:;_)]*$/) {
- return 0;}
- return 1;
+ my $remark = $_[0];
+
+ # Try to decode $remark into UTF-8. If this doesn't work,
+ # we assume that the string it not sane.
+ if (!utf8::decode($remark)) {
+ return 0;
+ }
+
+ # Check if the string only contains of printable characters.
+ if ($remark =~ /^[[:print:]]*$/) {
+ return 1;
+ }
+ return 0;
}
sub viewtablerule
{
&General::readhash("/var/ipfire/ethernet/settings", \%netsettings);
&viewtablenew(\%configfwdfw, $configfwdfw, $Lang::tr{'firewall rules'});
- &viewtablenew(\%configinputfw, $configinput, $Lang::tr{'external access'});
- &viewtablenew(\%configoutgoingfw, $configoutgoing, $Lang::tr{'outgoing firewall'});
+ &viewtablenew(\%configinputfw, $configinput, $Lang::tr{'incoming firewall access'});
+ &viewtablenew(\%configoutgoingfw, $configoutgoing, $Lang::tr{'outgoing firewall access'});
}
sub viewtablenew
{
if($$hash{$key}[3] eq 'ipsec_net_src'){
if(&fwlib::get_ipsec_net_ip($host,11) eq ''){
$coloryellow='on';
- &disable_rule($key);
- $$hash{$key}[2]='';
}
}elsif($$hash{$key}[3] eq 'ovpn_net_src'){
if(&fwlib::get_ovpn_net_ip($host,1) eq ''){
$coloryellow='on';
- &disable_rule($key);
- $$hash{$key}[2]='';
}
}elsif($$hash{$key}[3] eq 'ovpn_n2n_src'){
if(&fwlib::get_ovpn_n2n_ip($host,27) eq ''){
$coloryellow='on';
- &disable_rule($key);
- $$hash{$key}[2]='';
}
}elsif($$hash{$key}[3] eq 'ovpn_host_src'){
if(&fwlib::get_ovpn_host_ip($host,33) eq ''){
$coloryellow='on';
- &disable_rule($key);
- $$hash{$key}[2]='';
}
}
}
if($$hash{$key}[5] eq 'ipsec_net_tgt'){
if(&fwlib::get_ipsec_net_ip($host,11) eq ''){
$coloryellow='on';
- &disable_rule($key);
- $$hash{$key}[2]='';
}
}elsif($$hash{$key}[5] eq 'ovpn_net_tgt'){
if(&fwlib::get_ovpn_net_ip($host,1) eq ''){
$coloryellow='on';
- &disable_rule($key);
- $$hash{$key}[2]='';
}
}elsif($$hash{$key}[5] eq 'ovpn_n2n_tgt'){
if(&fwlib::get_ovpn_n2n_ip($host,27) eq ''){
$coloryellow='on';
- &disable_rule($key);
- $$hash{$key}[2]='';
}
}elsif($$hash{$key}[5] eq 'ovpn_host_tgt'){
if(&fwlib::get_ovpn_host_ip($host,33) eq ''){
$coloryellow='on';
- &disable_rule($key);
- $$hash{$key}[2]='';
}
}
}
foreach my $netgroup (sort keys %customgrp){
if(($$hash{$key}[4] eq $customgrp{$netgroup}[0] || $$hash{$key}[6] eq $customgrp{$netgroup}[0]) && $customgrp{$netgroup}[2] eq 'none'){
$coloryellow='on';
- &disable_rule($key);
- $$hash{$key}[2]='';
}
}
foreach my $srvgroup (sort keys %customservicegrp){
if($$hash{$key}[15] eq $customservicegrp{$srvgroup}[0] && $customservicegrp{$srvgroup}[2] eq 'none'){
$coloryellow='on';
- &disable_rule($key);
- $$hash{$key}[2]='';
}
}
$$hash{'ACTIVE'}=$$hash{$key}[2];
push (@protocols,$Lang::tr{'all'});
}
- my $protz=join(",",@protocols);
+ my $protz=join(", ",@protocols);
if($protz eq 'ICMP' && $$hash{$key}[9] ne 'All ICMP-Types' && $$hash{$key}[14] ne 'cust_srvgrp'){
&General::readhasharray("${General::swroot}/fwhosts/icmp-types", \%icmptypes);
foreach my $keyicmp (sort { ncmp($icmptypes{$a}[0],$icmptypes{$b}[0]) }keys %icmptypes){
last;
}
}
+ }elsif($#protocols gt '3'){
+ print"<td align='center'><span title='$protz'>$Lang::tr{'fwdfw many'}</span></td>";
}else{
print"<td align='center'>$protz</td>";
}
<td align='center' $tdcolor>
END
#Is this a DNAT rule?
+ my $natstring;
if ($$hash{$key}[31] eq 'dnat' && $$hash{$key}[28] eq 'ON'){
- print "Firewall ($$hash{$key}[29])";
+ if ($$hash{$key}[29] eq 'Default IP'){$$hash{$key}[29]=$Lang::tr{'red1'};}
+ if ($$hash{$key}[29] eq 'AUTO'){
+ my @src_addresses=&fwlib::get_addresses(\%$hash,$key,'src');
+ my @nat_ifaces;
+ foreach my $val (@src_addresses){
+ push (@nat_ifaces,&fwlib::get_nat_address($$hash{$key}[29],$val));
+ }
+ @nat_ifaces=&del_double(@nat_ifaces);
+ $natstring = "";
+ }else{
+ $natstring = "($$hash{$key}[29])";
+ }
+ print "$Lang::tr{'firewall'} $natstring";
if($$hash{$key}[30] ne ''){
$$hash{$key}[30]=~ tr/|/,/;
print": $$hash{$key}[30]";
<font color="$Header::colourorange">$Lang::tr{'orange'}</font>
($Lang::tr{'fwdfw pol block'})
</td>
+END
+ }
+
+ print <<END;
<td align='center'>
<font color="$Header::colourgreen">$Lang::tr{'green'}</font>
($Lang::tr{'fwdfw pol block'})
</td>
+ </tr>
END
- }
-
- print"</tr>";
}
print <<END;