Commit 46068860 authored by Leigh Stoller's avatar Leigh Stoller

A bunch o' account managment script schanges. I have reworked

mkprojdir, mkacct-cntrl, mkgroup, and group-update into a set of new
scripts that are more specific to their intended operation, and strive
to do less work.

1. mkacct - Replaces mkacct-cntrl. This script no longer does any
   group stuff. All it does is create new accounts, or update the
   password and gecos fields of existing accounts. Usage is the same
   as it was: "mkacct <userid>", and is typically invoked from the web
   interface via the approveuser form.

2. mkgroup - Replaces group-update. This script creates new groups,
   either for the main project when it is approved, or for subgroup
   creation. This script does not alter the group membership. Usage
   is typically from the web interface, but mkgroup can be invoked
   from the command line: "mkgroup [-b | -a] <pid> <gid>" where -b
   puts it in the background and sends email later, while -a just
   captures the log and emails. This "audit" feature is going to find
   its way into more scripts as soon as I figure out a neat and clean
   perl mechanism to make it easy.

3. setgroups - Replaces group-update. This script modifies the group
   membership of either specific users, or all the users in a
   project. It is typically invoked from the web interface when a
   project leader edits the subgroup membership or when a user is
   first approved to a project or subgroup. Command line usage is:

	setgroups [-b | -a] -p <pid> [user ...]
        setgroups [-b | -a] [user ...]\n

   The first form is mostly a means to speed things up. The web
   interfaces knows exactly what users have need to be changed, but a
   global project update is nice too.

4. mkproj - Replaces mkprojdir. Actually, mkproj still has all that
   directory code, but it also handles creating the groups and the
   account for the project leader. Part of my policy to move as much
   random code out of the web interface and into the PERL backend
   where it belongs.
