Handle hostnames with upper-case letters
[webmin.git] / cluster-webmin / create_user.cgi
1 #!/usr/local/bin/perl
2 # create_user.cgi
3 # Create a new Webmin user across multiple servers
4
5 require './cluster-webmin-lib.pl';
6 &ReadParse();
7 &error_setup($text{'user_err1'});
8 @hosts = &list_webmin_hosts();
9
10 # Validate inputs
11 $in{'name'} =~ /^[A-z0-9\-\_\.]+$/ ||
12         &error(&text('user_ename', $in{'name'}));
13 $in{'pass_def'} == 0 && $in{'pass'} =~ /:/ && &error($text{'user_ecolon'});
14 if ($in{'ipmode'} > 0) {
15         @ips = split(/\s+/, $in{'ips'});
16         }
17
18 # Setup error handler for down hosts
19 sub user_error
20 {
21 $user_error_msg = join("", @_);
22 }
23 &remote_error_setup(\&user_error);
24
25 # Work out which hosts to create on
26 &ui_print_header(undef, $text{'user_title1'}, "");
27 foreach $h (@hosts) {
28         local ($alr) = grep { $_->{'name'} eq $in{'name'} } @{$h->{'users'}};
29         push(@already, $h) if ($alr);
30         }
31 @hosts = &create_on_parse('user_doing', \@already, $in{'name'});
32 foreach $h (@hosts) {
33         foreach $ug (@{$h->{'users'}}, @{$h->{'groups'}}) {
34                 $taken{$ug->{'name'}}++;
35                 }
36         }
37 $taken{$in{'name'}} && &error(&text('user_etaken', $in{'name'}));
38
39 # Create the user on all servers
40 #print "<b>",&text('user_doing', $in{'name'}),"</b><p>\n";
41 @servers = &list_servers();
42 $p = 0;
43 foreach $h (@hosts) {
44         local ($s) = grep { $_->{'id'} == $h->{'id'} } @servers;
45         local ($rh = "READ$p", $wh = "WRITE$p");
46         pipe($rh, $wh);
47         if (!fork()) {
48                 close($rh);
49                 &remote_foreign_require($s->{'host'}, "acl", "acl-lib.pl");
50                 if ($user_error_msg) {
51                         # Host is down
52                         print $wh &serialise_variable([ 0, $user_error_msg ]);
53                         exit;
54                         }
55
56                 # Create the user
57                 local %user = ( 'name', $in{'name'} );
58                 if ($in{'lang'}) {
59                         $user{'lang'} = $in{'lang'};
60                         }
61                 if ($in{'theme'}) {
62                         $user{'theme'} = $in{'theme'} eq 'webmin' ? undef :
63                                                                  $in{'theme'};
64                         }
65                 if ($in{'ipmode'} == 1) {
66                         $user{'allow'} = join(" ", @ips);
67                         }
68                 elsif ($in{'ipmode'} == 2) {
69                         $user{'deny'} = join(" ", @ips);
70                         }
71                 if ($in{'pass_def'} == 0) {
72                         $salt = chr(int(rand(26))+65).chr(int(rand(26))+65);
73                         $user{'pass'} = &unix_crypt($in{'pass'}, $salt);
74                         }
75                 elsif ($in{'pass_def'} == 3) {
76                         $user{'pass'} = 'x';
77                         }
78                 elsif ($in{'pass_def'} == 4) {
79                         $user{'pass'} = '*LK*';
80                         }
81                 elsif ($in{'pass_def'} == 5) {
82                         $user{'pass'} = 'e';
83                         }
84                 $user{'sync'} = 0;
85
86                 local @mods = ( split(/\0/, $in{'mods1'}),
87                                 split(/\0/, $in{'mods2'}),
88                                 split(/\0/, $in{'mods3'}) );
89
90                 if ($in{'group'}) {
91                         # Add user to the chosen group
92                         ($group) = grep { $_->{'name'} eq $in{'group'} }
93                                         @{$h->{'groups'}};
94                         if (!$group) {
95                                 # Doesn't exist on this server
96                                 print $wh &serialise_variable(
97                                         [ 0, $text{'user_egroup'} ]);
98                                 exit;
99                                 }
100                         push(@{$group->{'members'}}, $user{'name'});
101                         &remote_foreign_call($s->{'host'}, "acl", "modify_group",
102                                              $group->{'name'}, $group);
103
104                         # Add modules from group
105                         local @ownmods;
106                         foreach $m (@mods) {
107                                 push(@ownmods, $m)
108                                     if (&indexof($m, @{$group->{'modules'}}) < 0);
109                                 }
110                         @mods = &unique(@mods, @{$group->{'modules'}});
111                         $user{'ownmods'} = \@ownmods;
112
113                         # Copy ACL files for group
114                         &remote_foreign_call($s->{'host'}, "acl", "copy_acl_files",
115                                              $group->{'name'}, $user{'name'},
116                                              [ @{$group->{'modules'}}, "" ]);
117                         }
118
119                 $user{'modules'} = \@mods;
120                 &remote_foreign_call($s->{'host'}, "acl", "create_user", \%user);
121                 push(@{$h->{'users'}}, \%user);
122                 &save_webmin_host($h);
123
124                 # Restart the remote webmin
125                 print $wh &serialise_variable([ 1 ]);
126                 &remote_foreign_call($s->{'host'}, "acl", "restart_miniserv");
127                 exit;
128                 }
129         close($wh);
130         $p++;
131         }
132
133 # Read back the results
134 $p = 0;
135 foreach $h (@hosts) {
136         local ($s) = grep { $_->{'id'} == $h->{'id'} } @servers;
137         local $d = &server_name($s);
138         local $rh = "READ$p";
139         local $line = <$rh>;
140         local $rv = &unserialise_variable($line);
141         close($rh);
142
143         if ($rv && $rv->[0] == 1) {
144                 # It worked
145                 print &text('user_success', $d),"<br>\n";
146                 }
147         else {
148                 # Something went wrong
149                 print &text('user_failed', $d, $rv->[1]),"<br>\n";
150                 }
151         $p++;
152         }
153
154 print "<p><b>$text{'user_done'}</b><p>\n";
155
156 &remote_finished();
157 &ui_print_footer("", $text{'index_return'});
158