fwhosts.cgi: Fix for bug 13876 & bug 13877

sync IPFire fwhosts.cgi

commit 2398cc431a3fb2cd4141b6a846f0cd0742f6a97c
Author: Michael Tremer <michael.tremer@ipfire.org>
Date:   Thu Sep 25 17:05:32 2025 +0200

    fwhosts.cgi: Escape PROT in the right place

    Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>

commit ad995081302f6b28ea11c74e56306d94a7bee076
Author: Michael Tremer <michael.tremer@ipfire.org>
Date:   Thu Sep 25 17:02:18 2025 +0200

    fwhosts.cgi: Check country code before proceeding

    Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>

commit a2c624b99dbcecb469e6001505731049ef5cbbd3
Author: Adolf Belka <adolf.belka@ipfire.org>
Date:   Thu Sep 25 13:12:37 2025 +0200

    fwhosts.cgi Fix for bug 13876 & bug 13877

    Fixes: Bug 13876 savelocationgrp COUNTRY_CODE Stored Cross-Site Scripting
    Fixes: Bug 13877 saveservice PROT Stored Cross-Site Scripting
    Signed-off-by: Adolf Belka <adolf.belka@ipfire.org>
    Reviewed-by: Bernhard Bitsch <bbitsch@ipfire.org>
    Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>

commit 798556ec29207d5131a7600d5489f1ee92a7b87a
Author: Michael Tremer <michael.tremer@ipfire.org>
Date:   Mon Jun 23 17:16:57 2025 +0000

    fwhosts.cgi: Move the tooltip into the usage counter

    This will clutter the page less as we don't have any good icon sets.

    Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
    Tested-by: Adolf Belka <adolf.belka@ipfire.org>
    Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>

commit 61b277aa9c578a9a69e552f593a8bde421b811bc
Author: Michael Tremer <michael.tremer@ipfire.org>
Date:   Mon Jun 23 17:16:56 2025 +0000

    fwhosts.cgi: Don't show anything if a host/group is unused

    Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>

commit ca811a746a79f0e02cfb780cbd4543a057131e3a
Author: Michael Tremer <michael.tremer@ipfire.org>
Date:   Mon Jun 23 17:16:55 2025 +0000

    fwhosts.cgi: Remove whitespace issues

    Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>

commit 5511d94ed0d8ea6fd372d52cba515b4d6726abed
Author: Peer Dietzmann <dietzmann@brecht-schule.hamburg>
Date:   Mon Jun 23 17:16:54 2025 +0000

    fwhosts.cgi: Show in which firewall rule objects are being used

    Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
    Tested-by: Adolf Belka <adolf.belka@ipfire.org>
    Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>

commit 341eb00a821c4254ddd04968beed2e98e5a33aff
Author: Michael Tremer <michael.tremer@ipfire.org>
Date:   Sat May 3 15:10:16 2025 +0200

    fwhosts.cgi: Correctly show IP addresses for WireGuard RW peers

    Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>

Signed-off-by: Vincent Li <vincent.mc.li@gmail.com>
This commit is contained in:
Vincent Li
2025-10-09 17:15:40 +00:00
parent 13dfd638bf
commit 3a815d1814
4 changed files with 346 additions and 17 deletions

View File

