All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 2181fc33 authored by Leigh B. Stoller's avatar Leigh B. Stoller

Next step in the locally unique uid project. This commits add the luid to

most of the rest of the tables in the system (still a few exceptions).
Bound to be some bugs ...
parent d243779f
# #
# EMULAB-COPYRIGHT # EMULAB-COPYRIGHT
# Copyright (c) 2000-2006 University of Utah and the Flux Group. # Copyright (c) 2000-2007 University of Utah and the Flux Group.
# All rights reserved. # All rights reserved.
# #
......
#!/usr/bin/perl -wT #!/usr/bin/perl -wT
# #
# EMULAB-COPYRIGHT # EMULAB-COPYRIGHT
# Copyright (c) 2000-2006 University of Utah and the Flux Group. # Copyright (c) 2000-2007 University of Utah and the Flux Group.
# All rights reserved. # All rights reserved.
# #
use English; use English;
...@@ -48,12 +48,16 @@ my $USERUID; ...@@ -48,12 +48,16 @@ my $USERUID;
# Locals # Locals
my $user; my $user;
my $this_user;
my $target_user;
my $keyfile; my $keyfile;
my $keyline; my $keyline;
my $key; my $key;
my $comment; my $comment;
my $user_name; my $user_name;
my $user_email; my $user_email;
my $user_dbid;
my $user_uid;
# #
# Testbed Support libraries # Testbed Support libraries
...@@ -151,12 +155,22 @@ else { ...@@ -151,12 +155,22 @@ else {
# Untaint the arguments. # Untaint the arguments.
# #
if (defined($user)) { if (defined($user)) {
if ($user =~ /^([-\w_]+)$/i) { if ($user =~ /^([-\w]+)$/i) {
$user = $1; $user = $1;
} }
else { else {
fatal("Tainted username: $user"); fatal("Tainted username: $user");
} }
# Map user to object.
$target_user = User->Lookup($user);
if (! defined($target_user)) {
fatal("$user does not exist!")
}
$user_name = $target_user->name();
$user_email = $target_user->email();
$user_dbid = $target_user->dbid();
$user_uid = $target_user->uid();
} }
# #
...@@ -170,6 +184,13 @@ if (getpwuid($UID) eq "nobody") { ...@@ -170,6 +184,13 @@ if (getpwuid($UID) eq "nobody") {
} }
else { else {
$USERUID = getpwnam($user); $USERUID = getpwnam($user);
# Map invoking user to object.
$this_user = User->LookupByUnixId($UID);
if (! defined($this_user)) {
fatal("You ($UID) do not exist!");
}
} }
# #
...@@ -214,28 +235,19 @@ else { ...@@ -214,28 +235,19 @@ else {
# #
if (!$verify) { if (!$verify) {
# If its the user himself, then we can generate a new authkeys file. # If its the user himself, then we can generate a new authkeys file.
if (!$nobody && getpwuid($UID) ne "$user" && !TBAdmin($UID)) { if (!$nobody && !TBAdmin() && !$target_user->SameUser($this_user)) {
fatal("You are not allowed to set pubkeys for $user.\n"); fatal("You are not allowed to set pubkeys for $target_user\n");
} }
if (-d "$HOMEDIR/$user/.ssh") { if (-d "$HOMEDIR/$user_uid/.ssh") {
$genmode = 1; $genmode = 1;
} }
# #
# This script is audited when not in verify mode. Since all keys are first # This script is audited when not in verify mode. Since all keys are first
# checked with verify mode, this should not cause any extra email from bad # checked with verify mode, this should not cause any extra email from bad
# keys. # keys.
# #
AuditStart(0); AuditStart(0);
if (! UserDBInfo($user, \$user_name, \$user_email)) {
if ($nobody) {
$noemail = 1;
}
else {
fatal("No DB info for $user!");
}
}
} }
# Drop root privs, switching to user. # Drop root privs, switching to user.
...@@ -323,12 +335,13 @@ sub ParseKey($) { ...@@ -323,12 +335,13 @@ sub ParseKey($) {
$key = "$key $comment"; $key = "$key $comment";
DBQueryFatal("replace into user_pubkeys ". DBQueryFatal("replace into user_pubkeys ".
"values ('$user', 0, '$key', now(), '$comment')"); "values ('$user_uid', '$user_dbid', ".
" 0, '$key', now(), '$comment')");
# #
# Mark user record as modified so nodes are updated. # Mark user record as modified so nodes are updated.
# #
TBNodeUpdateAccountsByUID($user); TBNodeUpdateAccountsByUID($user_uid);
my $chunked = ""; my $chunked = "";
...@@ -348,8 +361,8 @@ sub ParseKey($) { ...@@ -348,8 +361,8 @@ sub ParseKey($) {
if (! $noemail) { if (! $noemail) {
SENDMAIL("$user_name <$user_email>", SENDMAIL("$user_name <$user_email>",
"SSH Public Key for '$user' Added", "SSH Public Key for '$user_uid' Added",
"SSH Public Key for '$user' added:\n". "SSH Public Key for '$user_uid' added:\n".
"\n". "\n".
"$chunked\n", "$chunked\n",
"$TBOPS"); "$TBOPS");
...@@ -364,7 +377,7 @@ sub ParseKey($) { ...@@ -364,7 +377,7 @@ sub ParseKey($) {
# #
sub InitUser() sub InitUser()
{ {
my $sshdir = "$HOMEDIR/$user/.ssh"; my $sshdir = "$HOMEDIR/$user_uid/.ssh";
# #
# Set up the ssh key, but only if not done so already. # Set up the ssh key, but only if not done so already.
...@@ -384,7 +397,7 @@ sub InitUser() ...@@ -384,7 +397,7 @@ sub InitUser()
if ($ident =~ /(\d*\s\d*\s[0-9a-zA-Z]*)\s([-\w\@\.]*)/) { if ($ident =~ /(\d*\s\d*\s[0-9a-zA-Z]*)\s([-\w\@\.]*)/) {
DBQueryFatal("delete from user_pubkeys ". DBQueryFatal("delete from user_pubkeys ".
"where uid='$user' and pubkey='$1 $2'"); "where uid_idx='$user_dbid' and pubkey='$1 $2'");
} }
unlink("$sshdir/identity"); unlink("$sshdir/identity");
} }
...@@ -404,7 +417,8 @@ sub InitUser() ...@@ -404,7 +417,8 @@ sub InitUser()
if ($ident =~ /(\d*\s\d*\s[0-9a-zA-Z]*)\s([-\w\@\.]*)/) { if ($ident =~ /(\d*\s\d*\s[0-9a-zA-Z]*)\s([-\w\@\.]*)/) {
DBQueryFatal("replace into user_pubkeys ". DBQueryFatal("replace into user_pubkeys ".
"values ('$user', 0, '$1 $2', now(), '$2')"); "values ('$user_uid', '$user_dbid', ".
" 0, '$1 $2', now(), '$2')");
} }
else { else {
fatal("Bad protocol 1 public key: $ident\n"); fatal("Bad protocol 1 public key: $ident\n");
...@@ -425,7 +439,7 @@ sub InitUser() ...@@ -425,7 +439,7 @@ sub InitUser()
if ($ident =~ if ($ident =~
/^(ssh-rsa [-\w\.\@\+\/\=]*) ([-\w\@\.\ ]*)$/) { /^(ssh-rsa [-\w\.\@\+\/\=]*) ([-\w\@\.\ ]*)$/) {
DBQueryFatal("delete from user_pubkeys ". DBQueryFatal("delete from user_pubkeys ".
"where uid='$user' and pubkey='$1 $2'"); "where uid_idx='$user_dbid' and pubkey='$1 $2'");
} }
unlink("$sshdir/id_rsa"); unlink("$sshdir/id_rsa");
} }
...@@ -446,13 +460,8 @@ sub InitUser() ...@@ -446,13 +460,8 @@ sub InitUser()
if ($ident =~ if ($ident =~
/^(ssh-rsa [-\w\.\@\+\/\=]*) ([-\w\@\.\ ]*)$/) { /^(ssh-rsa [-\w\.\@\+\/\=]*) ([-\w\@\.\ ]*)$/) {
DBQueryFatal("replace into user_pubkeys ". DBQueryFatal("replace into user_pubkeys ".
"values ('$user', 0, '$1 $2', now(), '$2')"); "values ('$user_uid', '$user_dbid', ".
" 0, '$1 $2', now(), '$2')");
#
# Backwards compat. Remove later.
#
DBQueryFatal("update users set emulab_pubkey='$1 $2' ".
"where uid='$user'");
} }
else { else {
fatal("Bad protocol 2 public key: $ident\n"); fatal("Bad protocol 2 public key: $ident\n");
...@@ -468,7 +477,7 @@ sub InitUser() ...@@ -468,7 +477,7 @@ sub InitUser()
sub GenerateKeyFile() sub GenerateKeyFile()
{ {
my @pkeys = (); my @pkeys = ();
my $sshdir = "$HOMEDIR/$user/.ssh"; my $sshdir = "$HOMEDIR/$user_uid/.ssh";
my $keyfile = "$sshdir/authorized_keys"; my $keyfile = "$sshdir/authorized_keys";
if (! -e $sshdir) { if (! -e $sshdir) {
...@@ -478,7 +487,8 @@ sub GenerateKeyFile() ...@@ -478,7 +487,8 @@ sub GenerateKeyFile()
} }
} }
my $query_result = my $query_result =
DBQueryFatal("select pubkey from user_pubkeys where uid='$user'"); DBQueryFatal("select pubkey from user_pubkeys ".
"where uid_idx='$user_dbid'");
while (my ($key) = $query_result->fetchrow_array()) { while (my ($key) = $query_result->fetchrow_array()) {
push(@pkeys, $key); push(@pkeys, $key);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# #
# EMULAB-COPYRIGHT # EMULAB-COPYRIGHT
# Copyright (c) 2000-2004 University of Utah and the Flux Group. # Copyright (c) 2000-2004, 2006 University of Utah and the Flux Group.
# All rights reserved. # All rights reserved.
# #
use English; use English;
...@@ -16,6 +16,7 @@ use lib "@prefix@/lib"; ...@@ -16,6 +16,7 @@ use lib "@prefix@/lib";
use libaudit; use libaudit;
use libdb; use libdb;
use libtestbed; use libtestbed;
use User;
# #
# Create user SSL certificates. # Create user SSL certificates.
...@@ -48,7 +49,6 @@ my $CACONFIG = "$SSLDIR/ca.cnf"; ...@@ -48,7 +49,6 @@ my $CACONFIG = "$SSLDIR/ca.cnf";
my $EMULAB_CERT = "$TB/etc/emulab.pem"; my $EMULAB_CERT = "$TB/etc/emulab.pem";
my $EMULAB_KEY = "$TB/etc/emulab.key"; my $EMULAB_KEY = "$TB/etc/emulab.key";
my $OPENSSL = "/usr/bin/openssl"; my $OPENSSL = "/usr/bin/openssl";
my $lockfile = "/var/tmp/testbed_mkusercert_lockfile";
my $WORKDIR = "$TB/ssl"; my $WORKDIR = "$TB/ssl";
my $SAVEUID = $UID; my $SAVEUID = $UID;
...@@ -137,6 +137,18 @@ else { ...@@ -137,6 +137,18 @@ else {
die("Tainted argument: $user\n"); die("Tainted argument: $user\n");
} }
# Map target user to object.
my $target_user = User->Lookup($user);
if (! defined($target_user)) {
fatal("$user does not exist!");
}
# Map invoking user to object.
my $this_user = User->LookupByUnixId($UID);
if (! defined($this_user)) {
fatal("You ($UID) do not exist!");
}
# #
# This script is always audited. Mail is sent automatically upon exit. # This script is always audited. Mail is sent automatically upon exit.
# #
...@@ -154,103 +166,38 @@ if (AuditStart(0)) { ...@@ -154,103 +166,38 @@ if (AuditStart(0)) {
chdir("$WORKDIR") or chdir("$WORKDIR") or
fatal("Could not chdir to $WORKDIR: $!"); fatal("Could not chdir to $WORKDIR: $!");
open(LOCK, ">>$lockfile") || fatal("Couldn't open $lockfile\n"); TBScriptLock("mkusercert") == 0 or
$count = 0; fatal("Could not get the lock!");
if (flock(LOCK, LOCK_EX|LOCK_NB) == 0) {
#
# If we don't get it the first time, we wait for:
# 1) The lock to become free, in which case we do our thing
# 2) The time on the lock to change, in which case we wait for that process
# to finish
#
my $oldlocktime = (stat(LOCK))[9];
my $gotlock = 0;
while (1) {
print "Another exports update in progress, waiting for it to finish\n";
if (flock(LOCK, LOCK_EX|LOCK_NB) != 0) {
# OK, got the lock, we can do what we're supposed to
$gotlock = 1;
last;
}
$locktime = (stat(LOCK))[9];
if ($locktime != $oldlocktime) {
$oldlocktime = $locktime;
last;
}
if ($count++ > 60) {
fatal("Could not get the lock after a long time!\n");
}
sleep(1);
}
$count = 0;
#
# If we didn't get the lock, wait for the processes that did to finish
#
if (!$gotlock) {
while (1) {
if ((stat(LOCK))[9] != $oldlocktime) {
exit(0);
}
if (flock(LOCK, LOCK_EX|LOCK_NB) != 0) {
close(LOCK);
exit(0);
}
if ($count++ > 20) {
fatal("Process with the lock did not finish after ".
"a long time!\n");
}
sleep(1);
}
}
}
#
# Perl-style touch(1)
#
my $now = time;
utime $now, $now, $lockfile;
# #
# Get the user info (the user being operated on). # Get the user info (the user being operated on).
# #
my $query_result = my $fullname = $target_user->name();
DBQueryFatal("select u.usr_name,u.usr_email,u.admin,u.unix_uid ". my $user_email = $target_user->email();
"from users as u ". my $usr_admin = $target_user->admin();
"where u.uid='$user'"); my $user_number = $target_user->uid_idx();
my $user_uid = $target_user->uid();
if ($query_result->numrows == 0) { my $user_dbid = $target_user->dbid();
fatal("$user is not in the DB. This is bad.\n");
}
my @row = $query_result->fetchrow_array();
my $fullname = $row[0];
my $user_email = $row[1];
my $usr_admin = $row[2];
my $user_number = $row[3];
# #
# Get the users earliest project membership to use as the default group # Get the users earliest project membership to use as the default group
# for the case that the account is being (re)created. We convert that to # for the case that the account is being (re)created. We convert that to
# the unix info. # the unix info.
# #
my $default_groupname; my $default_project;
my $default_groupgid; my $default_groupgid;
$query_result = if ($target_user->FirstApprovedProject(\$default_project) < 0) {
DBQueryFatal("select m.pid from group_membership as m ". fatal("Could not locate default project for $target_user");
"where m.uid='$user' and m.pid=m.gid and m.trust!='none' ". }
"order by date_approved asc limit 1");
if (my ($defpid) = $query_result->fetchrow_array) { if (defined($default_project)) {
if (! TBGroupUnixInfo($defpid, $defpid, $default_groupgid = $default_project->unix_gid();
\$default_groupgid, \$default_groupname)) {
fatal("No info for default project $defpid!");
}
} }
else { else {
print "No group membership for $user; using the guest group!\n"; print "No group membership for $target_user; using the guest group!\n";
($default_groupname,undef,$default_groupgid,undef) = getgrnam("guest"); (undef,undef,$default_groupgid,undef) = getgrnam("guest");
} }
# #
...@@ -264,8 +211,8 @@ open(TEMP, ">>usercert.cnf") ...@@ -264,8 +211,8 @@ open(TEMP, ">>usercert.cnf")
or fatal("Could not open $TEMPLATE for append: $!"); or fatal("Could not open $TEMPLATE for append: $!");
print TEMP "OU\t\t= sslxmlrpc\n"; print TEMP "OU\t\t= sslxmlrpc\n";
print TEMP "CN\t\t= $user\n"; print TEMP "CN\t\t= $user_uid\n";
print TEMP "emailAddress\t= $user" . "\@" . "$OURDOMAIN\n"; print TEMP "emailAddress\t= $user_uid" . "\@" . "$OURDOMAIN\n";
close(TEMP) close(TEMP)
or fatal("Could not close usercert.cnf: $!"); or fatal("Could not close usercert.cnf: $!");
...@@ -310,14 +257,15 @@ $UID = $SAVEUID; ...@@ -310,14 +257,15 @@ $UID = $SAVEUID;
# unencrypted). Might change that at some point. # unencrypted). Might change that at some point.
# #
DBQueryFatal("delete from user_sslcerts ". DBQueryFatal("delete from user_sslcerts ".
"where uid='$user' and ". "where uid_idx='$user_dbid' and ".
" encrypted=" . (defined($password) ? 1 : 0)); " encrypted=" . (defined($password) ? 1 : 0));
# #
# Create a new entry in the table. # Create a new entry in the table.
# #
DBQueryFatal("insert into user_sslcerts (uid, idx, created, encrypted) ". DBQueryFatal("insert into user_sslcerts ".
" values ('$user', $curidx, now(), ". "(uid, uid_idx, idx, created, encrypted) values ".
"('$user_uid', '$user_dbid', $curidx, now(), ".
(defined($password) ? 1 : 0) . ")"); (defined($password) ? 1 : 0) . ")");
# #
...@@ -353,7 +301,7 @@ close(PKEY); ...@@ -353,7 +301,7 @@ close(PKEY);
$pkeystring = DBQuoteSpecial($pkeystring); $pkeystring = DBQuoteSpecial($pkeystring);
$certstring = DBQuoteSpecial($certstring); $certstring = DBQuoteSpecial($certstring);
DBQueryFatal("update user_sslcerts set cert=$certstring,privkey=$pkeystring ". DBQueryFatal("update user_sslcerts set cert=$certstring,privkey=$pkeystring ".
"where uid='$user' and idx=$curidx"); "where uid_idx='$user_dbid' and idx=$curidx");
# #
# Combine the key and the certificate into one file which is installed # Combine the key and the certificate into one file which is installed
...@@ -366,7 +314,7 @@ system("cat usercert_key.pem usercert_cert.pem > usercert.pem") == 0 ...@@ -366,7 +314,7 @@ system("cat usercert_key.pem usercert_cert.pem > usercert.pem") == 0
# #
# Copy the certificate to the users .ssl directory. # Copy the certificate to the users .ssl directory.
# #
my $ssldir = "$USERDIR/$user/.ssl"; my $ssldir = "$USERDIR/$user_uid/.ssl";
if (! -d $ssldir) { if (! -d $ssldir) {
mkdir($ssldir, 0700) or mkdir($ssldir, 0700) or
fatal("Could not mkdir $ssldir: $!"); fatal("Could not mkdir $ssldir: $!");
...@@ -390,12 +338,13 @@ system("cp -f usercert.pem $target") == 0 ...@@ -390,12 +338,13 @@ system("cp -f usercert.pem $target") == 0
chown($user_number, $default_groupgid, "$target") chown($user_number, $default_groupgid, "$target")
or fatal("Could not chown $target: $!"); or fatal("Could not chown $target: $!");
close(LOCK); TBScriptUnlock();
exit(0); exit(0);
sub fatal($) { sub fatal($) {
my($mesg) = $_[0]; my($mesg) = $_[0];
TBScriptUnlock();
die("*** $0:\n". die("*** $0:\n".
" $mesg\n"); " $mesg\n");
} }
...@@ -145,7 +145,7 @@ my $HOMEDIR = USERROOT(); ...@@ -145,7 +145,7 @@ my $HOMEDIR = USERROOT();
# #
# Rewrite audit version of ARGV to prevent password in mail logs. # Rewrite audit version of ARGV to prevent password in mail logs.
# #
if ($ARGV[0] eq "passwd" && scalar(@ARGV) == 3) { if (scalar(@ARGV) == 3 && $ARGV[0] eq "passwd") {
my @NEWARGV = @ARGV; my @NEWARGV = @ARGV;
$NEWARGV[scalar(@NEWARGV) - 1] = "**********"; $NEWARGV[scalar(@NEWARGV) - 1] = "**********";
......
#!/usr/bin/perl -wT #!/usr/bin/perl -wT
# #
# EMULAB-COPYRIGHT # EMULAB-COPYRIGHT
# Copyright (c) 2005, 2006 University of Utah and the Flux Group. # Copyright (c) 2005, 2006, 2007 University of Utah and the Flux Group.
# All rights reserved. # All rights reserved.
# #
package Experiment; package Experiment;
...@@ -130,6 +130,8 @@ sub dpdb($) { return field($_[0], 'dpdb');} ...@@ -130,6 +130,8 @@ sub dpdb($) { return field($_[0], 'dpdb');}
sub dpdbname($) { return field($_[0], 'dpdbname');} sub dpdbname($) { return field($_[0], 'dpdbname');}
sub dpdbpassword($) { return field($_[0], 'dpdbpassword');} sub dpdbpassword($) { return field($_[0], 'dpdbpassword');}
sub instance_idx($) { return field($_[0], 'instance_idx'); } sub instance_idx($) { return field($_[0], 'instance_idx'); }
sub creator_idx($) { return field($_[0], 'creator_idx');}
sub swapper_idx($) { return field($_[0], 'swapper_idx');}
# #
# Lookup an experiment given an experiment index. # Lookup an experiment given an experiment index.
...@@ -335,20 +337,21 @@ sub Create($$$$) ...@@ -335,20 +337,21 @@ sub Create($$$$)
tberror("Error inserting experiment resources record for $pid/$eid!"); tberror("Error inserting experiment resources record for $pid/$eid!");
return undef; return undef;
} }
my $rsrcidx = $query_result->insertid; my $rsrcidx = $query_result->insertid;
my $creator = $argref->{'expt_head_uid'}; my $creator_uid = $argref->{'expt_head_uid'};
my $gid = $argref->{'gid'}; my $creator_idx = $argref->{'creator_idx'};
my $batchmode = $argref->{'batchmode'}; my $gid = $argref->{'gid'};
my $batchmode = $argref->{'batchmode'};
# #
# Now create an experiment_stats record to match. # Now create an experiment_stats record to match.
# #
if (! DBQueryWarn("insert into experiment_stats ". if (! DBQueryWarn("insert into experiment_stats ".