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

3
### 
4
### $Id: mkacct,v 1.19 2000-11-20 19:16:35 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
##
21
## arg: @row = {user, passwd, unix_uid, comment};
22
##
23
sub untaint_user_data {
24
    my @row = @_;
25
26
27
28
29
30
31
32
33
34
35
36
37

    if ( @row < 4 ) {                           # need 4 fields 
	return 0;    
    }

    if ( $row[0] =~ /^(([a-z]|\d)+)$/ ) {       # user
	$row[0] = $1;
    } else { 
	return 0;
    }

    if ( $row[1] =~ /^(\w+)$/ ) {               # encrypted passwd
	$row[1] = $1;
38
39
40
    } else {
	return 0;
    }
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

    if ( $row[2] =~ /^(\d+)$/ &&                # unix UID
	 $row[2] < 32000 ) {                    # unix UID must be < 32000   
	$row[2] = $1;
    } else {
	return 0;
    }
	 
    if ( $row[3] =~ /^(([^:]+$|^))$/ ) {          # comment (fullname)
	$row[3] = $1;
    } else {
	return 0;
    } 
	 
    return 1;
56
57
58
}

my $d = 1;			#debug flag
Kristin Wright's avatar
Kristin Wright committed
59
if ($#ARGV < 0) { 
60
    die("Usage: mkacct <eid>\n".
Kristin Wright's avatar
Kristin Wright committed
61
	"\tCreates user accounts by experiment.\n");
Kristin Wright's avatar
Kristin Wright committed
62
63
64
}
my $eid = $ARGV[0];
if ( !($eid =~ /^[A-Za-z0-9\.\-\_ ]+$/) ) { 
65
    die("Invalid eid '$eid' contains illegal characters.\n"); 
Kristin Wright's avatar
Kristin Wright committed
66
67
}

68
69
70
##
## Check for valid user
##
Kristin Wright's avatar
Kristin Wright committed
71
open(WHO,"/usr/bin/whoami 2>&1 |");
72
chop($_ = <WHO>);
Kristin Wright's avatar
Kristin Wright committed
73
close(WHO);
74
if ($_ ne "root") { die("Must be root.\n"); }
Kristin Wright's avatar
Kristin Wright committed
75

76
77
78
##
## Open database
##
Kristin Wright's avatar
Kristin Wright committed
79
80
my $dbh = Mysql->connect("localhost","tbdb","script","none");

81
##
82
## If the EID doesn't exist, it's invalid.
83
##
84
print "Checking that $eid is a valid EID...";
Kristin Wright's avatar
Kristin Wright committed
85
my $cmd = "select eid from experiments where eid='$eid'";
86
my $sth = $dbh->query($cmd);
Kristin Wright's avatar
Kristin Wright committed
87
my $rows =0;
88
## Must put in check that $sth defined. May be undefined if
89
## query command above is syntactically incorrect. -kw
Kristin Wright's avatar
Kristin Wright committed
90
while ($sth->fetchrow_array) {
91
    $rows += 1;
Kristin Wright's avatar
Kristin Wright committed
92
}
93
94
95
96
97
if ( $rows != 1 ) { 
    die("Invalid eid '$eid' (not in database).\n"); 
} else {
    print "ok.\n";
}
98
99
100
101
102

##
## Select user parameters for users in given experiment.
## Join: exp.pid -> p.pid
##
103
print "Selecting users...\n";
Kristin Wright's avatar
Kristin Wright committed
104
105
106
107
108
109
110
111
112
113
$cmd = 
  "select u.uid,u.usr_pswd,u.unix_uid,u.usr_name ".
  "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 = ();
114
my %fullname = ();
Kristin Wright's avatar
Kristin Wright committed
115
while (@row = $sth->fetchrow_array) {
116
    if ( untaint_user_data(@row) == 1 ) {
117
118
119
120
121
122
123
	$passwd{$row[0]}   = $row[1];
	$unix_uid{$row[0]} = $row[2];
	$fullname{$row[0]} = $row[3];
	print "\t$row[0]\n";
    } else {
	print "Invalid user data. Row skipped.\n";
    }
Kristin Wright's avatar
Kristin Wright committed
124
125
}

