Handle hostnames with upper-case letters
[webmin.git] / xinetd / save_serv.cgi
1 #!/usr/local/bin/perl
2 # save_serv.cgi
3 # Create, modify or delete an internet service
4
5 require './xinetd-lib.pl';
6 &ReadParse();
7 @conf = &get_xinetd_config();
8 if ($in{'new'}) {
9         $xinet = { 'name' => 'service',
10                    'members' => [ ] };
11         }
12 else {
13         $xinet = $conf[$in{'idx'}];
14         ($defs) = grep { $_->{'name'} eq 'defaults' } @conf;
15         foreach $m (@{$defs->{'members'}}) {
16                 $ddisable{$m->{'value'}} = $m if ($m->{'name'} eq 'disabled');
17                 }
18         $oldid = $xinet->{'quick'}->{'id'}->[0] || $xinet->{'value'};
19         }
20
21 &lock_file($config{'xinetd_conf'});
22 if ($in{'delete'}) {
23         # Delete a service
24         &delete_xinet($xinet);
25         }
26 else {
27         # Validate inputs
28         &error_setup($text{'serv_err'});
29         $in{'id'} =~ /^\S+$/ || &error($text{'serv_eid'});
30         $in{'bind_def'} || &check_ipaddress($in{'bind'}) ||
31             &check_ip6address($in{'bind'}) ||
32                 &error($text{'serv_ebind'});
33         foreach $p (&list_protocols()) {
34                 @ps = getservbyname($in{'id'}, $p);
35                 last if (@ps);
36                 }
37         if ($in{'port_def'}) {
38                 # make sure the service actually exists
39                 if ($in{'proto'}) {
40                         @s = getservbyname($in{'id'}, $in{'proto'});
41                         }
42                 else {
43                         @s = @ps;
44                         }
45                 @s || &error(&text('serv_estd', $in{'name'}));
46                 }
47         else {
48                 $in{'port'} =~ /^\d+$/ || &error($text{'serv_eport'});
49                 $in{'proto'} || @ps || &error($text{'serv_eproto'});
50                 }
51         $in{'inst_def'} || $in{'inst'} =~ /^\d+$/ ||
52                 &error($text{'serv_einst'});
53         $in{'user'} || $in{'prog'} == 0 || &error($text{'serv_euser'});
54         $in{'group_def'} || $in{'group'} || &error($text{'serv_egroup'});
55         $in{'nice_def'} || $in{'nice'} =~ /^\d+$/ ||
56                 &error($text{'serv_enice'});
57         if (!$in{'cps_def'}) {
58                 $in{'cps0'} =~ /^\d+$/ || &error($text{'serv_ecps0'});
59                 $in{'cps1'} =~ /^\d+$/ || &error($text{'serv_ecps1'});
60                 }
61         if (!$in{'times_def'}) {
62                 @times = split(/\s+/, $in{'times'});
63                 map { &error($text{'serv_etimes'}) if (!/^\d+:\d+\-\d+:\d+$/) }
64                     @times;
65                 }
66
67         # Create service structure
68         $xinet->{'values'} = [ $in{'id'} ];
69         &set_member_value($xinet, 'disable', $in{'disable'} ? 'yes' : undef);
70         &set_member_value($xinet, 'port',
71                           $in{'port_def'} ? undef : $in{'port'});
72         &set_member_value($xinet, 'bind',
73                           $in{'bind_def'} ? undef : $in{'bind'});
74         &set_member_value($xinet, 'socket_type', $in{'sock'});
75         &set_member_value($xinet, 'protocol', $in{'proto'} ? $in{'proto'}
76                                                            : undef);
77
78         &set_member_value($xinet, 'user', $in{'user'}) if ($in{'user'});
79         &set_member_value($xinet, 'group',
80                           $in{'group_def'} ? undef : $in{'group'});
81         @type = @{$q->{'type'}};
82         @flags = @{$q->{'flags'}};
83         if ($in{'prog'} == 0) {
84                 @type = &unique(@type, 'INTERNAL');
85                 &set_member_value($xinet, 'server');
86                 &set_member_value($xinet, 'server_args');
87                 &set_member_value($xinet, 'redirect');
88                 }
89         elsif ($in{'prog'} == 1) {
90                 @type = grep { $_ ne 'INTERNAL' } @type;
91                 @s = split(/\s+/, $in{'server'});
92                 $in{'disable'} || @s && -x $s[0] ||
93                         &error($text{'serv_eserver'});
94                 &set_member_value($xinet, 'server', shift(@s));
95                 &set_member_value($xinet, 'server_args', @s);
96                 &set_member_value($xinet, 'redirect');
97                 }
98         else {
99                 &to_ipaddress($in{'rhost'}) ||
100                         &error($text{'serv_erhost'});
101                 $in{'rport'} =~ /^\d+$/ || &error($text{'serv_erport'});
102                 @type = grep { $_ ne 'INTERNAL' } @type;
103                 &set_member_value($xinet, 'server');
104                 &set_member_value($xinet, 'server_args');
105                 &set_member_value($xinet, 'redirect',
106                                   $in{'rhost'}, $in{'rport'});
107                 }
108         if ($in{'port_def'} || (!$in{'port_def'} && !$in{'proto'} && @ps)) {
109                 @type = grep { $_ ne 'UNLISTED' } @type;
110                 }
111         else {
112                 @type = &unique(@type, 'UNLISTED');
113                 }
114         &set_member_value($xinet, 'type', @type);
115         &set_member_value($xinet, 'wait', $in{'wait'} ? 'yes' : 'no');
116         &set_member_value($xinet, 'instances',
117                           $in{'inst_def'} ? undef : $in{'inst'});
118         &set_member_value($xinet, 'nice',
119                           $in{'nice_def'} ? undef : $in{'nice'});
120         &set_member_value($xinet, 'cps',
121                           $in{'cps_def'} ? ( ) : ( $in{'cps0'},$in{'cps1'} ) );
122         &set_member_value($xinet, 'only_from', $in{'from_def'} ? undef :
123                           $in{'from'} ? split(/\s+/, $in{'from'}) : ("") );
124         &set_member_value($xinet, 'no_access', $in{'access_def'} ? undef :
125                           $in{'access'} ? split(/\s+/, $in{'access'}) : ("") );
126         &set_member_value($xinet, 'access_times', $in{'times_def'} ? undef
127                                                                    : @times);
128
129         if ($in{'new'}) {
130                 foreach $xi (@conf) {
131                         if ($xi->{'name'} eq 'service' &&
132                             $xi->{'value'} eq $in{'id'}) {
133                                 # A service with the same name exists!
134                                 &set_member_value(
135                                         $xinet, 'id', "$in{'id'}-$in{'sock'}");
136                                 }
137                         }
138                 if (-d $config{'add_dir'}) {
139                         &lock_file($newfile);
140                         $newfile = "$config{'add_dir'}/$in{'id'}";
141                         &create_xinet($xinet, $newfile);
142                         &unlock_file($newfile);
143                         }
144                 else {
145                         &create_xinet($xinet);
146                         }
147                 }
148         else {
149                 &modify_xinet($xinet);
150                 if ($ddisable{$oldid}) {
151                         # Take out old global disabled
152                         &delete_xinet($ddisable{$oldid});
153                         }
154                 }
155         }
156 &unlock_file($config{'xinetd_conf'});
157 &webmin_log($in{'delete'} ? 'delete' : $in{'new'} ? 'create' : 'modify',
158             'serv', $xinet->{'values'}->[0], $xinet->{'quick'});
159 &redirect("");
160