mkacct 9.36 KB
Newer Older
1
#!/usr/local/bin/perl -wT
Kristin Wright's avatar
Kristin Wright committed
2

3
### 
Kristin Wright's avatar
Kristin Wright committed
4
### $Id: mkacct,v 1.23 2000-11-27 22:34:23 kwright Exp $
5
###
Kristin Wright's avatar
Kristin Wright committed
6
7
8
### Address 'lkw' comments:
### Break up into subroutines, possibly libraries. We'll
### need some of the same things for the removal script.
9
10
11
12
13
14
15
###
### mkacct - Makes accounts for all users in this experiment's project.
### Adds accounts to currently booted OS only.
###

use Mysql;

16
17
18
19
## un-taint path
$ENV{'PATH'} = '/bin:/usr/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

20
## check usage
Kristin Wright's avatar
Kristin Wright committed
21
if ($#ARGV < 0) { 
22
    die("Usage: mkacct <eid>\n".
Kristin Wright's avatar
Kristin Wright committed
23
	"\tCreates user accounts by experiment.\n");
Kristin Wright's avatar
Kristin Wright committed
24
}
25
26

## sanitize EID arg
Kristin Wright's avatar
Kristin Wright committed
27
28
my $eid = $ARGV[0];
if ( !($eid =~ /^[A-Za-z0-9\.\-\_ ]+$/) ) { 
29
    die("Invalid eid '$eid' contains illegal characters.\n"); 
Kristin Wright's avatar
Kristin Wright committed
30
31
}

32
33
34
##
## Check for valid user
##
Kristin Wright's avatar
Kristin Wright committed
35
open(WHO,"/usr/bin/whoami 2>&1 |");
36
chop($_ = <WHO>);
Kristin Wright's avatar
Kristin Wright committed
37
close(WHO);
38
if ($_ ne "root") { die("Must be root.\n"); }
Kristin Wright's avatar
Kristin Wright committed
39

40
41
42
##
## Open database
##
Kristin Wright's avatar
Kristin Wright committed
43
44
my $dbh = Mysql->connect("localhost","tbdb","script","none");

45
##
46
## If the EID doesn't exist, it's invalid.
47
##
48
print "Checking that $eid is a valid EID...";
Kristin Wright's avatar
Kristin Wright committed
49
my $cmd = "select eid from experiments where eid='$eid'";
50
my $sth = $dbh->query($cmd);
Kristin Wright's avatar
Kristin Wright committed
51
my $rows =0;
52

53
## Must put in check that $sth defined. May be undefined if
54
55
## query command above is syntactically incorrect which could
## conceivably be caused by a weird eid argument. -kw
Kristin Wright's avatar
Kristin Wright committed
56
while ($sth->fetchrow_array) {
57
    $rows += 1;
Kristin Wright's avatar
Kristin Wright committed
58
}
59
60
61
62
63
if ( $rows != 1 ) { 
    die("Invalid eid '$eid' (not in database).\n"); 
} else {
    print "ok.\n";
}
64
65
66
67

##
## Select user parameters for users in given experiment.
##
68
print "Selecting users...\n";
Kristin Wright's avatar
Kristin Wright committed
69
$cmd = 
70
  "select u.uid,u.usr_pswd,u.unix_uid,u.usr_name, p.control_node, p.pid ".
Kristin Wright's avatar
Kristin Wright committed
71
72
73
74
75
76
77
78
  "from experiments as e ".
  "left join projects as p on e.pid = p.pid ".
  "left join proj_memb as pm on p.pid = pm.pid ".
  "left join users as u on u.uid = pm.uid ".
  "where e.eid = '$eid'";
