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