Commit 68e019a5 authored by Leigh Stoller's avatar Leigh Stoller

Add new status for users, "inactive". Mostly to support not having so

many ZFS mounts on ops. which on the Mothership is on the order of 8000
or so. Deactivate/reactivate a user with:

	boss> wap tbacct deactivate -u <user>
	boss> wap tbacct reactivate -u <user>

Deactivate will set the shell to nologin and set the ZFS mountpoint=none.
Reactivate will undo that. Note that these do not HUP mountd.
parent 57fa9bba
......@@ -49,6 +49,8 @@ sub usage()
print " accountsetup checkdotfiles ...\n";
print " accountsetup createsshkey ...\n";
print " accountsetup dropfile ...\n";
print " accountsetup deactivateuser ...\n";
print " accountsetup reactivateuser ...\n";
exit(1);
}
my $optlist = "dnf";
......@@ -80,6 +82,7 @@ my $CHPASS = "/usr/bin/chpass";
my $CHOWN = "/usr/sbin/chown";
my $CHMOD = "/bin/chmod";
my $MKDIR = "/bin/mkdir";
my $NOLOGIN = "/sbin/nologin";
my $MV = "/bin/mv";
my $ZFS = "/sbin/zfs";
my $KEYGEN = "/usr/bin/ssh-keygen";
......@@ -128,6 +131,8 @@ sub DelGroup();
sub DropFile();
sub CheckDotFiles();
sub CreateSSHKey();
sub ReactivateUser();
sub DeactivateUser();
sub fatal($);
sub ZFSexists($);
sub MakeDir($$);
......@@ -199,6 +204,14 @@ SWITCH: for ($cmd) {
CreateSSHKey();
last SWITCH;
};
/^deactivateuser$/ && do {
DeactivateUser();
last SWITCH;
};
/^reactivateuser$/ && do {
ReactivateUser();
last SWITCH;
};
# Default
usage();
}
......@@ -352,6 +365,53 @@ sub ModifyUser()
return 0;
}
#
# Usage: deactivate username
#
sub DeactivateUser()
{
if (@ARGV != 1) {
fatal("deactivateuser: Wrong number of arguments");
}
my $user = shift(@ARGV);
if ($WITHZFS) {
my $zfsdir = $ZFS_ROOT . USERROOT() . "/$user";
if (ZFSexists($zfsdir) &&
mysystem("$ZFS set mountpoint=none $zfsdir")) {
fatal("Could not set ZFS dir $zfsdir to mountpoint=none");
}
}
if (mysystem("$USERMOD $user -s $NOLOGIN")) {
fatal("Could not set shell to $NOLOGIN");
}
return 0;
}
#
# Usage: reactivate username
#
# The shell is changed via ModifyUser (we do not know the correct
# shell here), this is just for ZFS.
#
sub ReactivateUser()
{
if (@ARGV != 1) {
fatal("reactivateuser: Wrong number of arguments");
}
my $user = shift(@ARGV);
if ($WITHZFS) {
my $zfsdir = $ZFS_ROOT . USERROOT() . "/$user";
my $hdir = USERROOT() . "/$user";
if (ZFSexists($zfsdir) &&
mysystem("$ZFS set mountpoint=$hdir $zfsdir")) {
fatal("Could not set ZFS dir $zfsdir to mountpoint=$hdir");
}
}
return 0;
}
#
# Usage: addproject projname unix_gname unix_gid unix_uid
#
......
......@@ -171,6 +171,8 @@ sub UpdateWindowsPassword();
sub UpdateUser(;$);
sub FreezeUser();
sub ThawUser();
sub DeactivateUser();
sub ReactivateUser();
sub VerifyUser();
sub UpdateEmail();
sub CheckDotFiles();
......@@ -225,7 +227,7 @@ else {
die("Tainted argument: $user\n");
}
if ($cmd =~
/^(add|del|mod|freeze|passwd|wpasswd|thaw|email|verify|revoke|dots)$/) {
/^(add|del|mod|freeze|passwd|wpasswd|thaw|email|verify|revoke|dots|deactivate|reactivate)$/) {
$cmd = $1;
}
else {
......@@ -350,6 +352,14 @@ SWITCH: for ($cmd) {
ThawUser();
last SWITCH;
};
/^deactivate$/ && do {
DeactivateUser();
last SWITCH;
};
/^reactivate$/ && do {
ReactivateUser();
last SWITCH;
};
/^revoke$/ && do {
RevokeUser();
last SWITCH;
......@@ -862,8 +872,8 @@ sub UpdateUser(;$)
# If doing a modification to a frozen user, then just ignore
# it; the modification will happen later when the user is thawed.
#
if ($status eq USERSTATUS_FROZEN) {
print "Ignoring update of frozen user $user\n";
if ($status eq USERSTATUS_FROZEN || $status eq USERSTATUS_INACTIVE) {
print "Ignoring update of frozen/inactive user $user\n";
return 0;
}
fatal("$user is not active! Cannot update the account!");
......@@ -1078,6 +1088,88 @@ sub ThawUser()
return 0;
}
#
# Deactivate a user.
#
sub DeactivateUser()
{
#
# Only admin people can do this.
#
if (! TBAdmin($UID)) {
fatal("You do not have permission to deactivate user $user.");
}
#
# Check status.
#
if ($status ne USERSTATUS_INACTIVE) {
fatal("$user is still active! Cannot deactivate the account!")
if (!$update);
$target_user->SetStatus(USERSTATUS_INACTIVE());
$status = USERSTATUS_INACTIVE();
}
#
# Shell goes to nologin on the CONTROL node.
#
$UID = 0;
if (system("$USERMOD $user -s $NOLOGIN")) {
fatal("Could not set shell to $NOLOGIN for $user on local node.");
}
if ($CONTROL ne $BOSSNODE) {
print "Deactivating user $user ($user_number) on $CONTROL\n";
if (system("$SSH -host $CONTROL '$ACCOUNTPROXY deactivateuser $user'")){
fatal("Could not deactivate $user on $CONTROL.");
}
}
$UID = $SAVEUID;
return 0;
}
#
# Reactivate a user.
#
sub ReactivateUser()
{
#
# Only admin people can do this.
#
if (! TBAdmin($UID)) {
fatal("You do not have permission to reactivate user $user.");
}
#
# Check status.
#
if ($status ne USERSTATUS_ACTIVE) {
fatal("$user is not active! Cannot reactivate the account!")
if (!$update);
$target_user->SetStatus(USERSTATUS_ACTIVE());
$status = USERSTATUS_ACTIVE();
}
$UID = 0;
if ($CONTROL ne $BOSSNODE) {
print "Reactivating user $user ($user_number) on $CONTROL\n";
if (system("$SSH -host $CONTROL '$ACCOUNTPROXY reactivateuser $user'")){
fatal("Could not reactivate $user on $CONTROL.");
}
}
$UID = $SAVEUID;
# Similar to freeze/thaw for our purposes.
UpdateUser(0) == 0
or fatal("Cannot reactivate $user");
#
# Invoke as real user for auditing.
#
$EUID = $UID;
system("$SETGROUPS $user");
$EUID = 0;
return 0;
}
#
# Verify a user. Converts status and sends email
#
......
......@@ -56,7 +56,7 @@ use vars qw(@ISA @EXPORT);
TB_USERINFO_READINFO TB_USERINFO_MODIFYINFO
TB_USERINFO_MIN TB_USERINFO_MAX
USERSTATUS_ACTIVE USERSTATUS_FROZEN
USERSTATUS_ACTIVE USERSTATUS_FROZEN USERSTATUS_INACTIVE
USERSTATUS_UNAPPROVED USERSTATUS_UNVERIFIED USERSTATUS_NEWUSER
USERSTATUS_ARCHIVED USERSTATUS_NONLOCAL
......@@ -310,6 +310,7 @@ sub USERSTATUS_UNVERIFIED() { "unverified"; }
sub USERSTATUS_NEWUSER() { "newuser"; }
sub USERSTATUS_ARCHIVED() { "archived"; }
sub USERSTATUS_NONLOCAL() { "nonlocal"; }
sub USERSTATUS_INACTIVE() { "inactive"; }
#
# We want valid project membership to be non-zero for easy membership
......
......@@ -266,6 +266,7 @@ endif
$(INSTALL_CVSWEBCGI)
$(INSTALL_OPSCVSWEBCONF)
$(INSTALL_OPSCVSWEBCGI)
cd $(OBJDIR) && gmake install-setbuildinfo
apt-install: $(addprefix $(INSTALL_WWWDIR)/apt/, $(ALLAPTUI)) \
$(addprefix $(INSTALL_WWWDIR)/apt/js/, $(ALLAPTJS)) \
......
......@@ -188,7 +188,7 @@ function Do_VerifySpeaksfor()
global $ajax_args;
global $TBDIR, $COOKDIEDOMAIN, $TBMAINSITE, $PROTOGENI_GENIWEBLOGIN;
global $TBAUTHCOOKIE, $TBLOGINCOOKIE, $TBAUTHTIMEOUT, $TBNAMECOOKIE;
global $OURDOMAIN;
global $OURDOMAIN, $TBMAILADDR;
$embedded = 0;
if (! ($TBMAINSITE || $PROTOGENI_GENIWEBLOGIN)) {
......@@ -340,6 +340,13 @@ function Do_VerifySpeaksfor()
TBDB_TRUSTSTRING_LOCALROOT);
}
}
if ($this_user->status() == TBDB_USERSTATUS_INACTIVE) {
SPITAJAX_ERROR(1, "Your account has gone inactive. Please ".
"contact $TBMAILADDR to have your ".
"account restored.");
session_destroy();
return;
}
}
}
list ($loginhash, $logincrc) =
......
......@@ -242,12 +242,28 @@ else {
sleep(1);
SPITHEADER();
echo "<h3>
echo "<h4>
Your account has been frozen due to earlier login attempt
failures. You must contact $TBMAILADDR to have your account
restored. <br> <br>
Please do not attempt to login again; it will not work!
</h3>\n";
</h4>\n";
echo "<script src='js/lib/jquery-2.0.3.min.js'></script>\n";
echo "<script src='js/lib/bootstrap.js'></script>\n";
echo "<script src='js/lib/require.js' data-main='js/main'></script>";
SPITFOOTER();
return;
}
else if ($dologin_status == DOLOGIN_STATUS_INACTIVE) {
# Short delay.
sleep(1);
SPITHEADER();
echo "<h4>
Your account has gone <b>inactive</b>. Please contact $TBMAILADDR
to have your account restored. <br> <br>
Please do not attempt to login again; it will not work!
</h4>\n";
echo "<script src='js/lib/jquery-2.0.3.min.js'></script>\n";
echo "<script src='js/lib/bootstrap.js'></script>\n";
echo "<script src='js/lib/require.js' data-main='js/main'></script>";
......
......@@ -77,6 +77,7 @@ define("TBDB_USERSTATUS_UNVERIFIED", "unverified");
define("TBDB_USERSTATUS_FROZEN", "frozen");
define("TBDB_USERSTATUS_ARCHIVED", "archived");
define("TBDB_USERSTATUS_NONLOCAL", "nonlocal");
define("TBDB_USERSTATUS_INACTIVE", "inactive");
#
# Type of new account.
......@@ -108,7 +109,7 @@ define("TBDB_TRUSTSTRING_GROUPROOT", "group_root");
define("TBDB_TRUSTSTRING_PROJROOT", "project_root");
#
# Map to new names
# Map to new names in the UI, the old ones are nonsensical.
#
$newTrustMap = array("none" => "none",
"user" => "user",
......
<?php
#
# Copyright (c) 2000-2014 University of Utah and the Flux Group.
# Copyright (c) 2000-2014, 2016 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -252,12 +252,25 @@ else {
sleep(1);
PAGEHEADER("Login", $view);
echo "<h3>
echo "<h4>
Your account has been frozen due to earlier login attempt
failures. You must contact $TBMAILADDR to have your account
restored. <br> <br>
Please do not attempt to login again; it will not work!
</h3>\n";
</h4>\n";
PAGEFOOTER($view);
die("");
}
else if ($dologin_status == DOLOGIN_STATUS_INACTIVE) {
# Short delay.
sleep(1);
PAGEHEADER("Login", $view);
echo "<h4>
Your account has gone <b>inactive</b>. Please contact $TBMAILADDR
to have your account restored. <br> <br>
Please do not attempt to login again; it will not work!
</h4>\n";
PAGEFOOTER($view);
die("");
}
......
......@@ -69,6 +69,7 @@ define("CHECKLOGIN_WIKIONLY", 0x0200000);
define("CHECKLOGIN_OPSGUY", 0x0400000); # Member of emulab-ops.
define("CHECKLOGIN_ISFOREIGN_ADMIN", 0x0800000); # Admin of another Emulab.
define("CHECKLOGIN_NONLOCAL", 0x1000000);
define("CHECKLOGIN_INACTIVE", 0x2000000);
#
# Constants for tracking possible login attacks.
......@@ -82,6 +83,7 @@ define("DOLOGIN_STATUS_OKAY", 0);
define("DOLOGIN_STATUS_ERROR", -1);
define("DOLOGIN_STATUS_IPFREEZE", -2);
define("DOLOGIN_STATUS_WEBFREEZE", -3);
define("DOLOGIN_STATUS_INACTIVE", -4);
# So we can redefine this in the APT pages.
$CHANGEPSWD_PAGE = "moduserinfo.php3";
......@@ -448,6 +450,8 @@ function LoginStatus() {
$CHECKLOGIN_STATUS |= CHECKLOGIN_UNVERIFIED;
if (strcmp($status, TBDB_USERSTATUS_ACTIVE) == 0)
$CHECKLOGIN_STATUS |= CHECKLOGIN_ACTIVE;
if (strcmp($status, TBDB_USERSTATUS_INACTIVE) == 0)
$CHECKLOGIN_STATUS |= CHECKLOGIN_INACTIVE;
if (isset($wikiname) && $wikiname != "")
$CHECKLOGIN_WIKINAME = $wikiname;
if ($opsguy)
......@@ -572,7 +576,7 @@ function LOGGEDINORDIE($uid, $modifier = 0, $login_url = NULL) {
#
function CheckLoginConditions($status)
{
global $CHANGEPSWD_PAGE;
global $CHANGEPSWD_PAGE, $TBMAILADDR;
if ($status & CHECKLOGIN_PSWDEXPIRED)
USERERROR("Your password has expired. ".
......@@ -581,6 +585,10 @@ function CheckLoginConditions($status)
if ($status & CHECKLOGIN_FROZEN)
USERERROR("Your account has been frozen!",
1, HTTP_403_FORBIDDEN);
if ($status & CHECKLOGIN_INACTIVE)
USERERROR("Your account has gone inactive. ".
"Please contact $TBMAILADDR to restore it.",
1, HTTP_403_FORBIDDEN);
if ($status & (CHECKLOGIN_UNVERIFIED|CHECKLOGIN_NEWUSER))
USERERROR("You have not verified your account yet!",
1, HTTP_403_FORBIDDEN);
......@@ -883,6 +891,10 @@ function DOLOGIN($token, $password, $adminmode = 0, $nopassword = 0) {
$user->UpdateWebLoginFail();
return DOLOGIN_STATUS_WEBFREEZE;
}
# inactive users need special handling for now.
if ($user->status() == TBDB_USERSTATUS_INACTIVE) {
return DOLOGIN_STATUS_INACTIVE;
}
if (!$nopassword) {
$encoding = crypt("$password", $db_encoding);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment