ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
LogoutStore.php
Go to the documentation of this file.
1<?php
2
9
15 private static function createLogoutTable(\SimpleSAML\Store\SQL $store) {
16
17 $tableVer = $store->getTableVersion('saml_LogoutStore');
18 if ($tableVer === 2) {
19 return;
20 } elseif ($tableVer === 1) {
21 /* TableVersion 2 increased the column size to 255 which is the maximum length of a FQDN. */
22 $query = 'ALTER TABLE ' . $store->prefix . '_saml_LogoutStore MODIFY _authSource VARCHAR(255) NOT NULL';
23 try {
24 $ret = $store->pdo->exec($query);
25 } catch (Exception $e) {
26 SimpleSAML\Logger::warning($store->pdo->errorInfo());
27 return;
28 }
29 $store->setTableVersion('saml_LogoutStore', 2);
30 return;
31 }
32
33 $query = 'CREATE TABLE ' . $store->prefix . '_saml_LogoutStore (
34 _authSource VARCHAR(255) NOT NULL,
35 _nameId VARCHAR(40) NOT NULL,
36 _sessionIndex VARCHAR(50) NOT NULL,
37 _expire TIMESTAMP NOT NULL,
38 _sessionId VARCHAR(50) NOT NULL,
39 UNIQUE (_authSource, _nameID, _sessionIndex)
40 )';
41 $store->pdo->exec($query);
42
43 $query = 'CREATE INDEX ' . $store->prefix . '_saml_LogoutStore_expire ON ' . $store->prefix . '_saml_LogoutStore (_expire)';
44 $store->pdo->exec($query);
45
46 $query = 'CREATE INDEX ' . $store->prefix . '_saml_LogoutStore_nameId ON ' . $store->prefix . '_saml_LogoutStore (_authSource, _nameId)';
47 $store->pdo->exec($query);
48
49 $store->setTableVersion('saml_LogoutStore', 2);
50 }
51
52
58 private static function cleanLogoutStore(\SimpleSAML\Store\SQL $store) {
59
60 SimpleSAML\Logger::debug('saml.LogoutStore: Cleaning logout store.');
61
62 $query = 'DELETE FROM ' . $store->prefix . '_saml_LogoutStore WHERE _expire < :now';
63 $params = array('now' => gmdate('Y-m-d H:i:s'));
64
65 $query = $store->pdo->prepare($query);
66 $query->execute($params);
67 }
68
69
78 private static function addSessionSQL(\SimpleSAML\Store\SQL $store, $authId, $nameId, $sessionIndex, $expire, $sessionId) {
79 assert('is_string($authId)');
80 assert('is_string($nameId)');
81 assert('is_string($sessionIndex)');
82 assert('is_string($sessionId)');
83 assert('is_int($expire)');
84
86
87 if (rand(0, 1000) < 10) {
89 }
90
91 $data = array(
92 '_authSource' => $authId,
93 '_nameId' => $nameId,
94 '_sessionIndex' => $sessionIndex,
95 '_expire' => gmdate('Y-m-d H:i:s', $expire),
96 '_sessionId' => $sessionId,
97 );
98 $store->insertOrUpdate($store->prefix . '_saml_LogoutStore', array('_authSource', '_nameId', '_sessionIndex'), $data);
99 }
100
101
110 private static function getSessionsSQL(\SimpleSAML\Store\SQL $store, $authId, $nameId) {
111 assert('is_string($authId)');
112 assert('is_string($nameId)');
113
115
116 $params = array(
117 '_authSource' => $authId,
118 '_nameId' => $nameId,
119 'now' => gmdate('Y-m-d H:i:s'),
120 );
121
122 // We request the columns in lowercase in order to be compatible with PostgreSQL
123 $query = 'SELECT _sessionIndex AS _sessionindex, _sessionId AS _sessionid FROM ' . $store->prefix . '_saml_LogoutStore' .
124 ' WHERE _authSource = :_authSource AND _nameId = :_nameId AND _expire >= :now';
125 $query = $store->pdo->prepare($query);
126 $query->execute($params);
127
128 $res = array();
129 while ( ($row = $query->fetch(PDO::FETCH_ASSOC)) !== FALSE) {
130 $res[$row['_sessionindex']] = $row['_sessionid'];
131 }
132
133 return $res;
134 }
135
136
146 private static function getSessionsStore(\SimpleSAML\Store $store, $authId, $nameId, array $sessionIndexes) {
147 assert('is_string($authId)');
148 assert('is_string($nameId)');
149
150 $res = array();
151 foreach ($sessionIndexes as $sessionIndex) {
152 $sessionId = $store->get('saml.LogoutStore', $nameId . ':' . $sessionIndex);
153 if ($sessionId === NULL) {
154 continue;
155 }
156 assert('is_string($sessionId)');
157 $res[$sessionIndex] = $sessionId;
158 }
159
160 return $res;
161 }
162
163
177 public static function addSession($authId, $nameId, $sessionIndex, $expire) {
178 assert('is_string($authId)');
179 assert('is_string($sessionIndex) || is_null($sessionIndex)');
180 assert('is_int($expire)');
181
182 if ($sessionIndex === NULL) {
183 /* This IdP apparently did not include a SessionIndex, and thus probably does not
184 * support SLO. We still want to add the session to the data store just in case
185 * it supports SLO, but we don't want an LogoutRequest with a specific
186 * SessionIndex to match this session. We therefore generate our own session index.
187 */
189 }
190
192 if ($store === FALSE) {
193 // We don't have a datastore.
194 return;
195 }
196
197 // serialize and anonymize the NameID
198 // TODO: remove this conditional statement
199 if (is_array($nameId)) {
201 }
202 $strNameId = serialize($nameId);
203 $strNameId = sha1($strNameId);
204
205 /* Normalize SessionIndex. */
206 if (strlen($sessionIndex) > 50) {
208 }
209
211 $sessionId = $session->getSessionId();
212
213 if ($store instanceof \SimpleSAML\Store\SQL) {
214 self::addSessionSQL($store, $authId, $strNameId, $sessionIndex, $expire, $sessionId);
215 } else {
216 $store->set('saml.LogoutStore', $strNameId . ':' . $sessionIndex, $sessionId, $expire);
217 }
218 }
219
220
229 public static function logoutSessions($authId, $nameId, array $sessionIndexes) {
230 assert('is_string($authId)');
231
233 if ($store === FALSE) {
234 /* We don't have a datastore. */
235 return FALSE;
236 }
237
238 // serialize and anonymize the NameID
239 // TODO: remove this conditional statement
240 if (is_array($nameId)) {
242 }
243 $strNameId = serialize($nameId);
244 $strNameId = sha1($strNameId);
245
246 /* Normalize SessionIndexes. */
247 foreach ($sessionIndexes as &$sessionIndex) {
248 assert('is_string($sessionIndex)');
249 if (strlen($sessionIndex) > 50) {
251 }
252 }
253 unset($sessionIndex); // Remove reference
254
255 if ($store instanceof \SimpleSAML\Store\SQL) {
256 $sessions = self::getSessionsSQL($store, $authId, $strNameId);
257 } elseif (empty($sessionIndexes)) {
258 /* We cannot fetch all sessions without a SQL store. */
259 return FALSE;
260 } else {
262 $sessions = self::getSessionsStore($store, $authId, $strNameId, $sessionIndexes);
263
264 }
265
266 if (empty($sessionIndexes)) {
267 $sessionIndexes = array_keys($sessions);
268 }
269
271
272 $numLoggedOut = 0;
273 foreach ($sessionIndexes as $sessionIndex) {
274 if (!isset($sessions[$sessionIndex])) {
275 SimpleSAML\Logger::info('saml.LogoutStore: Logout requested for unknown SessionIndex.');
276 continue;
277 }
278
279 $sessionId = $sessions[$sessionIndex];
280
282 if ($session === NULL) {
283 SimpleSAML\Logger::info('saml.LogoutStore: Skipping logout of missing session.');
284 continue;
285 }
286
287 if (!$session->isValid($authId)) {
288 SimpleSAML\Logger::info('saml.LogoutStore: Skipping logout of session because it isn\'t authenticated.');
289 continue;
290 }
291
292 SimpleSAML\Logger::info('saml.LogoutStore: Logging out of session with trackId [' . $session->getTrackID() . '].');
293 $session->doLogout($authId);
294 $numLoggedOut += 1;
295 }
296
297 return $numLoggedOut;
298 }
299
300}
An exception for terminatinating execution or to throw for unit testing.
static fromArray(array $nameId)
Create a \SAML2\XML\saml\NameID object from an array with its contents.
Definition: NameIDType.php:87
static info($string)
Definition: Logger.php:201
static warning($string)
Definition: Logger.php:179
static debug($string)
Definition: Logger.php:213
static getSessionHandler()
This function retrieves the current instance of the session handler.
static getInstance()
Retrieve our singleton instance.
Definition: Store.php:31
static generateID()
Generate a random identifier, ID_LENGTH bytes long.
Definition: Random.php:26
static getSession($sessionId=null)
Get a session from the session handler.
Definition: Session.php:317
static getSessionFromRequest()
Retrieves the current session.
Definition: Session.php:243
static addSession($authId, $nameId, $sessionIndex, $expire)
Register a new session in the datastore.
static cleanLogoutStore(\SimpleSAML\Store\SQL $store)
Clean the logout table of expired entries.
Definition: LogoutStore.php:58
static addSessionSQL(\SimpleSAML\Store\SQL $store, $authId, $nameId, $sessionIndex, $expire, $sessionId)
Register a session in the SQL datastore.
Definition: LogoutStore.php:78
static getSessionsSQL(\SimpleSAML\Store\SQL $store, $authId, $nameId)
Retrieve sessions from the SQL datastore.
static getSessionsStore(\SimpleSAML\Store $store, $authId, $nameId, array $sessionIndexes)
Retrieve all session IDs from a key-value store.
static createLogoutTable(\SimpleSAML\Store\SQL $store)
Create logout table in SQL, if it is missing.
Definition: LogoutStore.php:15
if(! $oauthconfig->getBoolean('getUserInfo.enable', FALSE)) $store
Definition: getUserInfo.php:11
$nameId
Definition: saml2-acs.php:138
$expire
Definition: saml2-acs.php:140
$sessionIndex
Definition: saml2-acs.php:139
Attribute-related utility methods.
$ret
Definition: parser.php:6
$query
$session
foreach($_POST as $key=> $value) $res
$params
Definition: disable.php:11