126
127
128
##
## Select group ID for experiment.
##
129
print "Selecting group ID for experiment...";
Kristin Wright's avatar
Kristin Wright committed
130
$cmd = 
131
  "select unix_gid from projects as p ".
Kristin Wright's avatar
Kristin Wright committed
132
133
134
135
  "left join experiments as e on e.pid = p.pid ".
  "where e.eid = '$eid'";
$sth = $dbh->query($cmd);
if (@row = $sth->fetchrow_array) {
136
    $unix_gid = $row[0];
137
138
139
    print "$unix_gid\n";
} else {
    die("Invalid group ID.\n"); 
Kristin Wright's avatar
Kristin Wright committed
140
141
}

142
 
143
144
145
##
## Select machines.
##
Kristin Wright's avatar
Kristin Wright committed
146
print "Selecting machines...";
Kristin Wright's avatar
Kristin Wright committed
147
$cmd = 
148
  "select IP from interfaces as ip ".
Kristin Wright's avatar
Kristin Wright committed
149
150
  "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
151
  "where e.eid = '$eid' and card=4";
Kristin Wright's avatar
Kristin Wright committed
152
153
154
$sth = $dbh->query($cmd);
my @nodes = ();
while (@row = $sth->fetchrow_array) {
155
    push(@nodes,$row[0]);
Kristin Wright's avatar
Kristin Wright committed
156
    print " $row[0] ";
Kristin Wright's avatar
Kristin Wright committed
157
}
Kristin Wright's avatar
Kristin Wright committed
158
print "\n";
Kristin Wright's avatar
Kristin Wright committed
159