@@ -2,7 +2,7 @@
###############################################################################
# #
# IPFire.org - A linux based firewall #
# Copyright (C) 2013 Alexander Marx <amarx@ipfire.org> #
# Copyright (C) 2013-2025 IPFire Team <info@ipfire.org> #
# #
# 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 #
@@ -703,6 +703,10 @@ if ($fwhostsettings{'ACTION'} eq 'savelocationgrp')
# Check name
if (!&validhostname($grp)){$errormessage.=$Lang::tr{'fwhost err name'};}
unless (&General::validcc($fwhostsettings{'COUNTRY_CODE'})) {
$errormessage = $Lang::tr{'fwhost invalid country code'};
}
# Check for existing group name.
if (!&checkgroup($grp) && $fwhostsettings{'update'} ne 'on'){
$errormessage = $Lang::tr{'fwhost err grpexist'};
@@ -714,7 +718,7 @@ if ($fwhostsettings{'ACTION'} eq 'savelocationgrp')
}
if ($fwhostsettings{'update'} eq 'on'){
@target=$fwhostsettings{'COUNTRY_CODE'};
@target = $fwhostsettings{'COUNTRY_CODE'};
$type='Location Group';
#check if host/net exists in grp
@@ -1544,21 +1548,20 @@ END
<select name='WG_PEER' style='width:16em;'>"
EOF
foreach my $key (sort { $Wireguard::peers{$a}[2] cmp $Wireguard::peers{$b}[2] } keys %Wireguard::peers) {
my $peer = &Wireguard::load_peer($key);
foreach my $key (sort { $Wireguard::peers{$a}[2] cmp $Wireguard::peers{$b}[2] } keys %Wireguard::peers) {
my $peer = &Wireguard::load_peer($key);
print <<EOF;
print <<EOF;
<option value="$peer->{"NAME"}">$peer->{"NAME"}</option>
EOF
}
}
print <<EOF;
print <<EOF;
</select>
</td>
</tr>
EOF
}
#OVPN networks
if (! -z $configccdnet){
print<<END;
@@ -1780,7 +1783,7 @@ sub addservice
{
$fwhostsettings{'oldsrvname'} = $fwhostsettings{'SRV_NAME'};
$fwhostsettings{'oldsrvport'} = $fwhostsettings{'SRV_PORT'};
$fwhostsettings{'oldsrvprot'} = $fwhostsettings{'PROT'};
$fwhostsettings{'oldsrvprot'} = &Header::escape($fwhostsettings{'PROT'});
$fwhostsettings{'oldsrvicmp'} = $fwhostsettings{'ICMP'};
}
print<<END;
@@ -1953,7 +1956,8 @@ END
}
my $colnet="$customnetwork{$key}[1]/".&General::subtocidr($customnetwork{$key}[2]);
my $netcount=&getnetcount($customnetwork{$key}[0]);
print"<td width='20%' $col><form method='post'>$customnetwork{$key}[0]</td><td width='15%' align='center' $col>".&getcolor($colnet)."</td><td width='40%' $col>$customnetwork{$key}[3]</td><td align='center' $col>$netcount x</td>";
my $netusedin=&getusedin($customnetwork{$key}[0]);
print"<td width='20%' $col><form method='post'>$customnetwork{$key}[0]</td><td width='15%' align='center' $col>".&getcolor($colnet)."</td><td width='40%' $col>$customnetwork{$key}[3]</td><td align='center' $col><span title='$netusedin'>$netcount x</span></td>";
print<<END;
<td width='1%' $col><input type='image' src='/images/edit.gif' align='middle' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
<input type='hidden' name='ACTION' value='editnet'>
@@ -2107,8 +2111,10 @@ END
$customhost{$key}[4]=~s/\s+//g;
my $hostcount=0;
$hostcount=&gethostcount($customhost{$key}[0]);
print"<td width='20%' $col>$customhost{$key}[0]</td><td width='20%' align='center' $col >".&getcolor($ip)."</td><td width='50%' align='left' $col>$customhost{$key}[3]</td><td align='center' $col>$hostcount x</td>";
print<<END;
my $hostusedin=&getusedin($customhost{$key}[0]);
my $color = &getcolor($ip);
print <<END;
<td width='20%' $col>$customhost{$key}[0]</td><td width='20%' align='center' $col >$color</td><td width='50%' align='left' $col>$customhost{$key}[3]</td><td align='center' $col><span title="$hostusedin">$hostcount x</span></td>
<td width='1%' $col><form method='post'><input type='image' src='/images/edit.gif' align='middle' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
<input type='hidden' name='ACTION' value='edithost' />
<input type='hidden' name='HOSTNAME' value='$customhost{$key}[0]' />
@@ -2183,7 +2189,8 @@ sub viewtablegrp
print "<br><b><u>$grpname</u></b>&nbsp; &nbsp;";
print " <b>$Lang::tr{'remark'}:</b>&nbsp $remark &nbsp " if ($remark ne '');
my $netgrpcount=&getnetcount($grpname);
print "<b>$Lang::tr{'used'}:</b> $netgrpcount x";
my $groupusedin=&getusedin($grpname);
print "<b>$Lang::tr{'used'}:</b> <span title='$groupusedin'>$netgrpcount x</span>";
if($netgrpcount == '0')
{
print"<form method='post' style='display:inline'><input type='image' src='/images/delete.gif' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' align='right' /><input type='hidden' name='grp_name' value='$grpname' ><input type='hidden' name='ACTION' value='delgrp'></form>";
@@ -2321,8 +2328,8 @@ sub viewtablelocationgrp
# Get group count.
my $locationgrpcount=&getlocationcount($grpname);
print "<b>$Lang::tr{'used'}:</b> $locationgrpcount x";
my $locationusedin=&getlocusedin($grpname);
print "<b>$Lang::tr{'used'}:</b> <span title='$locationusedin'>$locationgrpcount x</span>";
# Only display delete icon, if the group is not used by a firewall rule.
if($locationgrpcount == '0') {
print"<form method='post' style='display:inline'>\n";
@@ -2464,10 +2471,11 @@ END
END
#Neuer count
$srvcount=&getsrvcount($customservice{$key}[0]);
my $serviceusedin=&getsrvusedin($customservice{$key}[0]);
if($customservice{$key}[3] eq 'All ICMP-Types'){print $Lang::tr{'fwdfw all icmp'};}
elsif($customservice{$key}[3] ne 'BLANK'){print $customservice{$key}[3];}
print<<END;
</td><td align='center' $col>$srvcount x</td>
</td><td align='center' $col><span title='$serviceusedin'>$srvcount x</span></td>
<td width='1%' $col><form method='post'><input type='image' src='/images/edit.gif' align='middle' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' /><input type='hidden' name='ACTION' value='editservice' />
<input type='hidden' name='SRV_NAME' value='$customservice{$key}[0]' />
<input type='hidden' name='SRV_PORT' value='$customservice{$key}[1]' />
@@ -2539,7 +2547,8 @@ sub viewtableservicegrp
if($count >0){print"</table>";$count=1;}
print "<br><b><u>$grpname</u></b>&nbsp; &nbsp; ";
print "<b>$Lang::tr{'remark'}:</b>&nbsp; $remark " if ($remark ne '');
print "&nbsp; <b>$Lang::tr{'used'}:</b> $grpcount x";
my $srvgrpusedin=&getsrvusedin($customservicegrp{$key}[0]);
print "&nbsp; <b>$Lang::tr{'used'}:</b> <span title='$srvgrpusedin'>$grpcount x</span>";
if($grpcount == '0')
{
print"<form method='post' style='display:inline'><input type='image' src='/images/delete.gif' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' align='right' /><input type='hidden' name='SRVGRP_NAME' value='$grpname' ><input type='hidden' name='ACTION' value='delservicegrp'></form>";
@@ -2812,6 +2821,106 @@ sub getlocationcount
}
return $counter;
}
sub getlocusedin
{
my $groupname=shift;
my $titletext="";
# Location groups are stored as "group:groupname" in the
# firewall settings files.
my $searchstring = join(':', "group",$groupname);
#Count services used in firewall - config
my $fwfwtext="";
# first set title if found
foreach my $key1 (keys %fwfwd) {
if($fwfwd{$key1}[4] eq $searchstring){
$fwfwtext = "$Lang::tr{'firewall rules'}:";
}
if($fwfwd{$key1}[6] eq $searchstring){
$fwfwtext = "$Lang::tr{'firewall rules'}:";
}
}
# then add rule numbers
my @fwfwrules = ();
foreach my $key1 (keys %fwfwd) {
if($fwfwd{$key1}[4] eq $searchstring){
push(@fwfwrules, $key1);
}
if($fwfwd{$key1}[6] eq $searchstring){
push(@fwfwrules, $key1);
}
}
my @fwfwarraysorted = sort { $a <=> $b } @fwfwrules;
foreach my $rule (@fwfwarraysorted)
{
$fwfwtext .= "&#010- $rule";
}
#Count services used in firewall - input
my $fwintext="";
foreach my $key2 (keys %fwinp) {
if($fwinp{$key2}[4] eq $searchstring){
$fwintext = "$Lang::tr{'incoming firewall access'}:";
}
if($fwinp{$key2}[6] eq $searchstring){
$fwintext = "$Lang::tr{'incoming firewall access'}:";
}
}
my @fwinrules = ();
foreach my $key2 (keys %fwinp) {
if($fwinp{$key2}[4] eq $searchstring){
push(@fwinrules, $key2);
}
if($fwinp{$key2}[6] eq $searchstring){
push(@fwinrules, $key2);
}
}
my @fwinarraysorted = sort { $a <=> $b } @fwinrules;
foreach my $rule (@fwinarraysorted)
{
$fwintext .= "&#010- $rule";
}
#Count services used in firewall - outgoing
my $fwouttext="";
foreach my $key3 (keys %fwout) {
if($fwout{$key3}[4] eq $searchstring){
$fwouttext = "$Lang::tr{'outgoing firewall access'}:";
}
if($fwout{$key3}[6] eq $searchstring){
$fwouttext = "$Lang::tr{'outgoing firewall access'}:";
}
}
my @fwoutrules = ();
foreach my $key3 (keys %fwout) {
if($fwout{$key3}[4] eq $searchstring){
push(@fwoutrules, $key3);
}
if($fwout{$key3}[6] eq $searchstring){
push(@fwoutrules, $key3);
}
}
my @fwoutarraysorted = sort { $a <=> $b } @fwoutrules;
foreach my $rule (@fwoutarraysorted)
{
$fwouttext .= "&#010- $rule";
}
if ($fwfwtext) {
$titletext .= "$fwfwtext"
}
if ($fwintext) {
if ($titletext) {
$titletext .= "&#010 "
}
$titletext .= "$fwintext"
}
if ($fwouttext) {
if ($titletext) {
$titletext .= "&#010 "
}
$titletext .= "$fwouttext"
}
return $titletext;
}
sub getnetcount
{
my $searchstring=shift;
@@ -2851,6 +2960,122 @@ sub getnetcount
}
return $srvcounter;
}
sub getusedin
{
my $searchstring=shift;
my $titletext="";
my $groups=();
my $rules=();
#Count services used in Network/Host group
my $servicegrouptext="";
foreach my $key (keys %customgrp) {
if($customgrp{$key}[2] eq $searchstring){
$servicegrouptext = "$Lang::tr{'fwhost cust grp'}:";
}
}
foreach my $key (keys %customgrp) {
if($customgrp{$key}[2] eq $searchstring){
$servicegrouptext .= "&#010- $customgrp{$key}[0]";
}
}
#Count services used in firewall - config
my $fwfwtext="";
# first set title if found
foreach my $key1 (keys %fwfwd) {
if($fwfwd{$key1}[4] eq $searchstring){
$fwfwtext = "$Lang::tr{'firewall rules'}:";
}
if($fwfwd{$key1}[6] eq $searchstring){
$fwfwtext = "$Lang::tr{'firewall rules'}:";
}
}
# then add rule numbers
my @fwfwrules = ();
foreach my $key1 (keys %fwfwd) {
if($fwfwd{$key1}[4] eq $searchstring){
push(@fwfwrules, $key1);
}
if($fwfwd{$key1}[6] eq $searchstring){
push(@fwfwrules, $key1);
}
}
my @fwfwarraysorted = sort { $a <=> $b } @fwfwrules;
foreach my $rule (@fwfwarraysorted)
{
$fwfwtext .= "&#010- $rule";
}
#Count services used in firewall - input
my $fwintext="";
foreach my $key2 (keys %fwinp) {
if($fwinp{$key2}[4] eq $searchstring){
$fwintext = "$Lang::tr{'incoming firewall access'}:";
}
if($fwinp{$key2}[6] eq $searchstring){
$fwintext = "$Lang::tr{'incoming firewall access'}:";
}
}
my @fwinrules = ();
foreach my $key2 (keys %fwinp) {
if($fwinp{$key2}[4] eq $searchstring){
push(@fwinrules, $key2);
}
if($fwinp{$key2}[6] eq $searchstring){
push(@fwinrules, $key2);
}
}
my @fwinarraysorted = sort { $a <=> $b } @fwinrules;
foreach my $rule (@fwinarraysorted)
{
$fwintext .= "&#010- $rule";
}
#Count services used in firewall - outgoing
my $fwouttext="";
foreach my $key3 (keys %fwout) {
if($fwout{$key3}[4] eq $searchstring){
$fwouttext = "$Lang::tr{'outgoing firewall access'}:";
}
if($fwout{$key3}[6] eq $searchstring){
$fwouttext = "$Lang::tr{'outgoing firewall access'}:";
}
}
my @fwoutrules = ();
foreach my $key3 (keys %fwout) {
if($fwout{$key3}[4] eq $searchstring){
push(@fwoutrules, $key3);
}
if($fwout{$key3}[6] eq $searchstring){
push(@fwoutrules, $key3);
}
}
my @fwoutarraysorted = sort { $a <=> $b } @fwoutrules;
foreach my $rule (@fwoutarraysorted)
{
$fwouttext .= "&#010- $rule";
}
if ($servicegrouptext) {
$titletext .= "$servicegrouptext"
}
if ($fwfwtext) {
if ($titletext) {
$titletext .= "&#010 "
}
$titletext .= "$fwfwtext"
}
if ($fwintext) {
if ($titletext) {
$titletext .= "&#010 "
}
$titletext .= "$fwintext"
}
if ($fwouttext) {
if ($titletext) {
$titletext .= "&#010 "
}
$titletext .= "$fwouttext"
}
return $titletext
}
sub getsrvcount
{
my $searchstring=shift;
@@ -2881,6 +3106,100 @@ sub getsrvcount
}
return $srvcounter;
}
sub getsrvusedin
{
my $searchstring=shift;
my $titletext="";
#Count services used in servicegroups
my $servicegrouptext="";
foreach my $key (keys %customservicegrp) {
if($customservicegrp{$key}[2] eq $searchstring){
$servicegrouptext = "$Lang::tr{'outgoing firewall access'}:";
}
}
foreach my $key (keys %customservicegrp) {
if($customservicegrp{$key}[2] eq $searchstring){
$servicegrouptext .= "&#010- $customservicegrp{$key}[0]";
}
}
my $fwfwtext="";
# first set title if found
foreach my $key1 (keys %fwfwd) {
if($fwfwd{$key1}[15] eq $searchstring){
$fwfwtext = "$Lang::tr{'firewall rules'}:";
}
}
# then add rule numbers
my @fwfwrules = ();
foreach my $key1 (keys %fwfwd) {
if($fwfwd{$key1}[15] eq $searchstring){
push(@fwfwrules, $key1);
}
}
my @fwfwarraysorted = sort { $a <=> $b } @fwfwrules;
foreach my $rule (@fwfwarraysorted)
{
$fwfwtext .= "&#010- $rule";
}
#Count services used in firewall - input
my $fwintext="";
foreach my $key2 (keys %fwinp) {
if($fwinp{$key2}[15] eq $searchstring){
$fwintext = "$Lang::tr{'incoming firewall access'}:";
}
}
my @fwinrules = ();
foreach my $key2 (keys %fwinp) {
if($fwinp{$key2}[15] eq $searchstring){
push(@fwinrules, $key2);
}
}
my @fwinarraysorted = sort { $a <=> $b } @fwinrules;
foreach my $rule (@fwinarraysorted)
{
$fwintext .= "&#010- $rule";
}
#Count services used in firewall - outgoing
my $fwouttext="";
foreach my $key3 (keys %fwout) {
if($fwout{$key3}[15] eq $searchstring){
$fwouttext = "$Lang::tr{'outgoing firewall access'}:";
}
}
my @fwoutrules = ();
foreach my $key3 (keys %fwout) {
if($fwout{$key3}[15] eq $searchstring){
push(@fwoutrules, $key3);
}
}
my @fwoutarraysorted = sort { $a <=> $b } @fwoutrules;
foreach my $rule (@fwoutarraysorted)
{
$fwouttext .= "&#010- $rule";
}
if ($servicegrouptext ne '') {
$titletext .= "$servicegrouptext";
}
if ($fwfwtext ne '') {
if ($titletext) {
$titletext .= "&#010 ";
}
$titletext .= "$fwfwtext";
}
if ($fwintext ne '') {
if ($titletext) {
$titletext .= "&#010 ";
}
$titletext .= "$fwintext";
}
if ($fwouttext) {
if ($titletext ne '') {
$titletext .= "&#010 ";
}
$titletext .= "$fwouttext";
}
return $titletext
}
sub deletefromgrp
{
my $target=shift;