]>
git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - html/cgi-bin/portfw.cgi
2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2007 Michael Tremer & Christian Schmidt #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
24 # enable only the following on debugging purpose
26 #use CGI::Carp 'fatalsToBrowser';
28 require '/var/ipfire/general-functions.pl';
29 require "${General::swroot}/lang.pl";
30 require "${General::swroot}/header.pl";
32 #workaround to suppress a warning when a variable is used only once
33 my @dummy = ( ${Header
::colouryellow
} );
37 my %mainsettings = ();
38 &General
::readhash
("${General::swroot}/main/settings", \
%mainsettings);
39 &General
::readhash
("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \
%color);
46 my $errormessage = '';
47 my $filename = "${General::swroot}/portfw/config";
48 my $aliasfile = "${General::swroot}/ethernet/aliases";
50 &Header
::showhttpheaders
();
52 $cgiparams{'ENABLED'} = 'off';
53 $cgiparams{'KEY1'} = '0';
54 $cgiparams{'KEY2'} = '0';
55 $cgiparams{'PROTOCOL'} = '';
56 $cgiparams{'SRC_PORT'} = '';
57 $cgiparams{'DEST_IP'} = '';
58 $cgiparams{'DEST_PORT'} = '';
59 $cgiparams{'SRC_IP'} = '';
60 $cgiparams{'ORIG_IP'} = '';
61 $cgiparams{'REMARK'} = '';
62 $cgiparams{'OVERRIDE'} = 'off';
63 $cgiparams{'ACTION'} = '';
65 &Header
::getcgihash
(\
%cgiparams);
67 my $disable_all = "0";
70 if ($cgiparams{'ACTION'} eq $Lang::tr
{'add'})
74 # Darren Critchley - if there is an error, don't waste any more time processing
75 if ($errormessage) { goto ERROR
; }
77 open(FILE
, $filename) or die 'Unable to open config file.';
80 my $key1 = 0; # used for finding last sequence number used
81 foreach my $line (@current)
83 my @temp = split(/\,/,$line);
86 if ($cgiparams{'KEY2'} eq "0"){ # if key2 is 0 then it is a portfw addition
87 if ( $cgiparams{'SRC_PORT'} eq $temp[3] &&
88 $cgiparams{'PROTOCOL'} eq $temp[2] &&
89 $cgiparams{'SRC_IP'} eq $temp[7])
92 "$Lang::tr{'source port in use'} $cgiparams{'SRC_PORT'}";
94 # Check if key2 = 0, if it is then it is a port forward entry and we want the sequence number
95 if ( $temp[1] eq "0") {
98 # Darren Critchley - Duplicate or overlapping Port range check
99 if ($temp[1] eq "0" &&
100 $cgiparams{'PROTOCOL'} eq $temp[2] &&
101 $cgiparams{'SRC_IP'} eq $temp[7] &&
104 &portchecks
($temp[3], $temp[5]);
107 if ( $cgiparams{'KEY1'} eq $temp[0] &&
108 $cgiparams{'ORIG_IP'} eq $temp[8])
111 "$Lang::tr{'source ip in use'} $cgiparams{'ORIG_IP'}";
117 unless ($errormessage)
119 # Darren Critchley - we only want to store ranges with Colons
120 $cgiparams{'SRC_PORT'} =~ tr/-/:/;
121 $cgiparams{'DEST_PORT'} =~ tr/-/:/;
123 if ($cgiparams{'KEY1'} eq "0") { # 0 in KEY1 indicates it is a portfw add
124 $key1++; # Add one to last sequence number
125 open(FILE
,">>$filename") or die 'Unable to open config file.';
127 if ($cgiparams{'ORIG_IP'} eq '0.0.0.0/0') {
128 # if the default/all is taken, then write it to the rule
129 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";
130 } else { # else create an extra record so it shows up
131 print FILE
"$key1,0,$cgiparams{'PROTOCOL'},$cgiparams{'SRC_PORT'},$cgiparams{'DEST_IP'},$cgiparams{'DEST_PORT'},$cgiparams{'ENABLED'},$cgiparams{'SRC_IP'},0,$cgiparams{'REMARK'}\n";
132 print FILE
"$key1,1,$cgiparams{'PROTOCOL'},0,$cgiparams{'DEST_IP'},$cgiparams{'DEST_PORT'},$cgiparams{'ENABLED'},0,$cgiparams{'ORIG_IP'},$cgiparams{'REMARK'}\n";
136 &General
::log($Lang::tr
{'forwarding rule added'});
137 system('/usr/local/bin/setportfw');
138 } else { # else key1 eq 0
139 my $insertpoint = ($cgiparams{'KEY2'} - 1);
140 open(FILE
, ">$filename") or die 'Unable to open config file.';
142 foreach my $line (@current) {
144 my @temp = split(/\,/,$line);
145 if ($cgiparams{'KEY1'} eq $temp[0] && $insertpoint eq $temp[1]) {
146 if ($temp[1] eq "0") { # this is the first xtaccess rule, therefore modify the portfw rule
149 print FILE
"$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6],$temp[7],$temp[8],$temp[9]\n";
150 print FILE
"$cgiparams{'KEY1'},$cgiparams{'KEY2'},$cgiparams{'PROTOCOL'},0,$cgiparams{'DEST_IP'},$cgiparams{'DEST_PORT'},$cgiparams{'ENABLED'},0,$cgiparams{'ORIG_IP'},$cgiparams{'REMARK'}\n";
152 print FILE
"$line\n";
157 &General
::log($Lang::tr
{'external access rule added'});
158 system('/usr/local/bin/setportfw');
159 } # end if if KEY1 eq 0
160 } # end unless($errormessage)
163 if ($cgiparams{'ACTION'} eq $Lang::tr
{'update'})
167 # Darren Critchley - If there is an error don't waste any more processing time
168 if ($errormessage) { $cgiparams{'ACTION'} = $Lang::tr
{'edit'}; goto UPD_ERROR
; }
170 open(FILE
, $filename) or die 'Unable to open config file.';
171 my @current = <FILE
>;
173 my $disabledpfw = '0';
175 my $xtaccessdel = '0';
177 foreach my $line (@current)
179 my @temp = split(/\,/,$line);
180 if ( $temp[1] eq "0" ) { # keep track of the last portfw and if it is enabled
181 $disabledpfw = $temp[6];
185 if ( $cgiparams{'SRC_PORT'} eq $temp[3] &&
186 $cgiparams{'PROTOCOL'} eq $temp[2] &&
187 $cgiparams{'SRC_IP'} eq $temp[7])
189 if ($cgiparams{'KEY1'} ne $temp[0] && $cgiparams{'KEY2'} eq "0")
192 "$Lang::tr{'source port in use'} $cgiparams{'SRC_PORT'}";
195 if ($cgiparams{'ORIG_IP'} eq $temp[8])
197 if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} ne $temp[1])
198 # If we have the same source ip within a portfw group, then we have a problem!
200 $errormessage = "$Lang::tr{'source ip in use'} $cgiparams{'ORIG_IP'}";
201 $cgiparams{'ACTION'} = $Lang::tr
{'edit'};
205 # Darren Critchley - Flag when a user disables an xtaccess
206 if ($cgiparams{'KEY1'} eq $temp[0] &&
207 $cgiparams{'KEY2'} eq $temp[1] &&
208 $cgiparams{'KEY2'} ne "0" && # if KEY2 is 0 then it is a portfw
209 $cgiparams{'ENABLED'} eq "off" &&
210 $temp[6] eq "on") { # we have determined that someone has turned an xtaccess off
214 # Darren Critchley - Portfw enabled, then enable xtaccess for all associated xtaccess records
215 if ($cgiparams{'ENABLED'} eq "on" && $cgiparams{'KEY2'} eq "0" && $cgiparams{'ENABLED'} ne $temp[6])
221 # Darren Critchley - Portfw disabled, then disable xtaccess for all associated xtaccess records
222 if ($cgiparams{'ENABLED'} eq "off" && $cgiparams{'KEY2'} eq "0")
229 # Darren Critchley - if we are enabling an xtaccess, only allow if the associated Portfw is enabled
230 if ($cgiparams{'KEY1'} eq $lastpfw && $cgiparams{'KEY2'} ne "0") { # identifies an xtaccess record in the group
231 if ($cgiparams{'ENABLED'} eq "on" && $cgiparams{'ENABLED'} ne $temp[6] ){ # a change has been made
232 if ($disabledpfw eq "off")
234 $errormessage = "$Lang::tr{'cant enable xtaccess'}";
235 $cgiparams{'ACTION'} = $Lang::tr
{'edit'};
240 # Darren Critchley - rule to stop someone from entering ALL into a external access rule,
241 # the portfw is the only place that ALL can be specified
242 if ($cgiparams{'KEY2'} ne "0" && $cgiparams{'ORIG_IP'} eq "0.0.0.0/0") {
243 $errormessage = "$Lang::tr{'xtaccess all error'}";
244 $cgiparams{'ACTION'} = $Lang::tr
{'edit'};
247 # Darren Critchley - Duplicate or overlapping Port range check
248 if ($temp[1] eq "0" &&
249 $cgiparams{'KEY1'} ne $temp[0] &&
250 $cgiparams{'PROTOCOL'} eq $temp[2] &&
251 $cgiparams{'SRC_IP'} eq $temp[7] &&
254 &portchecks
($temp[3], $temp[5]);
259 # Darren Critchley - if an xtaccess was disabled, now we need to check to see if it was the only xtaccess
260 if($xtaccessdel eq "1") {
262 foreach my $line (@current)
264 my @temp = split(/\,/,$line);
265 if($temp[0] eq $cgiparams{'KEY1'} &&
266 $temp[6] eq "on") { # we only want to count the enabled xtaccess's
276 unless ($errormessage)
278 # Darren Critchley - we only want to store ranges with Colons
279 $cgiparams{'SRC_PORT'} =~ tr/-/:/;
280 $cgiparams{'DEST_PORT'} =~ tr/-/:/;
282 open(FILE
, ">$filename") or die 'Unable to open config file.';
284 foreach my $line (@current) {
286 my @temp = split(/\,/,$line);
287 if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1]) {
288 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";
290 # Darren Critchley - If it is a port forward record, then chances are good that a change was made to
291 # Destination Ip or Port, and we need to update all the associated external access records
292 if ($cgiparams{'KEY2'} eq "0" && $cgiparams{'KEY1'} eq $temp[0]) {
293 $temp[4] = $cgiparams{'DEST_IP'};
294 $temp[5] = $cgiparams{'DEST_PORT'};
295 $temp[2] = $cgiparams{'PROTOCOL'};
298 # Darren Critchley - If a Portfw has been disabled, then set all associated xtaccess as disabled
299 if ( $disable_all eq "1" && $cgiparams{'KEY1'} eq $temp[0] ) {
302 if ( $enable_all eq "1" && $cgiparams{'KEY1'} eq $temp[0] ) {
305 # Darren Critchley - Deal with the override to allow ALL
306 if ( $cgiparams{'OVERRIDE'} eq "on" && $temp[1] ne "0" && $cgiparams{'KEY1'} eq $temp[0] ) {
309 print FILE
"$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6],$temp[7],$temp[8],$temp[9]\n";
314 &General
::log($Lang::tr
{'forwarding rule updated'});
315 system('/usr/local/bin/setportfw');
318 $cgiparams{'ACTION'} = $Lang::tr
{'edit'};
322 # Darren Critchley - Allows rules to be enabled and disabled
323 if ($cgiparams{'ACTION'} eq $Lang::tr
{'toggle enable disable'})
325 open(FILE
, $filename) or die 'Unable to open config file.';
326 my @current = <FILE
>;
328 my $disabledpfw = '0';
330 my $xtaccessdel = '0';
332 foreach my $line (@current)
334 my @temp = split(/\,/,$line);
335 if ( $temp[1] eq "0" ) { # keep track of the last portfw and if it is enabled
336 $disabledpfw = $temp[6];
339 # Darren Critchley - Flag when a user disables an xtaccess
340 if ($cgiparams{'KEY1'} eq $temp[0] &&
341 $cgiparams{'KEY2'} eq $temp[1] &&
342 $cgiparams{'KEY2'} ne "0" && # if KEY2 is 0 then it is a portfw
343 $cgiparams{'ENABLED'} eq "off" &&
344 $temp[6] eq "on") { # we have determined that someone has turned an xtaccess off
348 # Darren Critchley - Portfw enabled, then enable xtaccess for all associated xtaccess records
349 if ($cgiparams{'ENABLED'} eq "on" && $cgiparams{'KEY2'} eq "0" && $cgiparams{'ENABLED'} ne $temp[6])
355 # Darren Critchley - Portfw disabled, then disable xtaccess for all associated xtaccess records
356 if ($cgiparams{'ENABLED'} eq "off" && $cgiparams{'KEY2'} eq "0")
363 # Darren Critchley - if we are enabling an xtaccess, only allow if the associated Portfw is enabled
364 if ($cgiparams{'KEY1'} eq $lastpfw && $cgiparams{'KEY2'} ne "0") { # identifies an xtaccess record in the group
365 if ($cgiparams{'ENABLED'} eq "on" && $cgiparams{'ENABLED'} ne $temp[6] ){ # a change has been made
366 if ($disabledpfw eq "off")
368 $errormessage = "$Lang::tr{'cant enable xtaccess'}";
375 # Darren Critchley - if an xtaccess was disabled, now we need to check to see if it was the only xtaccess
376 if($xtaccessdel eq "1") {
378 foreach my $line (@current)
380 my @temp = split(/\,/,$line);
381 if($temp[0] eq $cgiparams{'KEY1'} &&
382 $temp[6] eq "on") { # we only want to count the enabled xtaccess's
391 open(FILE
, ">$filename") or die 'Unable to open config file.';
393 foreach my $line (@current) {
395 my @temp = split(/\,/,$line);
396 if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1]) {
397 print FILE
"$cgiparams{'KEY1'},$cgiparams{'KEY2'},$temp[2],$temp[3],$temp[4],$temp[5],$cgiparams{'ENABLED'},$temp[7],$temp[8],$temp[9]\n";
399 # Darren Critchley - If a Portfw has been disabled, then set all associated xtaccess as disabled
400 if ( $disable_all eq "1" && $cgiparams{'KEY1'} eq $temp[0] ) {
403 if ( $enable_all eq "1" && $cgiparams{'KEY1'} eq $temp[0] ) {
406 print FILE
"$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6],$temp[7],$temp[8],$temp[9]\n";
410 &General
::log($Lang::tr
{'forwarding rule updated'});
411 system('/usr/local/bin/setportfw');
417 # Darren Critchley - broke out Edit routine from the delete routine - Edit routine now just puts values in fields
418 if ($cgiparams{'ACTION'} eq $Lang::tr
{'edit'})
420 open(FILE
, "$filename") or die 'Unable to open config file.';
421 my @current = <FILE
>;
424 unless ($errormessage)
426 foreach my $line (@current)
429 my @temp = split(/\,/,$line);
430 if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1] ) {
431 $cgiparams{'PROTOCOL'} = $temp[2];
432 $cgiparams{'SRC_PORT'} = $temp[3];
433 $cgiparams{'DEST_IP'} = $temp[4];
434 $cgiparams{'DEST_PORT'} = $temp[5];
435 $cgiparams{'ENABLED'} = $temp[6];
436 $cgiparams{'SRC_IP'} = $temp[7];
437 $cgiparams{'ORIG_IP'} = $temp[8];
438 $cgiparams{'REMARK'} = $temp[9];
445 # Darren Critchley - broke out Remove routine as the logic is getting too complex to be combined with the Edit
446 if ($cgiparams{'ACTION'} eq $Lang::tr
{'remove'})
448 open(FILE
, "$filename") or die 'Unable to open config file.';
449 my @current = <FILE
>;
452 # If the record being deleted is an xtaccess record, and it is the only one for a portfw record
453 # then we need to adjust the portfw record to be open to ALL ip addressess or an error will occur
456 if ($cgiparams{'KEY2'} ne "0") {
458 foreach my $line (@current)
461 my @temp = split(/\,/,$line);
462 if ($temp[0] eq $cgiparams{'KEY1'}) {
471 unless ($errormessage)
473 open(FILE
, ">$filename") or die 'Unable to open config file.';
476 foreach my $line (@current)
479 my @temp = split(/\,/,$line);
481 if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1] ||
482 $cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq "0" )
486 if ($temp[0] eq $cgiparams{'KEY1'} && $temp[1] eq "0" && $fixportfw eq "1") {
487 $temp[8] = '0.0.0.0/0';
489 print FILE
"$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6],$temp[7],$temp[8],$temp[9]\n";
490 # print FILE "$line\n";
494 if ($linedeleted == 1) {
495 &General
::log($Lang::tr
{'forwarding rule removed'});
498 system('/usr/local/bin/setportfw');
502 # Darren Critchley - Added routine to allow external access rules to be added
503 if ($cgiparams{'ACTION'} eq $Lang::tr
{'add xtaccess'})
505 open(FILE
, $filename) or die 'Unable to open config file.';
506 my @current = <FILE
>;
508 my $key = 0; # used for finding last sequence number used
509 foreach my $line (@current)
511 my @temp = split(/\,/,$line);
512 if ($temp[0] eq $cgiparams{'KEY1'}) {
515 if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1] ) {
516 $cgiparams{'PROTOCOL'} = $temp[2];
517 $cgiparams{'SRC_PORT'} = $temp[3];
518 $cgiparams{'DEST_IP'} = $temp[4];
519 $cgiparams{'DEST_PORT'} = $temp[5];
520 $cgiparams{'ENABLED'} = $temp[6];
521 $cgiparams{'SRC_IP'} = $temp[7];
522 $cgiparams{'ORIG_IP'} = '';
523 $cgiparams{'REMARK'} = $temp[9];
527 $cgiparams{'KEY2'} = $key;
528 # Until the ADD button is hit, there needs to be no change to portfw rules
531 if ($cgiparams{'ACTION'} eq $Lang::tr
{'reset'})
536 if ($cgiparams{'ACTION'} eq '')
538 $cgiparams{'PROTOCOL'} = 'tcp';
539 $cgiparams{'ENABLED'} = 'on';
540 $cgiparams{'SRC_IP'} = '0.0.0.0';
543 $selected{'PROTOCOL'}{'udp'} = '';
544 $selected{'PROTOCOL'}{'tcp'} = '';
545 $selected{'PROTOCOL'}{'gre'} = '';
546 $selected{'PROTOCOL'}{$cgiparams{'PROTOCOL'}} = "selected='selected'";
548 $selected{'SRC_IP'}{$cgiparams{'SRC_IP'}} = "selected='selected'";
550 $checked{'ENABLED'}{'off'} = '';
551 $checked{'ENABLED'}{'on'} = '';
552 $checked{'ENABLED'}{$cgiparams{'ENABLED'}} = "checked='checked'";
554 &Header
::openpage
($Lang::tr
{'port forwarding configuration'}, 1, '');
556 &Header
::openbigbox
('100%', 'left', '', $errormessage);
559 &Header
::openbox
('100%', 'left', $Lang::tr
{'error messages'});
560 print "<class name='base'><font color='${Header::colourred}'>$errormessage\n</font>";
561 print " </class>\n";
565 print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>\n";
567 if ($cgiparams{'ACTION'} eq $Lang::tr
{'edit'}){
568 &Header
::openbox
('100%', 'left', $Lang::tr
{'edit a rule'});
570 &Header
::openbox
('100%', 'left', $Lang::tr
{'add a new rule'});
573 if ($cgiparams{'ACTION'} eq $Lang::tr
{'edit'} && $cgiparams{'KEY2'} ne "0" || $cgiparams{'ACTION'} eq $Lang::tr
{'add xtaccess'}){
574 # if it is not a port forward record, don't validate as the fields are disabled
575 my $PROT = "\U$cgiparams{'PROTOCOL'}\E";
576 # Darren Critchley - Format the source and destination ports
577 my $dstprt = $cgiparams{'DEST_PORT'};
584 <td class='base'>$Lang::tr{'protocol'}: <b>$PROT</b></td>
585 <td width='20'> </td>
586 <td class='base' align='right'>$Lang::tr{'destination ip'}: </td>
587 <td><b>$cgiparams{'DEST_IP'}</b></td>
588 <td width='20'> </td>
589 <td class='base' align='right'>$Lang::tr{'destination port'}: </td>
590 <td><b>$dstprt</b></td>
594 <input type='hidden' name='PROTOCOL' value='$cgiparams{'PROTOCOL'}' />
595 <input type='hidden' name='SRC_IP' value='$cgiparams{'SRC_IP'}' />
596 <input type='hidden' name='SRC_PORT' value='$cgiparams{'SRC_PORT'}' />
597 <input type='hidden' name='DEST_IP' value='$cgiparams{'DEST_IP'}' />
598 <input type='hidden' name='DEST_PORT' value='$cgiparams{'DEST_PORT'}' />
605 <td width='10%'>$Lang::tr{'protocol'}: </td>
607 <select name='PROTOCOL'>
608 <option value='tcp' $selected{'PROTOCOL'}{'tcp'}>TCP</option>
609 <option value='udp' $selected{'PROTOCOL'}{'udp'}>UDP</option>
610 <option value='gre' $selected{'PROTOCOL'}{'gre'}>GRE</option>
613 <td class='base' width='20%'><font color='${Header::colourred}'>$Lang::tr{'alias ip'}:</font></td>
615 <select name='SRC_IP'>
616 <option value='0.0.0.0' $selected{'SRC_IP'}{'0.0.0.0'}>DEFAULT IP</option>
619 open(ALIASES
, "$aliasfile") or die 'Unable to open aliases file.';
623 my @temp = split(/\,/,$_);
624 if ($temp[1] eq 'on') {
625 print "<option value='$temp[0]' $selected{'SRC_IP'}{$temp[0]}>$temp[0]";
626 if (defined $temp[2] and ($temp[2] ne '')) { print " ($temp[2])"; }
634 <td class='base' width='20%'><font color='${Header::colourred}'>$Lang::tr{'source port'}:</font></td>
635 <td width='10%'><input type='text' name='SRC_PORT' value='$cgiparams{'SRC_PORT'}' size='8' /></td>
638 <td class='base'> </td>
640 <td class='base'>$Lang::tr{'destination ip'}:</td>
641 <td><input type='text' name='DEST_IP' value='$cgiparams{'DEST_IP'}' size='15' /></td>
642 <td class='base'>$Lang::tr{'destination port'}:</td>
643 <td><input type='text' name='DEST_PORT' value='$cgiparams{'DEST_PORT'}' size='8' /></td>
653 <td class='base'>$Lang::tr{'remark title'} <img src='/blob.gif' alt='*' /> </td>
654 <td><input type='text' name='REMARK' value='$cgiparams{'REMARK'}' size='55' maxlength='50' /></td>
657 unless ($cgiparams{'ACTION'} eq $Lang::tr
{'add xtaccess'} && $cgiparams{'ENABLED'} eq "off") {
658 print "<td width='20'> </td>";
659 print "<td>$Lang::tr{'enabled'} </td><td><input type='checkbox' name='ENABLED' $checked{'ENABLED'}{'on'} /></td>\n";
667 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")){
668 # if it is a port forward rule with a 0 in the orig_port field, this means there are xtaccess records, and we
669 # don't want to allow a person to change the orig_ip field as it will mess other logic up
670 print "<input type='hidden' name='ORIG_IP' value='$cgiparams{'ORIG_IP'}' />\n";
675 <td class='base'><font class='boldbase' color='${Header::colourred}'>$Lang::tr{'source network'}</font> <img src='/blob.gif' alt='*' /> </td>
676 <td><input type='text' name='ORIG_IP' value='$cgiparams{'ORIG_IP'}' size='15' /></td>
687 <td class='base' width='25%'><img src='/blob.gif' alt ='*' align='top' /> <font class='base'>$Lang::tr{'this field may be blank'}</font></td>
692 if ($cgiparams{'ACTION'} eq $Lang::tr
{'edit'}){
693 if($cgiparams{'KEY2'} eq "0"){
694 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";
696 print "<td width='40%'> </td>\n";
698 print "<td align='center' width='15%'><input type='submit' name='ACTION' value='$Lang::tr{'update'}' />";
699 print "<input type='hidden' name='KEY1' value='$cgiparams{'KEY1'}' />";
700 print "<input type='hidden' name='KEY2' value='$cgiparams{'KEY2'}' /></TD>";
701 print "<td align='center' width='15%'><input type='submit' name='ACTION' value='$Lang::tr{'reset'}' /></td>";
702 # on an edit and an xtaccess add, for some reason the "Reset" button stops working, so I make it a submit button
704 print "<td width='30%'> </td>\n";
705 print "<td align='center' width='15%'><input type='submit' name='ACTION' value='$Lang::tr{'add'}' /></td>";
706 if ($cgiparams{'ACTION'} eq $Lang::tr
{'add xtaccess'}) {
707 print "<td align='center' width='15%'><input type='hidden' name='KEY1' value='$cgiparams{'KEY1'}' />";
708 print "<input type='hidden' name='KEY2' value='$cgiparams{'KEY2'}' />";
709 print "<input type='submit' name='ACTION' value='$Lang::tr{'reset'}' /></td>";
710 } elsif ($errormessage ne '') {
711 print "<td align='center' width='15%'><input type='submit' name='ACTION' value='$Lang::tr{'reset'}' /></td>";
713 print "<td align='center' width='15%'><input type='reset' name='ACTION' value='$Lang::tr{'reset'}' /></td>";
717 <td width='5%' align='right'> </td>
726 &Header
::openbox
('100%', 'left', $Lang::tr
{'current rules'});
730 <td width='7%' class='boldbase' align='center'><b>$Lang::tr{'proto'}</b></td>
731 <td width='31%' class='boldbase' align='center'><b>$Lang::tr{'source'}</b></td>
732 <td width='2%' class='boldbase' align='center'> </td>
733 <td width='31%' class='boldbase' align='center'><b>$Lang::tr{'destination'}</b></td>
734 <td width='24%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b></td>
735 <td width='4%' class='boldbase' colspan='4' align='center'><b>$Lang::tr{'action'}</b></td>
741 my $xtaccesscolor = '#F6F4F4';
742 open(RULES
, "$filename") or die 'Unable to open config file.';
750 my @temp = split(/\,/,$_);
751 $temp[9] ='' unless defined $temp[9];# Glles ESpinasse : suppress warning on page init
752 if ($temp[2] eq 'udp') {
754 elsif ($temp[2] eq 'gre') {
758 # Change bgcolor when a new portfw rule is added
759 if ($temp[1] eq "0"){
762 # Darren Critchley highlight the row we are editing
763 if ( $cgiparams{'ACTION'} eq $Lang::tr
{'edit'} && $cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1] ) {
764 print "<tr bgcolor='${Header::colouryellow}'>\n";
767 print "<tr bgcolor='$color{'color22'}'>\n";
770 print "<tr bgcolor='$color{'color20'}'>\n";
774 if ($temp[6] eq 'on') { $gif = 'on.gif'; $toggle='off'; $gdesc=$Lang::tr
{'click to disable'};}
775 else { $gif = 'off.gif'; $toggle='on'; $gdesc=$Lang::tr
{'click to enable'}; }
777 # Darren Critchley - this code no longer works - should we remove?
778 # catch for 'old-style' rules file - assume default ip if
780 if (!&General
::validip
($temp[7]) || $temp[7] eq '0.0.0.0') {
781 $temp[7] = 'DEFAULT IP'; }
782 if ($temp[1] eq '0') { # Port forwarding entry
784 # Darren Critchley - Format the source and destintation ports
785 my $srcprt = $temp[3];
788 my $dstprt = $temp[5];
792 # Darren Critchley - Get Port Service Name if we can - code borrowed from firewalllog.dat
795 my $servi = uc(getservbyport($temp[3], lc($temp[2])));
796 if ($servi ne '' && $temp[3] < 1024) {
797 $srcprt = "$srcprt($servi)"; }
801 my $servi = uc(getservbyport($temp[5], lc($temp[2])));
802 if ($servi ne '' && $temp[5] < 1024) {
803 $dstprt = "$dstprt($servi)"; }
806 # Darren Critchley - If the line is too long, wrap the port numbers
807 my $srcaddr = "$temp[7] : $srcprt";
808 if (length($srcaddr) > 22) {
809 $srcaddr = "$temp[7] :<br /> $srcprt";
811 my $dstaddr = "$temp[4] : $dstprt";
812 if (length($dstaddr) > 26) {
813 $dstaddr = "$temp[4] :<br /> $dstprt";
816 <td align='center'>$protocol</td>
817 <td align='center'>$srcaddr</td>
818 <td align='center'><img src='/images/forward.gif' alt='=>' /></td>
819 <td align='center'>$dstaddr</td>
820 <td align='left'> $temp[9]</td>
822 <form method='post' name='frm$temp[0]c' action='$ENV{'SCRIPT_NAME'}'>
823 <input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
824 <input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
825 <input type='hidden' name='KEY1' value='$temp[0]' />
826 <input type='hidden' name='KEY2' value='$temp[1]' />
827 <input type='hidden' name='ENABLED' value='$toggle' />
832 <form method='post' name='frm$temp[0]' action='$ENV{'SCRIPT_NAME'}'>
833 <input type='hidden' name='ACTION' value='$Lang::tr{'add xtaccess'}' />
834 <input type='image' name='$Lang::tr{'add xtaccess'}' src='/images/add.gif' alt='$Lang::tr{'add xtaccess'}' title='$Lang::tr{'add xtaccess'}' />
835 <input type='hidden' name='KEY1' value='$temp[0]' />
836 <input type='hidden' name='KEY2' value='$temp[1]' />
841 <form method='post' name='frm$temp[0]' action='$ENV{'SCRIPT_NAME'}'>
842 <input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
843 <input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
844 <input type='hidden' name='KEY1' value='$temp[0]' />
845 <input type='hidden' name='KEY2' value='$temp[1]' />
850 <form method='post' name='frm$temp[0]b' action='$ENV{'SCRIPT_NAME'}'>
851 <input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
852 <input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
853 <input type='hidden' name='KEY1' value='$temp[0]' />
854 <input type='hidden' name='KEY2' value='$temp[1]' />
861 } else { # external access entry
863 <td align='center'> </td>
865 <td align='left' colspan='4'> <font color='${Header::colourred}'>$Lang::tr{'access allowed'}</font> $temp[8] ($temp[9])</td>
868 <form method='post' name='frm$temp[0]$temp[1]t' action='$ENV{'SCRIPT_NAME'}'>
869 <input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$Lang::tr{'toggle enable disable'}' title='$Lang::tr{'toggle enable disable'}' />
870 <input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
871 <input type='hidden' name='KEY1' value='$temp[0]' />
872 <input type='hidden' name='KEY2' value='$temp[1]' />
873 <input type='hidden' name='ENABLED' value='$toggle' />
877 <td align='center'> </td>
880 <form method='post' name='frm$temp[0]$temp[1]' action='$ENV{'SCRIPT_NAME'}'>
881 <input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
882 <input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
883 <input type='hidden' name='KEY1' value='$temp[0]' />
884 <input type='hidden' name='KEY2' value='$temp[1]' />
889 <form method='post' name='frm$temp[0]b$temp[1]b' action='$ENV{'SCRIPT_NAME'}'>
890 <input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
891 <input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
892 <input type='hidden' name='KEY1' value='$temp[0]' />
893 <input type='hidden' name='KEY2' value='$temp[1]' />
907 # If the fixed lease file contains entries, print Key to action icons
908 if ( ! -z
"$filename") {
912 <td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td>
913 <td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
914 <td class='base'>$Lang::tr{'click to disable'}</td>
915 <td> </td>
916 <td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
917 <td class='base'>$Lang::tr{'click to enable'}</td>
918 <td> </td>
919 <td><img src='/images/add.gif' alt='$Lang::tr{'add xtaccess'}' /></td>
920 <td class='base'>$Lang::tr{'add xtaccess'}</td>
921 <td> </td>
922 <td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
923 <td class='base'>$Lang::tr{'edit'}</td>
924 <td> </td>
925 <td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
926 <td class='base'>$Lang::tr{'remove'}</td>
935 &Header
::closebigbox
();
937 &Header
::closepage
();
939 # Validate Field Entries
942 # Darren Critchley - Get rid of dashes in port ranges
943 $cgiparams{'DEST_PORT'}=~ tr/-/:/;
944 $cgiparams{'SRC_PORT'}=~ tr/-/:/;
946 # Darren Critchley - code to substitue wildcards
947 if ($cgiparams{'SRC_PORT'} eq "*") {
948 $cgiparams{'SRC_PORT'} = "1:65535";
950 if ($cgiparams{'SRC_PORT'} =~ /^(\D)\:(\d+)$/) {
951 $cgiparams{'SRC_PORT'} = "1:$2";
953 if ($cgiparams{'SRC_PORT'} =~ /^(\d+)\:(\D)$/) {
954 $cgiparams{'SRC_PORT'} = "$1:65535";
956 if ($cgiparams{'DEST_PORT'} eq "*") {
957 $cgiparams{'DEST_PORT'} = "1:65535";
959 if ($cgiparams{'DEST_PORT'} =~ /^(\D)\:(\d+)$/) {
960 $cgiparams{'DEST_PORT'} = "1:$2";
962 if ($cgiparams{'DEST_PORT'} =~ /^(\d+)\:(\D)$/) {
963 $cgiparams{'DEST_PORT'} = "$1:65535";
966 # Darren Critchley - Add code for GRE protocol - we want to ignore ports, but we need a place holder
967 if ($cgiparams{'PROTOCOL'} eq 'gre') {
968 $cgiparams{'SRC_PORT'} = "GRE";
969 $cgiparams{'DEST_PORT'} = "GRE";
972 unless($cgiparams{'PROTOCOL'} =~ /^(tcp|udp|gre)$/) { $errormessage = $Lang::tr
{'invalid input'}; }
973 # Darren Critchley - Changed how the error routine works a bit - for the validportrange check, we need to
974 # pass in src or dest to determine which side we are working with.
975 # the routine returns the complete error or ''
976 if ($cgiparams{'PROTOCOL'} ne 'gre') {
977 $errormessage = &General
::validportrange
($cgiparams{'SRC_PORT'}, 'src');
979 if( ($cgiparams{'ORIG_IP'} ne "0" && $cgiparams{'KEY2'} ne "0") || $cgiparams{'ACTION'} eq $Lang::tr
{'add'}) {
980 # if it is a port forward record with 0 in orig_ip then ignore checking this field
981 unless(&General
::validipormask
($cgiparams{'ORIG_IP'}))
983 if ($cgiparams{'ORIG_IP'} ne '') {
984 $errormessage = $Lang::tr
{'source ip bad'}; }
986 $cgiparams{'ORIG_IP'} = '0.0.0.0/0'; }
989 # Darren Critchey - New rule that sets destination same as source if dest_port is blank.
990 if ($cgiparams{'DEST_PORT'} eq ''){
991 $cgiparams{'DEST_PORT'} = $cgiparams{'SRC_PORT'};
993 # Darren Critchey - Just in case error message is already set, this routine would wipe it out if
994 # we don't do a test here
995 if ($cgiparams{'PROTOCOL'} ne 'gre') {
996 unless($errormessage) {$errormessage = &General
::validportrange
($cgiparams{'DEST_PORT'}, 'dest');}
998 unless(&General
::validip
($cgiparams{'DEST_IP'})) { $errormessage = $Lang::tr
{'destination ip bad'}; }
1002 # Darren Critchley - we want to make sure that a port range does not overlap another port range
1003 sub checkportoverlap
1005 my $portrange1 = $_[0]; # New port range
1006 my $portrange2 = $_[1]; # existing port range
1007 my @tempr1 = split(/\:/,$portrange1);
1008 my @tempr2 = split(/\:/,$portrange2);
1010 unless (&checkportinc
($tempr1[0], $portrange2)){ return 0;}
1011 unless (&checkportinc
($tempr1[1], $portrange2)){ return 0;}
1013 unless (&checkportinc
($tempr2[0], $portrange1)){ return 0;}
1014 unless (&checkportinc
($tempr2[1], $portrange1)){ return 0;}
1016 return 1; # Everything checks out!
1019 # Darren Critchley - we want to make sure that a port entry is not within an already existing range
1022 my $port1 = $_[0]; # Port
1023 my $portrange2 = $_[1]; # Port range
1024 my @tempr1 = split(/\:/,$portrange2);
1026 if ($port1 < $tempr1[0] || $port1 > $tempr1[1]) {
1033 # Darren Critchley - certain ports are reserved for Ipcop
1034 # TCP 67,68,81,222,445
1036 # Params passed in -> port, rangeyn, protocol
1037 sub disallowreserved
1039 # port 67 and 68 same for tcp and udp, don't bother putting in an array
1041 my @tcp_reserved = ();
1042 my $prt = $_[0]; # the port or range
1043 my $ryn = $_[1]; # tells us whether or not it is a port range
1044 my $prot = $_[2]; # protocol
1045 my $srcdst = $_[3]; # source or destination
1047 if ($ryn) { # disect port range
1048 if ($srcdst eq "src") {
1049 $msg = "$Lang::tr{'rsvd src port overlap'}";
1051 $msg = "$Lang::tr{'rsvd dst port overlap'}";
1053 my @tmprng = split(/\:/,$prt);
1054 unless (67 < $tmprng[0] || 67 > $tmprng[1]) { $errormessage="$msg 67"; return; }
1055 unless (68 < $tmprng[0] || 68 > $tmprng[1]) { $errormessage="$msg 68"; return; }
1056 if ($prot eq "tcp") {
1057 foreach my $prange (@tcp_reserved) {
1058 unless ($prange < $tmprng[0] || $prange > $tmprng[1]) { $errormessage="$msg $prange"; return; }
1062 if ($srcdst eq "src") {
1063 $msg = "$Lang::tr{'reserved src port'}";
1065 $msg = "$Lang::tr{'reserved dst port'}";
1067 if ($prt == 67) { $errormessage="$msg 67"; return; }
1068 if ($prt == 68) { $errormessage="$msg 68"; return; }
1069 if ($prot eq "tcp") {
1070 foreach my $prange (@tcp_reserved) {
1071 if ($prange == $prt) { $errormessage="$msg $prange"; return; }
1078 # Darren Critchley - Attempt to combine Add/Update validation as they are almost the same
1081 if ($cgiparams{'KEY2'} eq "0"){ # if it is a port forward rule, then validate properly
1083 } else { # it is an xtaccess rule, just check for a valid ip
1084 unless(&General
::validipormask
($cgiparams{'ORIG_IP'}))
1086 if ($cgiparams{'ORIG_IP'} ne '') {
1087 $errormessage = $Lang::tr
{'source ip bad'}; }
1088 else { # this rule stops someone from adding an ALL xtaccess record
1089 $errormessage = $Lang::tr
{'xtaccess all error'};
1090 $cgiparams{'ACTION'} = $Lang::tr
{'add xtaccess'};
1093 # Darren Critchley - check for 0.0.0.0/0 - not allowed for xtaccess
1094 if ($cgiparams{'ORIG_IP'} eq "0.0.0.0/0" || $cgiparams{'ORIG_IP'} eq "0.0.0.0") {
1095 $errormessage = $Lang::tr
{'xtaccess all error'};
1096 $cgiparams{'ACTION'} = $Lang::tr
{'add xtaccess'};
1099 # Darren Critchley - Remove commas from remarks
1100 $cgiparams{'REMARK'} = &Header
::cleanhtml
($cgiparams{'REMARK'});
1102 # Darren Critchley - Check to see if we are working with port ranges
1103 our ($prtrange1, $prtrange2);
1104 $_ = $cgiparams{'SRC_PORT'};
1105 if ($cgiparams{'KEY2'} eq "0" && m/:/){
1108 if ($cgiparams{'SRC_IP'} eq '0.0.0.0') { # Dave Roberts - only check if using DEFAULT IP
1109 if ($prtrange1 == 1){ # check for source ports reserved for Ipcop
1110 &disallowreserved
($cgiparams{'SRC_PORT'},1,$cgiparams{'PROTOCOL'},"src");
1111 if ($errormessage) { goto EXITSUB
; }
1112 } else { # check for source port reserved for Ipcop
1113 &disallowreserved
($cgiparams{'SRC_PORT'},0,$cgiparams{'PROTOCOL'},"src");
1114 if ($errormessage) { goto EXITSUB
; }
1118 $_ = $cgiparams{'DEST_PORT'};
1119 if ($cgiparams{'KEY2'} eq "0" && m/:/){
1122 if ($cgiparams{'SRC_IP'} eq '0.0.0.0') { # Dave Roberts - only check if using DEFAULT IP
1123 if ($prtrange2 == 1){ # check for destination ports reserved for IPFire
1124 &disallowreserved
($cgiparams{'DEST_PORT'},1,$cgiparams{'PROTOCOL'},"dst");
1125 if ($errormessage) { goto EXITSUB
; }
1126 } else { # check for destination port reserved for IPFire
1127 &disallowreserved
($cgiparams{'DEST_PORT'},0,$cgiparams{'PROTOCOL'},"dst");
1128 if ($errormessage) { goto EXITSUB
; }
1137 # Darren Critchley - Duplicate or overlapping Port range check
1141 our ($prtrange1, $prtrange2);
1142 if (m/:/ && $prtrange1 == 1) { # comparing two port ranges
1143 unless (&checkportoverlap
($cgiparams{'SRC_PORT'},$_[0])) {
1144 $errormessage = "$Lang::tr{'source port overlaps'} $_[0]";
1147 if (m/:/ && $prtrange1 == 0 && $errormessage eq '') { # compare one port to a range
1148 unless (&checkportinc
($cgiparams{'SRC_PORT'}, $_[0])) {
1149 $errormessage = "$Lang::tr{'srcprt within existing'} $_[0]";
1152 if (! m/:/ && $prtrange1 == 1 && $errormessage eq '') { # compare one port to a range
1153 unless (&checkportinc
($_[0], $cgiparams{'SRC_PORT'})) {
1154 $errormessage = "$Lang::tr{'srcprt range overlaps'} $_[0]";
1158 if ($errormessage eq ''){
1160 if (m/:/ && $prtrange2 == 1) { # if true then there is a port range
1161 unless (&checkportoverlap
($cgiparams{'DEST_PORT'},$_[1])) {
1162 $errormessage = "$Lang::tr{'destination port overlaps'} $_[1]";
1165 if (m/:/ && $prtrange2 == 0 && $errormessage eq '') { # compare one port to a range
1166 unless (&checkportinc
($cgiparams{'DEST_PORT'}, $_[1])) {
1167 $errormessage = "$Lang::tr{'dstprt within existing'} $_[1]";
1170 if (! m/:/ && $prtrange2 == 1 && $errormessage eq '') { # compare one port to a range
1171 unless (&checkportinc
($_[1], $cgiparams{'DEST_PORT'})) {
1172 $errormessage = "$Lang::tr{'dstprt range overlaps'} $_[1]";