Gro├čes Update:
[ipfire-2.x.git] / html / cgi-bin / portfw.cgi
CommitLineData
ac1cfefa
MT
1#!/usr/bin/perl
2#
3# SmoothWall CGIs
4#
5# This code is distributed under the terms of the GPL
6#
7# (c) The SmoothWall Team
8# Copyright (c) 2002/04/13 Steve Bootes - Add source IP support
9#
10# $Id: portfw.cgi,v 1.5.2.18 2005/05/02 16:19:49 eoberlander Exp $
11#
12#
13# Darren Critchley February 2003 - I added the multiple external access rules for each port forward
14# A couple of things to remember when reading the code
15# There are two kinds of records in the config file, those with a number in the first field, and then 0,
16# these are port forward rules, these records will have a 0 or 0.0.0.0 in position 9 (ORIG_IP)
17# If there is a 0, it means that there are external access rules, otherwise the port is open to ALL.
18# The second type of record is a number followed by a number which indicates that it is an external access
19# rule. The first number indicates which Portfw rule it belongs to, and the second is just a unique key.
20#
21# Darren Critchley - March 5, 2003 - if you come along after me and work on this page, please comment your
22# work. Put your name, and date and then your comment - it helps the person that comes along after you
23# to figure out why and how things have changed, and it is considered good coding practice
24# Thanks . . .
25#
26
27use strict;
28
29# enable only the following on debugging purpose
30#use warnings;
31#use CGI::Carp 'fatalsToBrowser';
32
33require 'CONFIG_ROOT/general-functions.pl';
34require "${General::swroot}/lang.pl";
35require "${General::swroot}/header.pl";
36
37#workaround to suppress a warning when a variable is used only once
38my @dummy = ( ${Header::colouryellow} );
39undef (@dummy);
40
41my %cgiparams=();
42my %selected=();
43my %checked=();
44my $prtrange1=0;
45my $prtrange2=0;
46my $errormessage = '';
47my $filename = "${General::swroot}/portfw/config";
48my $aliasfile = "${General::swroot}/ethernet/aliases";
49
50&Header::showhttpheaders();
51
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'} = '';
64
65&Header::getcgihash(\%cgiparams);
66
67my $disable_all = "0";
68my $enable_all = "0";
69
70if ($cgiparams{'ACTION'} eq $Lang::tr{'add'})
71{
72 &valaddupdate();
73
74 # Darren Critchley - if there is an error, don't waste any more time processing
75 if ($errormessage) { goto ERROR; }
76
77 open(FILE, $filename) or die 'Unable to open config file.';
78 my @current = <FILE>;
79 close(FILE);
80 my $key1 = 0; # used for finding last sequence number used
81 foreach my $line (@current)
82 {
83 my @temp = split(/\,/,$line);
84
85 chomp ($temp[8]);
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])
90 {
91 $errormessage =
92 "$Lang::tr{'source port in use'} $cgiparams{'SRC_PORT'}";
93 }
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") {
96 $key1=$temp[0];
97 }
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] &&
102 $errormessage eq '')
103 {
104 &portchecks($temp[3], $temp[5]);
105 }
106 } else {
107 if ( $cgiparams{'KEY1'} eq $temp[0] &&
108 $cgiparams{'ORIG_IP'} eq $temp[8])
109 {
110 $errormessage =
111 "$Lang::tr{'source ip in use'} $cgiparams{'ORIG_IP'}";
112 }
113 }
114 }
115
116ERROR:
117 unless ($errormessage)
118 {
119 # Darren Critchley - we only want to store ranges with Colons
120 $cgiparams{'SRC_PORT'} =~ tr/-/:/;
121 $cgiparams{'DEST_PORT'} =~ tr/-/:/;
122
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.';
126 flock FILE, 2;
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";
133 }
134 close(FILE);
135 undef %cgiparams;
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.';
141 flock FILE, 2;
142 foreach my $line (@current) {
143 chomp($line);
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
147 $temp[8] = '0';
148 }
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";
151 } else {
152 print FILE "$line\n";
153 }
154 }
155 close(FILE);
156 undef %cgiparams;
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)
161}
162
163if ($cgiparams{'ACTION'} eq $Lang::tr{'update'})
164{
165 &valaddupdate();
166
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; }
169
170 open(FILE, $filename) or die 'Unable to open config file.';
171 my @current = <FILE>;
172 close(FILE);
173 my $disabledpfw = '0';
174 my $lastpfw = '';
175 my $xtaccessdel = '0';
176
177 foreach my $line (@current)
178 {
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];
182 $lastpfw = $temp[0];
183 }
184 chomp ($temp[8]);
185 if ( $cgiparams{'SRC_PORT'} eq $temp[3] &&
186 $cgiparams{'PROTOCOL'} eq $temp[2] &&
187 $cgiparams{'SRC_IP'} eq $temp[7])
188 {
189 if ($cgiparams{'KEY1'} ne $temp[0] && $cgiparams{'KEY2'} eq "0")
190 {
191 $errormessage =
192 "$Lang::tr{'source port in use'} $cgiparams{'SRC_PORT'}";
193 }
194 }
195 if ($cgiparams{'ORIG_IP'} eq $temp[8])
196 {
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!
199 {
200 $errormessage = "$Lang::tr{'source ip in use'} $cgiparams{'ORIG_IP'}";
201 $cgiparams{'ACTION'} = $Lang::tr{'edit'};
202 }
203 }
204
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
211 $xtaccessdel = "1";
212 }
213
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])
216 {
217 $enable_all = "1";
218 } else {
219 $enable_all = "0";
220 }
221 # Darren Critchley - Portfw disabled, then disable xtaccess for all associated xtaccess records
222 if ($cgiparams{'ENABLED'} eq "off" && $cgiparams{'KEY2'} eq "0")
223 {
224 $disable_all = "1";
225 } else {
226 $disable_all = "0";
227 }
228
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")
233 {
234 $errormessage = "$Lang::tr{'cant enable xtaccess'}";
235 $cgiparams{'ACTION'} = $Lang::tr{'edit'};
236 }
237 }
238 }
239
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'};
245 }
246
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] &&
252 $errormessage eq '')
253 {
254 &portchecks($temp[3], $temp[5]);
255 } # end port testing
256
257 }
258
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") {
261 my $xctr = 0;
262 foreach my $line (@current)
263 {
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
267 $xctr++;
268 }
269 }
270 if ($xctr == 2){
271 $disable_all = "1";
272 }
273 }
274
275UPD_ERROR:
276 unless ($errormessage)
277 {
278 # Darren Critchley - we only want to store ranges with Colons
279 $cgiparams{'SRC_PORT'} =~ tr/-/:/;
280 $cgiparams{'DEST_PORT'} =~ tr/-/:/;
281
282 open(FILE, ">$filename") or die 'Unable to open config file.';
283 flock FILE, 2;
284 foreach my $line (@current) {
285 chomp($line);
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";
289 } else {
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'};
296 }
297
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] ) {
300 $temp[6] = 'off';
301 }
302 if ( $enable_all eq "1" && $cgiparams{'KEY1'} eq $temp[0] ) {
303 $temp[6] = 'on';
304 }
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] ) {
307 $temp[6] = 'off';
308 }
309 print FILE "$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6],$temp[7],$temp[8],$temp[9]\n";
310 }
311 }
312 close(FILE);
313 undef %cgiparams;
314 &General::log($Lang::tr{'forwarding rule updated'});
315 system('/usr/local/bin/setportfw');
316 }
317 if ($errormessage) {
318 $cgiparams{'ACTION'} = $Lang::tr{'edit'};
319 }
320}
321
322# Darren Critchley - Allows rules to be enabled and disabled
323if ($cgiparams{'ACTION'} eq $Lang::tr{'toggle enable disable'})
324{
325 open(FILE, $filename) or die 'Unable to open config file.';
326 my @current = <FILE>;
327 close(FILE);
328 my $disabledpfw = '0';
329 my $lastpfw = '';
330 my $xtaccessdel = '0';
331
332 foreach my $line (@current)
333 {
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];
337 $lastpfw = $temp[0];
338 }
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
345 $xtaccessdel = "1";
346 }
347
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])
350 {
351 $enable_all = "1";
352 } else {
353 $enable_all = "0";
354 }
355 # Darren Critchley - Portfw disabled, then disable xtaccess for all associated xtaccess records
356 if ($cgiparams{'ENABLED'} eq "off" && $cgiparams{'KEY2'} eq "0")
357 {
358 $disable_all = "1";
359 } else {
360 $disable_all = "0";
361 }
362
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")
367 {
368 $errormessage = "$Lang::tr{'cant enable xtaccess'}";
369 goto TOGGLEEXIT;
370 }
371 }
372 }
373 }
374
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") {
377 my $xctr = 0;
378 foreach my $line (@current)
379 {
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
383 $xctr++;
384 }
385 }
386 if ($xctr == 2){
387 $disable_all = "1";
388 }
389 }
390
391 open(FILE, ">$filename") or die 'Unable to open config file.';
392 flock FILE, 2;
393 foreach my $line (@current) {
394 chomp($line);
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";
398 } else {
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] ) {
401 $temp[6] = 'off';
402 }
403 if ( $enable_all eq "1" && $cgiparams{'KEY1'} eq $temp[0] ) {
404 $temp[6] = 'on';
405 }
406 print FILE "$temp[0],$temp[1],$temp[2],$temp[3],$temp[4],$temp[5],$temp[6],$temp[7],$temp[8],$temp[9]\n";
407 }
408 }
409 close(FILE);
410 &General::log($Lang::tr{'forwarding rule updated'});
411 system('/usr/local/bin/setportfw');
412TOGGLEEXIT:
413 undef %cgiparams;
414}
415
416
417# Darren Critchley - broke out Edit routine from the delete routine - Edit routine now just puts values in fields
418if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'})
419{
420 open(FILE, "$filename") or die 'Unable to open config file.';
421 my @current = <FILE>;
422 close(FILE);
423
424 unless ($errormessage)
425 {
426 foreach my $line (@current)
427 {
428 chomp($line);
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];
439 }
440
441 }
442 }
443}
444
445# Darren Critchley - broke out Remove routine as the logic is getting too complex to be combined with the Edit
446if ($cgiparams{'ACTION'} eq $Lang::tr{'remove'})
447{
448 open(FILE, "$filename") or die 'Unable to open config file.';
449 my @current = <FILE>;
450 close(FILE);
451
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
454 # in setportfw.c
455 my $fixportfw = '0';
456 if ($cgiparams{'KEY2'} ne "0") {
457 my $counter = 0;
458 foreach my $line (@current)
459 {
460 chomp($line);
461 my @temp = split(/\,/,$line);
462 if ($temp[0] eq $cgiparams{'KEY1'}) {
463 $counter++;
464 }
465 }
466 if ($counter eq 2) {
467 $fixportfw = '1';
468 }
469 }
470
471 unless ($errormessage)
472 {
473 open(FILE, ">$filename") or die 'Unable to open config file.';
474 flock FILE, 2;
475 my $linedeleted = 0;
476 foreach my $line (@current)
477 {
478 chomp($line);
479 my @temp = split(/\,/,$line);
480
481 if ($cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1] ||
482 $cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq "0" )
483 {
484 $linedeleted = 1;
485 } else {
486 if ($temp[0] eq $cgiparams{'KEY1'} && $temp[1] eq "0" && $fixportfw eq "1") {
487 $temp[8] = '0.0.0.0/0';
488 }
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";
491 }
492 }
493 close(FILE);
494 if ($linedeleted == 1) {
495 &General::log($Lang::tr{'forwarding rule removed'});
496 undef %cgiparams;
497 }
498 system('/usr/local/bin/setportfw');
499 }
500}
501
502# Darren Critchley - Added routine to allow external access rules to be added
503if ($cgiparams{'ACTION'} eq $Lang::tr{'add xtaccess'})
504{
505 open(FILE, $filename) or die 'Unable to open config file.';
506 my @current = <FILE>;
507 close(FILE);
508 my $key = 0; # used for finding last sequence number used
509 foreach my $line (@current)
510 {
511 my @temp = split(/\,/,$line);
512 if ($temp[0] eq $cgiparams{'KEY1'}) {
513 $key = $temp[1]
514 }
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];
524 }
525 }
526 $key++;
527 $cgiparams{'KEY2'} = $key;
528 # Until the ADD button is hit, there needs to be no change to portfw rules
529}
530
531if ($cgiparams{'ACTION'} eq $Lang::tr{'reset'})
532{
533 undef %cgiparams;
534}
535
536if ($cgiparams{'ACTION'} eq '')
537{
538 $cgiparams{'PROTOCOL'} = 'tcp';
539 $cgiparams{'ENABLED'} = 'on';
540 $cgiparams{'SRC_IP'} = '0.0.0.0';
541}
542
543$selected{'PROTOCOL'}{'udp'} = '';
544$selected{'PROTOCOL'}{'tcp'} = '';
545$selected{'PROTOCOL'}{'gre'} = '';
546$selected{'PROTOCOL'}{$cgiparams{'PROTOCOL'}} = "selected='selected'";
547
548$selected{'SRC_IP'}{$cgiparams{'SRC_IP'}} = "selected='selected'";
549
550$checked{'ENABLED'}{'off'} = '';
551$checked{'ENABLED'}{'on'} = '';
552$checked{'ENABLED'}{$cgiparams{'ENABLED'}} = "checked='checked'";
553
554&Header::openpage($Lang::tr{'port forwarding configuration'}, 1, '');
555
556&Header::openbigbox('100%', 'left', '', $errormessage);
557
558if ($errormessage) {
559 &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
560 print "<class name='base'><font color='${Header::colourred}'>$errormessage\n</font>";
561 print "&nbsp;</class>\n";
562 &Header::closebox();
563}
564
565print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>\n";
566
567if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'}){
568 &Header::openbox('100%', 'left', $Lang::tr{'edit a rule'});
569} else {
570 &Header::openbox('100%', 'left', $Lang::tr{'add a new rule'});
571}
572
573if ($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'};
578 $dstprt =~ s/-/ - /;
579 $dstprt =~ s/:/ - /;
580
581print <<END
582<table>
583 <tr>
584 <td class='base'>$Lang::tr{'protocol'}: <b>$PROT</b></td>
585 <td width='20'>&nbsp;</td>
586 <td class='base' align='right'>$Lang::tr{'destination ip'}:&nbsp;</td>
587 <td><b>$cgiparams{'DEST_IP'}</b></td>
588 <td width='20'>&nbsp;</td>
589 <td class='base' align='right'>$Lang::tr{'destination port'}:&nbsp;</td>
590 <td><b>$dstprt</b></td>
591 </tr>
592</table>
593
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'}' />
599END
600;
601} else {
602print <<END
603<table width='100%'>
604 <tr>
605 <td width='10%'>$Lang::tr{'protocol'}:&nbsp;</td>
606 <td width='15%'>
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>
611 </select>
612 </td>
613 <td class='base' width='20%'><font color='${Header::colourred}'>$Lang::tr{'alias ip'}:</font></td>
614 <td>
615 <select name='SRC_IP'>
616 <option value='0.0.0.0' $selected{'SRC_IP'}{'0.0.0.0'}>DEFAULT IP</option>
617END
618;
619open(ALIASES, "$aliasfile") or die 'Unable to open aliases file.';
620while (<ALIASES>)
621{
622 chomp($_);
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])"; }
627 print "</option>\n";
628 }
629}
630close(ALIASES);
631print <<END
632 </select>
633 </td>
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>
636 </tr>
637 <tr>
638 <td class='base'>&nbsp;</td>
639 <td>&nbsp;</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>
644 </tr>
645</table>
646END
647;
648}
649
650print <<END
651<table>
652 <tr>
653 <td class='base'>$Lang::tr{'remark title'}&nbsp;<img src='/blob.gif' alt='*' />&nbsp;</td>
654 <td><input type='text' name='REMARK' value='$cgiparams{'REMARK'}' size='55' maxlength='50' /></td>
655END
656;
657unless ($cgiparams{'ACTION'} eq $Lang::tr{'add xtaccess'} && $cgiparams{'ENABLED'} eq "off") {
658 print "<td width='20'>&nbsp;</td>";
659 print "<td>$Lang::tr{'enabled'}&nbsp;</td><td><input type='checkbox' name='ENABLED' $checked{'ENABLED'}{'on'} /></td>\n";
660}
661print <<END
662 </tr>
663</table>
664END
665;
666
667if ($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";
671} else {
672print <<END
673<table>
674 <tr>
675 <td class='base'><font class='boldbase' color='${Header::colourred}'>$Lang::tr{'source network'}</font>&nbsp;<img src='/blob.gif' alt='*' />&nbsp;</td>
676 <td><input type='text' name='ORIG_IP' value='$cgiparams{'ORIG_IP'}' size='15' /></td>
677 </tr>
678</table>
679END
680;
681}
682
683print <<END
684<table width='100%'>
685 <hr />
686 <tr>
687 <td class='base' width='25%'><img src='/blob.gif' alt ='*' align='top' />&nbsp;<font class='base'>$Lang::tr{'this field may be blank'}</font></td>
688END
689;
690
691
692if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'}){
693 if($cgiparams{'KEY2'} eq "0"){
694 print "<td width='35%' align='right'>$Lang::tr{'open to all'}:&nbsp;</td><td width='5%'><input type='checkbox' name='OVERRIDE' $checked{'OVERRIDE'}{'on'} /></td>\n";
695 } else {
696 print "<td width='40%'>&nbsp;</td>\n";
697 }
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
703} else {
704 print "<td width='30%'>&nbsp;</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>";
712 } else {
713 print "<td align='center' width='15%'><input type='reset' name='ACTION' value='$Lang::tr{'reset'}' /></td>";
714 }
715}
716print <<END
717 <td width='5%' align='right'>
718 <a href='${General::adminmanualurl}/section-firewall.html#section-port-forwarding' target='_blank'>
719 <img src='/images/web-support.png' alt='$Lang::tr{'online help en'}' title='$Lang::tr{'online help en'}' /></a></td>
720 </tr>
721</table>
722END
723;
724&Header::closebox();
725
726print "</form>\n";
727
728&Header::openbox('100%', 'left', $Lang::tr{'current rules'});
729print <<END
730<table width='100%'>
731<tr>
732<td width='7%' class='boldbase' align='center'><b>$Lang::tr{'proto'}</b></td>
733<td width='31%' class='boldbase' align='center'><b>$Lang::tr{'source'}</b></td>
734<td width='2%' class='boldbase' align='center'>&nbsp;</td>
735<td width='31%' class='boldbase' align='center'><b>$Lang::tr{'destination'}</b></td>
736<td width='24%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b></td>
737<td width='4%' class='boldbase' colspan='4' align='center'><b>$Lang::tr{'action'}</b></td>
738</tr>
739END
740;
741
742my $id = 0;
743my $xtaccesscolor = '#F6F4F4';
744open(RULES, "$filename") or die 'Unable to open config file.';
745while (<RULES>)
746{
747 my $protocol = '';
748 my $gif = '';
749 my $gdesc = '';
750 my $toggle = '';
751 chomp($_);
752 my @temp = split(/\,/,$_);
753 $temp[9] ='' unless defined $temp[9];# Glles ESpinasse : suppress warning on page init
754 if ($temp[2] eq 'udp') {
755 $protocol = 'UDP'; }
756 elsif ($temp[2] eq 'gre') {
757 $protocol = 'GRE' }
758 else {
759 $protocol = 'TCP' }
760 # Change bgcolor when a new portfw rule is added
761 if ($temp[1] eq "0"){
762 $id++;
763 }
764 # Darren Critchley highlight the row we are editing
765 if ( $cgiparams{'ACTION'} eq $Lang::tr{'edit'} && $cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1] ) {
766 print "<tr bgcolor='${Header::colouryellow}'>\n";
767 } else {
768 if ($id % 2) {
769 print "<tr bgcolor='${Header::table1colour}'>\n";
770 }
771 else {
772 print "<tr bgcolor='${Header::table2colour}'>\n";
773 }
774 }
775
776 if ($temp[6] eq 'on') { $gif = 'on.gif'; $toggle='off'; $gdesc=$Lang::tr{'click to disable'};}
777 else { $gif = 'off.gif'; $toggle='on'; $gdesc=$Lang::tr{'click to enable'}; }
778
779 # Darren Critchley - this code no longer works - should we remove?
780 # catch for 'old-style' rules file - assume default ip if
781 # none exists
782 if (!&General::validip($temp[7]) || $temp[7] eq '0.0.0.0') {
783 $temp[7] = 'DEFAULT IP'; }
784 if ($temp[1] eq '0') { # Port forwarding entry
785
786 # Darren Critchley - Format the source and destintation ports
787 my $srcprt = $temp[3];
788 $srcprt =~ s/-/ - /;
789 $srcprt =~ s/:/ - /;
790 my $dstprt = $temp[5];
791 $dstprt =~ s/-/ - /;
792 $dstprt =~ s/:/ - /;
793
794 # Darren Critchley - Get Port Service Name if we can - code borrowed from firewalllog.dat
795 $_=$temp[3];
796 if (/^\d+$/) {
797 my $servi = uc(getservbyport($temp[3], lc($temp[2])));
798 if ($servi ne '' && $temp[3] < 1024) {
799 $srcprt = "$srcprt($servi)"; }
800 }
801 $_=$temp[5];
802 if (/^\d+$/) {
803 my $servi = uc(getservbyport($temp[5], lc($temp[2])));
804 if ($servi ne '' && $temp[5] < 1024) {
805 $dstprt = "$dstprt($servi)"; }
806 }
807
808 # Darren Critchley - If the line is too long, wrap the port numbers
809 my $srcaddr = "$temp[7] : $srcprt";
810 if (length($srcaddr) > 22) {
811 $srcaddr = "$temp[7] :<br /> $srcprt";
812 }
813 my $dstaddr = "$temp[4] : $dstprt";
814 if (length($dstaddr) > 26) {
815 $dstaddr = "$temp[4] :<br /> $dstprt";
816 }
817print <<END
818<td align='center'>$protocol</td>
819<td align='center'>$srcaddr</td>
820<td align='center'><img src='/images/forward.gif' alt='=&gt;' /></td>
821<td align='center'>$dstaddr</td>
822<td align='left'>&nbsp;$temp[9]</td>
823<td align='center'>
824 <form method='post' name='frm$temp[0]c' action='$ENV{'SCRIPT_NAME'}'>
825 <input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
826 <input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
827 <input type='hidden' name='KEY1' value='$temp[0]' />
828 <input type='hidden' name='KEY2' value='$temp[1]' />
829 <input type='hidden' name='ENABLED' value='$toggle' />
830 </form>
831</td>
832
833<td align='center'>
834 <form method='post' name='frm$temp[0]' action='$ENV{'SCRIPT_NAME'}'>
835 <input type='hidden' name='ACTION' value='$Lang::tr{'add xtaccess'}' />
836 <input type='image' name='$Lang::tr{'add xtaccess'}' src='/images/add.gif' alt='$Lang::tr{'add xtaccess'}' title='$Lang::tr{'add xtaccess'}' />
837 <input type='hidden' name='KEY1' value='$temp[0]' />
838 <input type='hidden' name='KEY2' value='$temp[1]' />
839 </form>
840</td>
841
842<td align='center'>
843 <form method='post' name='frm$temp[0]' action='$ENV{'SCRIPT_NAME'}'>
844 <input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
845 <input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
846 <input type='hidden' name='KEY1' value='$temp[0]' />
847 <input type='hidden' name='KEY2' value='$temp[1]' />
848 </form>
849</td>
850
851<td align='center'>
852 <form method='post' name='frm$temp[0]b' action='$ENV{'SCRIPT_NAME'}'>
853 <input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
854 <input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
855 <input type='hidden' name='KEY1' value='$temp[0]' />
856 <input type='hidden' name='KEY2' value='$temp[1]' />
857 </form>
858</td>
859
860</tr>
861END
862 ;
863 } else { # external access entry
864print <<END
865<td align='center'>&nbsp;</td>
866
867<td align='left' colspan='4'>&nbsp;<font color='${Header::colourred}'>$Lang::tr{'access allowed'}</font> $temp[8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;($temp[9])</td>
868
869<td align='center'>
870 <form method='post' name='frm$temp[0]$temp[1]t' action='$ENV{'SCRIPT_NAME'}'>
871 <input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$Lang::tr{'toggle enable disable'}' title='$Lang::tr{'toggle enable disable'}' />
872 <input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
873 <input type='hidden' name='KEY1' value='$temp[0]' />
874 <input type='hidden' name='KEY2' value='$temp[1]' />
875 <input type='hidden' name='ENABLED' value='$toggle' />
876 </form>
877</td>
878
879<td align='center'>&nbsp;</td>
880
881<td align='center'>
882 <form method='post' name='frm$temp[0]$temp[1]' action='$ENV{'SCRIPT_NAME'}'>
883 <input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
884 <input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
885 <input type='hidden' name='KEY1' value='$temp[0]' />
886 <input type='hidden' name='KEY2' value='$temp[1]' />
887 </form>
888</td>
889
890<td align='center'>
891 <form method='post' name='frm$temp[0]b$temp[1]b' action='$ENV{'SCRIPT_NAME'}'>
892 <input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
893 <input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
894 <input type='hidden' name='KEY1' value='$temp[0]' />
895 <input type='hidden' name='KEY2' value='$temp[1]' />
896 </form>
897</td>
898
899</tr>
900END
901 ;
902 }
903}
904
905close(RULES);
906
907print "</table>";
908
909# If the fixed lease file contains entries, print Key to action icons
910if ( ! -z "$filename") {
911print <<END
912<table>
913<tr>
914 <td class='boldbase'>&nbsp;<b>$Lang::tr{'legend'}:&nbsp;</b></td>
915 <td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
916 <td class='base'>$Lang::tr{'click to disable'}</td>
917 <td>&nbsp;&nbsp;</td>
918 <td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
919 <td class='base'>$Lang::tr{'click to enable'}</td>
920 <td>&nbsp;&nbsp;</td>
921 <td><img src='/images/add.gif' alt='$Lang::tr{'add xtaccess'}' /></td>
922 <td class='base'>$Lang::tr{'add xtaccess'}</td>
923 <td>&nbsp;&nbsp;</td>
924 <td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
925 <td class='base'>$Lang::tr{'edit'}</td>
926 <td>&nbsp;&nbsp;</td>
927 <td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
928 <td class='base'>$Lang::tr{'remove'}</td>
929</tr>
930</table>
931END
932;
933}
934
935&Header::closebox();
936
937&Header::closebigbox();
938
939&Header::closepage();
940
941# Validate Field Entries
942sub validateparams
943{
944 # Darren Critchley - Get rid of dashes in port ranges
945 $cgiparams{'DEST_PORT'}=~ tr/-/:/;
946 $cgiparams{'SRC_PORT'}=~ tr/-/:/;
947
948 # Darren Critchley - code to substitue wildcards
949 if ($cgiparams{'SRC_PORT'} eq "*") {
950 $cgiparams{'SRC_PORT'} = "1:65535";
951 }
952 if ($cgiparams{'SRC_PORT'} =~ /^(\D)\:(\d+)$/) {
953 $cgiparams{'SRC_PORT'} = "1:$2";
954 }
955 if ($cgiparams{'SRC_PORT'} =~ /^(\d+)\:(\D)$/) {
956 $cgiparams{'SRC_PORT'} = "$1:65535";
957 }
958 if ($cgiparams{'DEST_PORT'} eq "*") {
959 $cgiparams{'DEST_PORT'} = "1:65535";
960 }
961 if ($cgiparams{'DEST_PORT'} =~ /^(\D)\:(\d+)$/) {
962 $cgiparams{'DEST_PORT'} = "1:$2";
963 }
964 if ($cgiparams{'DEST_PORT'} =~ /^(\d+)\:(\D)$/) {
965 $cgiparams{'DEST_PORT'} = "$1:65535";
966 }
967
968 # Darren Critchley - Add code for GRE protocol - we want to ignore ports, but we need a place holder
969 if ($cgiparams{'PROTOCOL'} eq 'gre') {
970 $cgiparams{'SRC_PORT'} = "GRE";
971 $cgiparams{'DEST_PORT'} = "GRE";
972 }
973
974 unless($cgiparams{'PROTOCOL'} =~ /^(tcp|udp|gre)$/) { $errormessage = $Lang::tr{'invalid input'}; }
975 # Darren Critchley - Changed how the error routine works a bit - for the validportrange check, we need to
976 # pass in src or dest to determine which side we are working with.
977 # the routine returns the complete error or ''
978 if ($cgiparams{'PROTOCOL'} ne 'gre') {
979 $errormessage = &General::validportrange($cgiparams{'SRC_PORT'}, 'src');
980 }
981 if( ($cgiparams{'ORIG_IP'} ne "0" && $cgiparams{'KEY2'} ne "0") || $cgiparams{'ACTION'} eq $Lang::tr{'add'}) {
982 # if it is a port forward record with 0 in orig_ip then ignore checking this field
983 unless(&General::validipormask($cgiparams{'ORIG_IP'}))
984 {
985 if ($cgiparams{'ORIG_IP'} ne '') {
986 $errormessage = $Lang::tr{'source ip bad'}; }
987 else {
988 $cgiparams{'ORIG_IP'} = '0.0.0.0/0'; }
989 }
990 }
991 # Darren Critchey - New rule that sets destination same as source if dest_port is blank.
992 if ($cgiparams{'DEST_PORT'} eq ''){
993 $cgiparams{'DEST_PORT'} = $cgiparams{'SRC_PORT'};
994 }
995 # Darren Critchey - Just in case error message is already set, this routine would wipe it out if
996 # we don't do a test here
997 if ($cgiparams{'PROTOCOL'} ne 'gre') {
998 unless($errormessage) {$errormessage = &General::validportrange($cgiparams{'DEST_PORT'}, 'dest');}
999 }
1000 unless(&General::validip($cgiparams{'DEST_IP'})) { $errormessage = $Lang::tr{'destination ip bad'}; }
1001 return;
1002}
1003
1004# Darren Critchley - we want to make sure that a port range does not overlap another port range
1005sub checkportoverlap
1006{
1007 my $portrange1 = $_[0]; # New port range
1008 my $portrange2 = $_[1]; # existing port range
1009 my @tempr1 = split(/\:/,$portrange1);
1010 my @tempr2 = split(/\:/,$portrange2);
1011
1012 unless (&checkportinc($tempr1[0], $portrange2)){ return 0;}
1013 unless (&checkportinc($tempr1[1], $portrange2)){ return 0;}
1014
1015 unless (&checkportinc($tempr2[0], $portrange1)){ return 0;}
1016 unless (&checkportinc($tempr2[1], $portrange1)){ return 0;}
1017
1018 return 1; # Everything checks out!
1019}
1020
1021# Darren Critchley - we want to make sure that a port entry is not within an already existing range
1022sub checkportinc
1023{
1024 my $port1 = $_[0]; # Port
1025 my $portrange2 = $_[1]; # Port range
1026 my @tempr1 = split(/\:/,$portrange2);
1027
1028 if ($port1 < $tempr1[0] || $port1 > $tempr1[1]) {
1029 return 1;
1030 } else {
1031 return 0;
1032 }
1033}
1034
1035# Darren Critchley - certain ports are reserved for Ipcop
1036# TCP 67,68,81,222,445
1037# UDP 67,68
1038# Params passed in -> port, rangeyn, protocol
1039sub disallowreserved
1040{
1041 # port 67 and 68 same for tcp and udp, don't bother putting in an array
1042 my $msg = "";
1043 my @tcp_reserved = (81,222,444);
1044 my $prt = $_[0]; # the port or range
1045 my $ryn = $_[1]; # tells us whether or not it is a port range
1046 my $prot = $_[2]; # protocol
1047 my $srcdst = $_[3]; # source or destination
1048
1049 if ($ryn) { # disect port range
1050 if ($srcdst eq "src") {
1051 $msg = "$Lang::tr{'rsvd src port overlap'}";
1052 } else {
1053 $msg = "$Lang::tr{'rsvd dst port overlap'}";
1054 }
1055 my @tmprng = split(/\:/,$prt);
1056 unless (67 < $tmprng[0] || 67 > $tmprng[1]) { $errormessage="$msg 67"; return; }
1057 unless (68 < $tmprng[0] || 68 > $tmprng[1]) { $errormessage="$msg 68"; return; }
1058 if ($prot eq "tcp") {
1059 foreach my $prange (@tcp_reserved) {
1060 unless ($prange < $tmprng[0] || $prange > $tmprng[1]) { $errormessage="$msg $prange"; return; }
1061 }
1062 }
1063 } else {
1064 if ($srcdst eq "src") {
1065 $msg = "$Lang::tr{'reserved src port'}";
1066 } else {
1067 $msg = "$Lang::tr{'reserved dst port'}";
1068 }
1069 if ($prt == 67) { $errormessage="$msg 67"; return; }
1070 if ($prt == 68) { $errormessage="$msg 68"; return; }
1071 if ($prot eq "tcp") {
1072 foreach my $prange (@tcp_reserved) {
1073 if ($prange == $prt) { $errormessage="$msg $prange"; return; }
1074 }
1075 }
1076 }
1077 return;
1078}
1079
1080# Darren Critchley - Attempt to combine Add/Update validation as they are almost the same
1081sub valaddupdate
1082{
1083 if ($cgiparams{'KEY2'} eq "0"){ # if it is a port forward rule, then validate properly
1084 &validateparams();
1085 } else { # it is an xtaccess rule, just check for a valid ip
1086 unless(&General::validipormask($cgiparams{'ORIG_IP'}))
1087 {
1088 if ($cgiparams{'ORIG_IP'} ne '') {
1089 $errormessage = $Lang::tr{'source ip bad'}; }
1090 else { # this rule stops someone from adding an ALL xtaccess record
1091 $errormessage = $Lang::tr{'xtaccess all error'};
1092 $cgiparams{'ACTION'} = $Lang::tr{'add xtaccess'};
1093 }
1094 }
1095 # Darren Critchley - check for 0.0.0.0/0 - not allowed for xtaccess
1096 if ($cgiparams{'ORIG_IP'} eq "0.0.0.0/0" || $cgiparams{'ORIG_IP'} eq "0.0.0.0") {
1097 $errormessage = $Lang::tr{'xtaccess all error'};
1098 $cgiparams{'ACTION'} = $Lang::tr{'add xtaccess'};
1099 }
1100 }
1101 # Darren Critchley - Remove commas from remarks
1102 $cgiparams{'REMARK'} = &Header::cleanhtml($cgiparams{'REMARK'});
1103
1104 # Darren Critchley - Check to see if we are working with port ranges
1105 our ($prtrange1, $prtrange2);
1106 $_ = $cgiparams{'SRC_PORT'};
1107 if ($cgiparams{'KEY2'} eq "0" && m/:/){
1108 $prtrange1 = 1;
1109 }
1110 if ($cgiparams{'SRC_IP'} eq '0.0.0.0') { # Dave Roberts - only check if using DEFAULT IP
1111 if ($prtrange1 == 1){ # check for source ports reserved for Ipcop
1112 &disallowreserved($cgiparams{'SRC_PORT'},1,$cgiparams{'PROTOCOL'},"src");
1113 if ($errormessage) { goto EXITSUB; }
1114 } else { # check for source port reserved for Ipcop
1115 &disallowreserved($cgiparams{'SRC_PORT'},0,$cgiparams{'PROTOCOL'},"src");
1116 if ($errormessage) { goto EXITSUB; }
1117 }
1118 }
1119
1120 $_ = $cgiparams{'DEST_PORT'};
1121 if ($cgiparams{'KEY2'} eq "0" && m/:/){
1122 $prtrange2 = 1;
1123 }
1124 if ($cgiparams{'SRC_IP'} eq '0.0.0.0') { # Dave Roberts - only check if using DEFAULT IP
78331e30 1125 if ($prtrange2 == 1){ # check for destination ports reserved for IPFire
ac1cfefa
MT
1126 &disallowreserved($cgiparams{'DEST_PORT'},1,$cgiparams{'PROTOCOL'},"dst");
1127 if ($errormessage) { goto EXITSUB; }
78331e30 1128 } else { # check for destination port reserved for IPFire
ac1cfefa
MT
1129 &disallowreserved($cgiparams{'DEST_PORT'},0,$cgiparams{'PROTOCOL'},"dst");
1130 if ($errormessage) { goto EXITSUB; }
1131 }
1132 }
1133
1134
1135EXITSUB:
1136 return;
1137}
1138
1139# Darren Critchley - Duplicate or overlapping Port range check
1140sub portchecks
1141{
1142 $_ = $_[0];
1143 our ($prtrange1, $prtrange2);
1144 if (m/:/ && $prtrange1 == 1) { # comparing two port ranges
1145 unless (&checkportoverlap($cgiparams{'SRC_PORT'},$_[0])) {
1146 $errormessage = "$Lang::tr{'source port overlaps'} $_[0]";
1147 }
1148 }
1149 if (m/:/ && $prtrange1 == 0 && $errormessage eq '') { # compare one port to a range
1150 unless (&checkportinc($cgiparams{'SRC_PORT'}, $_[0])) {
1151 $errormessage = "$Lang::tr{'srcprt within existing'} $_[0]";
1152 }
1153 }
1154 if (! m/:/ && $prtrange1 == 1 && $errormessage eq '') { # compare one port to a range
1155 unless (&checkportinc($_[0], $cgiparams{'SRC_PORT'})) {
1156 $errormessage = "$Lang::tr{'srcprt range overlaps'} $_[0]";
1157 }
1158 }
1159
1160 if ($errormessage eq ''){
1161 $_ = $_[1];
1162 if (m/:/ && $prtrange2 == 1) { # if true then there is a port range
1163 unless (&checkportoverlap($cgiparams{'DEST_PORT'},$_[1])) {
1164 $errormessage = "$Lang::tr{'destination port overlaps'} $_[1]";
1165 }
1166 }
1167 if (m/:/ && $prtrange2 == 0 && $errormessage eq '') { # compare one port to a range
1168 unless (&checkportinc($cgiparams{'DEST_PORT'}, $_[1])) {
1169 $errormessage = "$Lang::tr{'dstprt within existing'} $_[1]";
1170 }
1171 }
1172 if (! m/:/ && $prtrange2 == 1 && $errormessage eq '') { # compare one port to a range
1173 unless (&checkportinc($_[1], $cgiparams{'DEST_PORT'})) {
1174 $errormessage = "$Lang::tr{'dstprt range overlaps'} $_[1]";
1175 }
1176 }
1177 }
1178 return;
1179}