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 2009/01/15 23:40:31 UTC

svn commit: r734842 - in /incubator/vcl/trunk/web: .ht-inc/authentication.php .ht-inc/authmethods/shibauth.php .ht-inc/conf.php .ht-inc/states.php .ht-inc/utils.php index.php shibauth/ shibauth/.htaccess shibauth/index.php

Author: jfthomps
Date: Thu Jan 15 14:40:30 2009
New Revision: 734842

URL: http://svn.apache.org/viewvc?rev=734842&view=rev
Log:
VCL-4
added support for Shibboleth authentication

authentication.php:
-modified getAuthCookieData to accept $shibauthid as an extra argument; if passed in, it is added to the end of the cookie data before encryption
-corrected description header for readAuthCookie
-modified readAuthCookie to set global $shibauthed to the value passed to getAuthCookieData as $shibauthid; if $shibauthed gets set, the shibauth table is checked to see if a corresponding record exists for it; if not the VCLAUTH cookie is cleared and the user is redirected to the login page
-modified ldapLogin and localLogin to set VCLAUTH as a session cookie instead of a lifetime cookie - this was done because the UNC Federation logout page uses iframes to load each SP's logout page and IE7 seems to only pass session cookies to iframes (and not lifetime cookies) so the user was not authenticated in the iframe to be correctly logged out

conf.php:
-added (commented out) Shibboleth as a type in $authMechs, leaving the UNC federation config as an example
-added (commented out ) require_once for .ht-inc/authmethods/shibauth.php

states.php:
-added shiblogout to $actions['entry']
-created entries for logout and shiblogout in $actions['pages'] array

utils.php:
-modified initGlobals - added check for _shibsession cookie to block of conditionals checking to see if user is authenticated
-modified getUserInfo to include shibonly in user data and to not try to pull updated information about the user if shibonly is true
-added getShibauthData
-modified sendHeaders - changed conditional for $mode being logout to a switch statement that handles $mode being both logout and shiblogout

index.php:
-added initialization of global $shibauthed

added .ht-inc/authmethods/shibauth.php
added added shibauth directory
added shibauth/.htaccess
added shibauth/index.php

Added:
    incubator/vcl/trunk/web/.ht-inc/authmethods/shibauth.php
    incubator/vcl/trunk/web/shibauth/
    incubator/vcl/trunk/web/shibauth/.htaccess
    incubator/vcl/trunk/web/shibauth/index.php
Modified:
    incubator/vcl/trunk/web/.ht-inc/authentication.php
    incubator/vcl/trunk/web/.ht-inc/conf.php
    incubator/vcl/trunk/web/.ht-inc/states.php
    incubator/vcl/trunk/web/.ht-inc/utils.php
    incubator/vcl/trunk/web/index.php

