Permalink
Browse files

Merge branch 'MDL-61351_34' of git://github.com/markn86/moodle into M…

…OODLE_34_STABLE
  • Loading branch information...
dmonllao committed Jul 17, 2018
2 parents b55fa75 + af4c2fb commit c650dd8568d4b12741c424e8a1ca218702758f62
Showing with 156 additions and 82 deletions.
  1. +123 −0 auth/shibboleth/classes/helper.php
  2. +8 −68 auth/shibboleth/logout.php
  3. +5 −0 auth/shibboleth/upgrade.txt
  4. +20 −14 lib/classes/session/manager.php
@@ -0,0 +1,123 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Contains a helper class for the Shibboleth authentication plugin.
*
* @package auth_shibboleth
* @copyright 2018 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace auth_shibboleth;
defined('MOODLE_INTERNAL') || die();
/**
* The helper class for the Shibboleth authentication plugin.
*
* @package auth_shibboleth
* @copyright 2018 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class helper {
/**
* Delete session of user using file sessions.
*
* @param string $spsessionid SP-provided Shibboleth Session ID
* @return \SoapFault or void if everything was fine
*/
public static function logout_file_session($spsessionid) {
global $CFG;
if (!empty($CFG->session_file_save_path)) {
$dir = $CFG->session_file_save_path;
} else {
$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)) {
// Read session file data.
$data = file($dir.'/'.$file);
if (isset($data[0])) {
$usersession = self::unserializesession($data[0]);
// Check if we have found session that shall be deleted.
if (isset($usersession['SESSION']) && isset($usersession['SESSION']->shibboleth_session_id)) {
// If there is a match, delete file.
if ($usersession['SESSION']->shibboleth_session_id == $spsessionid) {
// Delete session file.
if (!unlink($dir.'/'.$file)) {
return new SoapFault('LogoutError', 'Could not delete Moodle session file.');
}
}
}
}
}
}
closedir($dh);
}
}
}
/**
* Delete session of user using DB sessions.
*
* @param string $spsessionid SP-provided Shibboleth Session ID
*/
public static function logout_db_session($spsessionid) {
global $CFG, $DB;
$sessions = $DB->get_records_sql(
'SELECT userid, sessdata FROM {sessions} WHERE timemodified > ?',
array(time() - $CFG->sessiontimeout)
);
foreach ($sessions as $session) {
// Get user session from DB.
if (session_decode(base64_decode($session->sessdata))) {
if (isset($_SESSION['SESSION']) && isset($_SESSION['SESSION']->shibboleth_session_id)) {
// If there is a match, kill the session.
if ($_SESSION['SESSION']->shibboleth_session_id == trim($spsessionid)) {
// Delete this user's sessions.
\core\session\manager::kill_user_sessions($session->userid);
}
}
}
}
}
/**
* Unserialize a session string.
*
* @param string $serializedstring
* @return array
*/
private static function unserializesession($serializedstring) {
$variables = array();
$a = preg_split("/(\w+)\|/", $serializedstring, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
$counta = count($a);
for ($i = 0; $i < $counta; $i = $i + 2) {
$variables[$a[$i]] = unserialize($a[$i + 1]);
}
return $variables;
}
}
@@ -127,75 +127,15 @@
* @return SoapFault or void if everything was fine
*/
function LogoutNotification($spsessionid) {
global $CFG, $SESSION, $DB;
// Delete session of user using $spsessionid.
if(empty($CFG->dbsessions)) {
// 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)){
$session_key = preg_replace('/sess_/', '', $file);
// Read session file data
$data = file($dir.'/'.$file);
if (isset($data[0])){
$usersession = unserializesession($data[0]);
// Check if we have found session that shall be deleted
if (isset($usersession['SESSION']) && isset($usersession['SESSION']->shibboleth_session_id)) {
// If there is a match, delete file
if ($usersession['SESSION']->shibboleth_session_id == $spsessionid) {
// Delete session file
if (!unlink($dir.'/'.$file)){
return new SoapFault('LogoutError', 'Could not delete Moodle session file.');
}
}
}
}
}
}
closedir($dh);
}
}
} else {
// DB Sessions.
$sessions = $DB->get_records_sql(
'SELECT userid, sessdata FROM {sessions} WHERE timemodified > ?',
array(time() - $CFG->sessiontimeout)
);
foreach ($sessions as $session) {
// Get user session from DB.
if (session_decode(base64_decode($session->sessdata))) {
if (isset($_SESSION['SESSION']) && isset($_SESSION['SESSION']->shibboleth_session_id)) {
// If there is a match, kill the session.
if ($_SESSION['SESSION']->shibboleth_session_id == trim($spsessionid)) {
// Delete this user's sessions.
\core\session\manager::kill_user_sessions($session->userid);
}
}
}
}
$sessionclass = \core\session\manager::get_handler_class();
switch ($sessionclass) {
case '\core\session\file':
return \auth_shibboleth\helper::logout_file_session($spsessionid);
case '\core\session\database':
return \auth_shibboleth\helper::logout_db_session($spsessionid);
default:
throw new moodle_exception("Shibboleth logout not implemented for '$sessionclass'");
}
// If no SoapFault was thrown, the function will return OK as the SP assumes.
}
/*****************************************************************************/
// Same function as in adodb, but cannot be used for file session for some reason...
function unserializesession($serialized_string) {
$variables = array();
$a = preg_split("/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
$counta = count($a);
for ($i = 0; $i < $counta; $i = $i+2) {
$variables[$a[$i]] = unserialize($a[$i+1]);
}
return $variables;
}
@@ -1,6 +1,11 @@
This files describes API changes in /auth/shibboleth/*,
information provided here is intended especially for developers.
=== 3.4.5 ===
* Moved the public function unserializesession in auth/shibboleth/logout.php to auth/shibboleth/classes/helper.php and
made it private. This function should not have been used outside of this file.
=== 3.3 ===
* The config.html file was migrated to use the admin settings API.
@@ -123,28 +123,34 @@ public static function get_performance_info() {
}
/**
* Create handler instance.
* Get fully qualified name of session handler class.
*
* @return string The name of the handler class
*/
protected static function load_handler() {
public static function get_handler_class() {
global $CFG, $DB;
if (self::$handler) {
return;
}
// Find out which handler to use.
if (PHPUNIT_TEST) {
$class = '\core\session\file';
return '\core\session\file';
} else if (!empty($CFG->session_handler_class)) {
$class = $CFG->session_handler_class;
return $CFG->session_handler_class;
} else if (!empty($CFG->dbsessions) and $DB->session_lock_supported()) {
$class = '\core\session\database';
return '\core\session\database';
}
} else {
$class = '\core\session\file';
return '\core\session\file';
}
/**
* Create handler instance.
*/
protected static function load_handler() {
if (self::$handler) {
return;
}
// Find out which handler to use.
$class = self::get_handler_class();
self::$handler = new $class();
}

0 comments on commit c650dd8

Please sign in to comment.