]>
Commit | Line | Data |
---|---|---|
ac1cfefa | 1 | #!/usr/bin/perl |
70df8302 MT |
2 | ############################################################################### |
3 | # # | |
4 | # IPFire.org - A linux based firewall # | |
5 | # Copyright (C) 2007 Michael Tremer & Christian Schmidt # | |
6 | # # | |
7 | # This program is free software: you can redistribute it and/or modify # | |
8 | # it under the terms of the GNU General Public License as published by # | |
9 | # the Free Software Foundation, either version 3 of the License, or # | |
10 | # (at your option) any later version. # | |
11 | # # | |
12 | # This program is distributed in the hope that it will be useful, # | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
15 | # GNU General Public License for more details. # | |
16 | # # | |
17 | # You should have received a copy of the GNU General Public License # | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
19 | # # | |
20 | ############################################################################### | |
ac1cfefa MT |
21 | |
22 | use strict; | |
23 | ||
24 | # enable only the following on debugging purpose | |
25 | #use warnings; | |
26 | #use CGI::Carp 'fatalsToBrowser'; | |
27 | ||
986e08d9 | 28 | require '/var/ipfire/general-functions.pl'; |
ac1cfefa MT |
29 | require "${General::swroot}/lang.pl"; |
30 | require "${General::swroot}/header.pl"; | |
31 | ||
32 | #workaround to suppress a warning when a variable is used only once | |
33 | my @dummy = ( ${Header::colouryellow} ); | |
34 | undef (@dummy); | |
35 | ||
f2fdd0c1 CS |
36 | my %color = (); |
37 | my %mainsettings = (); | |
38 | &General::readhash("${General::swroot}/main/settings", \%mainsettings); | |
39 | &General::readhash("/srv/web/ipfire/html/themes/".$mainsettings{'THEME'}."/include/colors.txt", \%color); | |
40 | ||
ac1cfefa MT |
41 | my %cgiparams=(); |
42 | my %selected=(); | |
43 | my %checked=(); | |
44 | my $prtrange1=0; | |
45 | my $prtrange2=0; | |
46 | my $errormessage = ''; | |
47 | my $filename = "${General::swroot}/portfw/config"; | |
48 | my $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 | ||
67 | my $disable_all = "0"; | |
68 | my $enable_all = "0"; | |
69 | ||
70 | if ($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 | ||
116 | ERROR: | |
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 | ||
163 | if ($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 | ||
275 | UPD_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 | |
323 | if ($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'); | |
412 | TOGGLEEXIT: | |
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 | |
418 | if ($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 | |
446 | if ($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 | |
503 | if ($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 | ||
531 | if ($cgiparams{'ACTION'} eq $Lang::tr{'reset'}) | |
532 | { | |
533 | undef %cgiparams; | |
534 | } | |
535 | ||
536 | if ($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 | ||
558 | if ($errormessage) { | |
559 | &Header::openbox('100%', 'left', $Lang::tr{'error messages'}); | |
560 | print "<class name='base'><font color='${Header::colourred}'>$errormessage\n</font>"; | |
561 | print " </class>\n"; | |
562 | &Header::closebox(); | |
563 | } | |
564 | ||
565 | print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>\n"; | |
566 | ||
567 | if ($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 | ||
573 | if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'} && $cgiparams{'KEY2'} ne "0" || $cgiparams{'ACTION'} eq $Lang::tr{'add xtaccess'}){ | |
574 | # if it is not a port forward record, don't validate as the fields are disabled | |
575 | my $PROT = "\U$cgiparams{'PROTOCOL'}\E"; | |
576 | # Darren Critchley - Format the source and destination ports | |
577 | my $dstprt = $cgiparams{'DEST_PORT'}; | |
578 | $dstprt =~ s/-/ - /; | |
579 | $dstprt =~ s/:/ - /; | |
580 | ||
581 | print <<END | |
582 | <table> | |
583 | <tr> | |
584 | <td class='base'>$Lang::tr{'protocol'}: <b>$PROT</b></td> | |
585 | <td width='20'> </td> | |
586 | <td class='base' align='right'>$Lang::tr{'destination ip'}: </td> | |
587 | <td><b>$cgiparams{'DEST_IP'}</b></td> | |
588 | <td width='20'> </td> | |
589 | <td class='base' align='right'>$Lang::tr{'destination port'}: </td> | |
590 | <td><b>$dstprt</b></td> | |
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'}' /> | |
599 | END | |
600 | ; | |
601 | } else { | |
602 | print <<END | |
603 | <table width='100%'> | |
604 | <tr> | |
605 | <td width='10%'>$Lang::tr{'protocol'}: </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> | |
617 | END | |
618 | ; | |
619 | open(ALIASES, "$aliasfile") or die 'Unable to open aliases file.'; | |
620 | while (<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 | } | |
630 | close(ALIASES); | |
631 | print <<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'> </td> | |
639 | <td> </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> | |
646 | END | |
647 | ; | |
648 | } | |
649 | ||
650 | print <<END | |
651 | <table> | |
652 | <tr> | |
653 | <td class='base'>$Lang::tr{'remark title'} <img src='/blob.gif' alt='*' /> </td> | |
654 | <td><input type='text' name='REMARK' value='$cgiparams{'REMARK'}' size='55' maxlength='50' /></td> | |
655 | END | |
656 | ; | |
657 | unless ($cgiparams{'ACTION'} eq $Lang::tr{'add xtaccess'} && $cgiparams{'ENABLED'} eq "off") { | |
658 | print "<td width='20'> </td>"; | |
659 | print "<td>$Lang::tr{'enabled'} </td><td><input type='checkbox' name='ENABLED' $checked{'ENABLED'}{'on'} /></td>\n"; | |
660 | } | |
661 | print <<END | |
662 | </tr> | |
663 | </table> | |
664 | END | |
665 | ; | |
666 | ||
667 | if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'} && $cgiparams{'KEY2'} eq "0" && ($cgiparams{'ORIG_IP'} eq "0" || $cgiparams{'ORIG_IP'} eq "0.0.0.0/0")){ | |
668 | # if it is a port forward rule with a 0 in the orig_port field, this means there are xtaccess records, and we | |
669 | # don't want to allow a person to change the orig_ip field as it will mess other logic up | |
670 | print "<input type='hidden' name='ORIG_IP' value='$cgiparams{'ORIG_IP'}' />\n"; | |
671 | } else { | |
672 | print <<END | |
673 | <table> | |
674 | <tr> | |
675 | <td class='base'><font class='boldbase' color='${Header::colourred}'>$Lang::tr{'source network'}</font> <img src='/blob.gif' alt='*' /> </td> | |
676 | <td><input type='text' name='ORIG_IP' value='$cgiparams{'ORIG_IP'}' size='15' /></td> | |
677 | </tr> | |
678 | </table> | |
679 | END | |
680 | ; | |
681 | } | |
682 | ||
683 | print <<END | |
684 | <table width='100%'> | |
685 | <hr /> | |
686 | <tr> | |
687 | <td class='base' width='25%'><img src='/blob.gif' alt ='*' align='top' /> <font class='base'>$Lang::tr{'this field may be blank'}</font></td> | |
688 | END | |
689 | ; | |
690 | ||
691 | ||
692 | if ($cgiparams{'ACTION'} eq $Lang::tr{'edit'}){ | |
693 | if($cgiparams{'KEY2'} eq "0"){ | |
694 | print "<td width='35%' align='right'>$Lang::tr{'open to all'}: </td><td width='5%'><input type='checkbox' name='OVERRIDE' $checked{'OVERRIDE'}{'on'} /></td>\n"; | |
695 | } else { | |
696 | print "<td width='40%'> </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%'> </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 | } | |
716 | print <<END | |
39a7cc11 | 717 | <td width='5%' align='right'> </td> |
ac1cfefa MT |
718 | </tr> |
719 | </table> | |
720 | END | |
721 | ; | |
722 | &Header::closebox(); | |
723 | ||
724 | print "</form>\n"; | |
725 | ||
726 | &Header::openbox('100%', 'left', $Lang::tr{'current rules'}); | |
727 | print <<END | |
728 | <table width='100%'> | |
729 | <tr> | |
730 | <td width='7%' class='boldbase' align='center'><b>$Lang::tr{'proto'}</b></td> | |
731 | <td width='31%' class='boldbase' align='center'><b>$Lang::tr{'source'}</b></td> | |
732 | <td width='2%' class='boldbase' align='center'> </td> | |
733 | <td width='31%' class='boldbase' align='center'><b>$Lang::tr{'destination'}</b></td> | |
734 | <td width='24%' class='boldbase' align='center'><b>$Lang::tr{'remark'}</b></td> | |
735 | <td width='4%' class='boldbase' colspan='4' align='center'><b>$Lang::tr{'action'}</b></td> | |
736 | </tr> | |
737 | END | |
738 | ; | |
739 | ||
740 | my $id = 0; | |
741 | my $xtaccesscolor = '#F6F4F4'; | |
742 | open(RULES, "$filename") or die 'Unable to open config file.'; | |
743 | while (<RULES>) | |
744 | { | |
745 | my $protocol = ''; | |
746 | my $gif = ''; | |
747 | my $gdesc = ''; | |
748 | my $toggle = ''; | |
749 | chomp($_); | |
750 | my @temp = split(/\,/,$_); | |
751 | $temp[9] ='' unless defined $temp[9];# Glles ESpinasse : suppress warning on page init | |
752 | if ($temp[2] eq 'udp') { | |
753 | $protocol = 'UDP'; } | |
754 | elsif ($temp[2] eq 'gre') { | |
755 | $protocol = 'GRE' } | |
756 | else { | |
757 | $protocol = 'TCP' } | |
758 | # Change bgcolor when a new portfw rule is added | |
759 | if ($temp[1] eq "0"){ | |
760 | $id++; | |
761 | } | |
762 | # Darren Critchley highlight the row we are editing | |
763 | if ( $cgiparams{'ACTION'} eq $Lang::tr{'edit'} && $cgiparams{'KEY1'} eq $temp[0] && $cgiparams{'KEY2'} eq $temp[1] ) { | |
764 | print "<tr bgcolor='${Header::colouryellow}'>\n"; | |
765 | } else { | |
766 | if ($id % 2) { | |
f2fdd0c1 | 767 | print "<tr bgcolor='$color{'color22'}'>\n"; |
ac1cfefa MT |
768 | } |
769 | else { | |
f2fdd0c1 | 770 | print "<tr bgcolor='$color{'color20'}'>\n"; |
ac1cfefa MT |
771 | } |
772 | } | |
773 | ||
774 | if ($temp[6] eq 'on') { $gif = 'on.gif'; $toggle='off'; $gdesc=$Lang::tr{'click to disable'};} | |
775 | else { $gif = 'off.gif'; $toggle='on'; $gdesc=$Lang::tr{'click to enable'}; } | |
776 | ||
777 | # Darren Critchley - this code no longer works - should we remove? | |
778 | # catch for 'old-style' rules file - assume default ip if | |
779 | # none exists | |
780 | if (!&General::validip($temp[7]) || $temp[7] eq '0.0.0.0') { | |
781 | $temp[7] = 'DEFAULT IP'; } | |
782 | if ($temp[1] eq '0') { # Port forwarding entry | |
783 | ||
784 | # Darren Critchley - Format the source and destintation ports | |
785 | my $srcprt = $temp[3]; | |
786 | $srcprt =~ s/-/ - /; | |
787 | $srcprt =~ s/:/ - /; | |
788 | my $dstprt = $temp[5]; | |
789 | $dstprt =~ s/-/ - /; | |
790 | $dstprt =~ s/:/ - /; | |
791 | ||
792 | # Darren Critchley - Get Port Service Name if we can - code borrowed from firewalllog.dat | |
793 | $_=$temp[3]; | |
794 | if (/^\d+$/) { | |
795 | my $servi = uc(getservbyport($temp[3], lc($temp[2]))); | |
796 | if ($servi ne '' && $temp[3] < 1024) { | |
797 | $srcprt = "$srcprt($servi)"; } | |
798 | } | |
799 | $_=$temp[5]; | |
800 | if (/^\d+$/) { | |
801 | my $servi = uc(getservbyport($temp[5], lc($temp[2]))); | |
802 | if ($servi ne '' && $temp[5] < 1024) { | |
803 | $dstprt = "$dstprt($servi)"; } | |
804 | } | |
805 | ||
806 | # Darren Critchley - If the line is too long, wrap the port numbers | |
807 | my $srcaddr = "$temp[7] : $srcprt"; | |
808 | if (length($srcaddr) > 22) { | |
809 | $srcaddr = "$temp[7] :<br /> $srcprt"; | |
810 | } | |
811 | my $dstaddr = "$temp[4] : $dstprt"; | |
812 | if (length($dstaddr) > 26) { | |
813 | $dstaddr = "$temp[4] :<br /> $dstprt"; | |
814 | } | |
815 | print <<END | |
816 | <td align='center'>$protocol</td> | |
817 | <td align='center'>$srcaddr</td> | |
818 | <td align='center'><img src='/images/forward.gif' alt='=>' /></td> | |
819 | <td align='center'>$dstaddr</td> | |
820 | <td align='left'> $temp[9]</td> | |
821 | <td align='center'> | |
822 | <form method='post' name='frm$temp[0]c' action='$ENV{'SCRIPT_NAME'}'> | |
823 | <input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' /> | |
824 | <input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' /> | |
825 | <input type='hidden' name='KEY1' value='$temp[0]' /> | |
826 | <input type='hidden' name='KEY2' value='$temp[1]' /> | |
827 | <input type='hidden' name='ENABLED' value='$toggle' /> | |
828 | </form> | |
829 | </td> | |
830 | ||
831 | <td align='center'> | |
832 | <form method='post' name='frm$temp[0]' action='$ENV{'SCRIPT_NAME'}'> | |
833 | <input type='hidden' name='ACTION' value='$Lang::tr{'add xtaccess'}' /> | |
834 | <input type='image' name='$Lang::tr{'add xtaccess'}' src='/images/add.gif' alt='$Lang::tr{'add xtaccess'}' title='$Lang::tr{'add xtaccess'}' /> | |
835 | <input type='hidden' name='KEY1' value='$temp[0]' /> | |
836 | <input type='hidden' name='KEY2' value='$temp[1]' /> | |
837 | </form> | |
838 | </td> | |
839 | ||
840 | <td align='center'> | |
841 | <form method='post' name='frm$temp[0]' action='$ENV{'SCRIPT_NAME'}'> | |
842 | <input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' /> | |
843 | <input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' /> | |
844 | <input type='hidden' name='KEY1' value='$temp[0]' /> | |
845 | <input type='hidden' name='KEY2' value='$temp[1]' /> | |
846 | </form> | |
847 | </td> | |
848 | ||
849 | <td align='center'> | |
850 | <form method='post' name='frm$temp[0]b' action='$ENV{'SCRIPT_NAME'}'> | |
851 | <input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' /> | |
852 | <input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' /> | |
853 | <input type='hidden' name='KEY1' value='$temp[0]' /> | |
854 | <input type='hidden' name='KEY2' value='$temp[1]' /> | |
855 | </form> | |
856 | </td> | |
857 | ||
858 | </tr> | |
859 | END | |
860 | ; | |
861 | } else { # external access entry | |
862 | print <<END | |
863 | <td align='center'> </td> | |
864 | ||
865 | <td align='left' colspan='4'> <font color='${Header::colourred}'>$Lang::tr{'access allowed'}</font> $temp[8] ($temp[9])</td> | |
866 | ||
867 | <td align='center'> | |
868 | <form method='post' name='frm$temp[0]$temp[1]t' action='$ENV{'SCRIPT_NAME'}'> | |
869 | <input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$Lang::tr{'toggle enable disable'}' title='$Lang::tr{'toggle enable disable'}' /> | |
870 | <input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' /> | |
871 | <input type='hidden' name='KEY1' value='$temp[0]' /> | |
872 | <input type='hidden' name='KEY2' value='$temp[1]' /> | |
873 | <input type='hidden' name='ENABLED' value='$toggle' /> | |
874 | </form> | |
875 | </td> | |
876 | ||
877 | <td align='center'> </td> | |
878 | ||
879 | <td align='center'> | |
880 | <form method='post' name='frm$temp[0]$temp[1]' action='$ENV{'SCRIPT_NAME'}'> | |
881 | <input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' /> | |
882 | <input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' /> | |
883 | <input type='hidden' name='KEY1' value='$temp[0]' /> | |
884 | <input type='hidden' name='KEY2' value='$temp[1]' /> | |
885 | </form> | |
886 | </td> | |
887 | ||
888 | <td align='center'> | |
889 | <form method='post' name='frm$temp[0]b$temp[1]b' action='$ENV{'SCRIPT_NAME'}'> | |
890 | <input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' /> | |
891 | <input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' /> | |
892 | <input type='hidden' name='KEY1' value='$temp[0]' /> | |
893 | <input type='hidden' name='KEY2' value='$temp[1]' /> | |
894 | </form> | |
895 | </td> | |
896 | ||
897 | </tr> | |
898 | END | |
899 | ; | |
900 | } | |
901 | } | |
902 | ||
903 | close(RULES); | |
904 | ||
905 | print "</table>"; | |
906 | ||
907 | # If the fixed lease file contains entries, print Key to action icons | |
908 | if ( ! -z "$filename") { | |
909 | print <<END | |
910 | <table> | |
911 | <tr> | |
912 | <td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td> | |
913 | <td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td> | |
914 | <td class='base'>$Lang::tr{'click to disable'}</td> | |
915 | <td> </td> | |
916 | <td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td> | |
917 | <td class='base'>$Lang::tr{'click to enable'}</td> | |
918 | <td> </td> | |
919 | <td><img src='/images/add.gif' alt='$Lang::tr{'add xtaccess'}' /></td> | |
920 | <td class='base'>$Lang::tr{'add xtaccess'}</td> | |
921 | <td> </td> | |
922 | <td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td> | |
923 | <td class='base'>$Lang::tr{'edit'}</td> | |
924 | <td> </td> | |
925 | <td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td> | |
926 | <td class='base'>$Lang::tr{'remove'}</td> | |
927 | </tr> | |
928 | </table> | |
929 | END | |
930 | ; | |
931 | } | |
932 | ||
933 | &Header::closebox(); | |
934 | ||
935 | &Header::closebigbox(); | |
936 | ||
937 | &Header::closepage(); | |
938 | ||
939 | # Validate Field Entries | |
940 | sub validateparams | |
941 | { | |
942 | # Darren Critchley - Get rid of dashes in port ranges | |
943 | $cgiparams{'DEST_PORT'}=~ tr/-/:/; | |
944 | $cgiparams{'SRC_PORT'}=~ tr/-/:/; | |
945 | ||
946 | # Darren Critchley - code to substitue wildcards | |
947 | if ($cgiparams{'SRC_PORT'} eq "*") { | |
948 | $cgiparams{'SRC_PORT'} = "1:65535"; | |
949 | } | |
950 | if ($cgiparams{'SRC_PORT'} =~ /^(\D)\:(\d+)$/) { | |
951 | $cgiparams{'SRC_PORT'} = "1:$2"; | |
952 | } | |
953 | if ($cgiparams{'SRC_PORT'} =~ /^(\d+)\:(\D)$/) { | |
954 | $cgiparams{'SRC_PORT'} = "$1:65535"; | |
955 | } | |
956 | if ($cgiparams{'DEST_PORT'} eq "*") { | |
957 | $cgiparams{'DEST_PORT'} = "1:65535"; | |
958 | } | |
959 | if ($cgiparams{'DEST_PORT'} =~ /^(\D)\:(\d+)$/) { | |
960 | $cgiparams{'DEST_PORT'} = "1:$2"; | |
961 | } | |
962 | if ($cgiparams{'DEST_PORT'} =~ /^(\d+)\:(\D)$/) { | |
963 | $cgiparams{'DEST_PORT'} = "$1:65535"; | |
964 | } | |
965 | ||
966 | # Darren Critchley - Add code for GRE protocol - we want to ignore ports, but we need a place holder | |
967 | if ($cgiparams{'PROTOCOL'} eq 'gre') { | |
968 | $cgiparams{'SRC_PORT'} = "GRE"; | |
969 | $cgiparams{'DEST_PORT'} = "GRE"; | |
970 | } | |
971 | ||
972 | unless($cgiparams{'PROTOCOL'} =~ /^(tcp|udp|gre)$/) { $errormessage = $Lang::tr{'invalid input'}; } | |
973 | # Darren Critchley - Changed how the error routine works a bit - for the validportrange check, we need to | |
974 | # pass in src or dest to determine which side we are working with. | |
975 | # the routine returns the complete error or '' | |
976 | if ($cgiparams{'PROTOCOL'} ne 'gre') { | |
977 | $errormessage = &General::validportrange($cgiparams{'SRC_PORT'}, 'src'); | |
978 | } | |
979 | if( ($cgiparams{'ORIG_IP'} ne "0" && $cgiparams{'KEY2'} ne "0") || $cgiparams{'ACTION'} eq $Lang::tr{'add'}) { | |
980 | # if it is a port forward record with 0 in orig_ip then ignore checking this field | |
981 | unless(&General::validipormask($cgiparams{'ORIG_IP'})) | |
982 | { | |
983 | if ($cgiparams{'ORIG_IP'} ne '') { | |
984 | $errormessage = $Lang::tr{'source ip bad'}; } | |
985 | else { | |
986 | $cgiparams{'ORIG_IP'} = '0.0.0.0/0'; } | |
987 | } | |
988 | } | |
989 | # Darren Critchey - New rule that sets destination same as source if dest_port is blank. | |
990 | if ($cgiparams{'DEST_PORT'} eq ''){ | |
991 | $cgiparams{'DEST_PORT'} = $cgiparams{'SRC_PORT'}; | |
992 | } | |
993 | # Darren Critchey - Just in case error message is already set, this routine would wipe it out if | |
994 | # we don't do a test here | |
995 | if ($cgiparams{'PROTOCOL'} ne 'gre') { | |
996 | unless($errormessage) {$errormessage = &General::validportrange($cgiparams{'DEST_PORT'}, 'dest');} | |
997 | } | |
998 | unless(&General::validip($cgiparams{'DEST_IP'})) { $errormessage = $Lang::tr{'destination ip bad'}; } | |
999 | return; | |
1000 | } | |
1001 | ||
1002 | # Darren Critchley - we want to make sure that a port range does not overlap another port range | |
1003 | sub checkportoverlap | |
1004 | { | |
1005 | my $portrange1 = $_[0]; # New port range | |
1006 | my $portrange2 = $_[1]; # existing port range | |
1007 | my @tempr1 = split(/\:/,$portrange1); | |
1008 | my @tempr2 = split(/\:/,$portrange2); | |
1009 | ||
1010 | unless (&checkportinc($tempr1[0], $portrange2)){ return 0;} | |
1011 | unless (&checkportinc($tempr1[1], $portrange2)){ return 0;} | |
1012 | ||
1013 | unless (&checkportinc($tempr2[0], $portrange1)){ return 0;} | |
1014 | unless (&checkportinc($tempr2[1], $portrange1)){ return 0;} | |
1015 | ||
1016 | return 1; # Everything checks out! | |
1017 | } | |
1018 | ||
1019 | # Darren Critchley - we want to make sure that a port entry is not within an already existing range | |
1020 | sub checkportinc | |
1021 | { | |
1022 | my $port1 = $_[0]; # Port | |
1023 | my $portrange2 = $_[1]; # Port range | |
1024 | my @tempr1 = split(/\:/,$portrange2); | |
1025 | ||
1026 | if ($port1 < $tempr1[0] || $port1 > $tempr1[1]) { | |
1027 | return 1; | |
1028 | } else { | |
1029 | return 0; | |
1030 | } | |
1031 | } | |
1032 | ||
1033 | # Darren Critchley - certain ports are reserved for Ipcop | |
1034 | # TCP 67,68,81,222,445 | |
1035 | # UDP 67,68 | |
1036 | # Params passed in -> port, rangeyn, protocol | |
1037 | sub disallowreserved | |
1038 | { | |
1039 | # port 67 and 68 same for tcp and udp, don't bother putting in an array | |
1040 | my $msg = ""; | |
1041 | my @tcp_reserved = (81,222,444); | |
1042 | my $prt = $_[0]; # the port or range | |
1043 | my $ryn = $_[1]; # tells us whether or not it is a port range | |
1044 | my $prot = $_[2]; # protocol | |
1045 | my $srcdst = $_[3]; # source or destination | |
1046 | ||
1047 | if ($ryn) { # disect port range | |
1048 | if ($srcdst eq "src") { | |
1049 | $msg = "$Lang::tr{'rsvd src port overlap'}"; | |
1050 | } else { | |
1051 | $msg = "$Lang::tr{'rsvd dst port overlap'}"; | |
1052 | } | |
1053 | my @tmprng = split(/\:/,$prt); | |
1054 | unless (67 < $tmprng[0] || 67 > $tmprng[1]) { $errormessage="$msg 67"; return; } | |
1055 | unless (68 < $tmprng[0] || 68 > $tmprng[1]) { $errormessage="$msg 68"; return; } | |
1056 | if ($prot eq "tcp") { | |
1057 | foreach my $prange (@tcp_reserved) { | |
1058 | unless ($prange < $tmprng[0] || $prange > $tmprng[1]) { $errormessage="$msg $prange"; return; } | |
1059 | } | |
1060 | } | |
1061 | } else { | |
1062 | if ($srcdst eq "src") { | |
1063 | $msg = "$Lang::tr{'reserved src port'}"; | |
1064 | } else { | |
1065 | $msg = "$Lang::tr{'reserved dst port'}"; | |
1066 | } | |
1067 | if ($prt == 67) { $errormessage="$msg 67"; return; } | |
1068 | if ($prt == 68) { $errormessage="$msg 68"; return; } | |
1069 | if ($prot eq "tcp") { | |
1070 | foreach my $prange (@tcp_reserved) { | |
1071 | if ($prange == $prt) { $errormessage="$msg $prange"; return; } | |
1072 | } | |
1073 | } | |
1074 | } | |
1075 | return; | |
1076 | } | |
1077 | ||
1078 | # Darren Critchley - Attempt to combine Add/Update validation as they are almost the same | |
1079 | sub valaddupdate | |
1080 | { | |
1081 | if ($cgiparams{'KEY2'} eq "0"){ # if it is a port forward rule, then validate properly | |
1082 | &validateparams(); | |
1083 | } else { # it is an xtaccess rule, just check for a valid ip | |
1084 | unless(&General::validipormask($cgiparams{'ORIG_IP'})) | |
1085 | { | |
1086 | if ($cgiparams{'ORIG_IP'} ne '') { | |
1087 | $errormessage = $Lang::tr{'source ip bad'}; } | |
1088 | else { # this rule stops someone from adding an ALL xtaccess record | |
1089 | $errormessage = $Lang::tr{'xtaccess all error'}; | |
1090 | $cgiparams{'ACTION'} = $Lang::tr{'add xtaccess'}; | |
1091 | } | |
1092 | } | |
1093 | # Darren Critchley - check for 0.0.0.0/0 - not allowed for xtaccess | |
1094 | if ($cgiparams{'ORIG_IP'} eq "0.0.0.0/0" || $cgiparams{'ORIG_IP'} eq "0.0.0.0") { | |
1095 | $errormessage = $Lang::tr{'xtaccess all error'}; | |
1096 | $cgiparams{'ACTION'} = $Lang::tr{'add xtaccess'}; | |
1097 | } | |
1098 | } | |
1099 | # Darren Critchley - Remove commas from remarks | |
1100 | $cgiparams{'REMARK'} = &Header::cleanhtml($cgiparams{'REMARK'}); | |
1101 | ||
1102 | # Darren Critchley - Check to see if we are working with port ranges | |
1103 | our ($prtrange1, $prtrange2); | |
1104 | $_ = $cgiparams{'SRC_PORT'}; | |
1105 | if ($cgiparams{'KEY2'} eq "0" && m/:/){ | |
1106 | $prtrange1 = 1; | |
1107 | } | |
1108 | if ($cgiparams{'SRC_IP'} eq '0.0.0.0') { # Dave Roberts - only check if using DEFAULT IP | |
1109 | if ($prtrange1 == 1){ # check for source ports reserved for Ipcop | |
1110 | &disallowreserved($cgiparams{'SRC_PORT'},1,$cgiparams{'PROTOCOL'},"src"); | |
1111 | if ($errormessage) { goto EXITSUB; } | |
1112 | } else { # check for source port reserved for Ipcop | |
1113 | &disallowreserved($cgiparams{'SRC_PORT'},0,$cgiparams{'PROTOCOL'},"src"); | |
1114 | if ($errormessage) { goto EXITSUB; } | |
1115 | } | |
1116 | } | |
1117 | ||
1118 | $_ = $cgiparams{'DEST_PORT'}; | |
1119 | if ($cgiparams{'KEY2'} eq "0" && m/:/){ | |
1120 | $prtrange2 = 1; | |
1121 | } | |
1122 | if ($cgiparams{'SRC_IP'} eq '0.0.0.0') { # Dave Roberts - only check if using DEFAULT IP | |
78331e30 | 1123 | if ($prtrange2 == 1){ # check for destination ports reserved for IPFire |
ac1cfefa MT |
1124 | &disallowreserved($cgiparams{'DEST_PORT'},1,$cgiparams{'PROTOCOL'},"dst"); |
1125 | if ($errormessage) { goto EXITSUB; } | |
78331e30 | 1126 | } else { # check for destination port reserved for IPFire |
ac1cfefa MT |
1127 | &disallowreserved($cgiparams{'DEST_PORT'},0,$cgiparams{'PROTOCOL'},"dst"); |
1128 | if ($errormessage) { goto EXITSUB; } | |
1129 | } | |
1130 | } | |
1131 | ||
1132 | ||
1133 | EXITSUB: | |
1134 | return; | |
1135 | } | |
1136 | ||
1137 | # Darren Critchley - Duplicate or overlapping Port range check | |
1138 | sub portchecks | |
1139 | { | |
1140 | $_ = $_[0]; | |
1141 | our ($prtrange1, $prtrange2); | |
1142 | if (m/:/ && $prtrange1 == 1) { # comparing two port ranges | |
1143 | unless (&checkportoverlap($cgiparams{'SRC_PORT'},$_[0])) { | |
1144 | $errormessage = "$Lang::tr{'source port overlaps'} $_[0]"; | |
1145 | } | |
1146 | } | |
1147 | if (m/:/ && $prtrange1 == 0 && $errormessage eq '') { # compare one port to a range | |
1148 | unless (&checkportinc($cgiparams{'SRC_PORT'}, $_[0])) { | |
1149 | $errormessage = "$Lang::tr{'srcprt within existing'} $_[0]"; | |
1150 | } | |
1151 | } | |
1152 | if (! m/:/ && $prtrange1 == 1 && $errormessage eq '') { # compare one port to a range | |
1153 | unless (&checkportinc($_[0], $cgiparams{'SRC_PORT'})) { | |
1154 | $errormessage = "$Lang::tr{'srcprt range overlaps'} $_[0]"; | |
1155 | } | |
1156 | } | |
1157 | ||
1158 | if ($errormessage eq ''){ | |
1159 | $_ = $_[1]; | |
1160 | if (m/:/ && $prtrange2 == 1) { # if true then there is a port range | |
1161 | unless (&checkportoverlap($cgiparams{'DEST_PORT'},$_[1])) { | |
1162 | $errormessage = "$Lang::tr{'destination port overlaps'} $_[1]"; | |
1163 | } | |
1164 | } | |
1165 | if (m/:/ && $prtrange2 == 0 && $errormessage eq '') { # compare one port to a range | |
1166 | unless (&checkportinc($cgiparams{'DEST_PORT'}, $_[1])) { | |
1167 | $errormessage = "$Lang::tr{'dstprt within existing'} $_[1]"; | |
1168 | } | |
1169 | } | |
1170 | if (! m/:/ && $prtrange2 == 1 && $errormessage eq '') { # compare one port to a range | |
1171 | unless (&checkportinc($_[1], $cgiparams{'DEST_PORT'})) { | |
1172 | $errormessage = "$Lang::tr{'dstprt range overlaps'} $_[1]"; | |
1173 | } | |
1174 | } | |
1175 | } | |
1176 | return; | |
1177 | } |