diff --git a/lib/SimpleSAML/SessionHandler.php b/lib/SimpleSAML/SessionHandler.php new file mode 100644 index 0000000000000000000000000000000000000000..cefe7b0c1e5c3c270d9203ca06291ebd928a9ec2 --- /dev/null +++ b/lib/SimpleSAML/SessionHandler.php @@ -0,0 +1,126 @@ +<?php + +/* + * This file defines a base class for session handling. + * Instantiation of session handler objects should be done through + * the class method getSessionHandler(). + */ + +/* We need access to the configuration from config/config.php. */ +require_once('SimpleSAML/Configuration.php'); + + +abstract class SimpleSAML_SessionHandler { + + + /* This static variable contains a reference to the current + * instance of the session handler. This variable will be NULL if + * we haven't instantiated a session handler yet. + */ + private static $sessionHandler = NULL; + + + + /* This function retrieves the current instance of the session handler. + * The session handler will be instantiated if this is the first call + * to this fuunction. + * + * Returns: + * The current session handler. + */ + public static function getSessionHandler() { + if(self::$sessionHandler === NULL) { + self::createSessionHandler(); + } + + return self::$sessionHandler; + } + + + /* This constructor is included in case it is needed in the the + * future. Including it now allows us to write parent::__construct() in + * the subclasses of this class. + */ + protected function __construct() { + } + + + /* This function is used to store data in this session object. + * + * Note: You are allowed to store a reference to an object in the + * session. We will store the latest value the object has on script + * termination. + * + * Parameters: + * $key The key we are going to set the value of. This key must + * be an alphanumeric string. + * $value The value the key should have. + */ + abstract public function set($key, $value); + + + /* This function retrieves a value from this session object. + * + * Parameters: + * $key The key we are going to retrieve the value of. This key + * must be an alphanumeric string. + * + * Returns: + * The value of the key, or NULL if no value is associated with + * this key. + */ + abstract public function get($key); + + + /* This function creates an instance of the session handler which is + * selected in the 'session.handler' configuration directive. If no + * session handler is selected, then we will fall back to the default + * PHP session handler. + */ + public static function createSessionHandler() { + /* Get the configuration. */ + $config = SimpleSAML_Configuration::getInstance(); + assert($config instanceof SimpleSAML_Configuration); + + /* Get the session handler option from the configuration. */ + $handler = $config->getValue('session.handler'); + + /* If 'session.handler' is NULL or unset, then we want + * to fall back to the default PHP session handler. + */ + if(is_null($handler)) { + $handler = 'phpsession'; + } + + + /* The session handler must be a string. */ + if(!is_string($handler)) { + $e = 'Invalid setting for the \'session.handler\'' . + ' configuration option. This option should be' . + ' set to a valid string.'; + error_log($e); + die($e); + } + + $handler = strtolower($handler); + + if($handler === 'phpsession') { + require_once('SimpleSAML/SessionHandlerPHP.php'); + $sh = new SimpleSAML_SessionHandlerPHP(); + } else if($handler === 'memcache') { + require_once('SimpleSAML/SessionHandlerMemcache.php'); + $sh = new SimpleSAML_SessionHandlerMemcache(); + } else { + $e = 'Invalid value for the \'session.handler\'' . + ' configuration option. Unknown session' . + ' handler: ' . $handler; + error_log($e); + die($e); + } + + /* Set the session handler. */ + self::$sessionHandler = $sh; + } +} + +?> \ No newline at end of file diff --git a/lib/SimpleSAML/SessionHandlerCookie.php b/lib/SimpleSAML/SessionHandlerCookie.php new file mode 100644 index 0000000000000000000000000000000000000000..1c56d33686a3695c185f13cef286414d710e4b3e --- /dev/null +++ b/lib/SimpleSAML/SessionHandlerCookie.php @@ -0,0 +1,92 @@ +<?php + +/* + * This file defines a base class for session handlers that need to store + * the session id in a cookie. It takes care of storing and retrieving the + * session id. + */ + +/* We need access to the configuration from config/config.php. */ +require_once('SimpleSAML/Configuration.php'); + + +abstract class SimpleSAML_SessionHandlerCookie +extends SimpleSAML_SessionHandler { + + /* This variable contains the current session id. */ + protected $session_id = NULL; + + + + /* This constructor initializes the session id based on what + * we receive in a cookie. We create a new session id and set + * a cookie with this id if we don't have a session id. + */ + protected function __construct() { + /* Call the constructor in the base class in case it should + * become necessary in the future. + */ + parent::__construct(); + + /* Attempt to retrieve the session id from the cookie. */ + if(array_key_exists('SimpleSAMLSessionID', $_COOKIE)) { + $this->session_id = $_COOKIE['SimpleSAMLSessionID']; + } + + /* Check if we have a valid session id. */ + if(self::isValidSessionID($this->session_id)) { + /* We are done now if it was valid. */ + return; + } + + /* We don't have a valid session. Create a new session id. */ + $this->session_id = self::createSessionID(); + setcookie('SimpleSAMLSessionID', $this->session_id, 0, '/'); + } + + + /* This static function creates a session id. A session id consists + * of 32 random hexadecimal characters. + * + * Returns: + * A random session id. + */ + private static function createSessionID() { + $id = ''; + for($i = 0; $i < 32; $i++) { + /* TODO: Is rand(...) secure enough? */ + $id .= dechex(rand(0, 15)); + } + + return $id; + } + + + /* This static function validates a session id. A session id is valid + * if it only consists of characters which are allowed in a session id + * and it is the correct length. + * + * Parameters: + * $session_id The session id we should validate. + * + * Returns: + * TRUE if this session id is valid, FALSE if not. + */ + private static function isValidSessionID($session_id) { + if(!is_string($session_id)) { + return FALSE; + } + + if(strlen($session_id) != 32) { + return FALSE; + } + + if(preg_match('/[^0-9a-f]/', $session_id)) { + return FALSE; + } + + return TRUE; + } +} + +?> \ No newline at end of file diff --git a/lib/SimpleSAML/SessionHandlerMemcache.php b/lib/SimpleSAML/SessionHandlerMemcache.php new file mode 100644 index 0000000000000000000000000000000000000000..4dcffbd894dd5ce47efc82b42c88bbbf00cef25a --- /dev/null +++ b/lib/SimpleSAML/SessionHandlerMemcache.php @@ -0,0 +1,72 @@ +<?php + +/* This file defines a session handler which uses the MemcacheStore + * class to store data in memcache servers. + */ + +/* We use the MemcacheStore class to store session information. */ +require_once('SimpleSAML/MemcacheStore.php'); + +/* We base this session handler on the SessionHandlerCookie helper + * class. This saves us from having to handle session ids in this class. + */ +require_once('SimpleSAML/SessionHandlerCookie.php'); + + +class SimpleSAML_SessionHandlerMemcache +extends SimpleSAML_SessionHandlerCookie { + + + /* This variable contains a reference to the MemcacheStore object + * which contains the session data. + */ + private $store = NULL; + + + + /* Initialize the memcache session handling. This constructor is + * protected because it should only be called from + * SimpleSAML_SessionHandler::createSessionHandler(...). + */ + protected function __construct() { + + /* Call parent constructor to allow it to configure the session + * id. + */ + parent::__construct(); + + /* Load the session object if it already exists. */ + $this->store = SimpleSAML_MemcacheStore::find($this->session_id); + + if($this->store === NULL) { + /* We didn't find the session. This may be because the + * session has expired, or it could be because this is + * a new session. In any case we create a new session. + */ + $this->store = new SimpleSAML_MemcacheStore( + $this->session_id); + } + } + + + /* This function is used to store data in this session object. + * + * See the information in SimpleSAML_SessionHandler::set(...) for + * more information. + */ + public function set($key, $value) { + $this->store->set($key, $value); + } + + + /* This function retrieves a value from this session object. + * + * See the information in SimpleSAML_SessionHandler::get(...) for + * more information. + */ + public function get($key) { + return $this->store->get($key); + } +} + +?> \ No newline at end of file diff --git a/lib/SimpleSAML/SessionHandlerPHP.php b/lib/SimpleSAML/SessionHandlerPHP.php new file mode 100644 index 0000000000000000000000000000000000000000..b639ec51c59485c3b75829919657f77b02c45443 --- /dev/null +++ b/lib/SimpleSAML/SessionHandlerPHP.php @@ -0,0 +1,45 @@ +<?php + +/* This file defines a session handler which uses the default php + * session handler for storage. + */ + +class SimpleSAML_SessionHandlerPHP extends SimpleSAML_SessionHandler { + + /* Initialize the PHP session handling. This constructor is protected + * because it should only be called from + * SimpleSAML_SessionHandler::createSessionHandler(...). + */ + protected function __construct() { + + /* Call the parent constructor in case it should become + * necessary in the future. + */ + parent::__construct(); + + /* Initialize the php session handling. */ + session_start(); + } + + + /* This function is used to store data in this session object. + * + * See the information in SimpleSAML_SessionHandler::set(...) for + * more information. + */ + public function set($key, $value) { + $_SESSION[$key] = $value; + } + + + /* This function retrieves a value from this session object. + * + * See the information in SimpleSAML_SessionHandler::get(...) for + * more information. + */ + public function get($key) { + return $_SESSION[$key]; + } +} + +?> \ No newline at end of file