160
161
162
163
164
##
## 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
165
166
167
168
my $last = "";
my $OS = "";
my $IP = "";
foreach $IP (@nodes) {
169
    ## If this machine is not the same as the last one, get the OS
170
    ## Check also that the IP address is valid (some interfaces might
171
    ## not have an IP address). 
172
173
174

    if ( $IP ne $last && $IP =~ /([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/) {
	$IP = $1;
Kristin Wright's avatar
Kristin Wright committed
175
        $last = $IP;
176
	
177
         if (-e "/bin/ping") {
Kristin Wright's avatar
Kristin Wright committed
178
179
180
181
182
            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/ );
183
	close(PING); 
184

185
186
187
188
189
        if ( $1 <= 0 ) {

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

	} else {  
190

191
	    print "Checking OS on $IP...";
Mac Newbold's avatar
Mac Newbold committed
192
            open(UNAME,"/usr/local/bin/sshtb $IP uname 2>&1 |");
Kristin Wright's avatar
Kristin Wright committed
193
            $_ = <UNAME>;
194
	    print $_;
195

196
197
	    ## FreeBSD says "155.99.214.129: Connection refused"
	    ##    and can also say "Host key doesn't match..."  
198
199
200
	    ##    and can also say "@@@@@@... WARNING HOST ID CHANGED..."
            if ( ($_=~/^Sorry/) || ($_=~/^$IP/) || ($_=~/^Host key/) 
		 || ($_ =~/^@+/) ) { 
Mac Newbold's avatar
Mac Newbold committed
201
202
203
204
205
206
207
	      
		print "Uname failed on $IP:$_";
		while (<UNAME>) {
		  print;
		}
		close(UNAME);
		die("\n"); 
208
	    } else { 
209
		$OS = $_;
210
	    }
Mac Newbold's avatar
Mac Newbold committed
211
	    close(UNAME);
212

213
        } 
214

215
        if ( $OS =~ /Linux/ ) {  
216
217
218
219
	    
	    ## 1) Use groupadd to add group
	    ## 2) Use useradd to add users
	    ##
220
221
	    ## Rather than use useradd's defaults (which are normally
	    ## fine), we're explicit.
222
223
224
	    ##  
	    ## If either the group or the user exists, groupadd and useradd
            ## will report it and move on.
225
226

	    print "Creating group $unix_gid on $IP.\n";
Mac Newbold's avatar
Mac Newbold committed
227
	    open(GROUPADD, "/usr/local/bin/sshtb $IP /usr/sbin/groupadd -g $unix_gid $eid 2>&1 |");
228
	    while (<GROUPADD>) { print "$_"; }
229
230
231
	    close(GROUPADD); 
	    my $i = 1;
	    foreach my $user (keys %passwd) {
232

233
		print "Creating user $user on $IP.\n";
Mac Newbold's avatar
Mac Newbold committed
234
		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 |");
235
		while (<USERADD>) { print "$_"; }
236
		close(USERADD);
237
	    }
238

239
	} elsif ($OS =~ /FreeBSD/) { 
240

241
242
243
	    ## 1) Append new account info to master.passwd
	    ## 2) Create secure (spwd.db) and insecure (pwd.db) password 
	    ##    databases and
244
245
	    ## 4) Create home directories

246
 	    ## Fetch remote login information
247
	    open(SCP, "/usr/local/bin/scp -pq $IP:/etc/master.passwd /tmp/master.passwd.$IP |");
248
249
250
	    while ( <SCP> ) { print $_; }
	    close SCP;

251
252
253
254
255
	    my $addon   = "";
	    $chpassf = "/tmp/chpasstmp";
	    open (TMPCHPASS, ">$chpassf") or die "Couldn't open $chpassf for writing.\n";
	    print TMPCHPASS "#!/bin/sh\n";

256
	    foreach my $user (keys %passwd) {
257
258
259
260
261
262
263
264
265
266
267
268

		## 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;

269
270
271
272
273
		### 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. 

274
		if ( $prev == 0 ) {
275
276
		    print "Adding $user to $IP\n";
		    $addon = "$user:$passwd{$user}:$unix_uid{$user}:" .
277
			     "$unix_gid:\:0:0:$fullname{$user}:/users/$user:" .
278
			     "/bin/tcsh";
279

280
		    print TMPCHPASS "/usr/bin/chpass -a '$addon'\n";
281
		}		
282
283

		## Create home directory
284
285
286
287
		if ( -e "/users/$user" ) {
		    print "/users/$user already exists.\n";
		} else  { 
		    print "Creating /users/$user.\n";
288
289
290
291
292
		    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
293
294
		    if (-e "/users/$user") {
			open(CHOWN, "/usr/sbin/chown $unix_uid{$user} /users/$user 2>&1 |" );
295
296
297
			while ( <CHOWN> ) {print "$_"; }
			close(CHOWN); 

Kristin Wright's avatar
Kristin Wright committed
298
			open(CHGRP, "/usr/bin/chgrp $unix_gid /users/$user 2>&1 |" );
299
300
301
302
			while ( <CHGRP> ) {print "$_"; }
			close(CHGRP); 
		    }
		}
303
	    }
304
305
306
307
308
309
310
311
312
313
314
315
316
317
	    close TMPCHPASS;
	    open(SCP, "/usr/local/bin/scp -pq $chpassf $IP:$chpassf 2>&1 |");
	    while ( <SCP> ) { print $_; }
	    close SCP;

	    print "Before chpass.\n";
	    open (CHPASS, "/usr/local/bin/sshtb $IP source $chpassf 2>&1 |");
	    print "After chpass open.\n";
	    while ( <CHPASS> ) {print "$_"; }
	    print "After print.\n";
	    close(CHPASS);
	    print "After close.\n";
	    sleep 2;

318
	} else {
319
	    print "$IP is unreachable or has an unknown OS ($OS).\n";
320
	}
Kristin Wright's avatar
Kristin Wright committed
321
322
    }
}
323

324