Handle hostnames with upper-case letters
[webmin.git] / nis / debian-linux-lib.pl
1 # debian-linux-lib.pl
2 # NIS functions for debian linux NIS client and server
3
4 $yp_makefile = "/var/yp/Makefile";
5 $ypserv_conf = "/etc/ypserv.conf";
6 $pid_file = "/var/run/ypserv.pid";
7
8 # get_nis_support()
9 # Returns 0 for no support, 1 for client only, 2 for server and 3 for both
10 sub get_nis_support
11 {
12 local $rv;
13 $rv += 1 if (&has_command("ypbind"));
14 $rv += 2 if (&has_command("ypserv"));
15 return $rv;
16 }
17
18 # get_client_config()
19 # Returns a hash ref containg details of the client's NIS settings
20 sub get_client_config
21 {
22 local $nis = { 'broadcast' => 1 };
23 open(CONF, $config{'client_conf'});
24 while(<CONF>) {
25         s/\r|\n//g;
26         s/#.*$//g;
27         if (/^\s*domain\s*(\S+)\s*server\s*(\S+)/i) {
28                 push(@{$nis->{'servers'}}, $2);
29                 $nis->{'broadcast'} = 0;
30                 }
31         elsif (/^\s*ypserver\s*(\S+)/) {
32                 push(@{$nis->{'servers'}}, $1);
33                 $nis->{'broadcast'} = 0;
34                 }
35         }
36 close(CONF);
37 open(DOMAIN, "/etc/defaultdomain");
38 chop($nis->{'domain'} = <DOMAIN>);
39 close(DOMAIN);
40 return $nis;
41 }
42
43 # save_client_config(&config)
44 # Saves and applies the NIS client configuration in the give hash.
45 # Returns an error message if any, or undef on success.
46 sub save_client_config
47 {
48 # Save the config file
49 &open_tempfile(CONF, ">$config{'client_conf'}");
50 &open_tempfile(DOMAIN, ">/etc/defaultdomain");
51 if ($_[0]->{'domain'}) {
52         if (!$_[0]->{'broadcast'}) {
53                 local @s = @{$_[0]->{'servers'}};
54                 &print_tempfile(CONF, "domain $_[0]->{'domain'} server ",shift(@s),"\n");
55                 foreach $s (@s) {
56                         &print_tempfile(CONF, "ypserver $s\n");
57                         }
58                 }
59         &print_tempfile(DOMAIN, $_[0]->{'domain'},"\n");
60         }
61 &close_tempfile(CONF);
62 &close_tempfile(DOMAIN);
63 if ($_[0]->{'domain'}) {
64         &init::enable_at_boot("nis");
65         }
66
67 # Apply by running the init script
68 local $init = &init_script("nis");
69 &system_logged("$init stop >/dev/null 2>&1");
70 &system_logged("killall ypbind >/dev/null 2>&1");
71 &system_logged("$init start >/dev/null 2>&1");
72 if ($_[0]->{'domain'}) {
73         $out = `ypwhich 2>&1`;
74         if ($?) {
75                 system("killall ypbind >/dev/null 2>&1");
76                 return $text{'client_eypwhich'};
77                 }
78         }
79 return undef;
80 }
81
82 @nis_files = ( "passwd", "shadow", "group", "gshadow", "adjunct",
83                "aliases", "ethers", "bootparams", "hosts", "networks",
84                "printcap", "protocols", "publickeys", "rpc", "services",
85                "netgroup", "netid", "auto_master", "auto_home",
86                "auto_local" );
87
88 @nis_tables = ( "passwd", "group", "hosts", "rpc", "services", "netid",
89                 "protocols", "netgrp", "mail", "shadow", "publickey", "networks",
90                 "ethers", "bootparams", "printcap", "amd.home", "auto.master",
91                 "auto.home", "auto.local", "passwd.adjunct" );
92
93 # show_server_config()
94 # Display a form for editing NIS server options
95 sub show_server_config
96 {
97 local ($var, $rule) = &parse_yp_makefile();
98 local $init = &init_script("nis");
99 open(INIT, $init);
100 while(<INIT>) {
101         $mode = $1 if (/^\s*NISSERVER\s*=["\s]*([^"\s]+)/);
102         }
103 close(INIT);
104
105 print "<tr> <td><b>$text{'server_boot'}</b></td>\n";
106 printf "<td><input type=radio name=boot value=1 %s> %s\n",
107         $mode eq 'false' ? '' : 'checked', $text{'yes'};
108 printf "<input type=radio name=boot value=0 %s> %s</td>\n",
109         $mode eq 'false' ? 'checked' : '', $text{'no'};
110
111 local $dom = $var->{'LOCALDOMAIN'}->{'value'};
112 print "<td><b>$text{'server_domain'}</b></td>\n";
113 printf "<td><input type=radio name=domain_auto value=1 %s> %s\n",
114         $dom =~ /`.*domainname`/ ? 'checked' : '', $text{'server_domain_auto'};
115 printf "<input type=radio name=domain_auto value=0 %s>\n",
116         $dom =~ /`.*domainname`/ ? '' : 'checked';
117 printf "<input name=domain size=20 value='%s'></td> </tr>\n",
118         $dom =~ /`.*domainname`/ ? '' : $dom;
119
120 print "<tr> <td><b>$text{'server_type'}</b></td>\n";
121 printf "<td colspan=3><input type=radio name=type value=1 %s> %s\n",
122         $mode eq 'slave' ? '' : 'checked', $text{'server_master'};
123 printf "<input type=radio name=type value=0 %s> %s\n",
124         $mode eq 'slave' ? 'checked' : '', $text{'server_slave'};
125 printf "<input name=slave size=30 value='%s'></td> </tr>\n",
126         $mode eq 'slave' ? $config{'slave'} : '';
127
128 print "</table></td></tr></table><p>\n";
129 print "<table border width=100%>\n";
130 print "<tr $tb> <td><b>$text{'server_mheader'}</b></td> </tr>\n";
131 print "<tr $cb> <td><table width=100%>\n";
132
133 print "<tr> <td><b>$text{'server_dns'}</b></td>\n";
134 printf "<td><input type=radio name=b value='-b' %s> %s\n",
135         $var->{'B'}->{'value'} eq '-b' ? 'checked' : '', $text{'yes'};
136 printf "<input type=radio name=b value='' %s> %s</td>\n",
137         $var->{'B'}->{'value'} eq '-b' ? '' : 'checked', $text{'no'};
138
139 print "<td><b>$text{'server_push'}</b></td>\n";
140 printf "<td><input type=radio name=nopush value=false %s> %s\n",
141         $var->{'NOPUSH'}->{'value'} eq 'true' ? '' : 'checked', $text{'yes'};
142 printf "<input type=radio name=nopush value=true %s> %s</td> </tr>\n",
143         $var->{'NOPUSH'}->{'value'} eq 'true' ? 'checked' : '', $text{'no'};
144
145 local %inall;
146 map { $inall{$_}++ } split(/\s+/,&expand_vars($rule->{'all'}->{'value'}, $var));
147 print "<tr> <td rowspan=2 valign=top><b>$text{'server_tables'}</b></td>\n";
148 print "<td rowspan=2><select multiple size=5 name=tables>\n";
149 foreach $t (grep { $rule->{$_} } @nis_tables) {
150         printf "<option value=%s %s>%s\n",
151                 $t, $inall{$t} ? 'selected' : '', $t;
152         }
153 print "</select></td>\n";
154
155 print "<td><b>$text{'server_minuid'}</b></td>\n";
156 printf "<td><input name=minuid size=10 value='%s'></td> </tr>\n",
157         $var->{'MINUID'}->{'value'};
158
159 print "<td><b>$text{'server_mingid'}</b></td>\n";
160 printf "<td><input name=mingid size=10 value='%s'></td> </tr>\n",
161         $var->{'MINGID'}->{'value'};
162
163 print "<tr> <td><b>$text{'server_slaves'}</b></td>\n";
164 open(SLAVES, "/var/yp/ypservers");
165 while(<SLAVES>) {
166         s/\s//g;
167         push(@slaves, $_) if ($_);
168         }
169 close(SLAVES);
170 printf "<td colspan=3><input name=slaves size=60 value='%s'></td> </tr>\n",
171         join(" ", @slaves);
172
173 print "</table></td></tr></table><p>\n";
174 print "<table border width=100%>\n";
175 print "<tr $tb> <td><b>$text{'server_fheader'}</b></td> </tr>\n";
176 print "<tr $cb> <td><table width=100%>\n";
177
178 local $i = 0;
179 foreach $t (@nis_files) {
180         local $f = &expand_vars($var->{uc($t)}->{'value'}, $var);
181         next if (!$f);
182         print "<tr>\n" if ($i%2 == 0);
183         print "<td><b>",&text('server_file', $text{"desc_$t"} ? $text{"desc_$t"}
184                                                               : $t),"</b></td>\n";
185         print "<td><input name=$t size=30 value='$f'></td>\n";
186         print "</tr>\n" if ($i++%2 == 1);
187         }
188 }
189
190 # parse_server_config()
191 # Parse and save the NIS server options
192 sub parse_server_config
193 {
194 local ($var, $rule) = &parse_yp_makefile();
195 $in{'minuid'} =~ /^\d+$/ || &error($text{'server_eminuid'});
196 $in{'mingid'} =~ /^\d+$/ || &error($text{'server_emingid'});
197 $in{'domain_auto'} || $in{'domain'} =~ /^[A-Za-z0-9\.\-]+$/ ||
198         &error($text{'server_edomain'});
199 $in{'type'} || &to_ipaddress($in{'slave'}) ||
200         &to_ip6address($in{'slave'}) || &error($text{'server_eslave'});
201 &update_makefile($var->{'MINUID'}, $in{'minuid'});
202 &update_makefile($var->{'MINGID'}, $in{'mingid'});
203 &update_makefile($var->{'NOPUSH'}, $in{'nopush'});
204 &update_makefile($var->{'B'}, $in{'b'});
205 &update_makefile($var->{'LOCALDOMAIN'}, $in{'domain_auto'} ? "`domainname`"
206                                                            : $in{'domain'});
207 &update_makefile($rule->{'all'}, join(" ", split(/\0/, $in{'tables'})), "");
208
209 foreach $t (@nis_files) {
210         local $old = &expand_vars($var->{uc($t)}->{'value'}, $var);
211         next if (!$old);
212         if ($old ne $in{$t}) {
213                 $in{$t} =~ /\S/ || &error(&text('server_efile', $text{"desc_$t"}));
214                 &update_makefile($var->{uc($t)}, $in{$t});
215                 }
216         }
217
218 &open_tempfile(SLAVES, ">/var/yp/ypservers");
219 foreach $s (split(/\s+/, $in{'slaves'})) {
220         &print_tempfile(SLAVES, "$s\n");
221         }
222 &close_tempfile(SLAVES);
223
224 if ($in{'boot'}) {
225         &init::enable_at_boot("nis");
226         }
227 local $init = &init_script("nis");
228 local $lref = &read_file_lines($init);
229 foreach $l (@$lref) {
230         if ($l =~ /^\s*NISSERVER=/) {
231                 $l = "NISSERVER=".(!$in{'boot'} ? 'false' :
232                                    $in{'type'} ? 'master' : 'slave');
233                 }
234         }
235 &flush_file_lines();
236 &system_logged("$init stop >/dev/null 2>&1");
237 &system_logged("$init start >/dev/null 2>&1");
238 if ($in{'type'}) {
239         # Master server
240         delete($config{'slave'});
241         &apply_table_changes() if ($in{'boot'});
242         }
243 else {
244         $out = &backquote_logged("/usr/lib/yp/ypinit -s $in{'slave'} 2>&1");
245         if ($?) { &error("<tt>$out</tt>"); }
246         $config{'slave'} = $in{'slave'};
247         }
248 &write_file("$module_config_directory/config", \%config);
249 }
250
251 # get_server_mode()
252 # Returns 0 if the NIS server is inactive, 1 if active as a master, or 2 if
253 # active as a slave.
254 sub get_server_mode
255 {
256 if (&init::action_status("nis") != 2) {
257         return 0;
258         }
259 elsif ($config{'slave'}) {
260         return 2;
261         }
262 else {
263         return 1;
264         }
265 }
266
267 # list_nis_tables()
268 # Returns a list of structures of all NIS tables
269 sub list_nis_tables
270 {
271 local ($var, $rule) = &parse_yp_makefile();
272 local @rv;
273 local $dom = $var->{'LOCALDOMAIN'}->{'value'};
274 chop($dom = `domainname`) if ($dom =~ /`.*domainname`/);
275 local %file;
276 map { $file{uc($_)} = &expand_vars($var->{uc($_)}->{'value'},$var) } @nis_files;
277 local @all = split(/\s+/,  &expand_vars($rule->{'all'}->{'value'}, $var));
278 foreach $t (@all) {
279         local $table = { 'table' => $t,
280                          'index' => scalar(@rv),
281                          'domain' => $dom };
282         if ($t eq "passwd") {
283                 if ($var->{'MERGE_PASSWD'}->{'value'} eq 'true') {
284                         $table->{'type'} = 'passwd_shadow';
285                         $table->{'files'} = [ $file{'PASSWD'}, $file{'SHADOW'} ];
286                         }
287                 elsif (&indexof('shadow', @all) >= 0) {
288                         # Show separate shadow and passwd tables as one table
289                         $table->{'type'} = 'passwd_shadow_full';
290                         $table->{'files'} = [ $file{'PASSWD'}, $file{'SHADOW'} ];
291                         @all = grep { $_ ne 'shadow' } @all;
292                         }
293                 else {
294                         $table->{'type'} = 'passwd';
295                         $table->{'files'} = [ $file{'PASSWD'} ];
296                         }
297                 }
298         elsif ($t eq "group") {
299                 if ($var->{'MERGE_GROUP'}->{'value'} eq 'true') {
300                         $table->{'type'} = 'group_shadow';
301                         $table->{'files'} = [ $file{'GROUP'}, $file{'GSHADOW'} ];
302                         }
303                 else {
304                         $table->{'type'} = 'group';
305                         $table->{'files'} = [ $file{'GROUP'} ];
306                         }
307                 }
308         elsif ($t eq "netgrp") {
309                 $table->{'type'} = "netgroup";
310                 $table->{'files'} = [ $file{'NETGROUP'} ];
311                 }
312         elsif ($t eq "mail") {
313                 $table->{'type'} = "aliases";
314                 $table->{'files'} = [ $file{'ALIASES'} ];
315                 }
316         else {
317                 $table->{'type'} = $t;
318                 $table->{'files'} = [ $file{uc($t)} ];
319                 }
320         push(@rv, $table);
321         }
322 return @rv;
323 }
324
325 # apply_table_changes()
326 # Do whatever is necessary for the table text files to be loaded into
327 # the NIS server
328 sub apply_table_changes
329 {
330 &system_logged("(cd /var/yp ; make) >/dev/null 2>&1 </dev/null");
331 }
332
333 sub extra_config_files
334 {
335 return ( "/etc/defaultdomain", "/var/yp/ypservers" );
336 }
337
338 1;
339