2009-11-01 11:55:14 +00:00
|
|
|
<?php
|
2008-12-04 16:28:42 +00:00
|
|
|
|
|
|
|
// Implements logout for Shibboleth authenticated users according to:
|
|
|
|
// - https://spaces.internet2.edu/display/SHIB2/NativeSPLogoutInitiator
|
|
|
|
// - https://spaces.internet2.edu/display/SHIB2/NativeSPNotify
|
|
|
|
|
|
|
|
require_once("../../config.php");
|
|
|
|
|
|
|
|
require_once($CFG->dirroot."/auth/shibboleth/auth.php");
|
|
|
|
|
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// Find out whether host supports https
|
|
|
|
$protocol = 'http://';
|
|
|
|
if ( isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on'){
|
2011-01-24 16:20:30 +08:00
|
|
|
$protocol = 'https://';
|
2009-11-01 11:55:14 +00:00
|
|
|
}
|
2009-03-18 13:28:57 +00:00
|
|
|
|
2008-12-04 16:28:42 +00:00
|
|
|
// Front channel logout
|
|
|
|
if (
|
2009-11-01 11:55:14 +00:00
|
|
|
isset($_GET['return'])
|
2009-03-18 13:28:57 +00:00
|
|
|
&& isset($_GET['action'])
|
|
|
|
&& $_GET['action'] == 'logout'
|
2008-12-04 16:28:42 +00:00
|
|
|
){
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// Logout out user from application
|
|
|
|
// E.g. destroy application session/cookie etc
|
|
|
|
require_logout();
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// Finally, send user to the return URL
|
|
|
|
redirect($_GET['return']);
|
2008-12-04 16:28:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Back channel logout
|
|
|
|
elseif (!empty($HTTP_RAW_POST_DATA)) {
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// Requires PHP 5
|
2009-11-01 11:55:14 +00:00
|
|
|
|
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// Set SOAP header
|
|
|
|
$server = new SoapServer($protocol.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'/LogoutNotification.wsdl');
|
2009-11-01 11:55:14 +00:00
|
|
|
|
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
$server->addFunction("LogoutNotification");
|
|
|
|
$server->handle();
|
2009-11-01 11:55:14 +00:00
|
|
|
}
|
2008-12-04 16:28:42 +00:00
|
|
|
|
|
|
|
// Return WSDL
|
|
|
|
else {
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
header('Content-Type: text/xml');
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
echo <<<WSDL
|
2008-12-04 16:28:42 +00:00
|
|
|
<?xml version ="1.0" encoding ="UTF-8" ?>
|
|
|
|
<definitions name="LogoutNotification"
|
|
|
|
targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
|
|
|
|
xmlns:notify="urn:mace:shibboleth:2.0:sp:notify"
|
|
|
|
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
|
|
|
xmlns="http://schemas.xmlsoap.org/wsdl/">
|
|
|
|
|
|
|
|
<!--
|
|
|
|
This page either has to be called with the GET arguments 'action' and 'return' via
|
2009-11-01 11:55:14 +00:00
|
|
|
a redirect from the Shibboleth Service Provider logout handler (front-channel
|
|
|
|
logout) or via a SOAP request by a Shibboleth Service Provider (back-channel
|
2008-12-04 16:28:42 +00:00
|
|
|
logout).
|
2009-11-01 11:55:14 +00:00
|
|
|
Because neither of these two variants seems to be the case, the WSDL file for
|
2008-12-04 16:28:42 +00:00
|
|
|
the web service is returned.
|
|
|
|
|
|
|
|
For more information see:
|
|
|
|
- https://spaces.internet2.edu/display/SHIB2/NativeSPLogoutInitiator
|
|
|
|
- https://spaces.internet2.edu/display/SHIB2/NativeSPNotify
|
|
|
|
-->
|
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
<types>
|
|
|
|
<schema targetNamespace="urn:mace:shibboleth:2.0:sp:notify"
|
|
|
|
xmlns="http://www.w3.org/2000/10/XMLSchema"
|
|
|
|
xmlns:notify="urn:mace:shibboleth:2.0:sp:notify">
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
<simpleType name="string">
|
|
|
|
<restriction base="string">
|
|
|
|
<minLength value="1"/>
|
|
|
|
</restriction>
|
|
|
|
</simpleType>
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
<element name="OK" type="notify:OKType"/>
|
|
|
|
<complexType name="OKType">
|
|
|
|
<sequence/>
|
|
|
|
</complexType>
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
</schema>
|
|
|
|
</types>
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
<message name="getLogoutNotificationRequest">
|
|
|
|
<part name="SessionID" type="notify:string" />
|
|
|
|
</message>
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
<message name="getLogoutNotificationResponse" >
|
|
|
|
<part name="OK"/>
|
|
|
|
</message>
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
<portType name="LogoutNotificationPortType">
|
|
|
|
<operation name="LogoutNotification">
|
|
|
|
<input message="getLogoutNotificationRequest"/>
|
|
|
|
<output message="getLogoutNotificationResponse"/>
|
|
|
|
</operation>
|
|
|
|
</portType>
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
<binding name="LogoutNotificationBinding" type="notify:LogoutNotificationPortType">
|
|
|
|
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
|
|
|
|
<operation name="LogoutNotification">
|
|
|
|
<soap:operation soapAction="urn:xmethods-logout-notification#LogoutNotification"/>
|
|
|
|
</operation>
|
|
|
|
</binding>
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
<service name="LogoutNotificationService">
|
|
|
|
<port name="LogoutNotificationPort" binding="notify:LogoutNotificationBinding">
|
|
|
|
<soap:address location="{$protocol}{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}"/>
|
|
|
|
</port>
|
|
|
|
</service>
|
2008-12-04 16:28:42 +00:00
|
|
|
</definitions>
|
|
|
|
WSDL;
|
2009-03-18 13:28:57 +00:00
|
|
|
exit;
|
2008-12-04 16:28:42 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
function LogoutNotification($SessionID){
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-23 05:19:53 +00:00
|
|
|
global $CFG, $SESSION, $DB;
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// Delete session of user using $SessionID
|
|
|
|
if(empty($CFG->dbsessions)) {
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// File session
|
|
|
|
$dir = $CFG->dataroot .'/sessions';
|
|
|
|
if (is_dir($dir)) {
|
|
|
|
if ($dh = opendir($dir)) {
|
|
|
|
// Read all session files
|
|
|
|
while (($file = readdir($dh)) !== false) {
|
|
|
|
// Check if it is a file
|
|
|
|
if (is_file($dir.'/'.$file)){
|
2009-11-17 01:36:35 +00:00
|
|
|
$session_key = preg_replace('/sess_/', '', $file);
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// Read session file data
|
|
|
|
$data = file($dir.'/'.$file);
|
|
|
|
if (isset($data[0])){
|
|
|
|
$user_session = unserializesession($data[0]);
|
2009-11-01 11:55:14 +00:00
|
|
|
|
|
|
|
// Check if we have found session that shall be deleted
|
2009-03-18 13:28:57 +00:00
|
|
|
if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// If there is a match, delete file
|
|
|
|
if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
|
|
|
|
// Delete session file
|
|
|
|
if (!unlink($dir.'/'.$file)){
|
|
|
|
return new SoapFault('LogoutError', 'Could not delete Moodle session file.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
closedir($dh);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// DB Session
|
2010-09-17 10:43:15 +00:00
|
|
|
//TODO: this needs to be rewritten to use new session stuff
|
2009-03-18 13:28:57 +00:00
|
|
|
if (!empty($CFG->sessiontimeout)) {
|
|
|
|
$ADODB_SESS_LIFE = $CFG->sessiontimeout;
|
|
|
|
}
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-23 05:19:53 +00:00
|
|
|
if ($user_session_data = $DB->get_records_sql('SELECT sesskey, sessdata FROM {sessions2} WHERE expiry > NOW()')) {
|
2009-03-18 13:28:57 +00:00
|
|
|
foreach ($user_session_data as $session_data) {
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// Get user session
|
|
|
|
$user_session = adodb_unserialize( urldecode($session_data->sessdata) );
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
if (isset($user_session['SESSION']) && isset($user_session['SESSION']->shibboleth_session_id)){
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// If there is a match, delete file
|
|
|
|
if ($user_session['SESSION']->shibboleth_session_id == $SessionID){
|
|
|
|
// Delete this session entry
|
|
|
|
if (ADODB_Session::destroy($session_data->sesskey) !== true){
|
|
|
|
return new SoapFault('LogoutError', 'Could not delete Moodle session entry in database.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2009-03-18 13:28:57 +00:00
|
|
|
// If now SoapFault was thrown the function will return OK as the SP assumes
|
2009-11-01 11:55:14 +00:00
|
|
|
|
2008-12-04 16:28:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
// Same function as in adodb, but cannot be used for file session for some reason...
|
2011-01-24 13:38:12 +08:00
|
|
|
function unserializesession($serialized_string) {
|
|
|
|
$variables = array();
|
|
|
|
$a = preg_split("/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
|
|
|
$counta = count($a);
|
2011-01-24 16:20:30 +08:00
|
|
|
for ($i = 0; $i < $counta; $i = $i+2) {
|
2011-01-24 13:38:12 +08:00
|
|
|
$variables[$a[$i]] = unserialize($a[$i+1]);
|
2009-03-18 13:28:57 +00:00
|
|
|
}
|
2011-01-24 16:20:30 +08:00
|
|
|
return $variables;
|
2008-12-04 16:28:42 +00:00
|
|
|
}
|