Handle hostnames with upper-case letters
[webmin.git] / inetd / save_serv.cgi
1 #!/usr/local/bin/perl
2 # save_serv.cgi
3 # Save or create an internet service. This can be called N ways
4 #  - create a new services file entry
5 #  - create a new inetd.conf entry (and maybe update or add to services file)
6 #  - update inetd.conf (and maybe services)
7 #  - remove an entry from inetd.conf (and maybe change services)
8
9 require './inetd-lib.pl';
10 &error_setup($text{'error_saveservice'});
11 &ReadParse();
12
13 # Check inputs
14 $in{'name'} =~ /^[A-z][A-z0-9\_\-]+$/ ||
15         &error(&text('error_invalidservice' ,$in{'name'}));
16 $in{'port'} =~ /^[0-9]*$/ || &error(&text('error_invalidport', $in{'port'}));
17 if ($in{'port'} <= 0 || $in{'port'} > 65535) {
18         &error(&text('error_portnum', $in{'port'}));
19         }
20 if ($in{'act'} && $in{'serv'} == 2) {
21         $in{'program'} =~ /^\/\S+$/ ||
22                 &error(&text('error_invalidprg', $in{program}));
23         if ($in{'act'} == 2) {
24                 if (!$in{'qm'}) {
25                         -r $in{'program'} ||
26                                 &error(&text('error_notexist', $in{'program'}));
27                         -x $in{'program'} ||
28                                 &error(&text('error_notexecutable', $in{'program'}));
29                         }
30                 }
31         $in{'args'} =~ /^\S+/ ||&error(&text('error_invalidarg', $in{'args'}));
32         }
33 elsif ($in{'act'} && $in{serv} == 3) {
34         $in{tcpd} =~ /^\S+$/ ||
35                 &error(&text('error_invalidwrapper', $in{tcpd}));
36         }
37 if ($in{'act'}) {
38         $in{'user'} || &error($text{'error_nouser'});
39         defined(getpwnam($in{'user'})) || &error($text{'error_user'});
40         if ($config{'extended_inetd'} == 1) {
41                 $in{'group_def'} || defined(getgrnam($in{'group'})) ||
42                         &error($text{'error_group'});
43                 }
44         }
45 if ($config{'extended_inetd'} && !$in{'permin_def'} && $in{'permin'}!~/^\d+$/) {
46         &error(&text('error_invalidpermin', $in{'permin'}));
47         }
48 if ($config{'extended_inetd'} == 2 &&
49     !$in{'child_def'} && $in{'child'} !~ /^\d+$/) {
50         &error(&text('error_invalidchildnum', $in{'child'}));
51         }
52
53 # Build argument list
54 @sargs = ($in{'name'}, $in{'port'}, $in{'protocol'},
55           join(' ', split(/\s+/, $in{'aliases'})) );
56 @iargs = ($in{'act'} == 2, $in{'name'},
57           $in{'protocol'} =~ /^tcp/ ? "stream" : "dgram", $in{'protocol'});
58 $wait = $in{'wait'};
59 $user = $in{'user'};
60 if ($config{'extended_inetd'} == 1) {
61         if (!$in{'permin_def'}) { $wait .= ".$in{'permin'}"; }
62         if (!$in{'group_def'}) { $user .= ".$in{'group'}"; }
63         }
64 elsif ($config{'extended_inetd'} == 2) {
65         if (!$in{'child_def'}) { $wait .= "/$in{'child'}"; }
66         if (!$in{'permin_def'} && $in{'child_def'}) {
67                 &error($text{'error_childnum'});
68                 }
69         if (!$in{'permin_def'}) { $wait .= "/$in{'permin'}"; }
70         if ($in{'group'}) { $user .= ":$in{'group'}"; }
71         if ($in{'class'}) { $user .= "/$in{'class'}"; }
72         }
73 push(@iargs, $wait);
74 push(@iargs, $user);
75 if (($in{'serv'} == 1) & (!$config{'no_internal'})) {
76         push(@iargs, "internal", undef);
77         }
78 elsif (($in{'serv'} == 1) & ($config{'no_internal'})) {
79         &error(&text('error_invalidcmd', $in{args}));
80         }
81 elsif ($in{serv} == 2) {
82         push(@iargs, ($in{'qm'} ? "?" : "").$in{'program'});
83         push(@iargs, $in{'args'});
84         }
85 elsif ($in{serv} == 3) {
86         push(@iargs, $config{'tcpd_path'});
87         push(@iargs, $in{'tcpd'});
88         $iargs[$#iargs] .= " $in{'args2'}" if ($in{'args2'});
89         }
90
91 &lock_inetd_files();
92 @servs = &list_services();
93 @inets = &list_inets();
94 foreach $s (@servs) {
95         if ($s->[1] eq $sargs[0] && $s->[3] eq $sargs[2]) { $same_name = $s; }
96         if ($s->[2] == $sargs[1] && $s->[3] eq $sargs[2]) { $same_port = $s; }
97         }
98
99 if ($in{'spos'} =~ /\d/) {
100         # Changing a service..
101         @old_serv = @{$servs[$in{'spos'}]};
102         if ($in{'ipos'} =~ /\d/) {
103                 @old_inet = @{$inets[$in{'ipos'}]};
104                 }
105         if ($old_serv[1] ne $sargs[0] || $old_serv[2] != $sargs[1] ||
106             $old_serv[3] ne $sargs[2]) {
107                 if ($same_name && $same_name->[2] != $old_serv[2]) {
108                         &error(&text('error_nameexist', $sargs[0], $sargs[2]));
109                         }
110                 if ($same_port && $same_port->[1] ne $old_serv[1]) {
111                         &error(&text('error_serviceexist', $sargs[1], $sargs[2]));
112                         }
113                 }
114         &modify_service($old_serv[0], @sargs);
115         if ($in{'act'} && @old_inet) {
116                 # modify inetd
117                 &modify_inet($old_inet[0], @iargs, $old_inet[10]);
118                 }
119         elsif ($in{'act'} && !@old_inet) {
120                 # add to inetd
121                 &create_inet(@iargs);
122                 }
123         elsif (!$in{'act'} && @old_inet) {
124                 # remove from inetd
125                 &delete_inet($old_inet[0], $old_inet[10]);
126                 @iargs = ();
127                 }
128         &unlock_inetd_files();
129         &webmin_log("modify", "serv", $sargs[0],
130                     { 'name' => $sargs[0], 'port' => $sargs[1],
131                       'proto' => $sargs[2], 'active' => $iargs[0],
132                       'user' => $iargs[5], 'wait' => $iargs[4],
133                       'prog' => $in{'act'} ? join(" ", @iargs[6..@iargs-1])
134                                            : undef } );
135         }
136 else {
137         # Creating a new service...
138         # Check for a service with the same name or port and protocol
139         if ($same_name) {
140                 &error(&text('error_nameexist', $sargs[0], $sargs[2]));
141                 }
142         if ($same_port) {
143                 &error(&text('error_serviceexist', $sargs[1], $sargs[2]));
144                 }
145         # Check for an existing internet service
146         if ($in{'act'}) {
147                 foreach $i (@inets) {
148                         if ($i->[3] eq $iargs[1] && $i->[5] eq $iargs[3]) {
149                                 &error(&text('error_inetservice', $i->[3], $i->[5]));
150                                 }
151                         }
152                 }
153         &create_service(@sargs);
154         if ($in{'act'}) { &create_inet(@iargs); }
155         &unlock_inetd_files();
156         &webmin_log("create", "serv", $sargs[0],
157                     { 'name' => $sargs[0], 'port' => $sargs[1],
158                       'proto' => $sargs[2], 'active' => $iargs[0],
159                       'user' => $iargs[5], 'wait' => $iargs[4],
160                       'prog' => $in{'act'} ? join(" ", @iargs[6..@iargs-1])
161                                            : undef } );
162         }
163 &redirect("");
164