Commit 3e2bb386 authored by Leigh Stoller's avatar Leigh Stoller

More inventive ways to avoid real work; add password expiration

capability. New DB field in the users table (pswd_expires) which is a
date field that initially gets set to one year after the user account
is created. When the password is changed via the web form, it gets
bumped 1 more year into the future *unless* the current uid is
different from the target_uid (ie: you are changing a password for
someone else). In that case, the expiration is set to the current
date, which forces the target user to change his password next time he
logs in. I've changed the menu/auth code to look for password
expiration, and when expired the menu options contain just a single
option to change the password. All other https pages will fail with a
password expired message. Normal text pages will work of course.
parent a1dc57a9
......@@ -14,9 +14,8 @@ $uid = GETLOGIN();
# personal information for some random ?uid argument.
#
if ($uid) {
if (CHECKLOGIN($uid) != 1) {
USERERROR("You are not logged in. Please log in and try again.", 1);
}
LOGGEDINORDIE($uid);
$query_result = mysql_db_query($TBDBNAME,
"SELECT * FROM users WHERE uid='$uid'");
if (! $query_result) {
......
......@@ -980,11 +980,8 @@ function DBFatal($message)
DBWarn($message);
echo "<p><p>
Unexpected Error. Could not continue. Please contact $TBMAILADDR\n";
PAGEFOOTER();
die("");
PAGEERROR("<p><p>".
"Unexpected Error. Could not continue. ".
"Please contact $TBMAILADDR\n");
}
?>
......@@ -77,16 +77,14 @@ function TBERROR ($message, $death) {
sleep(1);
if ($death) {
echo "<h3><br><br>
$message
<br>
</h3>";
echo "<p><p>
Could not continue. Please contact $TBMAILADDR\n";
PAGEFOOTER();
die("");
$msg = "<h3><br><br>
$message
<br>
</h3>
<p><p>
Could not continue. Please contact $TBMAILADDR\n";
PAGEERROR($msg);
}
return 0;
}
......@@ -97,18 +95,18 @@ function TBERROR ($message, $death) {
function USERERROR($message, $death) {
global $TBMAILADDR;
echo "<h3><br><br>
$message
<br>
</h3>";
echo "<p><p>
Please contact $TBMAILADDR if you feel this message is an error.";
$msg = "<h3><br><br>
$message
<br>
</h3>
<p><p>
Please contact $TBMAILADDR if you feel this message is an error.";
if ($death) {
PAGEFOOTER();
die("");
PAGEERROR($msg);
}
else
echo "$msg\n";
}
#
......
......@@ -7,9 +7,11 @@ $STATUS_LOGINFAIL = 3;
$STATUS_TIMEDOUT = 4;
$STATUS_NOLOGINS = 5;
$login_status = $STATUS_NOSTATUS;
$pswd_expired = 0;
$login_message = "";
$error_message = 0;
$login_uid = 0;
$drewheader = 0;
$javacode = file("java.html");
#
......@@ -50,7 +52,7 @@ function WRITESIDEBAR() {
global $login_status, $login_message, $error_message, $login_uid;
global $STATUS_NOSTATUS, $STATUS_LOGGEDIN, $STATUS_LOGGEDOUT;
global $STATUS_LOGINFAIL, $STATUS_TIMEDOUT, $STATUS_NOLOGINS;
global $TBBASE, $TBDOCBASE, $TBDBNAME, $BASEPATH;
global $TBBASE, $TBDOCBASE, $TBDBNAME, $BASEPATH, $pswd_expired;
#
# The document base cannot be a mix of secure and nonsecure.
......@@ -94,12 +96,12 @@ function WRITESIDEBAR() {
</tr>\n";
}
elseif ($login_status == $STATUS_LOGGEDIN) {
$query_result = mysql_db_query($TBDBNAME,
"SELECT status,admin,stud FROM users WHERE uid='$login_uid'");
$query_result =
DBQueryFatal("SELECT status,admin ".
"FROM users WHERE uid='$login_uid'");
$row = mysql_fetch_row($query_result);
$status = $row[0];
$admin = $row[1];
$stud = $row[2];
#
# See if group_root in any projects, not just the last one in the DB!
......@@ -115,7 +117,11 @@ function WRITESIDEBAR() {
$trusted = 0;
}
if ($status == "active") {
if ($status == "active" && $pswd_expired) {
WRITESIDEBARBUTTON("Change your Password",
$TBBASE, "modusr_form.php3");
}
elseif ($status == "active") {
if ($admin) {
WRITESIDEBARBUTTON("New Project Approval",
$TBBASE, "approveproject_list.php3");
......@@ -174,6 +180,8 @@ function WRITESIDEBAR() {
switch ($login_status) {
case $STATUS_LOGGEDIN:
$login_message = "$login_uid Logged In";
if ($pswd_expired)
$login_message = "$login_message<br>(Password Expired!)";
break;
case $STATUS_LOGGEDOUT:
$login_message = "Logged Out";
......@@ -326,7 +334,10 @@ function PAGEHEADER($title) {
global $TBBASE, $TBDOCBASE, $TBDBNAME;
global $CHECKLOGIN_NOTLOGGEDIN, $CHECKLOGIN_LOGGEDIN;
global $CHECKLOGIN_TIMEDOUT, $CHECKLOGIN_MAYBEVALID;
global $BASEPATH, $SSL_PROTOCOL, $javacode;
global $CHECKLOGIN_PSWDEXPIRED;
global $BASEPATH, $SSL_PROTOCOL, $javacode, $drewheader, $pswd_expired;
$drewheader = 1;
#
# Determine the proper basepath, which depends on whether the page
......@@ -357,6 +368,8 @@ function PAGEHEADER($title) {
$login_status = $STATUS_NOSTATUS;
$login_uid = 0;
break;
case $CHECKLOGIN_PSWDEXPIRED:
$pswd_expired = 1;
case $CHECKLOGIN_LOGGEDIN:
case $CHECKLOGIN_MAYBEVALID:
$login_status = $STATUS_LOGGEDIN;
......@@ -493,4 +506,16 @@ function PAGEFOOTER() {
</body>
</html>\n";
}
function PAGEERROR($msg) {
global $drewheader;
if (! $drewheader)
PAGEHEADER("");
echo "$msg\n";
PAGEFOOTER();
die("");
}
?>
......@@ -9,8 +9,11 @@ PAGEHEADER("Modify User Information Form");
#
# Only known and logged in users can modify info.
#
# Note different test though, since we want to allow logged in
# users with expired passwords to change them.
#
$uid = GETLOGIN();
LOGGEDINORDIE($uid);
LOGGEDINORDIE_SPECIAL($uid);
$isadmin = ISADMIN($uid);
#
......
......@@ -5,15 +5,17 @@ include("showstuff.php3");
$changed_password = "No";
#
# Standard Testbed Header
# Hold off drawing header until later!
#
PAGEHEADER("Modify User Information");
#
# Only known and logged in users can modify info.
#
# Note different test though, since we want to allow logged in
# users with expired passwords to change them.
#
$uid = GETLOGIN();
LOGGEDINORDIE($uid);
LOGGEDINORDIE_SPECIAL($uid);
#
# The target_uid comes in as a POST var. It must be set. We allow
......@@ -111,7 +113,8 @@ VERIFYURL($usr_url);
# checks to make sure the two fields agree and that it passes our tests for
# safe passwords.
#
if (isset($new_password1) && strcmp($new_password2, "")) {
if ((isset($new_password1) && strcmp($new_password1, "")) ||
(isset($new_password2) && strcmp($new_password2, ""))) {
if (strcmp($new_password1, $new_password2)) {
USERERROR("You typed different passwords in each of the two password ".
"entry fields. <br> Please go back and correct them.", 1);
......@@ -137,17 +140,26 @@ if (isset($new_password1) && strcmp($new_password2, "")) {
# Password is good. Insert into database.
#
$encoding = crypt("$new_password1");
$insert_result = mysql_db_query($TBDBNAME,
"UPDATE users SET usr_pswd=\"$encoding\" ".
"WHERE uid=\"$target_uid\"");
if ($uid != $target_uid)
$expires = "now()";
else
$expires = "date_add(now(), interval 1 year)";
$insert_result =
DBQueryFatal("UPDATE users SET usr_pswd='$encoding', ".
"pswd_expires=$expires ".
"WHERE uid='$target_uid'");
if (! $insert_result) {
$err = mysql_error();
TBERROR("Database Error changing password for $target_uid: $err", 1);
}
$changed_password = "Yes";
}
#
# Okay, draw the header now that the password has been changed.
# This is a convenience to avoid asking the user to refresh after
# an expired password.
#
PAGEHEADER("Modify User Information");
#
# Add slashes. These should really be ereg checks, kicking back special
# chars since they are more trouble then they are worth.
......@@ -161,20 +173,15 @@ $usr_phone = addslashes($usr_phone);
#
# Now change the rest of the information.
#
$insert_result = mysql_db_query($TBDBNAME,
"UPDATE users SET ".
"usr_name=\"$usr_name\", ".
"usr_URL=\"$usr_url\", ".
"usr_addr=\"$usr_addr\", ".
"usr_phone=\"$usr_phone\", ".
"usr_title=\"$usr_title\", ".
"usr_affil=\"$usr_affil\" ".
"WHERE uid=\"$target_uid\"");
if (! $insert_result) {
$err = mysql_error();
TBERROR("Database Error changing user info for $target_uid: $err", 1);
}
$insert_result =
DBQueryFatal("UPDATE users SET ".
"usr_name=\"$usr_name\", ".
"usr_URL=\"$usr_url\", ".
"usr_addr=\"$usr_addr\", ".
"usr_phone=\"$usr_phone\", ".
"usr_title=\"$usr_title\", ".
"usr_affil=\"$usr_affil\" ".
"WHERE uid=\"$target_uid\"");
#
# Audit
......
......@@ -253,10 +253,12 @@ if (! $returning) {
$newuser_command = "INSERT INTO users ".
"(uid,usr_created,usr_expires,usr_name,usr_email,usr_addr,".
"usr_URL,usr_title,usr_affil,usr_phone,usr_pswd,unix_uid,status) ".
" usr_URL,usr_title,usr_affil,usr_phone,usr_pswd,unix_uid,".
" status,pswd_expires) ".
"VALUES ('$proj_head_uid', now(), '$proj_expires', '$usr_name', ".
"'$usr_email', '$usr_addr', '$usr_url', '$usr_title', '$usr_affil', ".
"'$usr_phones', '$encoding', NULL, 'newuser')";
"'$usr_phones', '$encoding', NULL, 'newuser', ".
"date_add(now(), interval 1 year))";
DBQueryFatal($newuser_command);
......
......@@ -14,9 +14,8 @@ $uid = GETLOGIN();
# personal information for some random ?uid argument.
#
if ($uid) {
if (CHECKLOGIN($uid) != 1) {
USERERROR("You are not logged in. Please log in and try again.", 1);
}
LOGGEDINORDIE($uid);
$query_result = mysql_db_query($TBDBNAME,
"SELECT * FROM users WHERE uid=\"$uid\"");
if (! $query_result) {
......
......@@ -7,6 +7,7 @@ $CHECKLOGIN_NOTLOGGEDIN = 0;
$CHECKLOGIN_LOGGEDIN = 1;
$CHECKLOGIN_TIMEDOUT = -1;
$CHECKLOGIN_MAYBEVALID = 2;
$CHECKLOGIN_PSWDEXPIRED = 3;
#
# Generate a hash value suitable for authorization. We use the results of
......@@ -31,12 +32,15 @@ function GENHASH() {
# logged in.
#
function GETLOGIN() {
global $CHECKLOGIN_LOGGEDIN;
global $CHECKLOGIN_LOGGEDIN, $CHECKLOGIN_PSWDEXPIRED;
if (($uid = GETUID()) == FALSE)
return FALSE;
if (CHECKLOGIN($uid) == $CHECKLOGIN_LOGGEDIN)
$check = CHECKLOGIN($uid);
if ($check == $CHECKLOGIN_LOGGEDIN ||
$check == $CHECKLOGIN_PSWDEXPIRED)
return $uid;
return FALSE;
......@@ -68,28 +72,36 @@ function GETUID() {
# if login record exists, is not timed out, but no hash cookie.
# this case will be caught later when the user tries to do
# something for which a valid login is required.
# if logged in okay but password is expired.
#
function CHECKLOGIN($uid) {
global $TBDBNAME, $TBAUTHCOOKIE, $HTTP_COOKIE_VARS, $TBAUTHTIMEOUT;
global $CHECKLOGIN_NOTLOGGEDIN, $CHECKLOGIN_LOGGEDIN;
global $CHECKLOGIN_TIMEDOUT, $CHECKLOGIN_MAYBEVALID;
global $CHECKLOGIN_PSWDEXPIRED;
$curhash = $HTTP_COOKIE_VARS[$TBAUTHCOOKIE];
$query_result = mysql_db_query($TBDBNAME,
"SELECT hashkey, timeout FROM login WHERE uid=\"$uid\"");
if (! $query_result) {
$err = mysql_error();
TBERROR("Database Error retrieving login info for $uid: $err\n", 1);
}
$query_result =
DBQueryFatal("select NOW()>=u.pswd_expires,l.hashkey,l.timeout ".
" from users as u ".
"left join login as l on l.uid=u.uid ".
"where u.uid='$uid'");
# Not logged in.
if (($row = mysql_fetch_array($query_result)) == 0) {
# No such user.
if (($row = mysql_fetch_row($query_result)) == 0) {
return $CHECKLOGIN_NOTLOGGEDIN;
}
$hashkey = $row[hashkey];
$timeout = $row[timeout];
$expired = $row[0];
$hashkey = $row[1];
$timeout = $row[2];
#
# If user exists, but login has no entry, quit now.
#
if (!$hashkey)
return $CHECKLOGIN_NOTLOGGEDIN;
# A match?
if ($timeout > time()) {
......@@ -101,34 +113,32 @@ function CHECKLOGIN($uid) {
#
$timeout = time() + $TBAUTHTIMEOUT;
$query_result = mysql_db_query($TBDBNAME,
"UPDATE login set timeout='$timeout' ".
"WHERE uid=\"$uid\"");
if (! $query_result) {
$err = mysql_error();
TBERROR("Database Error updating login timeout for ".
"$uid: $err", 1);
}
return $CHECKLOGIN_LOGGEDIN;
$query_result =
DBQueryFatal("UPDATE login set timeout='$timeout' ".
"WHERE uid='$uid'");
if ($expired)
return $CHECKLOGIN_PSWDEXPIRED;
else
return $CHECKLOGIN_LOGGEDIN;
}
elseif (!isset($curhash) || !$curhash || $curhash == NULL) {
#
# A login is valid, but we have no proof yet. Proof will be
# demanded later by whatever page wants it.
#
return $CHECKLOGIN_MAYBEVALID;
if ($expired)
return $CHECKLOGIN_PSWDEXPIRED;
else
return $CHECKLOGIN_MAYBEVALID;
}
}
#
# Clear out the database entry for completeness.
#
$query_result = mysql_db_query($TBDBNAME,
"DELETE FROM login WHERE uid=\"$uid\"");
if (! $query_result) {
$err = mysql_error();
TBERROR("Database Error deleting login info for $uid: $err\n", 1);
}
$query_result =
DBQueryFatal("DELETE FROM login WHERE uid='$uid'");
return $CHECKLOGIN_TIMEDOUT;
}
......@@ -140,6 +150,36 @@ function CHECKLOGIN($uid) {
function LOGGEDINORDIE($uid) {
global $CHECKLOGIN_NOTLOGGEDIN, $CHECKLOGIN_LOGGEDIN;
global $CHECKLOGIN_TIMEDOUT, $CHECKLOGIN_MAYBEVALID;
global $CHECKLOGIN_PSWDEXPIRED;
$status = CHECKLOGIN($uid);
switch ($status) {
case $CHECKLOGIN_NOTLOGGEDIN:
USERERROR("You do not appear to be logged in!", 1);
break;
case $CHECKLOGIN_LOGGEDIN:
return $uid;
break;
case $CHECKLOGIN_TIMEDOUT:
USERERROR("Your login has timed out! Please log in again.", 1);
break;
case $CHECKLOGIN_MAYBEVALID:
USERERROR("Your login cannot be verified. Are cookies turned on?", 1);
break;
case $CHECKLOGIN_PSWDEXPIRED:
USERERROR("Your password has expired. Please change it now!", 1);
break;
}
TBERROR("LOGGEDINORDIE failed mysteriously", 1);
}
#
# Special function for changing passwords.
#
function LOGGEDINORDIE_SPECIAL($uid) {
global $CHECKLOGIN_NOTLOGGEDIN, $CHECKLOGIN_LOGGEDIN;
global $CHECKLOGIN_TIMEDOUT, $CHECKLOGIN_MAYBEVALID;
global $CHECKLOGIN_PSWDEXPIRED;
$status = CHECKLOGIN($uid);
switch ($status) {
......@@ -147,6 +187,7 @@ function LOGGEDINORDIE($uid) {
USERERROR("You do not appear to be logged in!", 1);
break;
case $CHECKLOGIN_LOGGEDIN:
case $CHECKLOGIN_PSWDEXPIRED:
return $uid;
break;
case $CHECKLOGIN_TIMEDOUT:
......
......@@ -205,11 +205,13 @@ if (! $returning) {
$newuser_command = "INSERT INTO users ".
"(uid,usr_created,usr_expires,usr_name,usr_email,usr_addr,".
"usr_URL,usr_phone,usr_title,usr_affil,usr_pswd,unix_uid,status) ".
" usr_URL,usr_phone,usr_title,usr_affil,usr_pswd,unix_uid,".
" status,pswd_expires) ".
"VALUES ('$joining_uid', now(), '$usr_expires', '$usr_name', ".
"'$usr_email', ".
"'$usr_addr', '$usr_url', '$usr_phone', '$usr_title', '$usr_affil',".
"'$encoding', NULL, 'newuser')";
"'$usr_addr', '$usr_url', '$usr_phone', '$usr_title', '$usr_affil', ".
"'$encoding', NULL, 'newuser', ".
"date_add(now(), interval 1 year))";
$newuser_result = mysql_db_query($TBDBNAME, $newuser_command);
if (! $newuser_result) {
$err = mysql_error();
......
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