$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"]; 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 "\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"; /*if($skin == 'example1') printSelectInput("authtype", $methods, 'EXAMPLE1 LDAP'); elseif($skin == 'example2') printSelectInput("authtype", $methods, 'EXAMPLE2 LDAP'); else*/ printSelectInput("authtype", $methods, -1, 0, 0, '', 'tabindex=1'); print "
\n"; print "\n"; print "
\n"; 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 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; switch(getAffiliationName($authMechs[$authtype]['affiliationid'])) { case 'EXAMPLE1': $skin = 'example1'; break; case 'EXAMPLE2': $skin = 'example2'; break; default: $skin = 'default'; break; } 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']; $userid = processInputVar('userid', ARG_STRING, ''); if($userid == 'Proceed to Login') $userid = ''; if(! array_key_exists($authtype, $authMechs)) { // FIXME - hackerish dbDisconnect(); exit; } $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"; if(strlen($userid)) print "Login failed $extrafailedmsg\n"; print "\n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print "
Key Account:
Password:
\n"; print "
\n"; print "

\n"; $cdata = array('authtype' => $authtype); $cont = addContinuationsEntry('submitLogin', $cdata); print " \n"; print "
\n"; print "

\n"; print "
\n"; print "
\n"; print getFooter(); return; } else {*/ $useridLabel = 'Userid'; $passLabel = 'Password'; $text1 = "Login with $authtype"; $text2 = ""; #} print "

$text1

\n"; print "
\n"; if(strlen($userid)) print "Login failed $extrafailedmsg\n"; print "\n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print " \n"; print "
$useridLabel:
$passLabel:
\n"; $cdata = array('authtype' => $authtype); $cont = addContinuationsEntry('submitLogin', $cdata); print "\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; } $userid = processInputVar('userid', ARG_STRING, ''); $passwd = $_POST['password']; if(empty($userid) || empty($passwd)) { selectAuth(); return; } if(get_magic_quotes_gpc()) $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; 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($authtype == 'EXAMPLE1 LDAP') { # 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]; $res = ldap_bind($ds, $auth['masterlogin'], $auth['masterpwd']); if(! $res) { addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0); printLoginPageWithSkin($authtype); return; } $search = ldap_search($ds, $auth['binddn'], "cn=$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, $authMechs[$authtype]['affiliationid'], 0); printLoginPageWithSkin($authtype); return; } $ldapuser = $tmpdata[0]['dn']; } else { addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0); printLoginPageWithSkin($authtype); return; } } elseif($authtype == 'EXAMPLE2 LDAP') { # this is similar to EXAMPLE1, but here we do an anonymous bind $auth = $authMechs[$authtype]; $res = ldap_bind($ds); if(! $res) { addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0); printLoginPageWithSkin($authtype); return; } $search = ldap_search($ds, $auth['binddn'], "uid=$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, $authMechs[$authtype]['affiliationid'], 0); printLoginPageWithSkin($authtype); return; } $ldapuser = $tmpdata[0]['dn']; } else { addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 0); printLoginPageWithSkin($authtype); return; } } else*/ $ldapuser = sprintf($authMechs[$authtype]['userid'], $userid); $res = ldap_bind($ds, $ldapuser, $passwd); if(! $res) { // login failed 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 = '$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 /*if(getAffiliationName($authMechs[$authtype]['affiliationid']) == 'EXAMPLE1') setcookie("VCLSKIN", "EXAMPLE1", (time() + (SECINDAY * 31)), "/", COOKIEDOMAIN); elseif(getAffiliationName($authMechs[$authtype]['affiliationid']) == 'EXAMPLE2') setcookie("VCLSKIN", "EXAMPLE2", (time() + (SECINDAY * 31)), "/", COOKIEDOMAIN); else*/ setcookie("VCLSKIN", "DEFAULT", (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) { $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) /// /// \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 /// /// \brief adds an entry to the loginlog table /// //////////////////////////////////////////////////////////////////////////////// function addLoginLog($login, $mech, $affiliationid, $passfail) { $query = "INSERT INTO loginlog " . "(user, " . "authmech, " . "affiliationid, " . "passfail, " . "remoteIP) " . "VALUES " . "('$login', " . "'$mech', " . "$affiliationid, " . "$passfail, " . "'{$_SERVER['REMOTE_ADDR']}')"; 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); 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; } ?>