Modified: incubator/vcl/trunk/web/.ht-inc/authentication.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/authentication.php?rev=734842&r1=734841&r2=734842&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/authentication.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/authentication.php Thu Jan 15 14:40:30 2009
@@ -35,14 +35,19 @@
 /// a timestamp
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function getAuthCookieData($loginid, $valid=600) {
+function getAuthCookieData($loginid, $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";
-	$cdata = "$loginid|$remoteIP|$ts";
+	if($shibauthid)
+		$cdata = "$loginid|$remoteIP|$ts|$shibauthid";
+	else
+		$cdata = "$loginid|$remoteIP|$ts";
 
+	# 245 characters can be encrypted; anything over that, and
+	#   openssl_private_encrypt will fail
 	if(! openssl_private_encrypt($cdata, $cryptdata, $keys["private"]))
 		return "Failed to encrypt cookie data";
 
@@ -53,26 +58,16 @@
 ///
 /// \fn readAuthCookie()
 ///
-/// \return on success, an array with the following indices:\n
-/// \b userid - numeric user id\n
-/// \b first - first name\n
-/// \b middle - middle name (may be an empty string)\n
-/// \b last - last name\n
-/// \b email - email address\n
-/// \b created - timestamp of account creation (in mysql datetime format)\n
-/// \b ts - timestamp that authentication cookie will expire (in unix timestamp
-/// format)\n
-/// \b type - 'fixed' or 'floating' - fixed = tied to specific IP address;
-/// floating = not tied to any IP address (only fixed is supported at this time)\n
-/// \b remoteIP - empty for type 'floating'; user's IP address for type 'fixed'
-///
-/// \brief parses the ITECSAUTH cookie and returns an array; on failure, returns
-/// an empty array.  You will then need to call ITECSAUTH_getError to get
-/// the reason.
+/// \return on success, userid of user in VCLAUTH cookie in user@affil form;
+/// NULL on failure
+///
+/// \brief parses the VCLAUTH cookie to get the contained userid; also checks
+/// that the contained remoteIP matches the current remoteIP and that the cookie
+/// has not expired
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function readAuthCookie() {
-	global $keys, $AUTHERROR;
+	global $keys, $AUTHERROR, $shibauthed;
 	if(get_magic_quotes_gpc())
 		$cookie = stripslashes($_COOKIE["VCLAUTH"]);
 	else
@@ -87,6 +82,25 @@
 	$loginid = $tmparr[0];
 	$remoteIP = $tmparr[1];
 	$ts = $tmparr[2];
+	if(count($tmparr) > 3) {
+		$shibauthed = $tmparr[3];
+	
+		# check to see if shibauth entry still exists for $shibauthed
+		$query = "SELECT ts FROM shibauth WHERE id = $shibauthed";
+		$qh = doQuery($query, 101);
+		if($row = mysql_fetch_assoc($qh)) {
+			$shibstart = $row['ts'];
+			# TODO if $shibstart is too old, expire the login session
+		}
+		else {
+			# user should have been logged out, log them out now
+			setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN);
+			stopSession();
+			dbDisconnect();
+			header("Location: " . BASEURL);
+			exit;
+		}
+	}
 
    if($ts < time()) {
       $AUTHERROR["code"] = 4;
@@ -409,9 +423,9 @@
 		$cookie = getAuthCookieData("$userid@" . getAffiliationName($authMechs[$authtype]['affiliationid']));
 		// 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, 0);
 		# set skin cookie based on affiliation
 		/*if(getAffiliationName($authMechs[$authtype]['affiliationid']) == 'EXAMPLE1')
 			setcookie("VCLSKIN", "EXAMPLE1", (time() + (SECINDAY * 31)), "/", COOKIEDOMAIN);
@@ -452,9 +466,9 @@
 		//set cookie
 		$cookie = getAuthCookieData("$userid@local");
 		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);
 		//load main page
 		setcookie("VCLSKIN", "NCSU", (time() + (SECINDAY * 31)), "/", COOKIEDOMAIN);
 		header("Location: " . BASEURL . SCRIPT);

Added: incubator/vcl/trunk/web/.ht-inc/authmethods/shibauth.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/authmethods/shibauth.php?rev=734842&view=auto
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/authmethods/shibauth.php (added)
+++ incubator/vcl/trunk/web/.ht-inc/authmethods/shibauth.php Thu Jan 15 14:40:30 2009
@@ -0,0 +1,155 @@
+<?php
+/**
+ * \file
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn updateShibUser($userid)
+///
+/// \param $userid - id of a user in userid@affiliation form
+///
+/// \return an array with these keys:\n
+/// \b firstname
+/// \b lastname
+/// \b email
+/// \b unityid - userid for user
+/// \b affilid - id from affiliation table for user's affiliation
+/// \b id - id of user from user table
+///
+/// \brief updates user's first name, last name, and email address, and
+/// lastupdated timestamp in the user table from data provided by shibboleth
+///
+////////////////////////////////////////////////////////////////////////////////
+function updateShibUser($userid) {
+	global $mysql_link_vcl;
+	getAffilidAndLogin($userid, $affilid);
+
+	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']);
+			$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']);
+			$displast = array_pop($names);
+			$user['firstname'] = implode(' ', $names);
+		}
+	}
+	else
+		$user['firstname'] = $_SERVER['givenName'];
+	if(array_key_exists('sn', $_SERVER))
+		$user["lastname"] = $_SERVER['sn'];
+	else
+		$user['lastname'] = $displast;
+	$user["email"] = $_SERVER['mail'];
+	$user['unityid'] = $userid;
+	$user['affilid'] = $affilid;
+
+	# check to see if this user already exists in our db
+	$query = "SELECT id "
+	       . "FROM user "
+	       . "WHERE unityid = '$userid' AND "
+	       .       "affiliationid = $affilid";
+	$qh = doQuery($query, 101);
+	if(! $row = mysql_fetch_assoc($qh))
+		# add user to our db
+		return addShibUser($user);
+
+	# update user's data in db
+	$user['id'] = $row['id'];
+	$query = "UPDATE user "
+	       . "SET firstname = '{$user['firstname']}', "
+	       .     "lastname = '{$user['lastname']}', "
+	       .     "email = '{$user['email']}', " 
+	       .     "emailnotices = 0, " 
+	       .     "lastupdated = NOW() " 
+	       . "WHERE uid = {$user['id']}";
+	doQuery($query, 101, 'vcl', 1);
+	return $user;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn addShibUser($user)
+///
+/// \param $user - array of user data with these keys:\n
+/// \b unityid - userid\n
+/// \b affilid - id from affiliation table matching user's affiliation\n
+/// \b firstname\n
+/// \b lastname\n
+/// \b email
+///
+/// \return an array with all of the values from $user along with an additional
+/// key named 'id' that is the new user's id from the user table
+///
+/// \brief adds $user to the user table
+///
+////////////////////////////////////////////////////////////////////////////////
+function addShibUser($user) {
+	global $mysql_link_vcl;
+	$query = "INSERT INTO user "
+	       .        "(unityid, "
+	       .        "affiliationid, "
+	       .        "firstname, "
+	       .        "lastname, "
+	       .        "email, "
+	       .        "emailnotices, "
+	       .        "lastupdated) "
+	       . "VALUES ("
+	       .        "'{$user['unityid']}', "
+	       .        "{$user['affilid']}, "
+	       .        "'{$user['firstname']}', "
+	       .        "'{$user['lastname']}', "
+	       .        "'{$user['email']}', "
+	       .        "0, "
+	       .        "NOW())";
+	doQuery($query, 101, 'vcl', 1);
+	if(mysql_affected_rows($mysql_link_vcl)) {
+		$user['id'] = mysql_insert_id($mysql_link_vcl);
+		return $user;
+	}
+	else
+		return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn updateShibGroups($usernid, $groups)
+///
+/// \param $usernid - id from user table
+/// \param $groups - data provided in the eduPersonScopedAffiliation attribute
+///
+/// \brief converts the shibboleth affiliation to VCL affiliation, prepends
+/// 'shib-' to each of the group names and calls updateGroups to add the user
+/// to each of the shibboleth groups
+///
+////////////////////////////////////////////////////////////////////////////////
+function updateShibGroups($usernid, $groups) {
+	$groups = explode(';', $groups);
+	$newusergroups = array();
+	foreach($groups as $group) {
+		# make sure $group contains non-whitespace
+		if(! preg_match('/\w/', $group))
+			continue;
+		list($name, $shibaffil) = explode('@', $group);
+		# get id for the group's affiliation
+		$query = "SELECT id FROM affiliation WHERE shibname = '$shibaffil'";
+		$qh = doQuery($query, 101);
+		$row = mysql_fetch_assoc($qh);
+		$affilid = $row['id'];
+		# prepend shib- and escape it for mysql
+		$grp = mysql_escape_string("shib-" . $name);
+		array_push($newusergroups, getUserGroupID($grp, $affilid));
+	}
+	$newusergroups = array_unique($newusergroups);
+	if(! empty($newusergroups))
+		updateGroups($newusergroups, $usernid);
+}
+
+?>

Modified: incubator/vcl/trunk/web/.ht-inc/conf.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/conf.php?rev=734842&r1=734841&r2=734842&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/conf.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/conf.php Thu Jan 15 14:40:30 2009
@@ -77,6 +77,10 @@
 	"Local Account"    => array("type" => "local",
 	                            "affiliationid" => 4,
 	                            "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",
+	                     "affiliationid" => 0,
+	                     "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",
 	                           "server" => "ldap.example.com",   # hostname of the ldap server
 	                           "binddn" => "dc=example,dc=com",  # base dn for ldap server
@@ -124,4 +128,5 @@
 
 #require_once(".ht-inc/authmethods/itecsauth.php");
 #require_once(".ht-inc/authmethods/ldapauth.php");
+#require_once(".ht-inc/authmethods/shibauth.php");
 ?>

Modified: incubator/vcl/trunk/web/.ht-inc/states.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/states.php?rev=734842&r1=734841&r2=734842&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/states.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/states.php Thu Jan 15 14:40:30 2009
@@ -42,6 +42,7 @@
                           'helpform',
                           'viewdocs',
                           'logout',
+                          'shiblogout',
                           'xmlrpccall',
                           'selectauth',
                           'xmlrpcaffiliations',
@@ -583,5 +584,7 @@
 $actions['pages']['continuationsError'] = "misc";
 $actions['pages']['clearCache'] = "misc";
 $actions['pages']['errorrpt'] = "misc";
+$actions['pages']['logout'] = "misc";
+$actions['pages']['shiblogout'] = "misc";
 
 ?>

Modified: incubator/vcl/trunk/web/.ht-inc/utils.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/utils.php?rev=734842&r1=734841&r2=734842&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/utils.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/utils.php Thu Jan 15 14:40:30 2009
@@ -160,6 +160,12 @@
 		if(! is_null($userid))
 			$authed = 1;
 	}
+	elseif(preg_match('/_shibsession/', join(',', array_keys($_COOKIE)))) {
+		# redirect to shibauth directory
+		header('Location: ' . BASEURL . "/shibauth/");
+		dbDisconnect();
+		exit;
+	}
 	# end auth check
 
 	if($authed && $mode == 'selectauth')
@@ -189,6 +195,7 @@
 
 		require_once(".ht-inc/requests.php");
 		if($mode != "logout" &&
+			$mode != "shiblogout" &&
 			$mode != "vcldquery" &&
 			$mode != "xmlrpccall" &&
 			$mode != "xmlrpcaffiliations" &&
@@ -3117,7 +3124,8 @@
 	       .        "u.mapprinters AS mapprinters, "
 	       .        "u.mapserial AS mapserial, "
 	       .        "u.showallgroups, "
-	       .        "u.lastupdated AS lastupdated "
+	       .        "u.lastupdated AS lastupdated, "
+	       .        "af.shibonly "
 	       . "FROM user u, "
 	       .      "curriculum c, "
 	       .      "IMtype i, "
@@ -3136,7 +3144,8 @@
 	if($user = mysql_fetch_assoc($qh)) {
 		if((datetimeToUnix($user["lastupdated"]) > time() - SECINDAY) ||
 		   $user['unityid'] == 'vclreload' ||
-		   $user['affiliation'] == 'Local') {
+		   $user['affiliation'] == 'Local' ||
+		   $user['shibonly']) {
 			# get user's groups
 			$user["groups"] = getUsersGroups($user["id"], 1);
 
@@ -7991,6 +8000,45 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
+/// \fn getShibauthData($id)
+///
+/// \param $id - id for entry in shibauth table
+///
+/// \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 getShibauthData($id) {
+	$query = "SELECT id, "
+	       .        "userid, "
+	       .        "ts, "
+	       .        "sessid, "
+	       .        "data "
+	       . "FROM shibauth "
+	       . "WHERE id = $id";
+	$qh = doQuery($query, 101);
+	if($row = mysql_fetch_assoc($qh)) {
+		$data = unserialize($row['data']);
+		unset($row['data']);
+		$data2 = array_merge($row, $data);
+		return $data2;
+	}
+	return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \fn xmlrpccall()
 ///
 /// \brief registers all functions available to xmlrpc, handles the current
@@ -8321,6 +8369,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 function sendHeaders() {
 	global $mode, $user, $authed, $oldmode, $viewmode, $actionFunction, $skin;
+	global $shibauthed;
 	$setwrapreferer = processInputVar('am', ARG_NUMERIC, 0);
 	if(! $authed && $mode == "auth") {
 		/*if($oldmode != "auth" && $oldmode != "" && array_key_exists('mode', $_GET)) {
@@ -8346,12 +8395,59 @@
 			$cookieHeaderString = "WRAP_REFERER=https://vcl.ncsu.edu/; path=/; domain=" . COOKIEDOMAIN;
 		header("Set-Cookie: $cookieHeaderString");
 	}
-	if($mode == "logout") {
-		setcookie("VCLAUTH", "", time() - 10, "/", COOKIEDOMAIN);
-		header("Location: " . HOMEURL);
-		stopSession();
-		dbDisconnect();
-		exit;
+	switch($mode) {
+		case 'logout':
+			if($shibauthed) {
+				$shibdata = getShibauthData($shibauthed);
+				dbDisconnect();
+				header("Location: {$shibdata['Shib-logouturl']}");
+				exit;
+			}
+		case 'shiblogout':
+			setcookie("WRAP16", "", time() - 10, "/", COOKIEDOMAIN);
+			setcookie("WRAP_REFERER", "", time() - 10, "/", COOKIEDOMAIN);
+			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);
+				stopSession();
+				dbDisconnect();
+				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 "      <iframe src=\"http://{$_SERVER['SERVER_NAME']}/Shibboleth.sso/Logout\" class=hidden>\n";
+				#print "      </iframe>\n";
+				/*if($mode == 'logout') {
+					print "      <iframe src=\"{$shibdata['Shib-logouturl']}\" class=hidden>\n";
+					print "      </iframe>\n";
+				}*/
+				print "   </body>\n";
+				print "</html>\n";
+				exit;
+			}
+			header("Location: " . HOMEURL);
+			stopSession();
+			dbDisconnect();
+			exit;
 	}
 	if($mode == "submitviewmode") {
 		$expire = time() + 31536000; //expire in 1 year

Modified: incubator/vcl/trunk/web/index.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/index.php?rev=734842&r1=734841&r2=734842&view=diff
==============================================================================
--- incubator/vcl/trunk/web/index.php (original)
+++ incubator/vcl/trunk/web/index.php Thu Jan 15 14:40:30 2009
@@ -40,6 +40,7 @@
 $cache['unityids'] = array();
 $cache['nodeprivs']['resources'] = array();
 $docreaders = array();
+$shibauthed = 0;
 
 require_once(".ht-inc/states.php");
 

Added: incubator/vcl/trunk/web/shibauth/.htaccess
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/shibauth/.htaccess?rev=734842&view=auto
==============================================================================
--- incubator/vcl/trunk/web/shibauth/.htaccess (added)
+++ incubator/vcl/trunk/web/shibauth/.htaccess Thu Jan 15 14:40:30 2009
@@ -0,0 +1,3 @@
+AuthType shibboleth
+ShibRequireSession Off
+require shibboleth

Added: incubator/vcl/trunk/web/shibauth/index.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/shibauth/index.php?rev=734842&view=auto
==============================================================================
--- incubator/vcl/trunk/web/shibauth/index.php (added)
+++ incubator/vcl/trunk/web/shibauth/index.php Thu Jan 15 14:40:30 2009
@@ -0,0 +1,206 @@
+<?php
+chdir("..");
+require_once('.ht-inc/conf.php');
+
+header("Cache-Control: no-cache, must-revalidate");
+header("Expires: Sat, 1 Jan 2000 00:00:00 GMT");
+
+if(! array_key_exists('eppn', $_SERVER) ||
+   ! array_key_exists('mail', $_SERVER) ||
+   (! (array_key_exists('sn', $_SERVER) &&
+   array_key_exists('givenName', $_SERVER)) &&
+   ! array_key_exists('displayName', $_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
+		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");
+		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 all of these<br>\n";
+	print "attributes:<br>\n";
+	print "<ul>\n";
+	print "<li>eduPersonPrincipalName</li>\n";
+	print "<li>mail</li>\n";
+	print "</ul>\n";
+	print "and either:\n";
+	print "<ul>\n";
+	print "<li>sn and givenName</li>\n";
+	print "</ul>\n";
+	print "or:\n";
+	print "<ul>\n";
+	print "<li>displayName</li>\n";
+	print "</ul>\n";
+	print "You need to contact the administrator of your institution's<br>\n";
+	print "IdP to have all of those attributes be available to VCL in<br>\n";
+	print "order to log in using Shibboleth.\n";
+	exit;
+}
+
+require_once('.ht-inc/utils.php');
+require_once('.ht-inc/errors.php');
+function getFooter() {}
+$noHTMLwrappers = array();
+
+dbConnect();
+
+// 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']);
+$username = strtolower($tmp[0]);
+$tmp1 = 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 = mysql_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 "
+	       . "FROM affiliation "
+	       . "WHERE name LIKE '$affilname%' "
+	       . "ORDER BY name DESC "
+	       . "LIMIT 1";
+	$qh = doQuery($query, 101);
+	if($row = mysql_fetch_assoc($qh)) {
+		if(preg_match("/$affilname([0-9]+)/", $row['name'], $matches)) {
+			$cnt = $matches[1];
+			$cnt++;
+			$newaffilname = $affilname . $cnt;
+		}
+		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"
+			     . "mail: {$_SERVER['mail']}\n\n"
+			     . "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', "
+	       .        "'" . 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);
+
+# 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' => $_SERVER['Shib-logouturl'],
+                  'eppn' => $_SERVER['Shib-logouturl'],
+                  'unscoped-affiliation' => $_SERVER['unscoped-affiliation'],
+                  'affiliation' => $_SERVER['affiliation'],
+);
+$serdata = mysql_escape_string(serialize($shibdata));
+$query = "SELECT id "
+       . "FROM shibauth "
+       . "WHERE sessid = '{$_SERVER['Shib-Session-ID']}'";
+$qh = doQuery($query, 101);
+if($row = mysql_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 = mysql_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 'WakeTech':
+	case 'JohnstonCC':
+		$skin = strtoupper($affil);
+	case 'NCCU':
+	case 'ECU':
+	case 'UNCG':
+	case 'WCU':
+		setcookie("VCLSKIN", $skin, (time() + (SECINDAY * 31)), "/", COOKIEDOMAIN);
+		break;
+	default:
+		setcookie("VCLSKIN", "NCSU", (time() + (SECINDAY * 31)), "/", COOKIEDOMAIN);
+}
+header("Location: " . BASEURL . "/");
+dbDisconnect();
+?>