$sth = $dbh->query($cmd);
my %passwd = ();
my %unix_uid = ();
79
my %fullname = ();
Kristin Wright's avatar
Kristin Wright committed
80
while (@row = $sth->fetchrow_array) {
81
    if ( @row == 6 ) {
82
83
84
	if ( $row[0] =~ /^([a-z0-9]+)$/ ) {
	    $user = $1;
	} else {
85
	    die "Username from database invalid\n";
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
	}

	if ( $row[1] =~ /^(\w+)$/ ) {               # encrypted passwd
	    $passwd{$user} = $1;
	} else {
	    die "encrypted passwd from database not valid.\n";
	}

	if ( $row[2] =~ /^(\d+)$/ &&                # unix UID
	     $row[2] < 32000 ) {                    # unix UID must be < 32000 
	    $unix_uid{$user} = $1;
	} else {
	    die "unix UID from passwd not valid.\n";
	}

	if ( $row[3] =~ /^(([^:]+$|^))$/ ) {          # comment (fullname)
	    $fullname{$user} = $1;
	} else {
	    die "Fullname from database not valid.\n";
	} 

Kristin Wright's avatar
Kristin Wright committed
107
	if ( $row[4] =~ /^(([^:]+$|^))$/ ) {          # control node 
108
109
110
111
	    $control_node = $1;
	} else {
	    die "Control node from database not valid.\n";
	} 
112
113
114
115
116
117
118

	if ( $row[5] =~ /^([a-z0-9]+)$/ ) {          # project/group name
	    $group = $1;
	} else {
	    die "Group name from database not valid.\n";
	} 

119
	
120
    } else {
121
	die "User data query did not return correct number of elements.\n";
122
    }
123

124
    print "\t$user\n";    
Kristin Wright's avatar
Kristin Wright committed
125
126
}

127
128
print "Control node: $control_node\n";

129
130
131
##
## Select group ID for experiment.
##
132
print "Selecting group ID for experiment...";
Kristin Wright's avatar
Kristin Wright committed
133
$cmd = 
134
  "select unix_gid from projects as p ".
Kristin Wright's avatar
Kristin Wright committed
135
136
137
138
  "left join experiments as e on e.pid = p.pid ".
  "where e.eid = '$eid'";
$sth = $dbh->query($cmd);
if (@row = $sth->fetchrow_array) {
139
140
141
    if ( $row[0] =~ /^(\d+)$/ &&             # unix GID
	 $row[0] < 65536 ) {                 # unix GID must be < 65535 
	$unix_gid = $1;
142
	print "$group ($unix_gid)\n";
143
144
145
    } else {
	die("Invalid group ID.\n"); 
    }
Kristin Wright's avatar
Kristin Wright committed
146
}
147
 
148
149
150
##
## Select machines.
##
Kristin Wright's avatar
Kristin Wright committed
151
print "Selecting machines...";
Kristin Wright's avatar
Kristin Wright committed
152
$cmd = 
153
  "select IP from interfaces as ip ".
Kristin Wright's avatar
Kristin Wright committed
154
155
  "left join reserved as r on r.node_id=ip.node_id ".
  "left join experiments as e on r.eid = e.eid ".
Mac Newbold's avatar
Mac Newbold committed
156
  "where e.eid = '$eid' and card=4";
Kristin Wright's avatar
Kristin Wright committed
157
158
159
$sth = $dbh->query($cmd);
my @nodes = ();
while (@row = $sth->fetchrow_array) {
160
    push(@nodes,$row[0]);
Kristin Wright's avatar
Kristin Wright committed
161
    print " $row[0] ";
Kristin Wright's avatar
Kristin Wright committed
162
}
163
164
165
166
167
168
169
##
## XXX control nodes not currently set correctly by
## web interface (not yet implemented); all projects
## use plastic as their control node. Even if it did,
## it looks as if the database type is a string not an
## IP address.  
##
Kristin Wright's avatar
Kristin Wright committed
170
171
172
173
174
##push(@nodes, $control_node);
push(@nodes, "155.99.212.74"); 
print " 155.99.212.74";
print "\n";

175

