rmgroup.in 6.19 KB
Newer Older
1
#!/usr/bin/perl -wT
Leigh B. Stoller's avatar
Leigh B. Stoller committed
2 3
#
# EMULAB-COPYRIGHT
Mike Hibler's avatar
Mike Hibler committed
4
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
5 6
# All rights reserved.
#
Leigh B. Stoller's avatar
Leigh B. Stoller committed
7
use English;
8
use strict;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
9 10 11

#
# Remove a group. We delete the group directory and the we remove the
12 13 14 15 16 17 18
# group from /etc/group. Actually, the group directory is *renamed*
# since we do not want to be so destructive. This scrip can be called
# with pid=gid, but in that case it has to be a tbadmin, and the
# directory is not renamed. The caller (rmproj) is responsible for that.
#
sub usage()
{
19
    print STDOUT "Usage: rmgroup <gid>\n";
20 21
    exit(-1);
}
22
sub fatal($);
23 24
my  $optlist = "";

Leigh B. Stoller's avatar
Leigh B. Stoller committed
25
#
26
# We don't want to run this script unless its the real version.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
27
#
28 29 30 31 32 33 34 35 36 37 38 39 40
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");
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
41 42 43 44

#
# Configure variables
#
45 46 47 48
my $TB            = "@prefix@";
my $TBOPS         = "@TBOPSEMAIL@";
my $CONTROL       = "@USERNODE@";
my $BOSSNODE      = "@BOSSNODE@";
49
my $ELABINELAB    = @ELABINELAB@;
50
my $MAILMANSUPPORT= @MAILMANSUPPORT@;
51 52
my $BUGDBSUPPORT  = @BUGDBSUPPORT@;
my $OPSDBSUPPORT  = @OPSDBSUPPORT@;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
53

54 55 56 57 58
my $SSH           = "$TB/bin/sshtb";
my $GROUPDEL      = "/usr/sbin/pw groupdel";
my $DELMMLIST     = "$TB/sbin/delmmlist";
my $MODGROUPS     = "$TB/sbin/modgroups";
my $OPSDBCONTROL  = "$TB/sbin/opsdb_control";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

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

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

#
# Load the Testbed support stuff. 
#
use lib "@prefix@/lib";
75
use libaudit;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
76 77
use libdb;
use libtestbed;
Mike Hibler's avatar
Mike Hibler committed
78 79
use User;
use Group;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
80

81
# Defined in libtestbed;
82 83 84
my $PROJROOT    = PROJROOT();
my $GRPROOT     = GROUPROOT();

Leigh B. Stoller's avatar
Leigh B. Stoller committed
85 86 87
#
# Check args.
#
88
if (@ARGV != 1) {
89
    usage();
Leigh B. Stoller's avatar
Leigh B. Stoller committed
90 91
}

92 93 94 95
# Map invoking user to object.
my $this_user = User->ThisUser();
if (! defined($this_user)) {
    fatal("You ($UID) do not exist!");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
96
}
97 98 99 100 101 102 103 104
my $user_name  = $this_user->name();
my $user_email = $this_user->email();
my $user_uid   = $this_user->uid();

# Map the group to its object.
my $group = Group->Lookup($ARGV[0]);
if (!defined($group)) {
    fatal("Could not lookup group object for $ARGV[0]");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
105
}
106 107 108 109 110
my $unix_gid   = $group->unix_gid();
my $unix_name  = $group->unix_name();
my $pid        = $group->pid();
my $gid        = $group->gid();
my $gid_idx    = $group->gid_idx();
Leigh B. Stoller's avatar
Leigh B. Stoller committed
111 112

