Files
webmin/itsecur-firewall/save_service.cgi
2011-03-25 17:11:27 -07:00

118 lines
3.0 KiB
Perl
Executable File

#!/usr/bin/perl
# save_service.cgi
# Create, update or delete a service
require './itsecur-lib.pl';
&can_edit_error("services");
&ReadParse();
&lock_itsecur_files();
@servs = &list_services();
if (!$in{'new'}) {
$serv = $servs[$in{'idx'}];
}
if ($in{'delete'}) {
# Check if in use by a rule or other service
&error_setup($text{'service_err2'});
@rules = &list_rules();
foreach $r (@rules) {
@rservs = split(/,/, $r->{'service'});
&error($text{'service_einuse'})
if (&indexof($serv->{'name'}, @rservs) >= 0);
}
foreach $s (@servs) {
&error($text{'service_einuse2'})
if (&indexof($serv->{'name'}, @{$s->{'others'}}) >= 0);
}
# Just delete this service
splice(@servs, $in{'idx'}, 1);
&automatic_backup();
}
else {
# Validate inputs
&error_setup($text{'service_err'});
$in{'name'} =~ /\S/ || &error($text{'service_ename'});
@others = split(/\0/, $in{'others'});
for($i=0; defined($in{"proto_$i"}); $i++) {
next if (!$in{"proto_$i"});
if ($in{"proto_$i"} eq 'icmp') {
$in{"port_$i"} =~ /^\d+$/ ||
$in{"port_$i"} eq '*' ||
&error(&text('service_eicmp', $i+1));
}
elsif ($in{"proto_$i"} eq 'ip') {
$in{"port_$i"} =~ /^\d+$/ ||
&error(&text('service_eip', $i+1));
}
else {
$in{"port_$i"} =~ /^\d+$/ ||
$in{"port_$i"} =~ /^\d+\-\d+$/ ||
$in{"port_$i"} =~ /^\d+(\s+\d+)*$/ ||
&error(&text('service_eport', $i+1));
}
push(@protos, $in{"proto_$i"});
push(@ports, $in{"port_$i"});
}
@protos || @others || &error($text{'service_enone'});
#&unique(@protos) == 1 || &error($text{'service_eprotos'});
if ($in{'new'} || lc($in{'name'}) ne lc($serv->{'name'})) {
# Check for clash
($clash) = grep { lc($_->{'name'}) eq lc($in{'name'}) } @servs;
$clash && &error($text{'service_eclash'});
}
$oldname = $serv->{'name'};
$serv->{'name'} = $in{'name'};
$serv->{'protos'} = \@protos;
$serv->{'ports'} = \@ports;
$serv->{'others'} = \@others;
if ($in{'new'}) {
push(@servs, $serv);
}
&automatic_backup();
if (!$in{'new'} && $oldname ne $serv->{'name'}) {
# Has been re-named .. update all rules!
@rules = &list_rules();
foreach $r (@rules) {
$r->{'service'} = &replace_service_name(
$r->{'service'}, $oldname, $serv->{'name'});
}
&save_rules(@rules);
# Also update PAT services
@forwards = &get_pat();
foreach $f (@forwards) {
$f->{'service'} = &replace_service_name(
$f->{'service'}, $oldname, $serv->{'name'});
}
&save_pat(@forwards);
# Also update other services
foreach $s (@servs) {
$idx = &indexof($oldname, @{$s->{'others'}});
if ($idx >= 0) {
$s->{'others'}->[$idx] = $serv->{'name'};
}
}
}
}
&save_services(@servs);
&unlock_itsecur_files();
&remote_webmin_log($in{'delete'} ? "delete" : $in{'new'} ? "create" : "update",
"service", $serv->{'name'}, $serv);
&redirect("list_services.cgi");
# replace_service_name(comma-list, old, new)
sub replace_service_name
{
local @servs = split(/,/, $_[0]);
foreach $s (@servs) {
$s = $_[2] if ($s eq $_[1]);
}
return join(",", @servs);
}