176
177
178
179
180
##
## For each machine, ping to see if its alive.
## If alive, determine if its FreeBSD or Linux and
## create the user accounts. 
##
Kristin Wright's avatar
Kristin Wright committed
181
182
183
184
my $last = "";
my $OS = "";
my $IP = "";
foreach $IP (@nodes) {
185
    ## If this machine is not the same as the last one, get the OS
186
    ## Check also that the IP address is valid (some interfaces might
187
    ## not have an IP address). 
188
189
190

    if ( $IP ne $last && $IP =~ /([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/) {
	$IP = $1;
Kristin Wright's avatar
Kristin Wright committed
191
        $last = $IP;
192
	
193
         if (-e "/bin/ping") {
Kristin Wright's avatar
Kristin Wright committed
194
195
196
197
198
            open(PING,"/bin/ping -c 1 $IP 2>&1 |");
        } else {
            open(PING,"/sbin/ping -c 1 $IP 2>&1 |");
        }
        do { } until ( <PING> =~ /transmitted, (\d+) packets received/ );
199
	close(PING); 
200

201
202
203
204
205
        if ( $1 <= 0 ) {

	    die "Couldn't ping machine $IP\n";

	} else {  
206

207
	    print "Checking OS on $IP...";
Mac Newbold's avatar
Mac Newbold committed
208
            open(UNAME,"/usr/local/bin/sshtb $IP uname 2>&1 |");
Kristin Wright's avatar
Kristin Wright committed
209
            $_ = <UNAME>;
210
	    print $_;
211

212
213
	    ## FreeBSD says "155.99.214.129: Connection refused"
	    ##    and can also say "Host key doesn't match..."  
214
215
216
	    ##    and can also say "@@@@@@... WARNING HOST ID CHANGED..."
            if ( ($_=~/^Sorry/) || ($_=~/^$IP/) || ($_=~/^Host key/) 
		 || ($_ =~/^@+/) ) { 
Mac Newbold's avatar
Mac Newbold committed
217
218
219
220
221
222
223
	      
		print "Uname failed on $IP:$_";
		while (<UNAME>) {
		  print;
		}
		close(UNAME);
		die("\n"); 
224
	    } else { 
225
		$OS = $_;
226
	    }
Mac Newbold's avatar
Mac Newbold committed
227
	    close(UNAME);
228

229
        } 
230

231
        if ( $OS =~ /Linux/ ) {  
232
233
234
235
	    
	    ## 1) Use groupadd to add group
	    ## 2) Use useradd to add users
	    ##
236
237
	    ## Rather than use useradd's defaults (which are normally
	    ## fine), we're explicit.
238
239
240
	    ##  
	    ## If either the group or the user exists, groupadd and useradd
            ## will report it and move on.
241
242

	    print "Creating group $unix_gid on $IP.\n";
243
	    open(GROUPADD, "/usr/local/bin/sshtb $IP /usr/sbin/groupadd -g $unix_gid $group 2>&1 |");
244
	    while (<GROUPADD>) { print "$_"; }
245
246
247
	    close(GROUPADD); 
	    my $i = 1;
	    foreach my $user (keys %passwd) {
248

249
		print "Creating user $user on $IP.\n";
Mac Newbold's avatar
Mac Newbold committed
250
		open(USERADD, "/usr/local/bin/sshtb $IP /usr/sbin/useradd -c \"$fullname{$user}\" -d /users/$user -g $unix_gid -m -p $passwd{$user} -s /bin/tcsh -u $unix_uid{$user}  $user 2>&1 |");
251
		while (<USERADD>) { print "$_"; }
252
		close(USERADD);
253
	    }
254

255
	} elsif ($OS =~ /FreeBSD/) { 
256

257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
	    ## 1) Create groups
	    ## 2) Create user accts 
	    ## 3) Create home directories

	    ## Fetch remote group information
	    open(SCP, "/usr/local/bin/scp -pq $IP:/etc/group /tmp/group.$IP |");
	    while ( <SCP> ) { print $_; }
	    close SCP;

	    ## Does the group already exist?
	    open(GROUP, "+</tmp/group.$IP") or die "Couldn't open /tmp/group.$IP\n";
	    my $prev = 0;
	    while ( <GROUP> ) {
		if ( $_ =~ /^$group:/ ) { 
		    $prev = 1;
		}
	    }

	    if ( !$prev ) {
		print "Adding group $group to $IP\n"; 
		print GROUP "$group:*:$unix_gid:\n";
		close GROUP;
		open(SCP, "/usr/local/bin/scp -pq /tmp/group.$IP $IP:/etc/group |");
		while ( <SCP> ) { print $_; }
		close SCP;
	    } else {
		print "Group $group already exists on $IP\n";
		close GROUP;
	    }
286

287
 	    ## Fetch remote login information
288
	    open(SCP, "/usr/local/bin/scp -pq $IP:/etc/master.passwd /tmp/master.passwd.$IP |");
289
290
291
	    while ( <SCP> ) { print $_; }
	    close SCP;

292
293
294
295
296
	    my $addon   = "";
	    $chpassf = "/tmp/chpasstmp";
	    open (TMPCHPASS, ">$chpassf") or die "Couldn't open $chpassf for writing.\n";
	    print TMPCHPASS "#!/bin/sh\n";

297
	    foreach my $user (keys %passwd) {
298
299
300
301
302
303
304
305
306
307
308
309

		## Check if the user account already exists.
		my $prev = 0;
		open(MPWD, "/tmp/master.passwd.$IP");
		while ( <MPWD> ) {
		    if ( $_ =~ /^$user:/ ) { 
			$prev = 1;
			print "Account $user exists on $IP\n";
		    }
		}
		close MPWD;

310
311
312
313
314
		### LKW: I initially created the account by using 'ssh chpass',
		### but that stopped working for some reason unknown to me.
		### I replaced it with the script-creation, scp it, source it 
		### seen below. 

315
		if ( $prev == 0 ) {
316
317
		    print "Adding $user to $IP\n";
		    $addon = "$user:$passwd{$user}:$unix_uid{$user}:" .
318
			     "$unix_gid:\:0:0:$fullname{$user}:/users/$user:" .
319
			     "/bin/tcsh";
320

321
		    print TMPCHPASS "/usr/bin/chpass -a '$addon'\n";
322
		}		
323
324

		## Create home directory
325
326
327
328
		if ( -e "/users/$user" ) {
		    print "/users/$user already exists.\n";
		} else  { 
		    print "Creating /users/$user.\n";
329
330
331
332
333
		    open(MKDIR, "/bin/mkdir /users/$user 2>&1 |");
		    while ( <MKDIR> ) { print "$_"; }
		    close(MKDIR); 
		    
		    ## If created, chown and chgrp
Kristin Wright's avatar
Kristin Wright committed
334
335
		    if (-e "/users/$user") {
			open(CHOWN, "/usr/sbin/chown $unix_uid{$user} /users/$user 2>&1 |" );
336
337
338
			while ( <CHOWN> ) {print "$_"; }
			close(CHOWN); 

Kristin Wright's avatar
Kristin Wright committed
339
			open(CHGRP, "/usr/bin/chgrp $unix_gid /users/$user 2>&1 |" );
340
341
342
343
			while ( <CHGRP> ) {print "$_"; }
			close(CHGRP); 
		    }
		}
344
	    }
345
	    close TMPCHPASS;
346
347
348
	    open(SCP2, "/usr/local/bin/scp -pq $chpassf $IP:$chpassf 2>&1 |");
	    while ( <SCP2> ) { print $_; }
	    close SCP2;
349

350
	    print "Commiting password changes to $IP.\n";
351
	    open (CHPASS, "/usr/local/bin/sshtb $IP source $chpassf 2>&1 |");
352
	    while ( <CHPASS> ) {print "\t$_"; }
353
354
	    close(CHPASS);

355
	} else {
356
	    print "$IP is unreachable or has an unknown OS ($OS).\n";
357
	}
Kristin Wright's avatar
Kristin Wright committed
358
359
    }
}
360

361