#
113
# Figure out who called us. 
Leigh B. Stoller's avatar
Leigh B. Stoller committed
114
#
115
if (!TBAdmin()) {
116 117 118 119
    #
    # Only admin types can remove the project group. Typically, you won't
    # do this directly, but use rmproj instead.
    #
120
    if ($group->IsProjectGroup()) {
121 122 123
	die("*** $0:\n".
	    "    You do not have permission to remove a project group!\n");
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
124

125
    if (! $group->AccessCheck($this_user, TB_PROJECT_DELGROUP())) {
126
	die("*** $0:\n".
127
	    "    You do not have permission to remove group $group!\n");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
128 129 130 131
    }
}

#
132 133 134 135 136 137 138
# This script is always audited. Mail is sent automatically upon exit.
#
if (AuditStart(0)) {
    #
    # Parent exits normally
    #
    exit(0);
Leigh B. Stoller's avatar
Leigh B. Stoller committed
139 140
}

141
#
142
# Rename the group directory as long as its not the proj directory.
143
#
144
if (! $group->IsProjectGroup()) {
145 146
    my $groupdir  = "$GRPROOT/$pid";
    my $oldname   = "$groupdir/$gid";
147
    my $newname   = "$groupdir/$gid_idx";
148
    my $grouplink = "$PROJROOT/$pid/groups/$gid";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
149

150 151
    if (-e $grouplink && !unlink($grouplink)) {
	fatal("Could not unlink $grouplink: $!");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
152
    }
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171

    if (-e $oldname) {
	print "Renaming $oldname to $newname.\n";
    
	if (rename($oldname, $newname)) {
	    #
	    # Chown the owner/group to root and set the permissions so no
	    # one is allowed to look inside.
	    #
	    if (! chmod(0700, $newname)) {
		fatal("Could not chmod directory $newname to 0700: $!");
	    }
	    if (! chown(0, 0, $newname)) {
		fatal("Could not chown directory $newname to 0/0: $!");
	    }
	}
	else {
	    fatal("Could not rename $oldname to $newname: $!");
	}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
172 173 174
    }
}

175 176 177
#
# Remove all members from the group.
# If there was an error, the DB state is left so that this script can
178
# be run again.
179 180 181 182
#
# Must find out what users/groups to delete so that we can pass off to
# modgroups.
#
183 184 185 186
my @userlist = ();
$group->MemberList(\@userlist,
		   $Group::MEMBERLIST_FLAGS_ALLUSERS |
		   $Group::MEMBERLIST_FLAGS_UIDSONLY);
187

188
foreach my $uid (@userlist) {
189 190 191 192 193 194 195 196
    # For perl
    $EUID = $UID;
    if (system("$MODGROUPS -r $pid:$gid $uid")) {
	fatal("$MODGROUPS -r $pid:$gid $uid failed!");
    }
    $EUID = 0;
}

197 198 199 200 201 202
# If the group isn't in /etc/group yet, it wasn't approved and created.
if (system("grep -q '^${unix_gid}:' /etc/group")) {
    #
    # Now remove the group from the group file on both plastic and paper.
    #
    print "Removing group $unix_name ($unix_gid) on local node.\n";
203

204 205 206 207
    if (system("$GROUPDEL $unix_name")) {
	if (($? >> 8) != 65) {
	    fatal("Could not remove group $unix_name from local node!");
	}
208
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
209

210 211
    if ($MAILMANSUPPORT && !$ELABINELAB) {
	my $listname = ($pid eq $gid ? "${pid}-users" : "${pid}-${gid}-users");
212

213 214 215 216 217 218
	# For perl
	$EUID = $UID;
	system("$DELMMLIST -a $listname") == 0 or
	    fatal("$DELMMLIST -a $listname failed!");
	$EUID = 0;
    }
219

220 221 222 223 224 225 226
    if ($OPSDBSUPPORT && !$ELABINELAB) {
	# For perl
	$EUID = $UID;
	system("$OPSDBCONTROL delgroup $pid $gid") == 0 or
	    fatal("$OPSDBCONTROL delgroup $pid $gid failed!");
	$EUID = 0;
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
227

228 229 230 231
    #
    # Be real root for ssh.
    # 
    $UID = 0;
232

233 234 235 236 237 238 239
    if ($CONTROL ne $BOSSNODE) {
	print "Removing group $unix_name ($unix_gid) on $CONTROL.\n";

	if (system("$SSH -host $CONTROL $GROUPDEL $unix_name")) {
	    if (($? >> 8) != 65) {
		fatal("Could not remove group $unix_name from $CONTROL!");
	    }
240 241
	}
    }
Leigh B. Stoller's avatar
Leigh B. Stoller committed
242

243 244 245 246 247
    #
    # Remove group on the tip servers. 
    #
    foreach my $tipserver ( TBTipServers() ) {
	print "Removing group $unix_name ($unix_gid) on $tipserver.\n";
248

249 250 251 252
	if (system("$SSH -host $tipserver $GROUPDEL $unix_name")) {
	    if (($? >> 8) != 65) {
		fatal("Could not remove group $unix_name from $tipserver!");
	    }
253
	}
254 255 256
    }
}

257 258 259
# Last step, so we can repeat above actions on failures.
$group->Delete() == 0 or
    fatal("Could not delete group $group");
260

261
print "Group $pid/$gid ($gid_idx) has been removed!\n";
262
exit(0);
Leigh B. Stoller's avatar
Leigh B. Stoller committed
263

264 265 266 267 268 269
sub fatal($) {
    my($mesg) = $_[0];

    die("*** $0:\n".
	"    $mesg\n");
}