$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 "\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; $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"; 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; } 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; } ?>