aboutsummaryrefslogtreecommitdiff
path: root/engine/lib/sessions.php
diff options
context:
space:
mode:
Diffstat (limited to 'engine/lib/sessions.php')
-rw-r--r--engine/lib/sessions.php1055
1 files changed, 643 insertions, 412 deletions
diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php
index 02a3e06ca..e3d5ce9cd 100644
--- a/engine/lib/sessions.php
+++ b/engine/lib/sessions.php
@@ -1,425 +1,656 @@
-<?php
-
- /**
- * Elgg session management
- * Functions to manage logins
- *
- * @package Elgg
- * @subpackage Core
- * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU Public License version 2
- * @author Curverider Ltd
- * @copyright Curverider Ltd 2008
- * @link http://elgg.org/
- */
-
- /**
- * Returns whether or not the user is currently logged in
- *
- * @uses $_SESSION
- * @return true|false
- */
- function isloggedin() {
-
- if (!is_installed()) return false;
- if ((isset($_SESSION['guid'])) && ($_SESSION['guid'] > 0) && (isset($_SESSION['id'])) && ($_SESSION['id'] > 0) )
-
- return true;
- return false;
-
- }
-
- /**
- * Returns whether or not the user is currently logged in and that they are an admin user.
- *
- * @uses $_SESSION
- * @uses isloggedin()
- * @return true|false
- */
- function isadminloggedin()
- {
- if ((isloggedin()) && (($_SESSION['user']->admin || $_SESSION['user']->siteadmin)))
- return true;
-
- return false;
- }
-
- /**
- * Perform standard authentication with a given username and password.
- * Returns an ElggUser object for use with login.
- *
- * @see login
- * @param string $username The username, optionally (for standard logins)
- * @param string $password The password, optionally (for standard logins)
- * @return ElggUser|false The authenticated user object, or false on failure.
- */
-
- function authenticate($username, $password) {
-
- if (pam_authenticate(array('username' => $username, 'password' => $password)))
- return get_user_by_username($username);
-
- return false;
-
- }
-
- /**
- * Hook into the PAM system which accepts a username and password and attempts to authenticate
- * it against a known user.
- *
- * @param array $credentials Associated array of credentials passed to pam_authenticate. This function expects
- * 'username' and 'password' (cleartext).
- */
- function pam_auth_userpass($credentials = NULL)
- {
- if (is_array($credentials) && ($credentials['username']) && ($credentials['password']))
- {
- //$dbpassword = md5($credentials['password']);
-
-
- if ($user = get_user_by_username($credentials['username'])) {
- // Let admins log in without validating their email, but normal users must have validated their email
- if ((!$user->admin) && (!$user->validated) && (!$user->admin_created))
- return false;
-
- if ($user->password == generate_user_password($user, $credentials['password'])) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Logs in a specified ElggUser. For standard registration, use in conjunction
- * with authenticate.
- *
- * @see authenticate
- * @param ElggUser $user A valid Elgg user object
- * @param boolean $persistent Should this be a persistent login?
- * @return true|false Whether login was successful
- */
- function login(ElggUser $user, $persistent = false) {
-
- global $CONFIG;
-
- $_SESSION['user'] = $user;
- $_SESSION['guid'] = $user->getGUID();
- $_SESSION['id'] = $_SESSION['guid'];
- $_SESSION['username'] = $user->username;
- $_SESSION['name'] = $user->name;
-
- $code = (md5($user->name . $user->username . time() . rand()));
-
- $user->code = md5($code);
-
- $_SESSION['code'] = $code;
-
- if (($persistent))
- setcookie("elggperm", $code, (time()+(86400 * 30)),"/");
-
- if (!$user->save() || !trigger_elgg_event('login','user',$user)) {
- unset($_SESSION['username']);
- unset($_SESSION['name']);
- unset($_SESSION['code']);
- unset($_SESSION['guid']);
- unset($_SESSION['id']);
- unset($_SESSION['user']);
- setcookie("elggperm", "", (time()-(86400 * 30)),"/");
- return false;
- }
-
- // Users privilege has been elevated, so change the session id (help prevent session hijacking)
- session_regenerate_id();
-
- return true;
-
- }
-
- /**
- * Log the current user out
- *
- * @return true|false
- */
- function logout() {
- global $CONFIG;
-
- if (isset($_SESSION['user'])) {
- if (!trigger_elgg_event('logout','user',$_SESSION['user'])) return false;
- $_SESSION['user']->code = "";
- $_SESSION['user']->save();
- }
-
- unset($_SESSION['username']);
- unset($_SESSION['name']);
- unset($_SESSION['code']);
- unset($_SESSION['guid']);
- unset($_SESSION['id']);
- unset($_SESSION['user']);
-
- setcookie("elggperm", "", (time()-(86400 * 30)),"/");
-
- session_destroy();
-
- return true;
- }
-
- function get_session_fingerprint()
- {
- global $CONFIG;
-
- return md5($_SERVER['HTTP_USER_AGENT'] );
- }
-
- /**
- * Initialises the system session and potentially logs the user in
- *
- * This function looks for:
- *
- * 1. $_SESSION['id'] - if not present, we're logged out, and this is set to 0
- * 2. The cookie 'elggperm' - if present, checks it for an authentication token, validates it, and potentially logs the user in
- *
- * @uses $_SESSION
- * @param unknown_type $event
- * @param unknown_type $object_type
- * @param unknown_type $object
- */
- function session_init($event, $object_type, $object) {
-
- global $DB_PREFIX, $CONFIG;
-
- if (!is_db_installed()) return false;
-
- // Use database for sessions
- $DB_PREFIX = $CONFIG->dbprefix; // HACK to allow access to prefix after object distruction
- session_set_save_handler("__elgg_session_open", "__elgg_session_close", "__elgg_session_read", "__elgg_session_write", "__elgg_session_destroy", "__elgg_session_gc");
-
- session_name('Elgg');
- session_start();
-
- // Do some sanity checking by generating a fingerprint (makes some XSS attacks harder)
- if (isset($_SESSION['__elgg_fingerprint']))
- {
- if ($_SESSION['__elgg_fingerprint'] != get_session_fingerprint())
- {
- session_destroy();
- return false;
- }
- }
- else
- {
- $_SESSION['__elgg_fingerprint'] = get_session_fingerprint();
- }
-
- // Generate a simple token
- if (!isset($_SESSION['__elgg_session'])) $_SESSION['__elgg_session'] = md5(microtime().rand());
-
- if (empty($_SESSION['guid'])) {
- if (isset($_COOKIE['elggperm'])) {
- $code = $_COOKIE['elggperm'];
- $code = md5($code);
- $_SESSION['guid'] = 0;
- $_SESSION['id'] = 0;
- // $_SESSION['user'] = new ElggDummy();
- if ($user = get_user_by_code($code)) {
- $_SESSION['user'] = $user;
- $_SESSION['id'] = $user->getGUID();
- $_SESSION['guid'] = $_SESSION['id'];
- $_SESSION['code'] = $_COOKIE['elggperm'];
- }
- } else {
- //$_SESSION['user'] = new ElggDummy();
- $_SESSION['id'] = 0;
- $_SESSION['guid'] = 0;
- $_SESSION['code'] = "";
- }
- } else {
- if (!empty($_SESSION['code'])) {
- $code = md5($_SESSION['code']);
- if ($user = get_user_by_code($code)) {
- $_SESSION['user'] = $user;
- $_SESSION['id'] = $user->getGUID();
- $_SESSION['guid'] = $_SESSION['id'];
- } else {
- unset($_SESSION['user']);
- // $_SESSION['user'] = new ElggDummy();
- $_SESSION['guid'] = 0;
- $_SESSION['id'] = 0;
- $_SESSION['code'] = "";
- }
- } else {
- //$_SESSION['user'] = new ElggDummy();
- $_SESSION['guid'] = 0;
- $_SESSION['id'] = 0;
- $_SESSION['code'] = "";
- }
- }
- if ($_SESSION['id'] > 0) {
- set_last_action($_SESSION['id']);
- }
-
- register_action("login",true);
- register_action("logout");
-
- // Register a default PAM handler
- register_pam_handler('pam_auth_userpass');
-
- return true;
-
- }
-
- /**
- * Used at the top of a page to mark it as logged in users only.
- *
- */
- function gatekeeper() {
- if (!isloggedin()) {
- $_SESSION['last_forward_from'] = current_page_url();
- forward();
- }
- }
-
- /**
- * Used at the top of a page to mark it as logged in admin or siteadmin only.
- *
- */
- function admin_gatekeeper()
- {
- gatekeeper();
- if (!$_SESSION['user']->admin && !$_SESSION['user']->siteadmin) {
- $_SESSION['last_forward_from'] = current_page_url();
- forward();
+<?php
+
+/**
+ * Elgg session management
+ * Functions to manage logins
+ *
+ * @package Elgg.Core
+ * @subpackage Session
+ */
+
+/** Elgg magic session */
+global $SESSION;
+
+/**
+ * Return the current logged in user, or NULL if no user is logged in.
+ *
+ * If no user can be found in the current session, a plugin
+ * hook - 'session:get' 'user' to give plugin authors another
+ * way to provide user details to the ACL system without touching the session.
+ *
+ * @return ElggUser
+ */
+function elgg_get_logged_in_user_entity() {
+ global $SESSION;
+
+ if (isset($SESSION)) {
+ return $SESSION['user'];
+ }
+
+ return NULL;
+}
+
+/**
+ * Return the current logged in user by id.
+ *
+ * @see elgg_get_logged_in_user_entity()
+ * @return int
+ */
+function elgg_get_logged_in_user_guid() {
+ $user = elgg_get_logged_in_user_entity();
+ if ($user) {
+ return $user->guid;
+ }
+
+ return 0;
+}
+
+/**
+ * Returns whether or not the user is currently logged in
+ *
+ * @return bool
+ */
+function elgg_is_logged_in() {
+ $user = elgg_get_logged_in_user_entity();
+
+ if ((isset($user)) && ($user instanceof ElggUser) && ($user->guid > 0)) {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Returns whether or not the user is currently logged in and that they are an admin user.
+ *
+ * @return bool
+ */
+function elgg_is_admin_logged_in() {
+ $user = elgg_get_logged_in_user_entity();
+
+ if ((elgg_is_logged_in()) && $user->isAdmin()) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * Check if the given user has full access.
+ *
+ * @todo: Will always return full access if the user is an admin.
+ *
+ * @param int $user_guid The user to check
+ *
+ * @return bool
+ * @since 1.7.1
+ */
+function elgg_is_admin_user($user_guid) {
+ global $CONFIG;
+
+ $user_guid = (int)$user_guid;
+
+ // cannot use magic metadata here because of recursion
+
+ // must support the old way of getting admin from metadata
+ // in order to run the upgrade to move it into the users table.
+ $version = (int) datalist_get('version');
+
+ if ($version < 2010040201) {
+ $admin = get_metastring_id('admin');
+ $yes = get_metastring_id('yes');
+ $one = get_metastring_id('1');
+
+ $query = "SELECT * FROM {$CONFIG->dbprefix}users_entity as e,
+ {$CONFIG->dbprefix}metadata as md
+ WHERE (
+ md.name_id = '$admin'
+ AND md.value_id IN ('$yes', '$one')
+ AND e.guid = md.entity_guid
+ AND e.guid = {$user_guid}
+ AND e.banned = 'no'
+ )";
+ } else {
+ $query = "SELECT * FROM {$CONFIG->dbprefix}users_entity as e
+ WHERE (
+ e.guid = {$user_guid}
+ AND e.admin = 'yes'
+ )";
+ }
+
+ // normalizing the results from get_data()
+ // See #1242
+ $info = get_data($query);
+ if (!((is_array($info) && count($info) < 1) || $info === FALSE)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Perform user authentication with a given username and password.
+ *
+ * @warning This returns an error message on failure. Use the identical operator to check
+ * for access: if (true === elgg_authenticate()) { ... }.
+ *
+ *
+ * @see login
+ *
+ * @param string $username The username
+ * @param string $password The password
+ *
+ * @return true|string True or an error message on failure
+ * @access private
+ */
+function elgg_authenticate($username, $password) {
+ $pam = new ElggPAM('user');
+ $credentials = array('username' => $username, 'password' => $password);
+ $result = $pam->authenticate($credentials);
+ if (!$result) {
+ return $pam->getFailureMessage();
+ }
+ return true;
+}
+
+/**
+ * Hook into the PAM system which accepts a username and password and attempts to authenticate
+ * it against a known user.
+ *
+ * @param array $credentials Associated array of credentials passed to
+ * Elgg's PAM system. This function expects
+ * 'username' and 'password' (cleartext).
+ *
+ * @return bool
+ * @throws LoginException
+ * @access private
+ */
+function pam_auth_userpass(array $credentials = array()) {
+
+ if (!isset($credentials['username']) || !isset($credentials['password'])) {
+ return false;
+ }
+
+ $user = get_user_by_username($credentials['username']);
+ if (!$user) {
+ throw new LoginException(elgg_echo('LoginException:UsernameFailure'));
+ }
+
+ if (check_rate_limit_exceeded($user->guid)) {
+ throw new LoginException(elgg_echo('LoginException:AccountLocked'));
+ }
+
+ if ($user->password !== generate_user_password($user, $credentials['password'])) {
+ log_login_failure($user->guid);
+ throw new LoginException(elgg_echo('LoginException:PasswordFailure'));
+ }
+
+ return true;
+}
+
+/**
+ * Log a failed login for $user_guid
+ *
+ * @param int $user_guid User GUID
+ *
+ * @return bool
+ */
+function log_login_failure($user_guid) {
+ $user_guid = (int)$user_guid;
+ $user = get_entity($user_guid);
+
+ if (($user_guid) && ($user) && ($user instanceof ElggUser)) {
+ $fails = (int)$user->getPrivateSetting("login_failures");
+ $fails++;
+
+ $user->setPrivateSetting("login_failures", $fails);
+ $user->setPrivateSetting("login_failure_$fails", time());
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Resets the fail login count for $user_guid
+ *
+ * @param int $user_guid User GUID
+ *
+ * @return bool true on success (success = user has no logged failed attempts)
+ */
+function reset_login_failure_count($user_guid) {
+ $user_guid = (int)$user_guid;
+ $user = get_entity($user_guid);
+
+ if (($user_guid) && ($user) && ($user instanceof ElggUser)) {
+ $fails = (int)$user->getPrivateSetting("login_failures");
+
+ if ($fails) {
+ for ($n = 1; $n <= $fails; $n++) {
+ $user->removePrivateSetting("login_failure_$n");
}
- }
-
- /**
- * DB Based session handling code.
- */
- function __elgg_session_open($save_path, $session_name)
- {
- global $sess_save_path;
- $sess_save_path = $save_path;
-
- return true;
- }
-
- /**
- * DB Based session handling code.
- */
- function __elgg_session_close()
- {
+
+ $user->removePrivateSetting("login_failures");
+
return true;
}
-
- /**
- * DB Based session handling code.
- */
- function __elgg_session_read($id)
- {
- global $DB_PREFIX;
-
- $id = sanitise_string($id);
-
- try {
- $result = get_data_row("SELECT * from {$DB_PREFIX}users_sessions where session='$id'");
-
- if ($result)
- return (string)$result->data;
-
- } catch (DatabaseException $e) {
-
- // Fall back to file store in this case, since this likely means that the database hasn't been upgraded
- global $sess_save_path;
-
- $sess_file = "$sess_save_path/sess_$id";
- return (string) @file_get_contents($sess_file);
- }
-
- return '';
- }
-
- /**
- * DB Based session handling code.
- */
- function __elgg_session_write($id, $sess_data)
- {
- global $DB_PREFIX;
-
- $id = sanitise_string($id);
+
+ // nothing to reset
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Checks if the rate limit of failed logins has been exceeded for $user_guid.
+ *
+ * @param int $user_guid User GUID
+ *
+ * @return bool on exceeded limit.
+ */
+function check_rate_limit_exceeded($user_guid) {
+ // 5 failures in 5 minutes causes temporary block on logins
+ $limit = 5;
+ $user_guid = (int)$user_guid;
+ $user = get_entity($user_guid);
+
+ if (($user_guid) && ($user) && ($user instanceof ElggUser)) {
+ $fails = (int)$user->getPrivateSetting("login_failures");
+ if ($fails >= $limit) {
+ $cnt = 0;
$time = time();
-
- try {
- $sess_data_sanitised = sanitise_string($sess_data);
+ for ($n = $fails; $n > 0; $n--) {
+ $f = $user->getPrivateSetting("login_failure_$n");
+ if ($f > $time - (60 * 5)) {
+ $cnt++;
+ }
- if (insert_data("REPLACE INTO {$DB_PREFIX}users_sessions (session, ts, data) VALUES ('$id', '$time', '$sess_data_sanitised')")!==false)
+ if ($cnt == $limit) {
+ // Limit reached
return true;
-
- } catch (DatabaseException $e) {
- // Fall back to file store in this case, since this likely means that the database hasn't been upgraded
- global $sess_save_path;
-
- $sess_file = "$sess_save_path/sess_$id";
- if ($fp = @fopen($sess_file, "w")) {
- $return = fwrite($fp, $sess_data);
- fclose($fp);
- return $return;
- }
-
- else
- error_log('marcus FAILED TO WRITe ' . print_r($CONFIG, true));
+ }
}
-
- return false;
}
-
- /**
- * DB Based session handling code.
- */
- function __elgg_session_destroy($id)
- {
- global $DB_PREFIX;
-
- $id = sanitise_string($id);
-
- try {
- return (bool)delete_data("DELETE from {$DB_PREFIX}users_sessions where session='$id'");
- } catch (DatabaseException $e) {
- // Fall back to file store in this case, since this likely means that the database hasn't been upgraded
- global $sess_save_path;
-
- $sess_file = "$sess_save_path/sess_$id";
- return(@unlink($sess_file));
- }
-
+ }
+
+ return false;
+}
+
+/**
+ * Logs in a specified ElggUser. For standard registration, use in conjunction
+ * with elgg_authenticate.
+ *
+ * @see elgg_authenticate
+ *
+ * @param ElggUser $user A valid Elgg user object
+ * @param boolean $persistent Should this be a persistent login?
+ *
+ * @return true or throws exception
+ * @throws LoginException
+ */
+function login(ElggUser $user, $persistent = false) {
+ // User is banned, return false.
+ if ($user->isBanned()) {
+ throw new LoginException(elgg_echo('LoginException:BannedUser'));
+ }
+
+ $_SESSION['user'] = $user;
+ $_SESSION['guid'] = $user->getGUID();
+ $_SESSION['id'] = $_SESSION['guid'];
+ $_SESSION['username'] = $user->username;
+ $_SESSION['name'] = $user->name;
+
+ // if remember me checked, set cookie with token and store token on user
+ if (($persistent)) {
+ $code = (md5($user->name . $user->username . time() . rand()));
+ $_SESSION['code'] = $code;
+ $user->code = md5($code);
+ setcookie("elggperm", $code, (time() + (86400 * 30)), "/");
+ }
+
+ if (!$user->save() || !elgg_trigger_event('login', 'user', $user)) {
+ unset($_SESSION['username']);
+ unset($_SESSION['name']);
+ unset($_SESSION['code']);
+ unset($_SESSION['guid']);
+ unset($_SESSION['id']);
+ unset($_SESSION['user']);
+ setcookie("elggperm", "", (time() - (86400 * 30)), "/");
+ throw new LoginException(elgg_echo('LoginException:Unknown'));
+ }
+
+ // Users privilege has been elevated, so change the session id (prevents session fixation)
+ session_regenerate_id();
+
+ // Update statistics
+ set_last_login($_SESSION['guid']);
+ reset_login_failure_count($user->guid); // Reset any previous failed login attempts
+
+ // if memcache is enabled, invalidate the user in memcache @see https://github.com/Elgg/Elgg/issues/3143
+ if (is_memcache_available()) {
+ // this needs to happen with a shutdown function because of the timing with set_last_login()
+ register_shutdown_function("_elgg_invalidate_memcache_for_entity", $_SESSION['guid']);
+ }
+
+ return true;
+}
+
+/**
+ * Log the current user out
+ *
+ * @return bool
+ */
+function logout() {
+ if (isset($_SESSION['user'])) {
+ if (!elgg_trigger_event('logout', 'user', $_SESSION['user'])) {
return false;
}
-
- /**
- * DB Based session handling code.
- */
- function __elgg_session_gc($maxlifetime)
- {
- global $DB_PREFIX;
-
- $life = time()-$maxlifetime;
-
- try {
- return (bool)delete_data("DELETE from {$DB_PREFIX}users_sessions where ts<'$life'");
- } catch (DatabaseException $e) {
- // Fall back to file store in this case, since this likely means that the database hasn't been upgraded
- global $sess_save_path;
-
- foreach (glob("$sess_save_path/sess_*") as $filename) {
- if (filemtime($filename) < $life) {
- @unlink($filename);
- }
- }
+ $_SESSION['user']->code = "";
+ $_SESSION['user']->save();
+ }
+
+ unset($_SESSION['username']);
+ unset($_SESSION['name']);
+ unset($_SESSION['code']);
+ unset($_SESSION['guid']);
+ unset($_SESSION['id']);
+ unset($_SESSION['user']);
+
+ setcookie("elggperm", "", (time() - (86400 * 30)), "/");
+
+ // pass along any messages
+ $old_msg = $_SESSION['msg'];
+
+ session_destroy();
+
+ // starting a default session to store any post-logout messages.
+ _elgg_session_boot(NULL, NULL, NULL);
+ $_SESSION['msg'] = $old_msg;
+
+ return TRUE;
+}
+
+/**
+ * Initialises the system session and potentially logs the user in
+ *
+ * This function looks for:
+ *
+ * 1. $_SESSION['id'] - if not present, we're logged out, and this is set to 0
+ * 2. The cookie 'elggperm' - if present, checks it for an authentication
+ * token, validates it, and potentially logs the user in
+ *
+ * @uses $_SESSION
+ *
+ * @return bool
+ * @access private
+ */
+function _elgg_session_boot() {
+ global $DB_PREFIX, $CONFIG;
+
+ // Use database for sessions
+ // HACK to allow access to prefix after object destruction
+ $DB_PREFIX = $CONFIG->dbprefix;
+ if ((!isset($CONFIG->use_file_sessions))) {
+ session_set_save_handler("_elgg_session_open",
+ "_elgg_session_close",
+ "_elgg_session_read",
+ "_elgg_session_write",
+ "_elgg_session_destroy",
+ "_elgg_session_gc");
+ }
+
+ session_name('Elgg');
+ session_start();
+
+ // Generate a simple token (private from potentially public session id)
+ if (!isset($_SESSION['__elgg_session'])) {
+ $_SESSION['__elgg_session'] = md5(microtime() . rand());
+ }
+
+ // test whether we have a user session
+ if (empty($_SESSION['guid'])) {
+
+ // clear session variables before checking cookie
+ unset($_SESSION['user']);
+ unset($_SESSION['id']);
+ unset($_SESSION['guid']);
+ unset($_SESSION['code']);
+
+ // is there a remember me cookie
+ if (isset($_COOKIE['elggperm'])) {
+ // we have a cookie, so try to log the user in
+ $code = $_COOKIE['elggperm'];
+ $code = md5($code);
+ if ($user = get_user_by_code($code)) {
+ // we have a user, log him in
+ $_SESSION['user'] = $user;
+ $_SESSION['id'] = $user->getGUID();
+ $_SESSION['guid'] = $_SESSION['id'];
+ $_SESSION['code'] = $_COOKIE['elggperm'];
}
-
+ }
+ } else {
+ // we have a session and we have already checked the fingerprint
+ // reload the user object from database in case it has changed during the session
+ if ($user = get_user($_SESSION['guid'])) {
+ $_SESSION['user'] = $user;
+ $_SESSION['id'] = $user->getGUID();
+ $_SESSION['guid'] = $_SESSION['id'];
+ } else {
+ // user must have been deleted with a session active
+ unset($_SESSION['user']);
+ unset($_SESSION['id']);
+ unset($_SESSION['guid']);
+ unset($_SESSION['code']);
+ }
+ }
+
+ if (isset($_SESSION['guid'])) {
+ set_last_action($_SESSION['guid']);
+ }
+
+ elgg_register_action('login', '', 'public');
+ elgg_register_action('logout');
+
+ // Register a default PAM handler
+ register_pam_handler('pam_auth_userpass');
+
+ // Initialise the magic session
+ global $SESSION;
+ $SESSION = new ElggSession();
+
+ // Finally we ensure that a user who has been banned with an open session is kicked.
+ if ((isset($_SESSION['user'])) && ($_SESSION['user']->isBanned())) {
+ session_destroy();
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Used at the top of a page to mark it as logged in users only.
+ *
+ * @return void
+ */
+function gatekeeper() {
+ if (!elgg_is_logged_in()) {
+ $_SESSION['last_forward_from'] = current_page_url();
+ register_error(elgg_echo('loggedinrequired'));
+ forward('', 'login');
+ }
+}
+
+/**
+ * Used at the top of a page to mark it as logged in admin or siteadmin only.
+ *
+ * @return void
+ */
+function admin_gatekeeper() {
+ gatekeeper();
+
+ if (!elgg_is_admin_logged_in()) {
+ $_SESSION['last_forward_from'] = current_page_url();
+ register_error(elgg_echo('adminrequired'));
+ forward('', 'admin');
+ }
+}
+
+/**
+ * Handles opening a session in the DB
+ *
+ * @param string $save_path The path to save the sessions
+ * @param string $session_name The name of the session
+ *
+ * @return true
+ * @todo Document
+ * @access private
+ */
+function _elgg_session_open($save_path, $session_name) {
+ global $sess_save_path;
+ $sess_save_path = $save_path;
+
+ return true;
+}
+
+/**
+ * Closes a session
+ *
+ * @todo implement
+ * @todo document
+ *
+ * @return true
+ * @access private
+ */
+function _elgg_session_close() {
+ return true;
+}
+
+/**
+ * Read the session data from DB failing back to file.
+ *
+ * @param string $id The session ID
+ *
+ * @return string
+ * @access private
+ */
+function _elgg_session_read($id) {
+ global $DB_PREFIX;
+
+ $id = sanitise_string($id);
+
+ try {
+ $result = get_data_row("SELECT * from {$DB_PREFIX}users_sessions where session='$id'");
+
+ if ($result) {
+ return (string)$result->data;
+ }
+
+ } catch (DatabaseException $e) {
+
+ // Fall back to file store in this case, since this likely means
+ // that the database hasn't been upgraded
+ global $sess_save_path;
+
+ $sess_file = "$sess_save_path/sess_$id";
+ return (string) @file_get_contents($sess_file);
+ }
+
+ return '';
+}
+
+/**
+ * Write session data to the DB falling back to file.
+ *
+ * @param string $id The session ID
+ * @param mixed $sess_data Session data
+ *
+ * @return bool
+ * @access private
+ */
+function _elgg_session_write($id, $sess_data) {
+ global $DB_PREFIX;
+
+ $id = sanitise_string($id);
+ $time = time();
+
+ try {
+ $sess_data_sanitised = sanitise_string($sess_data);
+
+ $q = "REPLACE INTO {$DB_PREFIX}users_sessions
+ (session, ts, data) VALUES
+ ('$id', '$time', '$sess_data_sanitised')";
+
+ if (insert_data($q) !== false) {
return true;
}
-
- register_elgg_event_handler("boot","system","session_init",1);
-
-
-?> \ No newline at end of file
+ } catch (DatabaseException $e) {
+ // Fall back to file store in this case, since this likely means
+ // that the database hasn't been upgraded
+ global $sess_save_path;
+
+ $sess_file = "$sess_save_path/sess_$id";
+ if ($fp = @fopen($sess_file, "w")) {
+ $return = fwrite($fp, $sess_data);
+ fclose($fp);
+ return $return;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Destroy a DB session, falling back to file.
+ *
+ * @param string $id Session ID
+ *
+ * @return bool
+ * @access private
+ */
+function _elgg_session_destroy($id) {
+ global $DB_PREFIX;
+
+ $id = sanitise_string($id);
+
+ try {
+ return (bool)delete_data("DELETE from {$DB_PREFIX}users_sessions where session='$id'");
+ } catch (DatabaseException $e) {
+ // Fall back to file store in this case, since this likely means that
+ // the database hasn't been upgraded
+ global $sess_save_path;
+
+ $sess_file = "$sess_save_path/sess_$id";
+ return @unlink($sess_file);
+ }
+}
+
+/**
+ * Perform garbage collection on session table / files
+ *
+ * @param int $maxlifetime Max age of a session
+ *
+ * @return bool
+ * @access private
+ */
+function _elgg_session_gc($maxlifetime) {
+ global $DB_PREFIX;
+
+ $life = time() - $maxlifetime;
+
+ try {
+ return (bool)delete_data("DELETE from {$DB_PREFIX}users_sessions where ts<'$life'");
+ } catch (DatabaseException $e) {
+ // Fall back to file store in this case, since this likely means that the database
+ // hasn't been upgraded
+ global $sess_save_path;
+
+ foreach (glob("$sess_save_path/sess_*") as $filename) {
+ if (filemtime($filename) < $life) {
+ @unlink($filename);
+ }
+ }
+ }
+
+ return true;
+}