$cryptdata, "ts" => $ts);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn readAuthCookie()
///
/// \return on success, userid of user in VCLAUTH cookie in user@affil form;
/// NULL on failure
///
/// \brief parses the VCLAUTH cookie to get the contained userid; also checks
/// that the contained remoteIP matches the current remoteIP and that the cookie
/// has not expired
///
////////////////////////////////////////////////////////////////////////////////
function readAuthCookie() {
global $keys, $AUTHERROR, $shibauthed;
if(get_magic_quotes_gpc())
$cookie = stripslashes($_COOKIE["VCLAUTH"]);
else
$cookie = $_COOKIE["VCLAUTH"];
$cookie = base64_decode($cookie);
if(! openssl_public_decrypt($cookie, $tmp, $keys['public'])) {
$AUTHERROR["code"] = 3;
$AUTHERROR["message"] = "Failed to decrypt auth cookie";
return NULL;
}
$tmparr = explode('|', $tmp);
$loginid = $tmparr[0];
$remoteIP = $tmparr[1];
$ts = $tmparr[2];
if(count($tmparr) > 3) {
$shibauthed = $tmparr[3];
# check to see if shibauth entry still exists for $shibauthed
$query = "SELECT ts FROM shibauth WHERE id = $shibauthed";
$qh = doQuery($query, 101);
if($row = mysql_fetch_assoc($qh)) {
$shibstart = $row['ts'];
# TODO if $shibstart is too old, expire the login session
}
else {
# user should have been logged out, log them out now
setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN);
stopSession();
dbDisconnect();
header("Location: " . BASEURL);
exit;
}
}
if($ts < time()) {
$AUTHERROR["code"] = 4;
$AUTHERROR["message"] = "Auth cookie has expired";
return NULL;
}
if($_SERVER["REMOTE_ADDR"] != $remoteIP) {
//setcookie("ITECSAUTH", "", time() - 10, "/", COOKIEDOMAIN);
$AUTHERROR["code"] = 4;
$AUTHERROR["message"] = "remote IP in auth cookie doesn't match user's remote IP";
return NULL;
}
return $loginid;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn selectAuth()
///
/// \brief prints a page for the user to select the authentication method to use
///
////////////////////////////////////////////////////////////////////////////////
function selectAuth() {
global $HTMLheader, $printedHTMLheader, $authMechs, $skin;
$authtype = getContinuationVar('authtype', processInputVar("authtype", ARG_STRING));
if($authtype == '' && array_key_exists('VCLAUTHSEL', $_COOKIE))
$authtype = $_COOKIE['VCLAUTHSEL'];
if(array_key_exists('clearselection', $_GET) && $_GET['clearselection'] == 1) {
setcookie("VCLAUTHSEL", '', time() - 10, "/", COOKIEDOMAIN);
unset($authtype);
}
if(array_key_exists($authtype, $authMechs)) {
if(array_key_exists('remsel', $_POST) && $_POST['remsel'] == 1)
setcookie("VCLAUTHSEL", $authtype, time() + SECINYEAR, "/", COOKIEDOMAIN);
if($authMechs[$authtype]['type'] == 'redirect') {
header("Location: {$authMechs[$authtype]['URL']}");
dbDisconnect();
exit;
}
elseif($authMechs[$authtype]['type'] == 'ldap' ||
$authMechs[$authtype]['type'] == 'local') {
printLoginPageWithSkin($authtype);
return;
}
}
require_once("themes/$skin/page.php");
$HTMLheader = getHeader(0);
print $HTMLheader;
$printedHTMLheader = 1;
print _("
Welcome to the Virtual Computing Lab
\n");
print "\n";
print "\n";
print "\n";
print _("Please select an authentication method to use:
\n");
if(strlen($authtype))
print _("Selected method failed, please try again \n");
foreach(array_keys($authMechs) as $mech)
$methods["$mech"] = $mech;
print "\n";
print " | \n";
print "\n";
print _("Explanation of authentication methods:\n");
print "\n";
foreach($authMechs as $mech)
print "- {$mech['help']}
\n";
print " \n";
print " | \n";
print "
\n";
print "
\n";
print getFooter();
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn printLoginPageWithSkin($authtype, $servertimeout)
///
/// \param $authtype - and authentication type
/// \param $servertimeout - (optional, default=0) - set to 1 if calling because
/// connection to authentication server timed out, 0 otherwise
///
/// \brief sets up the skin for the page correctly, then calls printLoginPage
///
////////////////////////////////////////////////////////////////////////////////
function printLoginPageWithSkin($authtype, $servertimeout=0) {
global $authMechs, $HTMLheader, $skin, $printedHTMLheader;
$skin = getAffiliationTheme($authMechs[$authtype]['affiliationid']);
require_once("themes/$skin/page.php");
$HTMLheader = getHeader(0);
printHTMLHeader();
print $HTMLheader;
$printedHTMLheader = 1;
printLoginPage($servertimeout);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn printLoginPage($servertimeout)
///
/// \param $servertimeout - (optional, default=0) - set to 1 if calling because
/// connection to authentication server timed out, 0 otherwise
///
/// \brief prints a page for a user to login
///
////////////////////////////////////////////////////////////////////////////////
function printLoginPage($servertimeout=0) {
global $authMechs, $skin, $user;
$user['id'] = 0;
$authtype = getContinuationVar("authtype", processInputVar("authtype", ARG_STRING));
if($authtype == '' && array_key_exists('VCLAUTHSEL', $_COOKIE))
$authtype = $_COOKIE['VCLAUTHSEL'];
if(isset($_GET['userid']))
unset($_GET['userid']);
$userid = processInputVar('userid', ARG_STRING, '');
if($userid == _('Proceed to Login'))
$userid = '';
if(! array_key_exists($authtype, $authMechs)) {
// FIXME - hackerish
dbDisconnect();
exit;
}
if(get_magic_quotes_gpc())
$userid = stripslashes($userid);
$userid = htmlspecialchars($userid);
$extrafailedmsg = '';
if($servertimeout)
$extrafailedmsg = _(" (unable to connect to authentication server)");
/*if($skin == 'example1') {
$useridLabel = 'Pirateid';
$passLabel = 'Passphrase';
$text1 = 'Login with your Pirate ID';
$text2 = "";
}
elseif($skin == 'example2') {
print "
";
print "\n";
print getFooter();
return;
}
else {*/
$useridLabel = _('Userid');
$passLabel = _('Password');
$text1 = _("Login with ") . "$authtype";
$text2 = "";
#}
print "$text1
\n";
print "\n";
print "$text2
\n";
print getFooter();
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn submitLogin()
///
/// \brief processes a login page submission
///
////////////////////////////////////////////////////////////////////////////////
function submitLogin() {
global $authMechs;
$authtype = getContinuationVar("authtype", processInputVar('authtype', ARG_STRING));
if(! array_key_exists($authtype, $authMechs)) {
// FIXME - hackerish
dbDisconnect();
exit;
}
if(isset($_GET['userid']))
unset($_GET['userid']);
$userid = processInputVar('userid', ARG_STRING, '');
$passwd = $_POST['password'];
if(empty($userid) || empty($passwd)) {
selectAuth();
return;
}
if(get_magic_quotes_gpc()) {
$userid = stripslashes($userid);
$passwd = stripslashes($passwd);
}
if($authMechs[$authtype]['type'] == 'ldap')
ldapLogin($authtype, $userid, $passwd);
elseif($authMechs[$authtype]['type'] == 'local')
localLogin($userid, $passwd);
else
selectAuth();
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn ldapLogin($authtype, $userid, $passwd)
///
/// \param $authtype - index from $authMechs array
/// \param $userid - userid without affiliation
/// \param $passwd - submitted password
///
/// \brief tries to authenticate user via ldap; calls printLoginPageWithSkin if
/// authentication fails
///
////////////////////////////////////////////////////////////////////////////////
function ldapLogin($authtype, $userid, $passwd) {
global $HTMLheader, $printedHTMLheader, $authMechs, $phpVer;
$esc_userid = mysql_real_escape_string($userid);
if(! $fh = fsockopen($authMechs[$authtype]['server'], 636, $errno, $errstr, 5)) {
printLoginPageWithSkin($authtype, 1);
return;
}
fclose($fh);
$ds = ldap_connect("ldaps://{$authMechs[$authtype]['server']}/");
if(! $ds) {
addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0);
print $HTMLheader;
$printedHTMLheader = 1;
selectAuth();
return;
}
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
if(array_key_exists('lookupuserbeforeauth', $authMechs[$authtype]) &&
$authMechs[$authtype]['lookupuserbeforeauth'] &&
array_key_exists('lookupuserfield', $authMechs[$authtype])) {
# in this case, we have to look up what part of the tree the user is in
# before we can actually look up the user
$auth = $authMechs[$authtype];
if(array_key_exists('masterlogin', $auth) && strlen($auth['masterlogin']))
$res = ldap_bind($ds, $auth['masterlogin'], $auth['masterpwd']);
else
$res = ldap_bind($ds);
if(! $res) {
addLoginLog($userid, $authtype, $auth['affiliationid'], 0);
printLoginPageWithSkin($authtype);
return;
}
$search = ldap_search($ds,
$auth['binddn'],
"{$auth['lookupuserfield']}=$userid",
array('dn'), 0, 3, 15);
if($search) {
$tmpdata = ldap_get_entries($ds, $search);
if(! $tmpdata['count'] || ! array_key_exists('dn', $tmpdata[0])) {
addLoginLog($userid, $authtype, $auth['affiliationid'], 0);
printLoginPageWithSkin($authtype);
return;
}
$ldapuser = $tmpdata[0]['dn'];
}
else {
addLoginLog($userid, $authtype, $auth['affiliationid'], 0);
printLoginPageWithSkin($authtype);
return;
}
}
else
$ldapuser = sprintf($authMechs[$authtype]['userid'], $userid);
$res = ldap_bind($ds, $ldapuser, $passwd);
if(! $res) {
// login failed
$err = ldap_error($ds);
if($err == 'Invalid credentials')
addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0, $err);
else
addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0);
printLoginPageWithSkin($authtype);
return;
}
else {
addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 1);
// see if user in our db
$query = "SELECT id "
. "FROM user "
. "WHERE unityid = '$esc_userid' AND "
. "affiliationid = {$authMechs[$authtype]['affiliationid']}";
$qh = doQuery($query, 101);
if(! mysql_num_rows($qh)) {
// if not, add user
$newid = updateLDAPUser($authtype, $userid);
if(is_null($newid))
abort(8);
}
// get cookie data
$cookie = getAuthCookieData("$userid@" . getAffiliationName($authMechs[$authtype]['affiliationid']));
// set cookie
if(version_compare(PHP_VERSION, "5.2", ">=") == true)
setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0, 1);
else
setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0);
# set skin cookie based on affiliation
$skin = getAffiliationTheme($authMechs[$authtype]['affiliationid']);
$ucskin = strtoupper($skin);
setcookie("VCLSKIN", "$ucskin", (time() + (SECINDAY * 31)), "/", COOKIEDOMAIN);
// redirect to main page
header("Location: " . BASEURL . SCRIPT);
dbDisconnect();
exit;
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn localLogin($userid, $passwd)
///
/// \param $userid - userid without affiliation
/// \param $passwd - submitted password
///
/// \brief tries to authenticate user locally; calls printLoginPageWithSkin if
/// authentication fails
///
////////////////////////////////////////////////////////////////////////////////
function localLogin($userid, $passwd) {
global $HTMLheader, $phpVer, $authMechs;
if(validateLocalAccount($userid, $passwd)) {
addLoginLog($userid, 'Local', $authMechs['Local Account']['affiliationid'], 1);
//set cookie
$cookie = getAuthCookieData("$userid@local");
if(version_compare(PHP_VERSION, "5.2", ">=") == true)
setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0, 1);
else
setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN);
//load main page
setcookie("VCLSKIN", "default", (time() + (SECINDAY * 31)), "/", COOKIEDOMAIN);
header("Location: " . BASEURL . SCRIPT);
dbDisconnect();
exit;
}
else {
addLoginLog($userid, 'Local', $authMechs['Local Account']['affiliationid'], 0);
printLoginPageWithSkin('Local Account');
printHTMLFooter();
dbDisconnect();
exit;
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn validateLocalAccount($user, $pass)
///
/// \param $user - unityid from user table
/// \param $pass - user's password
///
/// \return 1 if account exists in localauth table, 0 if it does not
///
/// \brief checks to see if $user has an entry in the localauth table
///
////////////////////////////////////////////////////////////////////////////////
function validateLocalAccount($user, $pass) {
$user = mysql_real_escape_string($user);
$query = "SELECT l.salt "
. "FROM localauth l, "
. "user u, "
. "affiliation a "
. "WHERE u.unityid = '$user' AND "
. "u.affiliationid = a.id AND "
. "a.name = 'Local' AND "
. "l.userid = u.id";
$qh = doQuery($query, 101);
if(mysql_num_rows($qh) != 1 ||
(! ($row = mysql_fetch_assoc($qh))))
return 0;
$passhash = sha1("$pass{$row['salt']}");
$query = "SELECT u.id "
. "FROM user u, "
. "localauth l, "
. "affiliation a "
. "WHERE u.unityid = '$user' AND "
. "l.userid = u.id AND "
. "l.passhash = '$passhash' AND "
. "u.affiliationid = a.id AND "
. "a.name = 'Local'";
$qh = doQuery($query, 101);
if(mysql_num_rows($qh) == 1)
return 1;
else
return 0;
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn addLoginLog($login, $mech, $affiliationid, $passfail, $code)
///
/// \param $login - user id entered in login screen
/// \param $mech - authentication mechanism used
/// \param $affiliationid - affiliation id of authentication mechanism
/// \param $passfail - 1 for successful login, 0 for failed login
/// \param $code - (optional, default='none') additional code to save
///
/// \brief adds an entry to the loginlog table
///
////////////////////////////////////////////////////////////////////////////////
function addLoginLog($login, $mech, $affiliationid, $passfail, $code='none') {
$login = mysql_real_escape_string($login);
$mech = mysql_real_escape_string($mech);
$query = "INSERT INTO loginlog "
. "(user, "
. "authmech, "
. "affiliationid, "
. "passfail, "
. "remoteIP, "
. "code) "
. "VALUES "
. "('$login', "
. "'$mech', "
. "$affiliationid, "
. "$passfail, "
. "'{$_SERVER['REMOTE_ADDR']}', "
. "'$code')";
doQuery($query, 101);
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn checkExpiredDemoUser($userid, $groups)
///
/// \param $userid - id from user table
/// \param $groups - (optional) array of user's groups as returned by
/// getUsersGroups
///
/// \brief checks to see if user is only in demo group and if so check to see
/// if it has been 3 days since start of first reservation or if user has made
/// 3 reservations; if so, moves user to nodemo group
///
////////////////////////////////////////////////////////////////////////////////
function checkExpiredDemoUser($userid, $groups=0) {
global $mode, $skin, $noHTMLwrappers;
if($groups == 0)
$groups = getUsersGroups($userid, 1);
if(count($groups) != 1)
return;
$tmp = array_values($groups);
if($tmp[0] != 'demo')
return;
$query = "SELECT start "
. "FROM log "
. "WHERE userid = $userid "
. "AND finalend < NOW() "
. "ORDER BY start "
. "LIMIT 3";
$qh = doQuery($query, 101);
$expire = time() - (SECINDAY * 3);
$rows = mysql_num_rows($qh);
if($row = mysql_fetch_assoc($qh)) {
if($rows >= 3 || datetimeToUnix($row['start']) < $expire) {
if(in_array($mode, $noHTMLwrappers))
# do a redirect and handle removal on next page load so user can
# be notified - doesn't always work, but handles a few extra
# cases
header("Location: " . BASEURL . SCRIPT);
else {
$nodemoid = getUserGroupID('nodemo', getAffiliationID('ITECS'));
$query = "DELETE FROM usergroupmembers " # have to do the delete here
. "WHERE userid = $userid"; # because updateGroups doesn't
# delete from custom groups
doQuery($query, 101);
updateGroups(array($nodemoid), $userid);
checkUpdateServerRequestGroups($groupid);
if(empty($skin)) {
$skin = 'default';
require_once("themes/$skin/page.php");
}
$mode = 'expiredemouser';
printHTMLHeader();
print "Account Expired
\n";
print "The account you are using is a demo account that has now expired. ";
print "You cannot make any more reservations. Please contact " . HELPEMAIL . " if you need ";
print "further access to VCL.
\n";
}
semUnlock();
printHTMLFooter();
dbDisconnect();
exit;
}
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// \fn testGeneralAffiliation(&$login, &$affilid)
///
/// \param $login - (pass by ref) a login id with affiliation
/// \param $affilid - (pass by ref) gets overwritten
///
/// \return - 1 if successfully found known affiliation id in $login, 0 if
/// failed, -1 if found an unknown affilation in $login
///
/// \brief changes $login to be without affiliation and sticks the associated
/// affiliation id in $affilid
///
////////////////////////////////////////////////////////////////////////////////
function testGeneralAffiliation(&$login, &$affilid) {
if(preg_match('/^([^@]+)@([^@\.]*)$/', $login, $matches)) {
$login = $matches[1];
$affilid = getAffiliationID($matches[2]);
if(is_null($affilid))
return -1;
return 1;
}
return 0;
}
?>