File/program/lib/dbsessionlib.php

Description

/program/lib/dbsessionlib.php - functions to keep PHP-sessions in the database

This file provides the functions to handle sessions via the database rather than via files or other standard PHP-mechanisms.

Useful information about storing sessions can be found in these user comments: http://php.net/manual/en/function.session-set-save-handler.php

Important issues:

  • there is an issue with writing session data when using a database class because the database class is already destroyed when PHP tries to write the session data. Workaround: call session_commit() (alias for session_write_close()) near the end of the script.
  • there is a security risk when the script simply accepts any session id that is presented via a cookie; a session should exist/be created before data is written and the session key should have been created in a previous call en thus be present in the database
  • different versions of PHP handle callback parameters differently where object methods are involved. The most generic way to work around these incompatibilities is to use global functions for open, close, etc. rather than methods in some session class.
  • session keys should be sanitised before manipulating the database in order to prevent an SQL injection.
  • session.auto_start may make it impossible to substitute our own session handlers if it is set in php.ini
  • how about locking a session?
There is a difference between the maximum session duration and the session time out. A session could last for 'duration' seconds but only if there is still activity at least every timeout seconds. There should be a maximum session lifetime of say 24 hours. There also should be a timeout of say 60 minutes.

Sessions are stored in a table called 'sessions'. This table is defined as follows:

session_id       serial
session_key      varchar(172)
session_data     longtext
user_id          int unsigned 
user_information varchar(255)
ctime            datetime
atime            datetime
primary key(session_id)
foreign key(user_id) references users(user_id)
unique index(session_key)

Note: the size of the session_key was reduced from 255 to 172 after version 2011051100 to prevent database problems (see update_core_2011092100()).

Functions
dbsession_close (line 217)

'close' a session that was opened with dbsession_open() before

Since this function has no way to tell _which_ session should be closed, it is utterly useless (but it has to exist to satisfy session_set_save_handler()) The function dbsession_open() has the same uselessness, so they are a perfect pair.

  • return: always TRUE because this is really a dummy function
  • todo: should we do something with locking the session record from dbsession_open() until dbsession_close()? For now, the session record is not locked in any way, so the latest call gets to keep its changes Mmmm....
bool dbsession_close ()
dbsession_create (line 128)

create a new session in the session table, return the unique sessionkey

this creates generates a new unique session key and stores it in a new record in the sessions table. Additional information is recorded in the new record too: the user_id and auxiliary information. This information makes that a session can always be linked to a particular user (which is handy when dealing with locked pages, etc.). This routine attempts to create a unique session key a number of times. If it doesn't work out, the routine returns FALSE.

the optional parameter $user_information can be used to store additional information about this user, e.g. the IP-address. This is useful for generating messages like 'Node xxx is currently locked by user YYYY logged in from ZZZZ'.

Note that the generation of a unique session key is salted with both the main url of this website and the special salt that was recorded once during installation time. Also, pseudo-random data is added via rand(). Hopefully this will be hard to guess, even though we use md5() to condense this (semi-)random information into only 128 bits.

  • return: FALSE on error, the unique session key ('token') on success
  • todo: should we also record the IP-address of the user in the session record? In a way this is a case of information leak, even though it is only between authenticated users. Mmmm...
  • uses: $DB
  • uses: $CFG
bool|string dbsession_create (int $user_id, [string $user_information = ''])
  • int $user_id: link to the users table, identifies the user that started the session
  • string $user_information: (optional) auxiliary information about the user, e.g. the IP-address
dbsession_destroy (line 270)

remove a session record from the sessions table (it should still exist)

remove the specified record from the sessions table. it is an error if the record does not exist.

  • return: FALSE on failure, TRUE otherwise
bool dbsession_destroy (string $session_key)
  • string $session_key: the unique session_key that identifies the session
dbsession_exists (line 162)

check to see if $session_key exists in the session table