parent 3cb3f3c6
......@@ -1031,9 +1031,9 @@ outfiles="$outfiles Makeconf GNUmakefile \
os/GNUmakefile os/split-image.sh os/imagezip/GNUmakefile \
pxe/GNUmakefile pxe/proxydhcp.restart pxe/bootinfo.restart \
security/GNUmakefile security/paperbag security/lastlog_daemon \
tbsetup/GNUmakefile tbsetup/console_setup tbsetup/mkacct-ctrl \
tbsetup/GNUmakefile tbsetup/console_setup \
tbsetup/console_reset tbsetup/bwconfig tbsetup/power_rpc27.pm \
tbsetup/os_load tbsetup/os_setup tbsetup/mkprojdir tbsetup/power \
tbsetup/os_load tbsetup/os_setup tbsetup/power \
tbsetup/node_reboot tbsetup/webnscheck tbsetup/nscheck \
tbsetup/resetvlans tbsetup/rmacct-ctrl tbsetup/rmproj \
tbsetup/sched_reload tbsetup/sched_reserve tbsetup/reload_daemon \
......@@ -1048,17 +1048,20 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \
tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \
tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \
tbsetup/savelogs tbsetup/group-update tbsetup/webgroupupdate \
tbsetup/savelogs tbsetup/setgroups tbsetup/websetgroups \
tbsetup/rmgroup tbsetup/webrmgroup tbsetup/mkexpdir \
tbsetup/webnodecontrol tbsetup/node_control \
tbsetup/webmkgroup tbsetup/mkgroup \
tbsetup/webmkacct tbsetup/mkacct \
tbsetup/webmkproj tbsetup/mkproj \
tip/GNUmakefile \
tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \
tmcd/netbsd/GNUmakefile \
tmcd/tmcd.restart \
utils/GNUmakefile utils/vlandiff utils/vlansync utils/delay_config \
utils/sshtb utils/create_image utils/node_admin \
vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \
www/GNUmakefile www/defs.php3 www/dbdefs.php3 \
vis/GNUmakefile vis/vistopology vis/webvistopology vis/top2gif \
rc.d/GNUmakefile rc.d/2.mysql-server.sh rc.d/3.testbed.sh \
rc.d/cvsupd.sh"
......
......@@ -153,9 +153,9 @@ outfiles="$outfiles Makeconf GNUmakefile \
os/GNUmakefile os/split-image.sh os/imagezip/GNUmakefile \
pxe/GNUmakefile pxe/proxydhcp.restart pxe/bootinfo.restart \
security/GNUmakefile security/paperbag security/lastlog_daemon \
tbsetup/GNUmakefile tbsetup/console_setup tbsetup/mkacct-ctrl \
tbsetup/GNUmakefile tbsetup/console_setup \
tbsetup/console_reset tbsetup/bwconfig tbsetup/power_rpc27.pm \
tbsetup/os_load tbsetup/os_setup tbsetup/mkprojdir tbsetup/power \
tbsetup/os_load tbsetup/os_setup tbsetup/power \
tbsetup/node_reboot tbsetup/webnscheck tbsetup/nscheck \
tbsetup/resetvlans tbsetup/rmacct-ctrl tbsetup/rmproj \
tbsetup/sched_reload tbsetup/sched_reserve tbsetup/reload_daemon \
......@@ -170,9 +170,12 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \
tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \
tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \
tbsetup/savelogs tbsetup/group-update tbsetup/webgroupupdate \
tbsetup/savelogs tbsetup/setgroups tbsetup/websetgroups \
tbsetup/rmgroup tbsetup/webrmgroup tbsetup/mkexpdir \
tbsetup/webnodecontrol tbsetup/node_control \
tbsetup/webmkgroup tbsetup/mkgroup \
tbsetup/webmkacct tbsetup/mkacct \
tbsetup/webmkproj tbsetup/mkproj \
tip/GNUmakefile \
tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \
tmcd/netbsd/GNUmakefile \
......
......@@ -19,14 +19,15 @@ USERBINS = os_load node_reboot nscheck node_update savelogs node_control
SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
batch_daemon exports_setup reload_daemon sched_reserve \
console_reset db2ns bwconfig frisbeelauncher group-update \
rmgroup
console_reset db2ns bwconfig frisbeelauncher \
rmgroup mkgroup mkacct setgroups mkproj
LIBEXEC_STUFF = mkprojdir rmproj mkacct-ctrl rmacct-ctrl \
LIBEXEC_STUFF = rmproj rmacct-ctrl \
os_setup mkexpdir console_setup webnscheck webreport \
webstartexp webendexp webbatchexp \
assign_wrapper ptopgen webnodeupdate webgroupupdate \
webrmgroup webswapexp webnodecontrol
assign_wrapper ptopgen webnodeupdate \
webrmgroup webswapexp webnodecontrol \
webmkgroup webmkacct websetgroups webmkproj
LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \
snmpit_cisco.pm snmpit_lib.pm snmpit_apc.pm power_rpc27.pm \
......@@ -67,14 +68,16 @@ post-install:
chmod 775 $(INSTALL_SBINDIR)
chmod 775 $(INSTALL_LIBDIR)
chmod 775 $(INSTALL_LIBEXECDIR)
chown root $(INSTALL_LIBEXECDIR)/mkprojdir
chmod u+s $(INSTALL_LIBEXECDIR)/mkprojdir
chown root $(INSTALL_SBINDIR)/mkproj
chmod u+s $(INSTALL_SBINDIR)/mkproj
chown root $(INSTALL_LIBEXECDIR)/rmproj
chmod u+s $(INSTALL_LIBEXECDIR)/rmproj
chown root $(INSTALL_SBINDIR)/rmgroup
chmod u+s $(INSTALL_SBINDIR)/rmgroup
chown root $(INSTALL_LIBEXECDIR)/mkacct-ctrl
chmod u+s $(INSTALL_LIBEXECDIR)/mkacct-ctrl
chown root $(INSTALL_SBINDIR)/mkacct
chmod u+s $(INSTALL_SBINDIR)/mkacct
chown root $(INSTALL_SBINDIR)/mkgroup
chmod u+s $(INSTALL_SBINDIR)/mkgroup
chown root $(INSTALL_LIBEXECDIR)/rmacct-ctrl
chmod u+s $(INSTALL_LIBEXECDIR)/rmacct-ctrl
chown root $(INSTALL_SBINDIR)/named_setup
......@@ -83,8 +86,8 @@ post-install:
chmod u+s $(INSTALL_SBINDIR)/exports_setup
chown root $(INSTALL_BINDIR)/savevlans
chmod u+s $(INSTALL_BINDIR)/savevlans
chown root $(INSTALL_SBINDIR)/group-update
chmod u+s $(INSTALL_SBINDIR)/group-update
chown root $(INSTALL_SBINDIR)/setgroups
chmod u+s $(INSTALL_SBINDIR)/setgroups
chown root $(INSTALL_LIBEXECDIR)/console_setup
chmod u+s $(INSTALL_LIBEXECDIR)/console_setup
chown root $(INSTALL_BINDIR)/node_reboot
......
......@@ -7,7 +7,8 @@ use Exporter;
@ISA = "Exporter";
@EXPORT =
qw ( SENDMAIL OPENMAIL TBTimeStamp TBBackGround TBDateTimeFSSafe );
qw ( SENDMAIL OPENMAIL TBTimeStamp TBBackGround TBDateTimeFSSafe
TBMakeLogname );
# A library of useful stuff.
......@@ -155,4 +156,24 @@ sub TBBackGround($)
return 0;
}
#
# Create a logname and untaint it!
#
sub TBMakeLogname($)
{
my($prefix) = @_;
my $logname;
$logname = `mktemp /tmp/${prefix}.XXXXXX`;
if ($logname =~ /^([-\@\w\.\/]+)$/) {
$logname = $1;
}
else {
die("Bad data in logfile name: $logname");
}
return $logname;
}
1;
#!/usr/local/bin/perl -wT
use English;
use Getopt::Std;
#
# Create accounts.
# Create a user account. All this script does is create the account
# if it does not exist, or update the password and gecos fields.
# No groups processing is done here. The initial account is created in
# the "guest" group; use the setgroups command to set a users groups.
#
# XXX - The control node is hardwired. Look for $CONTROL.
# usage: mkacct <userid>
#
# usage: mkacct-ctrl <userid>
# XXX - /users wired in.
#
sub usage()
{
print STDOUT "Usage: mkacct <uid>\n";
exit(-1);
}
my $optlist = "";
#
# Configure variables
......@@ -15,15 +25,15 @@ use English;
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $CONTROL = "@USERNODE@";
my $TESTMODE= "@TESTMODE@";
my $HOMEDIR = "/users";
my $PBAG = "$TB/sbin/paperbag";
my $SSH = "$TB/bin/sshtb";
my $GROUPADD= "/usr/sbin/pw groupadd";
my $USERADD = "/usr/sbin/pw useradd";
my $USERMOD = "/usr/sbin/pw usermod";
my $CHPASS = "/usr/bin/chpass";
my $KEYGEN = "/usr/bin/ssh-keygen";
my $SETGROUPS = "$TB/sbin/setgroups";
my $GENELISTS = "$TB/sbin/genelists";
my $user;
......@@ -34,7 +44,17 @@ my $query_result;
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
die("Must be root! Maybe its a development version?");
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");
}
#
......@@ -56,10 +76,15 @@ use libdb;
use libtestbed;
#
# Check args.
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
if ($#ARGV < 0) {
die("Usage: mkacct-ctrl <userid>\n");
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (@ARGV != 1) {
usage();
}
$user = $ARGV[0];
......@@ -79,7 +104,7 @@ else {
# user has group/project root in at least one project, which indicates they
# have some level of responsibility.
#
if ($UID && !TBAdmin($UID)) {
if (!TBAdmin($UID)) {
my $dbuid;
if (! UNIX2DBUID($UID, \$dbuid)) {
......@@ -101,11 +126,16 @@ if ($UID && !TBAdmin($UID)) {
}
#
# Get the user info (the user being created).
# Get the user info (the user being created). This join picks out the
# user's earliest project membership to use for the default group.
#
$query_result =
DBQueryFatal("select usr_pswd,unix_uid,usr_name,usr_email ".
"from users where uid='$user'");
DBQueryFatal("select u.usr_pswd,u.unix_uid,u.usr_name,u.usr_email,m.pid ".
" from users as u ".
"left join group_membership as m ".
" on u.uid=m.uid and m.pid=m.gid ".
"where u.uid='$user' order by date_approved asc limit 1");
if ($query_result->numrows == 0) {
fatal("$user is not in the DB. This is bad.\n");
}
......@@ -114,40 +144,17 @@ my $pswd = $db_row[0];
my $user_number = $db_row[1];
my $fullname = $db_row[2];
my $user_email = $db_row[3];
my $defpid = $db_row[4];
#
# Get the group (projects user belongs to) names and numbers.
#
my @groupnames;
my %groupnumbers;
my @grouplist;
my @tipservers;
# Unix info for users default group.
#
# Form a list of project (group) membership names. We do this in two
# steps to ensure that we get the default group membership, since we
# want that to be the user's primary group. Not sure this really matters
# all that much, but might as well.
#
$query_result =
DBQueryFatal("select g.unix_name,g.unix_gid from group_membership as m ".
"left join groups as g on m.pid=g.pid and m.gid=g.gid ".
"where m.uid='$user' and m.pid=m.gid and m.trust!='none'");
if ($query_result->numrows == 0) {
fatal("$user is not in any groups!\n");
}
while (@db_row = $query_result->fetchrow_array() ) {
push(@groupnames, $db_row[0]);
$groupnumbers{$db_row[0]} = $db_row[1];
}
my $default_groupname;
my $default_groupgid;
$query_result =
DBQueryFatal("select g.unix_name,g.unix_gid from group_membership as m ".
"left join groups as g on m.pid=g.pid and m.gid=g.gid ".
"where m.uid='$user' and m.pid!=m.gid and m.trust!='none'");
while (@db_row = $query_result->fetchrow_array() ) {
push(@groupnames, $db_row[0]);
$groupnumbers{$db_row[0]} = $db_row[1];
if (! TBGroupUnixInfo($defpid, $defpid,
\$default_groupgid, \$default_groupname)) {
fatal("No info for default project $defpid!");
}
#
......@@ -156,20 +163,6 @@ while (@db_row = $query_result->fetchrow_array() ) {
my $control_node = $CONTROL;
#
# We need a list of tipservers to build groups on so that the console
# lines can get the appropriate group permissions.
#
$query_result =
DBQueryFatal("select * from tipservers");
while (@db_row = $query_result->fetchrow_array() ) {
push(@tipservers, $db_row[0]);
}
#
# Create groups on both the control and operations nodes. We assume
# FreeBSD for both.
#
# All this stuff must be done as root (ssh).
#
$UID = $EUID;
......@@ -183,109 +176,33 @@ $UID = $EUID;
#
system("$GENELISTS");
foreach my $group ( @groupnames ) {
my $group_number = $groupnumbers{$group};
print "Processing group $group (gid $group_number)\n";
#
# Create group locally if it does not exist. egrep returns 1 when
# no matches are found.
#
if (system("egrep -q -s '^${group}:' /etc/group")) {
print "Adding group $group to paper\n";
if (system("$GROUPADD $group -g $group_number")) {
fatal("Could not add $group ($group_number) to local node!\n");
}
}
#
# Create group on the control node if it does not exist.
#
if (system("$SSH $control_node egrep -q -s '^${group}:' /etc/group")) {
print "Adding group $group to $control_node.\n";
if (system("$SSH $control_node $GROUPADD $group -g $group_number")) {
fatal("Could not add $group ($group_number) to $control_node!\n");
}
}
#
# On tipservers too.
#
foreach my $tipserver ( @tipservers ) {
if (system("$SSH $tipserver egrep -q -s '^${group}:' /etc/group")) {
print "Adding group $group to $tipserver\n";
if (system("$SSH $tipserver $GROUPADD $group -g $group_number")) {
fatal("Could not add $group ($group_number) to $tipserver!\n");
}
}
}
}
#
# Construct an appropriate group list for the pw commands. Main project
# is the first on the list, and that becomes the primary group. The rest
# (if any) of the groups become a comma separated list for the -G option.
#
my $groupargument = " ";
my $project = shift @groupnames;
my $grouplist = join(",",@groupnames);
#
# Add special groups. These are listed in the DB so that special local
# users can have more unix groups than just the projects/groups they are
# in. These groups must already exist.
#
if ((my @extragrouplist = TBUnixGroupList($user))) {
print "Adding extra groups to list: @extragrouplist\n";
if ($grouplist) {
$grouplist = "$grouplist," . join(",", @extragrouplist);
}
else {
$grouplist = join(",", @extragrouplist);
}
}
if ($grouplist) {
$groupargument = "-G $grouplist";
}
else {
$groupargument = "-G \"\"";
}
#
# Make user on local. We don't give them a password since they are not
# allowed to log in, except via paperbaf. Be sure not overwrite the shell
# for a user who has a real shell.
# allowed to log in, except via paperbag.
#
if (system("egrep -q -s '^${user}:' /etc/passwd")) {
print "Adding user $user ($user_number) to local node.\n";
if (system("$USERADD $user -u $user_number -c \"$fullname\" ".
"-k /usr/share/skel -m -d $HOMEDIR/$user ".
"-g $project $groupargument -s $PBAG")) {
"-g $default_groupname -s $PBAG")) {
fatal("Could not add user $user to local node.");
}
}
else {
print "Updating user $user ($user_number) record on local node.\n";
print "Updating user $user ($user_number) on local node.\n";
#
# MAKE SURE not to update the shell
# MAKE SURE not to update anything else!
#
if (system("$USERMOD $user -u $user_number -c \"$fullname\" ".
"-g $project $groupargument")) {
if (system("$USERMOD $user -c \"$fullname\" ")) {
fatal("Could not modify user $user on local node.");
}
}
#
# Make user account on control node. We do the password setup as separate
# step since thats easier than trying to both via ssh.
# step since thats easier than trying to do both via ssh.
#
# Quote special chars for ssh and the shell on the other side
#
......@@ -295,22 +212,27 @@ $fullname =~ s/([^\\])([\'\"\(\)])/$1\\$2/g;
if (system("$SSH $control_node egrep -q -s '^${user}:' /etc/passwd")) {
print "Adding user $user ($user_number) to $control_node.\n";
if (system("$SSH $control_node '$USERADD ".
"$user -u $user_number -c \"$fullname\" ".
"-k /usr/share/skel -m -d $HOMEDIR/$user -g $project ".
"$groupargument -s /bin/tcsh'")) {
if (system("$SSH $control_node ".
"'$USERADD $user -u $user_number -c \"$fullname\" ".
"-k /usr/share/skel -m -d $HOMEDIR/$user ".
"-g $default_groupname -s /bin/tcsh'")) {
fatal("Could not add user $user ($user_number) to $control_node.\n");
}
}
else {
print "Updating user $user record on $control_node.\n";
print "Updating user $user ($user_number) on $control_node.\n";
if (system("$SSH $control_node '$USERMOD ".
"$user -u $user_number ".
"-c \"$fullname\" -g $project $groupargument'")) {
#
# MAKE SURE not to update anything else!
#
if (system("$SSH $control_node ".
"'$USERMOD $user -c \"$fullname\"'")) {
fatal("Could not modify user $user record on $control_node.");
}
}
print "Updating user $user password on $control_node.\n";
if (system("$SSH $control_node $CHPASS -p $pswd $user")) {
fatal("Could not change password for user $user on $control_node.\n");
}
......@@ -323,14 +245,14 @@ if (! -e "$HOMEDIR/$user/.ssh/" ) {
mkdir("$HOMEDIR/$user/.ssh", 0700) or
fatal("Could not mkdir $HOMEDIR/$user/.ssh: $!");
chown($user_number, $groupnumbers{$project}, "$HOMEDIR/$user/.ssh") or
chown($user_number, $default_groupgid, "$HOMEDIR/$user/.ssh") or
fatal("Could not chown $HOMEDIR/$user/.ssh: $!");
# Run commands below as the user
$EUID = $user_number;
$UID = $EUID;
if (system("/usr/bin/ssh-keygen -P '' -f $HOMEDIR/$user/.ssh/identity")) {
if (system("$KEYGEN -P '' -f $HOMEDIR/$user/.ssh/identity")) {
fatal("Failure in ssh-keygen");
}
if (system("/bin/cp $HOMEDIR/$user/.ssh/identity.pub ".
......@@ -338,7 +260,7 @@ if (! -e "$HOMEDIR/$user/.ssh/" ) {
fatal("Copying over $HOMEDIR/$user/.ssh/identity.pub to auth keys");
}
chmod(0600, "$HOMEDIR/$user/.ssh/authorized_keys") or
fatal("Could not chown $HOMEDIR/$user/.ssh/authorized_keys: $!");
fatal("Could not chmod $HOMEDIR/$user/.ssh/authorized_keys: $!");
}
#
......@@ -351,7 +273,7 @@ if (! -e "$HOMEDIR/$user/.forward" ) {
fatal("Could not create $HOMEDIR/$user/.forward");
}
chmod(0644, "$HOMEDIR/$user/.forward") or
fatal("Could not chown $HOMEDIR/$user/.forward");
fatal("Could not chmod $HOMEDIR/$user/.forward");
}
exit(0);
......@@ -360,5 +282,5 @@ sub fatal {
local($msg) = $_[0];
SENDMAIL($TBOPS, "TESTBED: mkacct-ctrl Failed", $msg);
die("$0: $msg");
die("$0: $msg\n");
}
......@@ -3,16 +3,19 @@ use English;
use Getopt::Std;
#
# Create/Update a group.
# Create a group on the control/ops nodes and any tipservers. This does
# not create accounts, or add users to groups; it just creates the group
# entries and the group directory.
#
# usage: group-update [-b] <pid> <gid>
# XXX - /proj wired in
# control node wired in.
#
sub usage()
{
print STDOUT "Usage: group-update -b <pid> <gid>\n";
print STDOUT "Usage: mkgroup [-b | -a] <pid> <gid>\n";
exit(-1);
}
my $optlist = "b";
my $optlist = "ba";
#
# Configure variables
......@@ -22,15 +25,12 @@ my $TBOPS = "@TBOPSEMAIL@";
my $TBLOGS = "@TBLOGSEMAIL@";
my $CONTROL = "@USERNODE@";
my $PROJROOT = "/proj";
my $SSH = "$TB/bin/sshtb";
my $GROUPADD = "/usr/sbin/pw groupadd";
my $USERMOD = "/usr/sbin/pw usermod";
my $mkacct = "$TB/libexec/mkacct-ctrl";
my $batchmode = 0;
my $auditmode = 0;
my $dbuid;
my $user;
my @db_row;
my $query_result;
my $leader;
......@@ -38,29 +38,15 @@ my $groupdir;
my $logname;
my $user_name;
my $user_email;
my $unix_gid;
my $unix_name;
my @tipservers;
#
# Note hardwired control node.
#
my $control_node = $CONTROL;
#
# 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");
}
#
# Untaint the path
#
......@@ -79,6 +65,23 @@ use lib "@prefix@/lib";
use libdb;
use libtestbed;
#
# 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");
}
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
......@@ -93,8 +96,11 @@ if (@ARGV != 2) {
if (defined($options{"b"})) {
$batchmode = 1;
}
my $pid = $ARGV[0];
my $gid = $ARGV[1];
if (defined($options{"a"})) {
$auditmode = 1;
}
my $pid = shift(@ARGV);
my $gid = shift(@ARGV);
#
# Untaint args.
......@@ -116,14 +122,16 @@ else {
# Get user DB uid.
#
if (! UNIX2DBUID($UID, \$dbuid)) {
die("*** You do not exist in the Emulab Database!\n");
die("*** $0:\n".
" You do not exist in the Emulab Database!\n");
}
#
# Get email info for mail.
#
if (! UserDBInfo($dbuid, \$user_name, \$user_email)) {
die("*** Cannot determine email info for you!\n");
die("*** $0:\n".
" Cannot determine email info for you!\n");
}
#
......@@ -137,7 +145,7 @@ if (!TBAdmin($UID)) {
#
$query_result =
DBQueryFatal("select trust from group_membership ".
"where pid='$pid' and uid='$dbuid' and gid='$pid' and ".
"where pid='$pid' and uid='$dbuid' and pid=gid and ".
"trust='project_root'");
if ($query_result->numrows == 0) {
......@@ -147,36 +155,47 @@ if (!TBAdmin($UID)) {
"and trust='group_root'");
if ($query_result->numrows == 0) {
die("*** $dbuid does not have permission to update groups!\n");
die("*** $0:\n".
" $dbuid does not have permission to update groups!\n");
}
}
}
if (! ($leader = GroupLeader($pid, $gid))) {
die("*** Could not determine group leader for $pid/$gid!\n");
die("*** $0:\n".
" Could not determine group leader for $pid/$gid!\n");
}
#
# The group directory lives here.
#
$groupdir = "$PROJROOT/$pid/groups/$gid";
#
# Unix info for the group
#
my $unix_gid;
my $unix_name;
if (! TBGroupUnixInfo($pid, $gid, \$unix_gid, \$unix_name)) {
die("*** No info for project/group $pid/$gid!");
die("*** $0:\n".
" No info for project/group $pid/$gid!");
}
#
# In batch mode, go to background and send email later.
#
if ($batchmode) {
if ($batchmode || $auditmode) {
my $childpid;
#
# Create a temporary name for a log file.
#
$logname = `mktemp /tmp/group-update-$pid-$gid.XXXXXX`;
chop($logname);
$logname = TBMakeLogname("mkgroup");
if (TBBackGround($logname)) {
if ($childpid = TBBackGround($logname)) {
if ($auditmode) {
waitpid($childpid, 0);
exit($? >> 8);
}
#
# Parent exits normally
#
......@@ -218,8 +237,6 @@ if (system("$SSH $control_node egrep -q -s '^${unix_name}:' /etc/group")) {
#
# Create group on the tip servers.
#
my @tipservers;
$query_result =
DBQueryFatal("select * from tipservers");
......@@ -232,17 +249,18 @@ foreach my $tipserver ( @tipservers ) {
print "Adding group $unix_name to $tipserver\n";
if (system("$SSH $tipserver $GROUPADD $unix_name -g $unix_gid")) {
fatal("Could not add $unix_name ($unix_gid) to $tipserver!\n");
fatal("*** Could not add $unix_name ($unix_gid) to $tipserver!\n");
}
}
}
#
# Create the group directory if it does not already exist.
# Create the group directory if it does not already exist, but not for
# the default group of the project.
#
$groupdir = "$PROJROOT/$pid/groups/$gid";
if (! -e $groupdir) {
if (! -e $groupdir && $pid ne $gid) {
print "Creating group directory: $groupdir.\n";
if (! mkdir("$groupdir", 0770)) {
fatal("*** Could not make directory $groupdir: $!");
}
......@@ -258,85 +276,32 @@ if (! -e $groupdir) {
}
}
#
# Grab the current user list for the group. These are people to add to
# the group list if they are not already in it.
#
$curmembers_result =
DBQueryWar