You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by jf...@apache.org on 2019/04/19 20:28:14 UTC

[vcl] branch VCL-1086_modular_web_authentication created (now aeb81d1)

This is an automated email from the ASF dual-hosted git repository.

jfthomps pushed a change to branch VCL-1086_modular_web_authentication
in repository https://gitbox.apache.org/repos/asf/vcl.git.


      at aeb81d1  VCL-1086 - improve modularization of authentication

This branch includes the following new commits:

     new aeb81d1  VCL-1086 - improve modularization of authentication

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[vcl] 01/01: VCL-1086 - improve modularization of authentication

Posted by jf...@apache.org.
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 <jf...@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>&nbsp;&nbsp;&nbsp;<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);
 ?>