This checks the existence of a session in the sessions table. Session keys are only generated from dbsession_create(). This prevents us accepting spurious session keys via a manipulated cookie. If the session key does not exist, the call fails and FALSE is returned.

  • return: FALSE on failure or non-existing, TRUE otherwise
bool dbsession_exists (string $session_key)
  • string $session_key: the unique session_key that identifies the session
dbsession_expire (line 316)

remove all sessions that were created more than $max_life seconds ago

not only are sessions terminated when there is no more activity for $time_out seconds (@see dbsession_garbage_collection()) but also the total lifetime of a session is limited to $life_time seconds. This routine is not part of the required session handlers but it can be called periodically (@see cron.php}.

bool dbsession_expire (int $max_lifetime)
  • int $max_lifetime: the lifetime value to automatically expire sessions (in seconds)
dbsession_garbage_collection (line 294)

remove all sessions that are last accessed more than $time_out seconds ago, maybe even more

we have our own session expire limit in $CFG->session_expiry and we overrule the $ime_out value here (ie. we ignore the php.ini setting) A session times out after $CFG->session_expiry seconds of inactivity. Also a session is terminated twice that amount of time after the start of the session. Both checks are performed here.

bool dbsession_garbage_collection (int $time_out)
  • int $time_out: the time-out value to automatically expire sessions (in seconds)
dbsession_get_session_id (line 176)

retrieve the session_id (pkey) that corresponds with session_key

this is very similar to dbsession_exists(). This routine returns the actual session_id integer, whereas dbsession_exists() only returns TRUE.

  • return: FALSE on failure or non-existing, session_id (primary key) otherwise
int|bool dbsession_get_session_id (string $session_key)
  • string $session_key: the unique session_key that identifies the session
dbsession_open (line 198)

'open' a session

this 'opens' a session. note that this function is unable to identify the session because it is only presented with

  • the $save_path (which is relevant only with file-based session handlers)
  • the $session_name (which is the _name_ of the session, but not the _token_)
there is no way to let this function do anything useful, so it boils down to a dummy always returning TRUE. The function dbsession_close() has the same uselessness, so they are a perfect pair.

  • return: always returns TRUE
bool dbsession_open (string $save_path, string $session_name)
  • string $save_path: (unused) pathname relevant for file based session handler
  • string $session_name: (unused) the non-unique session_name that identifies the cookie in the user's browser
dbsession_read (line 227)

read the (serialised) session data from the database

  • return: empty string on failure, existing session data otherwise
string dbsession_read (string $session_key)
  • string $session_key: the unique session_key that identifies the session
dbsession_remove_obsolete_sessions (line 340)

workhorse for removing obsolete sessions from the database

this logs and subsequently removes obsolete sessions from the sessions table It is a workhorse function for both dbsession_garbage_collection() and dbsession_expire().

Session records are removed when the $time_field in the sessions table contains a date/time that is older than $seconds seconds ago. Before the records are removed, we retrieve them and log pertinent information from each one via logger(), for future reference.

Note that we try to continue with deleting records, even if the logging appears to have generated errors.

bool dbsession_remove_obsolete_sessions (int $seconds, string $time_field)
  • int $seconds: the period of time after which the session is obsolete
  • string $time_field: the field to use for time comparisons: either 'atime' or 'ctime'
dbsession_setup (line 88)

setup database based handlers for session management

this is basically shorthand for session_set_save_handler() this routine replaces the existing session handlers with the handlers specified below in this file.

bool dbsession_setup (string $session_name)
  • string $session_name: the name of the session (usually 'PHPSESSID' in generic PHP-applications)
dbsession_write (line 247)

write the (serialised) data to the database

  • return: FALSE on failure, TRUE otherwise
bool dbsession_write (string $session_key, string $session_data)
  • string $session_key: the unique session_key that identifies the session
  • string $session_data: the string with (serialised) session variables

Documentation generated on Tue, 28 Jun 2016 19:09:07 +0200 by phpDocumentor 1.4.0