changeuid.in 4.36 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2004 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;

#
# Change the uid of an UNAPPROVED user. 
#
sub usage()
{
    print(STDERR "Usage: changeuid <olduid> <newuid>\n");
    exit(-1);
}
my $optlist = "df";
my $debug   = 0;
my $force   = 0;

#
# Configure variables
#
my $TB		= "@prefix@";

#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libaudit;
use libdb;
use libtestbed;

# Be careful not to exit on transient error
$libdb::DBQUERY_MAXTRIES = 30;

#
# Turn off line buffering on output
#
$| = 1;

#
# Untaint the path
# 
$ENV{'PATH'} = "/bin:/sbin:/usr/bin:/usr/sbin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

#
# We don't want to run this script unless its the real version.
#
#if ($EUID != 0) {
#    die("*** $0:\n".
#	"    Must be setuid! Maybe its a development version?\n");
#}

#
# This script is setuid, so please do not run it as root. Hard to track
# what has happened.
#
if ($UID == 0) {
    die("*** $0:\n".
	"    Please do not run this as root! Its already setuid!\n");
}

# Only admin types!
if (!TBAdmin($UID)) {
    die("*** $0:\n".
	"    Only TB administrators can run this script!\n");
}

#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
    usage();
}
if (defined($options{"d"})) {
    $debug = 1;
}
if (defined($options{"f"})) {
    $force = 1;
}
if (@ARGV != 2) {
    usage();
}
my $olduid = shift(@ARGV);
my $newuid = shift(@ARGV);

92 93 94 95 96 97 98 99 100
#
# Make sure that the new uid is valid!
#
if (! TBcheck_dbslot($newuid, "users", "uid",
		     TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR)) {
    die("*** $0:\n".
	"    Invalid characters in new uid: $newuid!\n");
}

101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
#
# This script is always audited. Mail is sent automatically upon exit.
#
if (AuditStart(0)) {
    #
    # Parent exits normally
    #
    exit(0);
}

#
# Get the user status. Only users in the new or unapproved state can
# have their uid changed. Once the account is created, it is much more
# difficult to deal with.
#
$query_result =
    DBQueryFatal("select status from users where uid='$olduid'");

if ($query_result->numrows == 0) {
    die("*** $0:\n".
	"    No such user '$olduid' in the DB!\n");
}
my ($status) = $query_result->fetchrow_array();

#
# Only operate on unapproved users (must be verified). Any other state
# is hard to deal with cause of exported homedirs, existing experiments,
# files that need to be changed on disk, etc. Maybe add this support later.
# 
if ($status ne USERSTATUS_UNAPPROVED()) {
    die("*** $0:\n".
	"    User '$olduid' must be an unapproved (verified) user!\n");
}

#
# Obviously the new user must not exist in the users table. This is the
# last table we change below ...
#
$query_result =
    DBQueryFatal("select status from users where uid='$newuid'");

if ($query_result->numrows) {
    die("*** $0:\n".
	"    User '$newuid' is already in the DB!\n");
}

#
# Change a bunch of tables!
#
print "Updating group_membership table ...\n";
DBQueryFatal("update group_membership set uid='$newuid' ".
	     "where uid='$olduid'");

print "Updating projects table ...\n";
DBQueryFatal("update projects set head_uid='$newuid' ".
	     "where head_uid='$olduid'");

print "Updating user_pubkeys table ...\n";
DBQueryFatal("update user_pubkeys set uid='$newuid' ".
	     "where uid='$olduid'");

print "Updating user_sfskeys table ...\n";
DBQueryFatal("update user_sfskeys set uid='$newuid' ".
	     "where uid='$olduid'");

print "Updating user_stats table ...\n";
DBQueryFatal("update user_stats set uid='$newuid' ".
	     "where uid='$olduid'");

print "Updating widearea_accounts table ...\n";
DBQueryFatal("update widearea_accounts set uid='$newuid' ".
	     "where uid='$olduid'");

174 175 176 177
print "Updating groups table ...\n";
DBQueryFatal("update groups set leader='$newuid' ".
	     "where leader='$olduid'");

178 179 180 181 182 183 184 185 186 187 188 189
# Auto logout old user. 
print "Clearing logins table ...\n";
DBQueryFatal("delete from login where uid='$olduid'");

#
# Lastly change users table; if anything breaks above we can still run
# this script to finish the job. Technically, we should lock these tables
# so that no one can sneak in and create a new user with the same uid
# as new one, but that is not likely to happen!
#
print "Updating users table ...\n";
DBQueryFatal("update users set uid='$newuid' where uid='$olduid'");