This is an automated email from the ASF dual-hosted git repository. jfthomps pushed a commit to branch VCL-1086_modular_web_authentication in repository https://gitbox.apache.org/repos/asf/vcl.git
commit aeb81d143d3ed20103c35962db614e9422d7e6ba Author: Josh Thompson <jftho...@ncsu.edu> AuthorDate: Fri Apr 19 16:12:50 2019 -0400 VCL-1086 - improve modularization of authentication authentication.php: -added $authFuncs['local'] array to top of file -modified getAuthCookieData: changed argument list from ($loginid, $valid) to ($loginid, $authtype, $valid, $shibauthid); added $authtype to data that is encrypted as 4th item -modified readAuthCookie: added more checks for cookie being invalid - if invalid, clear VCLAUTH cookie so user will be redirected back to login screen; decrypt encrypted data based on new number of parameters -added getAuthTypeFromAuthCookie -moved ldapLogin to authmethods/ldapauth.php -modified localLogin: added 'local' as 2nd argument when calling getAuthCookieData -added unauthLocal itecsauth.php: -added $authFuncs['itecs'] array to top of file -added testITECSAuth -added processITECSAuth -added unauthITECS ldapauth.php: -added $authFuncs['ldap'] array to top of file -added unauthLDAP -moved ldapLogin from authentication.php to here shibauth.php: -moved login code from vcl/shibauth/index.php to here -moved logout code from utils.php to here -added $authFuncs['shibboleth'] array to top of file -added testShibAuth -added processShibAuth (mostly stuff from shibauth/index.php) -added unauthShib (contains stuff from utils.php logout) -added getShibauthDataByUser -modified updateShibUser: utilize getShibVar to process data passed in from Shibboleth -modified updateShibGroups: added additional attempt to get id from affiliation table to use a wildcard with $shibaffil if first attempt fails -added getShibVar conf-default.php: removed "shibauth/" from example URL for Shibboleth authentication utils.php: modified sendHeaders: moved shibboleth logout code to shibauth.php and updated to use $authFuncs array and $authtype from getAuthTypeFromCookie to call correct logout functions shibauth/index.php: -moved code to authmethods/shibauth.php -replaced everything with a simple redirect to the main index page; this script no longer needs to be called - IdP's can redirect straight back to the main index page now --- web/.ht-inc/authentication.php | 249 +++++++++++-------------- web/.ht-inc/authmethods/itecsauth.php | 73 ++++++++ web/.ht-inc/authmethods/ldapauth.php | 137 ++++++++++++++ web/.ht-inc/authmethods/shibauth.php | 340 ++++++++++++++++++++++++++++++++-- web/.ht-inc/conf-default.php | 2 +- web/.ht-inc/utils.php | 96 +++------- web/shibauth/index.php | 263 +------------------------- 7 files changed, 669 insertions(+), 491 deletions(-) diff --git a/web/.ht-inc/authentication.php b/web/.ht-inc/authentication.php index 7a93cc0..cb72534 100644 --- a/web/.ht-inc/authentication.php +++ b/web/.ht-inc/authentication.php @@ -19,13 +19,21 @@ /** * \file */ + +$authFuncs['local'] = array('test' => function() {return 0;}, + 'auth' => function() {return NULL;}, + 'unauth' => 'unauthLocal'); + //////////////////////////////////////////////////////////////////////////////// /// -/// \fn getAuthCookieData($loginid, $valid) +/// \fn getAuthCookieData($loginid, $authtype, $valid, $shibauthid) /// /// \param $loginid - login id for user +/// \param $authtype - type of authentication used; should be an index from the +/// global $authFuncs array /// \param $valid - (optional, default=600) - time in minutes the cookie /// should be valid +/// \param $shibauthid - (optional) id of shibboleth session /// /// \return on failure, an error message; on success, an array with 2 elements:\n /// data - encrypted payload for auth cookie\n @@ -35,16 +43,16 @@ /// a timestamp /// //////////////////////////////////////////////////////////////////////////////// -function getAuthCookieData($loginid, $valid=600, $shibauthid=0) { +function getAuthCookieData($loginid, $authtype, $valid=600, $shibauthid=0) { global $keys; $ts = time() + ($valid * 60); $remoteIP = $_SERVER["REMOTE_ADDR"]; if(empty($remoteIP)) return "Failed to obtain remote IP address for fixed cookie type"; if($shibauthid) - $cdata = "$loginid|$remoteIP|$ts|$shibauthid"; + $cdata = "$loginid|$remoteIP|$ts|$authtype|$shibauthid"; else - $cdata = "$loginid|$remoteIP|$ts"; + $cdata = "$loginid|$remoteIP|$ts|$authtype"; # 245 characters can be encrypted; anything over that, and # openssl_private_encrypt will fail @@ -75,19 +83,32 @@ function readAuthCookie() { 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; - } + if(! openssl_public_decrypt($cookie, $tmp, $keys['public'])) { + # cookie is invalid; clear it and return NULL so will get redirected to log in again + setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN); + $AUTHERROR["code"] = 3; + $AUTHERROR["message"] = "Failed to decrypt auth cookie"; + return NULL; + } - $tmparr = explode('|', $tmp); + # $loginid|$remoteIP|$ts|$authtype|$shibauthid (shibauthd optional) + $tmparr = explode('|', $tmp); $loginid = $tmparr[0]; $remoteIP = $tmparr[1]; $ts = $tmparr[2]; - if(count($tmparr) > 3) { - $shibauthed = $tmparr[3]; - + + # check for old style auth cookie before $authtype was included + if(count($tmparr) < 4 || is_numeric($tmparr[3])) { + # log user out to get new style auth cookie + setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN); + stopSession(); + dbDisconnect(); + header("Location: " . BASEURL); + exit; + } + if(count($tmparr) > 4) { + $shibauthed = $tmparr[5]; + # check to see if shibauth entry still exists for $shibauthed $query = "SELECT ts FROM shibauth WHERE id = $shibauthed"; $qh = doQuery($query, 101); @@ -105,19 +126,61 @@ function readAuthCookie() { } } - 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; + if($ts < time()) { + # cookie is expired; clear it and return NULL so will get redirected to log in again + setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN); + $AUTHERROR["code"] = 4; + $AUTHERROR["message"] = "Auth cookie has expired"; + return NULL; + } + if($_SERVER["REMOTE_ADDR"] != $remoteIP) { + # cookie has wrong IP; clear it and return NULL so will get redirected to log in again + setcookie("VCLAUTH", "", 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 getAuthTypeFromAuthCookie() +/// +/// \return on success, type of authentication used; NULL on failure +/// +/// \brief parses the VCLAUTH cookie to get the authtype saved in it +/// +//////////////////////////////////////////////////////////////////////////////// +function getAuthTypeFromAuthCookie() { + global $keys, $AUTHERROR; + if(! array_key_exists('VCLAUTH', $_COOKIE)) + return NULL; + 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; + } + + # $loginid|$remoteIP|$ts|$authtype|$shibauthid (shibauthd optional) + $tmparr = explode('|', $tmp); + $remoteIP = $tmparr[1]; + $authtype = $tmparr[3]; + + 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 $authtype; } //////////////////////////////////////////////////////////////////////////////// @@ -351,120 +414,6 @@ function submitLogin() { //////////////////////////////////////////////////////////////////////////////// /// -/// \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 = vcl_mysql_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); - # used to rely on later code to update user info if update timestamp was expired - // 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(! mysqli_num_rows($qh)) { - // if not, add user - $newid = updateLDAPUser($authtype, $userid); - if(is_null($newid)) - abort(8); - }*/ - # now, we always update the user info - $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, $authtype) /// /// \param $userid - userid without affiliation @@ -480,7 +429,7 @@ function localLogin($userid, $passwd, $authtype) { if(validateLocalAccount($userid, $passwd)) { addLoginLog($userid, $authtype, $authMechs[$authtype]['affiliationid'], 1); //set cookie - $cookie = getAuthCookieData("$userid@local"); + $cookie = getAuthCookieData("$userid@local", 'local'); if(version_compare(PHP_VERSION, "5.2", ">=") == true) setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0, 1); else @@ -503,6 +452,24 @@ function localLogin($userid, $passwd, $authtype) { //////////////////////////////////////////////////////////////////////////////// /// +/// \fn unauthLocal +/// +/// \param $mode - headers or content +/// +/// \brief for headers, simply returns; for content, prints information that +/// user has been logged out; VCLAUTH cookie is cleared elsewhere +/// +//////////////////////////////////////////////////////////////////////////////// +function unauthLocal($mode) { + if($mode == 'headers') + return; + print "<h2>Logout</h2>\n"; + print "You are now logged out of VCL.<br><br>\n"; + print "<a href=\"" . BASEURL . SCRIPT . "?mode=selectauth\">Return to Login</a><br><br><br>\n"; +} + +//////////////////////////////////////////////////////////////////////////////// +/// /// \fn validateLocalAccount($user, $pass) /// /// \param $user - unityid from user table diff --git a/web/.ht-inc/authmethods/itecsauth.php b/web/.ht-inc/authmethods/itecsauth.php index be9b537..a271450 100644 --- a/web/.ht-inc/authmethods/itecsauth.php +++ b/web/.ht-inc/authmethods/itecsauth.php @@ -22,6 +22,79 @@ * \file */ +$authFuncs['itecs'] = array('test' => 'testITECSAuth', + 'auth' => 'processITECSAuth', + 'unauth' => 'unauthITECS'); + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn testITECSAuth() +/// +/// \return 1 if ITECSAUTH cookie found, 0 if not +/// +/// \brief tests for existance of authentication information for ITECS auth +/// +//////////////////////////////////////////////////////////////////////////////// +function testITECSAuth() { + if(array_key_exists('ITECSAUTH', $_COOKIE)) + return 1; + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn processITECSAuth() +/// +/// \return userid in form of emailaddress@ITECS or NULL +/// +/// \brief processes authentication information; returns userid or NULL if +/// unsuccessful +/// +//////////////////////////////////////////////////////////////////////////////// +function processITECSAuth() { + $authdata = authUser(); + if(! ($error = getAuthError())) { + $userid = "{$authdata["email"]}@ITECS"; + $affilid = getAffiliationID('ITECS'); + addLoginLog($userid, 'ITECS', $affilid, 1); + + # get cookie data + $cookie = getAuthCookieData($userid, 'itecs', 600); + # 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); + + return $userid; + } + return NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn unauthITECS($mode) +/// +/// \param $mode - headers or content +/// +/// \brief for headers mode, destroys authentication information; for content +/// mode, prints information about having been logged out +/// +//////////////////////////////////////////////////////////////////////////////// +function unauthITECS($mode) { + if($mode == 'headers') { + $time = time() - 10; + setcookie("ITECSAUTH_RETURN", "", $time, "/", COOKIEDOMAIN); + setcookie("ITECSAUTH_CSS", "", $time, "/", COOKIEDOMAIN); + setcookie("ITECSAUTH", "", $time, "/", COOKIEDOMAIN); + } + elseif($mode == 'content') { + print "<h2>Logout</h2>\n"; + print "You are now logged out of VCL.<br><br>\n"; + print "<a href=\"" . BASEURL . SCRIPT . "?mode=selectauth\">Return to Login</a><br><br><br>\n"; + } +} + //////////////////////////////////////////////////////////////////////////////// /// /// \fn addITECSUser($loginid) diff --git a/web/.ht-inc/authmethods/ldapauth.php b/web/.ht-inc/authmethods/ldapauth.php index 8aa53c6..1c2ee53 100644 --- a/web/.ht-inc/authmethods/ldapauth.php +++ b/web/.ht-inc/authmethods/ldapauth.php @@ -20,6 +20,143 @@ * \file */ +$authFuncs['ldap'] = array('test' => function() {return 0;}, + 'auth' => function() {return NULL;}, + 'unauth' => 'unauthLDAP'); + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn unauthLDAP($mode) +/// +/// \param $mode - headers or content +/// +/// \brief for headers, simply returns; for content, prints information that +/// user has been logged out; VCLAUTH cookie is cleared elsewhere +/// +//////////////////////////////////////////////////////////////////////////////// +function unauthLDAP($mode) { + if($mode == 'headers') + return; + print "<h2>" . _('Logout') . "</h2>\n"; + print _("You are now logged out of VCL.") . "<br><br>\n"; + print "<a href=\"" . BASEURL . SCRIPT . "?mode=selectauth\">" . _("Return to Login"); + print "</a><br><br><br>\n"; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \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 = vcl_mysql_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); + # used to rely on later code to update user info if update timestamp was expired + // 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(! mysqli_num_rows($qh)) { + // if not, add user + $newid = updateLDAPUser($authtype, $userid); + if(is_null($newid)) + abort(8); + }*/ + # now, we always update the user info + $newid = updateLDAPUser($authtype, $userid); + if(is_null($newid)) + abort(8); + // get cookie data + $cookie = getAuthCookieData("$userid@" . getAffiliationName($authMechs[$authtype]['affiliationid']), 'ldap'); + // 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 addLDAPUser($authtype, $userid) diff --git a/web/.ht-inc/authmethods/shibauth.php b/web/.ht-inc/authmethods/shibauth.php index 33d7b5d..947035e 100644 --- a/web/.ht-inc/authmethods/shibauth.php +++ b/web/.ht-inc/authmethods/shibauth.php @@ -20,6 +20,286 @@ * \file */ +$authFuncs['shibboleth'] = array('test' => 'testShibAuth', + 'auth' => 'processShibAuth', + 'unauth' => 'unauthShib'); + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn testShibAuth() +/// +/// \returns 1 if SHIB_EPPN found in $_SERVER; 0 otherwise +/// +/// \brief checks for authentication information related to Shibboleth +/// +//////////////////////////////////////////////////////////////////////////////// +function testShibAuth() { + // TODO check for other shib variables, if found but EPPN not found, alert user that EPPN is not being released + if(array_key_exists('SHIB_EPPN', $_SERVER)) + return 1; + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn processShibAuth() +/// +/// \returns userid in userid@AFFILIATION form +/// +/// \brief processes Shibboleth authentication information +/// +//////////////////////////////////////////////////////////////////////////////// +function processShibAuth() { + # get VCL affiliation from shib affiliation + $tmp = explode(';', $_SERVER['SHIB_EPPN']); + $tmp = explode('@', $tmp[0]); + $username = strtolower($tmp[0]); + $shibaffil = vcl_mysql_escape_string(strtolower($tmp[1])); + $query = "SELECT name, shibonly FROM affiliation WHERE shibname = '$shibaffil'"; + $qh = doQuery($query, 101); + # if shib affiliation not already in VCL, create affiliation + if(! ($row = mysqli_fetch_assoc($qh))) { + $affil = strtolower($tmp[1]); + $tmp = explode('.', $affil); + array_pop($tmp); + $affilname = strtoupper(implode('', $tmp)); + $affilname = preg_replace('/[^A-Z0-9]/', '', $affilname); + $query = "SELECT name, " + . "shibname " + . "FROM affiliation " + . "WHERE name LIKE '$affilname%' " + . "ORDER BY name DESC " + . "LIMIT 1"; + $qh = doQuery($query, 101); + if($row = mysqli_fetch_assoc($qh)) { + if(preg_match("/$affilname([0-9]+)/", $row['name'], $matches)) { + $cnt = $matches[1]; + $cnt++; + $newaffilname = $affilname . $cnt; + } + elseif($affilname != strtoupper($row['name']) && $affil != $row['shibname']) { + $newaffilname = $affilname; + } + else { + $msg = "Someone tried to log in to VCL using Shibboleth from an IdP " + . "affiliation that could not be automatically added.\n\n" + . "eppn: {$_SERVER['SHIB_EPPN']}\n" + . "givenName: {$_SERVER['SHIB_GIVENNAME']}\n" + . "sn: {$_SERVER['SHIB_SN']}\n"; + if(array_key_exists('SHIB_MAIL', $_SERVER)) + $msg .= "mail: {$_SERVER['SHIB_MAIL']}\n\n"; + $msg .="tried to add VCL affiliation name \"$affilname\" with " + . "shibname \"$affil\""; + $mailParams = "-f" . ENVELOPESENDER; + mail(ERROREMAIL, "Error with VCL pages (problem adding shib affil)", $msg, '', $mailParams); + print "<html><head></head><body>\n"; + print "<h2>Error encountered</h2>\n"; + print "You have attempted to log in to VCL using a Shibboleth<br>\n"; + print "Identity Provider that VCL has not been configured to<br>\n"; + print "work with. VCL administrators have been notified of the<br>\n"; + print "problem.<br>\n"; + print "</body></html>\n"; + dbDisconnect(); + exit; + } + } + else + $newaffilname = $affilname; + $query = "INSERT INTO affiliation " + . "(name, " + . "shibname, " + . "shibonly) " + . "VALUES " + . "('$newaffilname', " + . "'" . vcl_mysql_escape_string($affil) . "', " + . "1)"; + doQuery($query, 101, 'vcl', 1); + unset($row); + $row = array('name' => $newaffilname, 'shibonly' => 1); + } + $affil = $row['name']; + $affilid = getAffiliationID($affil); + + # create VCL userid + $userid = "$username@$affil"; + + if($row['shibonly']) { + $userdata = updateShibUser($userid); + if(array_key_exists('SHIB_AFFILIATION', $_SERVER)) + $groups = $_SERVER['SHIB_AFFILIATION']; + else + $groups = array('shibaffil' => $shibaffil); + updateShibGroups($userdata['id'], $groups); + $usernid = $userdata['id']; + } + else { + $usernid = getUserlistID($userid, 1); + # NCSU specific + if(is_null($userid) && $affil == 'NCSU') { + $tmp = updateLDAPUser('NCSU LDAP', $username); + $usernid = $tmp['id']; + } + /*if($affil == 'NCSU') { + if(array_key_exists('SHIB_AFFILIATION', $_SERVER)) + $groups = $_SERVER['SHIB_AFFILIATION']; + else + $groups = array('shibaffil' => $shibaffil); + updateShibGroups($usernid, $groups); + }*/ + # end NCSU specific + if(is_null($usernid)) { + $tmp = updateShibUser($userid); + $usernid = $tmp['id']; + # call this so that user groups get correctly populated + updateUserData($usernid, "numeric", $affilid); + } + } + + addLoginLog($userid, 'shibboleth', $affilid, 1); + + if($affil == 'UNCG') { + $gid = getUserGroupID('All UNCG Users', $affilid); + $query = "INSERT IGNORE INTO usergroupmembers " + . "(userid, usergroupid) " + . "VALUES ($usernid, $gid)"; + doQuery($query, 307); + } + + if(array_key_exists('SHIB_LOGOUTURL', $_SERVER)) + $logouturl = $_SERVER['SHIB_LOGOUTURL']; + else + $logouturl = ''; + + # save data to shibauth table + $shibdata = array('Shib-Application-ID' => $_SERVER['Shib-Application-ID'], + 'Shib-Identity-Provider' => $_SERVER['Shib-Identity-Provider'], + #'Shib-AuthnContext-Dec' => $_SERVER['Shib-AuthnContext-Decl'], + 'SHIB_LOGOUTURL' => $logouturl, + 'SHIB_EPPN' => $_SERVER['SHIB_EPPN'], + #'SHIB_UNAFFILIATION' => $_SERVER['SHIB_UNAFFILIATION'], + 'SHIB_AFFILIATION' => $_SERVER['SHIB_AFFILIATION'], + ); + $serdata = vcl_mysql_escape_string(serialize($shibdata)); + $query = "SELECT id " + . "FROM shibauth " + . "WHERE sessid = '{$_SERVER['Shib-Session-ID']}'"; + $qh = doQuery($query, 101); + if($row = mysqli_fetch_assoc($qh)) { + $shibauthid = $row['id']; + } + else { + $ts = strtotime($_SERVER['Shib-Authentication-Instant']); + $ts = unixToDatetime($ts); + $query = "INSERT INTO shibauth " + . "(userid, " + . "ts, " + . "sessid, " + . "data) " + . "VALUES " + . "($usernid, " + . "'$ts', " + . "'{$_SERVER['Shib-Session-ID']}', " + . "'$serdata')"; + doQuery($query, 101); + $qh = doQuery("SELECT LAST_INSERT_ID()", 101); + if(! $row = mysqli_fetch_row($qh)) { + # todo + } + $shibauthid = $row[0]; + } + + # get cookie data + $cookie = getAuthCookieData($userid, 'shibboleth', 600, $shibauthid); + # set cookie + if(version_compare(PHP_VERSION, "5.2", ">=") == true) + #setcookie("VCLAUTH", "{$cookie['data']}", $cookie['ts'], "/", COOKIEDOMAIN, 1, 1); + setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0, 1); + else + #setcookie("VCLAUTH", "{$cookie['data']}", $cookie['ts'], "/", COOKIEDOMAIN, 1); + setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN); + + # TODO do something to set VCLSKIN cookie based on affiliation + + return $userid; +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn unauthShib($mode) +/// +/// \param $mode - headers or content +// +/// \brief for headers, simply returns; for content, prints information that +/// user has been logged out and an iframe to log user out of Shibboleth if +/// SHIB_LOGOUTURL was provided; VCLAUTH cookie is cleared elsewhere +/// +//////////////////////////////////////////////////////////////////////////////// +function unauthShib($mode) { + global $user; + if($mode == 'headers') + return; + + print "<h2>Logout</h2>\n"; + print "You are now logged out of VCL and other Shibboleth authenticated web sites.<br><br>\n"; + print "<a href=\"" . BASEURL . SCRIPT . "?mode=selectauth\">Return to Login</a><br><br><br>\n"; + print "<iframe src=\"https://{$_SERVER['SERVER_NAME']}/Shibboleth.sso/Logout\" class=hidden>\n"; + print "</iframe>\n"; + if(array_key_exists('SHIB_LOGOUTURL', $_SERVER)) { + print "<iframe src=\"{$_SERVER['SHIB_LOGOUTURL']}\" class=hidden>\n"; + print "</iframe>\n"; + } + $shibdata = getShibauthDataByUser($user['id']); + if(array_key_exists('Shib-Identity-Provider', $shibdata) && + ! empty($shibdata['Shib-Identity-Provider'])) { + $tmp = explode('/', $shibdata['Shib-Identity-Provider']); + $idp = "{$tmp[0]}//{$tmp[2]}"; + print "<iframe src=\"$idp/idp/logout.jsp\" class=hidden>\n"; + print "</iframe>\n"; + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn getShibauthDataByUser($userid) +/// +/// \param $userid - numeric id of a user +/// +/// \return NULL if id not found in table or array of data with these keys:\n +/// \b userid - id of user that data belongs to\n +/// \b ts - datetime of when authdata was created\n +/// \b sessid - shibboleth session id\n +/// \b Shib-Application-ID - ??\n +/// \b Shib-Identity-Provider - ??\n +/// \b Shib-AuthnContext-Dec - ??\n +/// \b Shib-logouturl - idp's logout url\n +/// \b eppn - edu person principal name for user\n +/// \b unscoped-affiliation - shibboleth unscoped affiliation\n +/// \b affiliation - shibboleth scoped affiliation +/// +/// \brief gets entry from shibauth table +/// +//////////////////////////////////////////////////////////////////////////////// +function getShibauthDataByUser($userid) { + $query = "SELECT id, " + . "userid, " + . "ts, " + . "sessid, " + . "data " + . "FROM shibauth " + . "WHERE userid = $userid AND " + . "ts > DATE_SUB(NOW(), INTERVAL 12 HOUR) " + . "ORDER BY ts DESC " + . "LIMIT 1"; + $qh = doQuery($query, 101); + if($row = mysqli_fetch_assoc($qh)) { + $data = unserialize($row['data']); + unset($row['data']); + $data2 = array_merge($row, $data); + return $data2; + } + return NULL; +} + //////////////////////////////////////////////////////////////////////////////// /// /// \fn updateShibUser($userid) @@ -45,35 +325,40 @@ function updateShibUser($userid) { return NULL; $displast = ''; - if(array_key_exists('displayName', $_SERVER) && - ! empty($_SERVER['displayName'])) { - # split displayName into first and last names - if(preg_match('/,/', $_SERVER['displayName'])) { - $names = explode(',', $_SERVER['displayName']); + + $displayname = getShibVar('displayName'); + $givenname = getShibVar('givenName'); + $sn = getShibVar('sn'); + $mail = getShibVar('mail'); + + if($displayname != '') { + # split displayname into first and last names + if(preg_match('/,/', $displayname)) { + $names = explode(',', $displayname); $user['firstname'] = preg_replace('/^\s+/', '', $names[1]); $user['firstname'] = preg_replace('/\s+$/', '', $user['firstname']); $displast = preg_replace('/^\s+/', '', $names[0]); $displast = preg_replace('/\s+$/', '', $displast); } else { - $names = explode(' ', $_SERVER['displayName']); + $names = explode(' ', $displayname); $displast = array_pop($names); $user['firstname'] = array_shift($names); } } - elseif(array_key_exists('givenName', $_SERVER) && - ! empty($_SERVER['givenName'])) - $user['firstname'] = $_SERVER['givenName']; + elseif($givenname != '') + $user['firstname'] = $givenname; else $user['firstname'] = ''; - if(array_key_exists('sn', $_SERVER) && - ! empty($_SERVER['sn'])) - $user["lastname"] = $_SERVER['sn']; + if($sn != '') + $user["lastname"] = $sn; else $user['lastname'] = $displast; - if(array_key_exists('mail', $_SERVER)) - $user["email"] = $_SERVER['mail']; + + if($mail != '') + $user["email"] = $mail; + $user['unityid'] = $userid; $user['affilid'] = $affilid; @@ -188,7 +473,12 @@ function updateShibGroups($usernid, $groups) { # get id for the group's affiliation $query = "SELECT id FROM affiliation WHERE shibname = '$shibaffil'"; $qh = doQuery($query, 101); - $row = mysqli_fetch_assoc($qh); + if(! ($row = mysqli_fetch_assoc($qh))) { + $query = "SELECT id FROM affiliation WHERE shibname LIKE '%.$shibaffil'"; + $qh = doQuery($query, 101); + if(! ($row = mysqli_fetch_assoc($qh))) + continue; + } $affilid = $row['id']; # prepend shib- and escape it for mysql $grp = vcl_mysql_escape_string("shib-" . $name); @@ -244,4 +534,24 @@ function addShibUserStub($affilid, $userid) { return NULL; } +//////////////////////////////////////////////////////////////////////////////// +/// +/// \fn getShibVar($key) +/// +/// \param $key - shib variable to check for +/// +/// \return value of shib variable or empty string if not found +/// +/// \brief checks for various forms of $key in $_SERVER +/// +//////////////////////////////////////////////////////////////////////////////// +function getShibVar($key) { + $key2 = "SHIB_" . strtoupper($key); + $val = ''; + if(isset($_SERVER[$key]) && ! empty($_SERVER[$key])) + return $_SERVER[$key]; + elseif(isset($_SERVER[$key2]) && ! empty($_SERVER[$key2])) + return $_SERVER[$key2]; +} + ?> diff --git a/web/.ht-inc/conf-default.php b/web/.ht-inc/conf-default.php index d9022e3..50f204b 100644 --- a/web/.ht-inc/conf-default.php +++ b/web/.ht-inc/conf-default.php @@ -138,7 +138,7 @@ $authMechs = array( "affiliationid" => 1, "help" => "Only use Local Account if there are no other options"), /*"Shibboleth (UNC Federation)" => array("type" => "redirect", - "URL" => "https://federation.northcarolina.edu/wayf/wayf_framed.php?fed=FED_SHIB_UNC_DEV&version=dropdown&entityID=https%3A%2F%2Fvcl.ncsu.edu%2Fsp%2Fshibboleth&return=http%3A%2F%2Fvcl.ncsu.edu%2FShibboleth.sso%2FDS%3FSAMLDS%3D1%26target%3Dhttp%3A%2F%2Fvcl.ncsu.edu%2Fscheduling%2Fshibauth%2F", + "URL" => "https://federation.northcarolina.edu/wayf/wayf_framed.php?fed=FED_SHIB_UNC_DEV&version=dropdown&entityID=https%3A%2F%2Fvcl.ncsu.edu%2Fsp%2Fshibboleth&return=http%3A%2F%2Fvcl.ncsu.edu%2FShibboleth.sso%2FDS%3FSAMLDS%3D1%26target%3Dhttp%3A%2F%2Fvcl.ncsu.edu%2Fscheduling%2F/", "affiliationid" => 0, // this should always be 0 for Shibboleth authentication "help" => "Use Shibboleth (UNC Federation) if you are from a University in the UNC system and do not see another method specifically for your university"),*/ /*"EXAMPLE1 LDAP" => array("type" => "ldap", diff --git a/web/.ht-inc/utils.php b/web/.ht-inc/utils.php index 763e4b2..c13be06 100644 --- a/web/.ht-inc/utils.php +++ b/web/.ht-inc/utils.php @@ -170,11 +170,17 @@ function initGlobals() { if(! is_null($userid)) $authed = 1; } - elseif(preg_match('/_shibsession/', join(',', array_keys($_COOKIE)))) { - # redirect to shibauth directory - header('Location: ' . BASEURL . "/shibauth/"); - dbDisconnect(); - exit; + else { + global $authFuncs; + foreach($authFuncs as $type) { + if($type['test']()) { + $userid = $type['auth'](); + if(! is_null($userid)) { + $authed = 1; + break; + } + } + } } # end auth check @@ -13106,7 +13112,7 @@ function sendJSON($arr, $identifier='', $REST=0) { //////////////////////////////////////////////////////////////////////////////// function sendHeaders() { global $mode, $user, $authed, $oldmode, $actionFunction; - global $shibauthed; + global $shibauthed, $authFuncs; if(! $authed && $mode == "auth") { header("Location: " . BASEURL . SCRIPT . "?mode=selectauth"); dbDisconnect(); @@ -13114,78 +13120,22 @@ function sendHeaders() { } switch($mode) { case 'logout': - if($shibauthed) { - $shibdata = getShibauthData($shibauthed); - // TODO make shib-logouturl comparison caseless - if(array_key_exists('Shib-logouturl', $shibdata) && - ! empty($shibdata['Shib-logouturl'])) { - dbDisconnect(); - header("Location: {$shibdata['Shib-logouturl']}"); - exit; - } - } - case 'shiblogout': - setcookie("ITECSAUTH", "", time() - 10, "/", COOKIEDOMAIN); - setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN); - if($shibauthed) { - $msg = ''; - $shibdata = getShibauthData($shibauthed); - # find and clear shib cookies - /*foreach(array_keys($_COOKIE) as $key) { - if(preg_match('/^_shibsession[_0-9a-fA-F]+$/', $key)) - setcookie($key, "", time() - 10, "/", $_SERVER['SERVER_NAME']); - elseif(preg_match('/^_shibstate_/', $key)) - setcookie($key, "", time() - 10, "/", $_SERVER['SERVER_NAME']); - }*/ - doQuery("DELETE FROM shibauth WHERE id = $shibauthed", 101); + $authtype = getAuthTypeFromAuthCookie(); + if(is_null($authtype)) { stopSession(); dbDisconnect(); - if(array_key_exists('Shib-logouturl', $shibdata) && - ! empty($shibdata['Shib-logouturl'])) { - print "<html>\n"; - print " <head>\n"; - print " <style type=\"text/css\">\n"; - print " .red {\n"; - print " color: red;\n"; - print " }\n"; - print " body{\n"; - print " margin:0px; color: red;\n"; - print " }\n"; - print " </style>\n"; - print " </head>\n"; - print " <body>\n"; - print " <span class=red>Done.</span> <a target=\"_top\" href=\"" . BASEURL . "/\">Return to VCL</a>\n"; - print " </body>\n"; - print "</html>\n"; - } - else { - print "<html>\n"; - print "<head>\n"; - print "<META HTTP-EQUIV=REFRESH CONTENT=\"5;url=" . BASEURL . "\">\n"; - print "<style type=\"text/css\">\n"; - print " .hidden {\n"; - print " display: none;\n"; - print " }\n"; - print "</style>\n"; - print "</head>\n"; - print "<body>\n"; - print "Logging out of VCL..."; - print "<iframe src=\"https://{$_SERVER['SERVER_NAME']}/Shibboleth.sso/Logout\" class=hidden>\n"; - print "</iframe>\n"; - if(array_key_exists('Shib-Identity-Provider', $shibdata) && - ! empty($shibdata['Shib-Identity-Provider'])) { - $tmp = explode('/', $shibdata['Shib-Identity-Provider']); - $idp = "{$tmp[0]}//{$tmp[2]}"; - print "<iframe src=\"$idp/idp/logout.jsp\" class=hidden>\n"; - print "</iframe>\n"; - } - print "</body>\n"; - print "</html>\n"; - } + header("Location: " . BASEURL . SCRIPT); exit; } - header("Location: " . HOMEURL); + $authFuncs[$authtype]['unauth']('headers'); + setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN); + $authed = 0; + ob_start(); + printHTMLHeader(); + $authFuncs[$authtype]['unauth']('content'); + printHTMLFooter(); stopSession(); + ob_end_flush(); dbDisconnect(); exit; } diff --git a/web/shibauth/index.php b/web/shibauth/index.php index 64c33c5..c6ad42a 100644 --- a/web/shibauth/index.php +++ b/web/shibauth/index.php @@ -1,263 +1,4 @@ <?php -/* - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -chdir(".."); -require_once('.ht-inc/conf.php'); - -require_once('.ht-inc/utils.php'); -require_once('.ht-inc/errors.php'); -function getFooter() {} -$noHTMLwrappers = array(); - -dbConnect(); - -header("Cache-Control: no-cache, must-revalidate"); -header("Expires: Sat, 1 Jan 2000 00:00:00 GMT"); - -/* - # check for eppn; if there, see if it is a user we already have - if(array_key_exists('eppn', $_SERVER)) { - #$tmp = explode('@', $_SERVER['eppn']); - $tmp = explode(';', $_SERVER['eppn']); - $tmp = explode('@', $tmp[0]); - $query = "SELECT u.firstname, " - . "u.lastname " - . "FROM user u, " - . "affiliation a " - . "WHERE u.unityid = '{$tmp[0]}' AND " - . "a.shibname = '{$tmp[1]}' AND " - . "u.affiliationid = a.id"; - $qh = doQuery($query, 101); - if($row = mysqli_fetch_assoc($qh)) { - $_SERVER['sn'] = $row['lastname']; - $_SERVER['givenName'] = $row['firstname']; - } - else { -*/ - -if(! array_key_exists('eppn', $_SERVER)) { - # check to see if any shib stuff in $_SERVER, if not redirect - $keys = array_keys($_SERVER); - $allkeys = '{' . implode('{', $keys); - if(! preg_match('/\{Shib-/', $allkeys)) { - # no shib data, clear _shibsession cookie - #print "$allkeys<br>\n"; - foreach(array_keys($_COOKIE) as $key) { - if(preg_match('/^_shibsession[_0-9a-fA-F]+$/', $key)) - setcookie($key, "", time() - 10, "/", $_SERVER['SERVER_NAME']); - } - # redirect to main select auth page - header("Location: " . BASEURL . SCRIPT . "?mode=selectauth"); - dbDisconnect(); - exit; - } - print "<h2>Error with Shibboleth authentication</h2>\n"; - print "You have attempted to log in using Shibboleth from an<br>\n"; - print "institution that does not allow VCL to see your<br><br>\n"; - print "eduPersonPrincipalName.<br><br>\n"; - print "You need to contact the administrator of your institution's<br>\n"; - print "IdP to have eduPersonPrincipalName made available to VCL in<br>\n"; - print "order to log in using Shibboleth.\n"; - - $msg = "Someone tried to log in to VCL using Shibboleth from an IdP " - . "that does not release eppn to us.\n\n" - . "The following data was in \$_SERVER:\n\n"; - foreach($_SERVER as $key => $val) - $msg .= "$key => $val\n"; - $mailParams = "-f" . ENVELOPESENDER; - mail(ERROREMAIL, "Error with VCL pages (eppn not provided)", $msg, '', $mailParams); - dbDisconnect(); - exit; -} - -// open keys -$fp = fopen(".ht-inc/keys.pem", "r"); -$key = fread($fp, 8192); -fclose($fp); -$keys["private"] = openssl_pkey_get_private($key, $pemkey); -if(! $keys['private']) - abort(6); -$fp = fopen(".ht-inc/pubkey.pem", "r"); -$key = fread($fp, 8192); -fclose($fp); -$keys["public"] = openssl_pkey_get_public($key); -if(! $keys['public']) - abort(7); - -# get VCL affiliation from shib affiliation -$tmp = explode(';', $_SERVER['eppn']); -$tmp = explode('@', $tmp[0]); -$username = strtolower($tmp[0]); -$tmp1 = vcl_mysql_escape_string(strtolower($tmp[1])); -$query = "SELECT name, shibonly FROM affiliation WHERE shibname = '$tmp1'"; -$qh = doQuery($query, 101); -# if shib affiliation not already in VCL, create affiliation -if(! ($row = mysqli_fetch_assoc($qh))) { - $affil = strtolower($tmp[1]); - $tmp = explode('.', $affil); - array_pop($tmp); - $affilname = strtoupper(implode('', $tmp)); - $affilname = preg_replace('/[^A-Z0-9]/', '', $affilname); - $query = "SELECT name, " - . "shibname " - . "FROM affiliation " - . "WHERE name LIKE '$affilname%' " - . "ORDER BY name DESC " - . "LIMIT 1"; - $qh = doQuery($query, 101); - if($row = mysqli_fetch_assoc($qh)) { - if(preg_match("/$affilname([0-9]+)/", $row['name'], $matches)) { - $cnt = $matches[1]; - $cnt++; - $newaffilname = $affilname . $cnt; - } - elseif($affilname != $row['name'] && $affil != $row['shibname']) { - $newaffilname = $affilname; - } - else { - $msg = "Someone tried to log in to VCL using Shibboleth from an IdP " - . "affiliation that could not be automatically added.\n\n" - . "eppn: {$_SERVER['eppn']}\n" - . "givenName: {$_SERVER['givenName']}\n" - . "sn: {$_SERVER['sn']}\n"; - if(array_key_exists('mail', $_SERVER)) - $msg .= "mail: {$_SERVER['mail']}\n\n"; - $msg .="tried to add VCL affiliation name \"$affilname\" with " - . "shibname \"$affil\""; - $mailParams = "-f" . ENVELOPESENDER; - mail(ERROREMAIL, "Error with VCL pages (problem adding shib affil)", $msg, '', $mailParams); - print "<html><head></head><body>\n"; - print "<h2>Error encountered</h2>\n"; - print "You have attempted to log in to VCL using a Shibboleth<br>\n"; - print "Identity Provider that VCL has not been configured to<br>\n"; - print "work with. VCL administrators have been notified of the<br>\n"; - print "problem.<br>\n"; - print "</body></html>\n"; - dbDisconnect(); - exit; - } - } - else - $newaffilname = $affilname; - $query = "INSERT INTO affiliation " - . "(name, " - . "shibname, " - . "shibonly) " - . "VALUES " - . "('$newaffilname', " - . "'" . vcl_mysql_escape_string($affil) . "', " - . "1)"; - doQuery($query, 101, 'vcl', 1); - unset($row); - $row = array('name' => $newaffilname, 'shibonly' => 1); -} -$affil = $row['name']; -# create VCL userid -$userid = "$username@$affil"; - -if($row['shibonly']) { - $userdata = updateShibUser($userid); - updateShibGroups($userdata['id'], $_SERVER['affiliation']); - $usernid = $userdata['id']; -} -else { - $usernid = getUserlistID($userid, 1); - if(is_null($usernid)) { - $tmp = updateShibUser($userid); - $usernid = $tmp['id']; - } -} - -$affilid = getAffiliationID($affil); -addLoginLog($userid, 'shibboleth', $affilid, 1); - -# uncomment the following and change EXAMPLE1 to match your needs to add all -# users from a specific affiliation to a particular user group -/*if($affil == 'EXAMPLE1') { - $gid = getUserGroupID('All EXAMPLE1 Users', $affilid); - $query = "INSERT IGNORE INTO usergroupmembers " - . "(userid, usergroupid) " - . "VALUES ($usernid, $gid)"; - doQuery($query, 307); -}*/ - -if(array_key_exists('Shib-logouturl', $_SERVER)) - $logouturl = $_SERVER['Shib-logouturl']; -else - $logouturl = ''; - -# save data to shibauth table -$shibdata = array('Shib-Application-ID' => $_SERVER['Shib-Application-ID'], - 'Shib-Identity-Provider' => $_SERVER['Shib-Identity-Provider'], - #'Shib-AuthnContext-Dec' => $_SERVER['Shib-AuthnContext-Decl'], - 'Shib-logouturl' => $logouturl, - 'eppn' => $_SERVER['eppn'], - 'unscoped-affiliation' => $_SERVER['unscoped-affiliation'], - 'affiliation' => $_SERVER['affiliation'], -); -$serdata = vcl_mysql_escape_string(serialize($shibdata)); -$query = "SELECT id " - . "FROM shibauth " - . "WHERE sessid = '{$_SERVER['Shib-Session-ID']}'"; -$qh = doQuery($query, 101); -if($row = mysqli_fetch_assoc($qh)) { - $shibauthid = $row['id']; -} -else { - $ts = strtotime($_SERVER['Shib-Authentication-Instant']); - $ts = unixToDatetime($ts); - $query = "INSERT INTO shibauth " - . "(userid, " - . "ts, " - . "sessid, " - . "data) " - . "VALUES " - . "($usernid, " - . "'$ts', " - . "'{$_SERVER['Shib-Session-ID']}', " - . "'$serdata')"; - doQuery($query, 101); - $qh = doQuery("SELECT LAST_INSERT_ID() FROM shibauth", 101); - if(! $row = mysqli_fetch_row($qh)) { - # todo - } - $shibauthid = $row[0]; -} - -# get cookie data -$cookie = getAuthCookieData($userid, 600, $shibauthid); -# set cookie -if(version_compare(PHP_VERSION, "5.2", ">=") == true) - #setcookie("VCLAUTH", "{$cookie['data']}", $cookie['ts'], "/", COOKIEDOMAIN, 1, 1); - setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN, 0, 1); -else - #setcookie("VCLAUTH", "{$cookie['data']}", $cookie['ts'], "/", COOKIEDOMAIN, 1); - setcookie("VCLAUTH", "{$cookie['data']}", 0, "/", COOKIEDOMAIN); -# set skin cookie based on affiliation -switch($affil) { - case 'Example1': - case 'EXAMPLE2': - $skin = strtoupper($affil); - setcookie("VCLSKIN", $skin, (time() + 2678400), "/", COOKIEDOMAIN); - break; - default: - setcookie("VCLSKIN", "default", (time() + 2678400), "/", COOKIEDOMAIN); -} -header("Location: " . BASEURL . "/"); -dbDisconnect(); +@require_once('../.ht-inc/conf.php'); +header("Location: " . BASEURL . SCRIPT); ?>