diff --git a/public_html/admin/auth.inc.php b/public_html/admin/auth.inc.php
index 424773037..3ac6bf334 100644
--- a/public_html/admin/auth.inc.php
+++ b/public_html/admin/auth.inc.php
@@ -8,7 +8,7 @@
// | |
// | Geeklog admin authentication module |
// +---------------------------------------------------------------------------+
-// | Copyright (C) 2000-2010 by the following authors: |
+// | Copyright (C) 2000-2019 by the following authors: |
// | |
// | Authors: Tony Bibbs - tony AT tonybibbs DOT com |
// | Mark Limburg - mlimburg AT users DOT sourceforge DOT net |
@@ -36,6 +36,8 @@
die('This file can not be used on its own.');
}
+global $_TABLES;
+
// MAIN
COM_clearSpeedlimit($_CONF['login_speedlimit'], 'login');
if (COM_checkSpeedlimit('login', $_CONF['login_attempts']) > 0) {
@@ -65,22 +67,15 @@
if ($status == USER_ACCOUNT_ACTIVE) {
DB_query("UPDATE {$_TABLES['users']} SET pwrequestid = NULL WHERE uid = $uid");
$_USER = SESS_getUserDataFromId($uid);
- $sessid = SESS_newSession($_USER['uid'], $_SERVER['REMOTE_ADDR'],
- $_CONF['session_cookie_timeout'], $_CONF['cookie_ip']);
- SESS_setSessionCookie($sessid, $_CONF['session_cookie_timeout'],
- $_CONF['cookie_session'], $_CONF['cookie_path'],
- $_CONF['cookiedomain'], $_CONF['cookiesecure']);
+ SESS_newSession($_USER['uid'], $_SERVER['REMOTE_ADDR'], $_CONF['session_cookie_timeout']);
PLG_loginUser($_USER['uid']);
- // Now that we handled session cookies, handle longterm cookie
- if (!isset($_COOKIE[$_CONF['cookie_name']])) {
- // Either their cookie expired or they are new
- $cooktime = COM_getUserCookieTimeout();
-
- if (!empty($cooktime)) {
- // They want their cookie to persist for some amount of time so set it now
- SEC_setCookie($_CONF['cookie_name'], $_USER['uid'], time() + $cooktime);
- }
+ // Now that we handled session cookies, handle long-term cookie
+ $cookieTime = COM_getUserCookieTimeout();
+ if (!empty($cookieTime) && ($cookieTime > 0)) {
+ SESS_handleAutoLogin($cookieTime);
+ } else {
+ SESS_deleteAutoLoginKey();
}
if (!SEC_hasRights('story.edit,block.edit,topic.edit,user.edit,plugin.edit,syndication.edit,theme.edit','OR')) {
diff --git a/public_html/admin/install/classes/installer.class.php b/public_html/admin/install/classes/installer.class.php
index da2240ab9..6e9fc54bc 100644
--- a/public_html/admin/install/classes/installer.class.php
+++ b/public_html/admin/install/classes/installer.class.php
@@ -4586,7 +4586,7 @@ private function installEngine($installType, $installStep)
'1.3.5', '1.3.6', '1.3.7', '1.3.8', '1.3.9', '1.3.10', '1.3.11',
'1.4.0', '1.4.1', '1.5.0', '1.5.1', '1.5.2', '1.6.0', '1.6.1',
'1.7.0', '1.7.1', '1.7.2', '1.8.0', '1.8.1', '1.8.2', '2.0.0',
- '2.1.0', '2.1.1',
+ '2.1.0', '2.1.1', '2.2.0',
);
$tempCounter = 0;
diff --git a/public_html/admin/install/classes/micro_template.class.php b/public_html/admin/install/classes/micro_template.class.php
index 259a7885b..e461339f1 100644
--- a/public_html/admin/install/classes/micro_template.class.php
+++ b/public_html/admin/install/classes/micro_template.class.php
@@ -93,8 +93,6 @@ private function parseVarName($s)
/**
* Evaluate the content of a template
- *
- * @return string
*/
private function evaluate()
{
diff --git a/public_html/admin/install/config-install.php b/public_html/admin/install/config-install.php
index 1120bd836..148c2f447 100644
--- a/public_html/admin/install/config-install.php
+++ b/public_html/admin/install/config-install.php
@@ -414,12 +414,10 @@ function install_config()
$c->add('fs_cookies', NULL, 'fieldset', 7, 30, NULL, 0, TRUE, $me, 30);
$c->add('cookie_session','gl_session','text',7,30,NULL,530,TRUE, $me, 30);
$c->add('cookie_name','geeklog','text',7,30,NULL,540,TRUE, $me, 30);
- $c->add('cookie_password','password','text',7,30,NULL,550,TRUE, $me, 30);
$c->add('cookie_theme','theme','text',7,30,NULL,560,TRUE, $me, 30);
$c->add('cookie_language','language','text',7,30,NULL,570,TRUE, $me, 30);
$c->add('cookie_tzid','timezone','text',7,30,NULL,575,TRUE, $me, 30);
$c->add('cookie_anon_name','anon_name','text',7,30,NULL,577,TRUE, $me, 30);
- $c->add('cookie_ip',0,'select',7,30,0,580,TRUE, $me, 30);
$c->add('default_perm_cookie_timeout',28800,'select',7,30,NULL,590,TRUE, $me, 30);
$c->add('session_cookie_timeout',7200,'text',7,30,NULL,600,TRUE, $me, 30);
$c->add('cookie_path','/','text',7,30,NULL,610,TRUE, $me, 30);
diff --git a/public_html/users.php b/public_html/users.php
index 4cdb9dc45..d57073c4f 100644
--- a/public_html/users.php
+++ b/public_html/users.php
@@ -40,6 +40,8 @@
* @author Jason Whittenburg
*/
+use Geeklog\Session;
+
/**
* Geeklog common function library
*/
@@ -656,50 +658,13 @@ function USER_doLogin()
global $_CONF, $_USER, $USER_VERBOSE;
COM_resetSpeedlimit('login');
- $sessionId = SESS_newSession($_USER['uid'], $_SERVER['REMOTE_ADDR'], $_CONF['session_cookie_timeout'], $_CONF['cookie_ip']);
- SESS_setSessionCookie(
- $sessionId, $_CONF['session_cookie_timeout'], $_CONF['cookie_session'], $_CONF['cookie_path'],
- $_CONF['cookiedomain'], $_CONF['cookiesecure']
- );
+ SESS_newSession($_USER['uid'], $_SERVER['REMOTE_ADDR'], $_CONF['session_cookie_timeout']);
PLG_loginUser($_USER['uid']);
- // Now that we handled session cookies, handle long-term cookie
- if (!isset($_COOKIE[$_CONF['cookie_name']]) || !isset($_COOKIE['cookie_password'])) {
- // Either their cookie expired or they are new
- $cookTime = COM_getUserCookieTimeout();
- if ($USER_VERBOSE) {
- COM_errorLog("Trying to set permanent cookie with time of $cookTime", 1);
- }
- if ($cookTime > 0) {
- // They want their cookie to persist for some amount of time so set it now
- if ($USER_VERBOSE) {
- COM_errorLog('Trying to set permanent cookie', 1);
- }
- SEC_setCookie($_CONF['cookie_name'], $_USER['uid'], time() + $cookTime);
- SEC_setCookie($_CONF['cookie_password'], $_USER['passwd'], time() + $cookTime);
- }
- } else {
- $userId = Geeklog\Input::fCookie($_CONF['cookie_name']);
-
- if (!empty($userId) && ($userId !== 'deleted')) {
- $userId = (int) $userId;
-
- if ($userId > 1) {
- if ($USER_VERBOSE) {
- COM_errorLog('NOW trying to set permanent cookie', 1);
- COM_errorLog('Got ' . $userId . ' from perm cookie in users.php', 1);
- }
-
- // Create new session
- $_USER = SESS_getUserDataFromId($userId);
- if ($USER_VERBOSE) {
- COM_errorLog('Got ' . $_USER['username'] . ' for the username in user.php', 1);
- }
- }
- }
- }
+ // Issue an auto-login key
+ SESS_issueAutoLoginCookie($_USER['uid']);
- // Now that we have users data see if their theme cookie is set.
+ // Now that we have user's data see if their theme cookie is set.
// If not set it
if (!empty($_USER['theme'])) {
setcookie(
@@ -905,10 +870,8 @@ function USER_tryTwoFactorAuth()
SESS_endUserSession($_USER['uid']);
PLG_logoutUser($_USER['uid']);
}
- SEC_setCookie($_CONF['cookie_session'], '', time() - 10000);
- SEC_setCookie($_CONF['cookie_password'], '', time() - 10000);
- SEC_setCookie($_CONF['cookie_name'], '', time() - 10000);
-
+ SESS_deleteAutoLoginKey();
+
$msg = (int) Geeklog\Input::fGet('msg', 0);
if ($msg == 0) {
$msg = 8;
diff --git a/public_html/usersettings.php b/public_html/usersettings.php
index 2e5f9cb3c..570772d78 100644
--- a/public_html/usersettings.php
+++ b/public_html/usersettings.php
@@ -1142,12 +1142,6 @@ function saveuser(array $A)
(SEC_encryptUserPassword($A['old_passwd'], $_USER['uid']) == 0)
) {
SEC_updateUserPassword($A['passwd'], $_USER['uid']);
- if ($A['cooktime'] > 0) {
- $cooktime = $A['cooktime'];
- } else {
- $cooktime = -1000;
- }
- SEC_setCookie($_CONF['cookie_password'], $passwd, time() + $cooktime);
} elseif (SEC_encryptUserPassword($A['old_passwd'], $_USER['uid']) < 0) {
COM_redirect($_CONF['site_url'] . '/usersettings.php?msg=68');
} elseif ($A['passwd'] != $A['passwd_conf']) {
@@ -1158,12 +1152,6 @@ function saveuser(array $A)
}
} else {
// Cookie
- if ($A['cooktime'] > 0) {
- $cooktime = $A['cooktime'];
- } else {
- $cooktime = -1000;
- }
- SEC_setCookie($_CONF['cookie_password'], $passwd, time() + $cooktime);
}
if ($_US_VERBOSE) {
@@ -1171,10 +1159,9 @@ function saveuser(array $A)
}
if ($A['cooktime'] <= 0) {
- $cooktime = 1000;
- SEC_setCookie($_CONF['cookie_name'], $_USER['uid'], time() - $cooktime);
+ SESS_deleteAutoLoginKey();
} else {
- SEC_setCookie($_CONF['cookie_name'], $_USER['uid'], time() + $A['cooktime']);
+ SESS_handleAutoLogin();
}
if ($_CONF['allow_user_photo'] == 1) {
diff --git a/sql/mysql_tableanddata.php b/sql/mysql_tableanddata.php
index 7a20bc00b..798379720 100644
--- a/sql/mysql_tableanddata.php
+++ b/sql/mysql_tableanddata.php
@@ -1,5 +1,7 @@
add('likes_speedlimit',20,'text',$sg,$fs,NULL,$so,TRUE, $me, $tab);
$so += 10;
+ // Delete some cookie-related settings
+ $c->del('cookie_password', $me);
+ $c->del('cookie_ip', $me);
+
return true;
}
diff --git a/sql/updates/pgsql_2.2.0_to_2.2.1.php b/sql/updates/pgsql_2.2.0_to_2.2.1.php
index b7d522065..e7d746234 100644
--- a/sql/updates/pgsql_2.2.0_to_2.2.1.php
+++ b/sql/updates/pgsql_2.2.0_to_2.2.1.php
@@ -49,6 +49,15 @@
`id`);
";
+// Modify `sessions` table
+$_SQL[] = "DELETE FROM {$_TABLES['sessions']}";
+$_SQL[] = "ALTER TABLE {$_TABLES['sessions']} ALTER COLUMN sess_id TYPE VARCHAR(250) NOT NULL default ''";
+$_SQL[] = "ALTER TABLE {$_TABLES['sessions']} DROP COLUMN md5_sess_id}";
+$_SQL[] = "ALTER TABLE {$_TABLES['sessions']} DROP COLUMN topic}";
+
+// Add `autologin_key` column to `users' table
+$_SQL[] = "ALTER TABLE {$_TABLES['users']} ADD COLUMN autologin_key VARCHAR(250) NOT NULL DEFAULT ''";
+
/**
* Upgrade Messages
*/
@@ -112,6 +121,10 @@ function update_ConfValuesFor221()
$c->add('likes_speedlimit',20,'text',$sg,$fs,NULL,$so,TRUE, $me, $tab);
$so += 10;
+ // Delete some cookie-related settings
+ $c->del('cookie_password', $me);
+ $c->del('cookie_ip', $me);
+
return true;
}
diff --git a/system/classes/Session.php b/system/classes/Session.php
index 25067edab..971a83c3a 100644
--- a/system/classes/Session.php
+++ b/system/classes/Session.php
@@ -2,6 +2,8 @@
namespace Geeklog;
+use InvalidArgumentException;
+
/**
* Class Session
*
@@ -9,30 +11,24 @@
*/
abstract class Session
{
- // Index of $_SESSION array
- const GL_NAMESPACE = '__gl';
- const VAR_NAMESPACE = '__v';
- const FLASH_VAR_NAMESPACE = '__f';
+ // Indices of $_SESSION array
+ const NS_GL = '__gl';
+ const NS_FLASH_VAR = '__f';
+ const NS_VAR = '__v';
- // Default lifespan of the session in seconds
- const DEFAULT_LIFE_SPAN = 7200; // 60 * 60 * 2;
+ // Default session name
+ const DEFAULT_SESSION_NAME = 'GLSESSION';
// Anonymous user ID
const ANON_USER_ID = 1;
/**
- * User ID
- *
- * @var int
- */
- private static $uid = 1;
-
- /**
- * Lifespan of the session
+ * Lifespan of the current user's session
*
- * @var int
+ * @var int the length of time after which the session will expire. 0 means
+ * the session will expire when the user closes the browser window.
*/
- private static $lifeSpan = self::DEFAULT_LIFE_SPAN;
+ private static $sessionLifeTime = 0;
/**
* "flash", i.e., one-time session variables
@@ -51,74 +47,74 @@ abstract class Session
/**
* Init the Session class
*
- * @param array $config
+ * @param array $config
+ * @return bool whether the session cookie already exists
*/
public static function init(array $config)
{
+ $retval = true;
+
if (self::$isInitialized) {
- return;
+ return $retval;
}
- // Set PHP settings
- if (version_compare(PHP_VERSION, '5.5.2', '>=')) {
- ini_set('session.use_strict_mode', 1);
- }
+ // Make PHP session settings safer
+ if (is_callable('ini_set')) {
+ if (version_compare(PHP_VERSION, '5.5.2', '>=')) {
+ ini_set('session.use_strict_mode', 1);
- ini_set('session.use_cookies', 1);
- ini_set('session.use_only_cookies', 1);
- ini_set('session.use_trans_sid', 0);
+ if (version_compare(PHP_VERSION, '7.1.0', '>=')) {
+ ini_set('session.sid_length', 40);
+ ini_set('session.sid_bits_per_character', 5);
- if (isset($config['session_dir']) && is_readable($config['session_dir']) && is_dir($config['session_dir'])) {
- ini_set('session.save_path', $config['session_dir']);
+ if (version_compare(PHP_VERSION, '7.3.0', '>=')) {
+ ini_set('session.cookie_samesite', 'Lax');
+ }
+ }
+ }
+
+ ini_set('session.use_cookies', 1);
+ ini_set('session.use_only_cookies', 1);
+ ini_set('session.use_trans_sid', 0);
+ ini_set('session.cache_limiter', 'nocache');
+ ini_set('session.cookie_lifetime', 0);
}
+ // Set session cookie parameters
+ self::setSessionCookieParameters($config);
+
// Start a new session
if (!session_start()) {
die(__METHOD__ . ': Cannot start session.');
}
- // Check if the user is new
- if (!isset($_SESSION[self::GL_NAMESPACE])
- || !isset($_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE])
- || !is_array($_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE])
- || !isset($_SESSION[self::GL_NAMESPACE][self::FLASH_VAR_NAMESPACE])
- || !is_array($_SESSION[self::GL_NAMESPACE][self::FLASH_VAR_NAMESPACE])
- || !isset($_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE]['uid'])
- || ($_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE]['uid'] < self::ANON_USER_ID)
- || !isset($_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE]['expiresAt'])
- || self::isExpires()) {
- $_SESSION[self::GL_NAMESPACE] = array(
- self::FLASH_VAR_NAMESPACE => array(),
- self::VAR_NAMESPACE => array(
+ // Initialize the $_SESSION var if this is the first visit to the site
+ if (!isset($_SESSION[self::NS_GL]) ||
+ !isset($_SESSION[self::NS_GL][self::NS_FLASH_VAR]) ||
+ !is_array($_SESSION[self::NS_GL][self::NS_FLASH_VAR]) ||
+ !isset($_SESSION[self::NS_GL][self::NS_VAR]) ||
+ !is_array($_SESSION[self::NS_GL][self::NS_VAR]) ||
+ !isset($_SESSION[self::NS_GL][self::NS_VAR]['uid']) ||
+ !is_int($_SESSION[self::NS_GL][self::NS_VAR]['uid']) ||
+ ($_SESSION[self::NS_GL][self::NS_VAR]['uid'] < self::ANON_USER_ID)
+ ) {
+ $_SESSION[self::NS_GL] = array(
+ self::NS_FLASH_VAR => array(),
+ self::NS_VAR => array(
'uid' => self::ANON_USER_ID,
),
);
+ $retval = false;
}
- // Get user ID from session
- self::$uid = $_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE]['uid'];
-
// Move "flash" session vars to the property of the class
- self::$flashVars = $_SESSION[self::GL_NAMESPACE][self::FLASH_VAR_NAMESPACE];
- $_SESSION[self::GL_NAMESPACE][self::FLASH_VAR_NAMESPACE] = array();
-
- // Update life span
- self::setLifeSpan(self::$lifeSpan);
+ self::$flashVars = $_SESSION[self::NS_GL][self::NS_FLASH_VAR];
+ $_SESSION[self::NS_GL][self::NS_FLASH_VAR] = array();
- // Finished initialization
+ // Finish initialization
self::$isInitialized = true;
- }
- /**
- * Return if the current session has already expired
- *
- * @return bool
- */
- public static function isExpires()
- {
- return isset($_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE]['expiresAt'])
- && is_int($_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE]['expiresAt'])
- && ($_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE]['expiresAt']) < time();
+ return $retval;
}
/**
@@ -128,7 +124,7 @@ public static function isExpires()
*/
public static function isLoggedIn()
{
- return (self::$uid > self::ANON_USER_ID);
+ return (self::getUid() > self::ANON_USER_ID);
}
/**
@@ -138,99 +134,129 @@ public static function isLoggedIn()
*/
public static function getUid()
{
- return self::$uid;
+ return $_SESSION[self::NS_GL][self::NS_VAR]['uid'];
}
/**
* Set the current user id
*
- * @param int $uid
- * @throws \InvalidArgumentException
+ * @param int $uid
+ * @throws InvalidArgumentException
*/
public static function setUid($uid)
{
$uid = (int) $uid;
if ($uid >= self::ANON_USER_ID) {
- $_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE]['uid'] = $uid;
- self::regenerate();
+ $_SESSION[self::NS_GL][self::NS_VAR]['uid'] = $uid;
} else {
- throw new \InvalidArgumentException('User id must be ' . self::ANON_USER_ID . ' or greater.');
+ throw new InvalidArgumentException('User id must be ' . self::ANON_USER_ID . ' or greater.');
}
}
/**
- * Set a session value
+ * Set a session variable
*
- * @param string $name
- * @param mixed $value
+ * @param string $name
+ * @param mixed $value
*/
- public static function set($name, $value)
+ public static function setVar($name, $value)
{
- $_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE][$name] = $value;
+ $_SESSION[self::NS_GL][self::NS_VAR][$name] = $value;
}
/**
- * Set a "flash" session value
+ * Set a "flash" session variable
*
- * @param string $name
- * @param mixed $value
+ * @param string $name
+ * @param mixed $value
*/
- public static function setFlash($name, $value)
+ public static function setFlashVar($name, $value)
{
- $_SESSION[self::GL_NAMESPACE][self::FLASH_VAR_NAMESPACE][$name] = $value;
+ $_SESSION[self::NS_GL][self::NS_FLASH_VAR][$name] = $value;
}
/**
- * Get a session value
+ * Get a session variable
*
- * @param string $name
- * @param mixed $defaultValue
+ * @param string $name
+ * @param mixed $defaultValue
* @return mixed
*/
- public static function get($name, $defaultValue = null)
+ public static function getVar($name, $defaultValue = null)
{
- return isset($_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE][$name])
- ? $_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE][$name]
+ return isset($_SESSION[self::NS_GL][self::NS_VAR][$name])
+ ? $_SESSION[self::NS_GL][self::NS_VAR][$name]
: $defaultValue;
}
/**
- * Get a "flash" session value
+ * Get a "flash" session variable
*
- * @param string $name
- * @param mixed $defaultValue
+ * @param string $name
+ * @param mixed $defaultValue
* @return mixed
*/
- public static function getFlash($name, $defaultValue = null)
+ public static function getFlashVar($name, $defaultValue = null)
{
return isset(self::$flashVars[$name]) ? self::$flashVars[$name] : $defaultValue;
}
/**
* Regenerate the session id
+ *
+ * @return string the new session id
*/
- public static function regenerate()
+ public static function regenerateId()
{
session_regenerate_id(false);
+
+ return self::getSessionId();
}
/**
- * Set session lifespan
+ * Set session cookie parameters
*
- * @param int $lifeSpan
+ * @param array $config
*/
- public static function setLifeSpan($lifeSpan)
+ private static function setSessionCookieParameters(array $config)
{
- $lifeSpan = (int) $lifeSpan;
- if ($lifeSpan < 0) {
- $lifeSpan = 0;
+ $args = session_get_cookie_params();
+
+ // Override 'lifetime'
+ $args['lifetime'] = 0;
+
+ if (isset($config['cookie_path']) && (strlen($config['cookie_path']) > 0)) {
+ $args['path'] = $config['cookie_path'];
}
- self::$lifeSpan = $lifeSpan;
- $_SESSION[self::GL_NAMESPACE][self::VAR_NAMESPACE]['expiresAt'] = time() + self::$lifeSpan;
- $args = session_get_cookie_params();
- $args['lifetime'] = self::$lifeSpan;
+ if (isset($config['cookie_domain']) && (strlen($config['cookie_domain']) > 0)) {
+ $args['domain'] = $config['cookie_domain'];
+ }
+
+ if (isset($config['cookie_secure']) && (is_bool($config['cookie_secure']) || is_int($config['cookie_secure']))) {
+ $args['secure'] = (bool) $config['cookie_secure'];
+ }
+
+ if (!isset($config['session_name']) || preg_match('/\A[0-9]+\z/', $config['session_name'])) {
+ $config['session_name'] = self::DEFAULT_SESSION_NAME;
+ } else {
+ $config['session_name'] = str_replace('_', '', $config['session_name']);
+ $config['session_name'] = strtoupper($config['session_name']);
+ }
+
+ $args['httponly'] = true;
session_set_cookie_params($args['lifetime'], $args['path'], $args['domain'], $args['secure'], $args['httponly']);
+ session_name($config['session_name']);
+ }
+
+ /**
+ * Return the current session id
+ *
+ * @return string
+ */
+ public static function getSessionId()
+ {
+ return session_id();
}
}
diff --git a/system/lib-security.php b/system/lib-security.php
index d8d9aac7d..8a749f497 100644
--- a/system/lib-security.php
+++ b/system/lib-security.php
@@ -2125,7 +2125,7 @@ function SEC_randomBytes($length)
try {
$retval = random_bytes($length);
- } catch (\Exception $e) {
+ } catch (Exception $e) {
$retval = false;
if (is_callable('openssl_random_pseudo_bytes ')) {
diff --git a/system/lib-sessions.php b/system/lib-sessions.php
index 29cdf0ea6..0a5b25ab9 100644
--- a/system/lib-sessions.php
+++ b/system/lib-sessions.php
@@ -8,7 +8,7 @@
// | |
// | Geeklog session library. |
// +---------------------------------------------------------------------------+
-// | Copyright (C) 2000-2018 by the following authors: |
+// | Copyright (C) 2000-2019 by the following authors: |
// | |
// | Authors: Tony Bibbs - tony AT tonybibbs DOT com |
// | Mark Limburg - mlimburg AT users DOT sourceforge DOT net |
@@ -33,22 +33,24 @@
/**
* This is the session management library for Geeklog. Some of this code was
* borrowed from phpBB 1.4.x which is also GPL'd
-*
*/
+use Geeklog\Input;
+use Geeklog\Session;
+
// Turn this on if you want to see various debug messages from this library
$_SESS_VERBOSE = COM_isEnableDeveloperModeLog('session');
-if (strpos(strtolower($_SERVER['PHP_SELF']), 'lib-sessions.php') !== false) {
+if (stripos($_SERVER['PHP_SELF'], 'lib-sessions.php') !== false) {
die('This file can not be used on its own!');
}
-if (empty ($_CONF['cookiedomain'])) {
- preg_match ("/\/\/([^\/:]*)/", $_CONF['site_url'], $server);
- if (substr ($server[1], 0, 4) == 'www.') {
- $_CONF['cookiedomain'] = substr ($server[1], 3);
+if (empty($_CONF['cookiedomain'])) {
+ preg_match("/\/\/([^\/:]*)/", $_CONF['site_url'], $server);
+ if (substr($server[1], 0, 4) === 'www.') {
+ $_CONF['cookiedomain'] = substr($server[1], 3);
} else {
- if (strchr ($server[1], '.') === false) {
+ if (strpos($server[1], '.') === false) {
// e.g. 'localhost' or other local names
$_CONF['cookiedomain'] = '';
} else {
@@ -56,7 +58,7 @@
}
}
if ($_SESS_VERBOSE) {
- COM_errorLog ("Setting cookiedomain = '" . $_CONF['cookiedomain'] . "'", 1);
+ COM_errorLog("Setting cookiedomain = '" . $_CONF['cookiedomain'] . "'", 1);
}
}
@@ -65,9 +67,6 @@
*
* Much of this code if from phpBB (www.phpbb.org). This checks the session
* cookie and long term cookie to get the users state.
-*
-* @return void
-*
*/
function SESS_sessionCheck()
{
@@ -77,118 +76,96 @@ function SESS_sessionCheck()
COM_errorLog("*** Inside SESS_sessionCheck ***",1);
}
- $_USER = array();
+ $_USER = array(
+ 'uid' => Session::ANON_USER_ID,
+ );
// Check for a cookie on the users's machine. If the cookie exists, build
// an array of the users info and setup the theme.
// Flag indicates if session cookie and session data exist
- $session_exists = true;
-
- if (isset($_COOKIE[$_CONF['cookie_session']])) {
- $sessid = COM_applyFilter($_COOKIE[$_CONF['cookie_session']]);
+ $sessionExists = Session::init(array(
+ 'cookie_lifetime' => $_CONF['session_cookie_timeout'],
+ 'cookie_path' => $_CONF['cookie_path'],
+ 'cookie_domain' => $_CONF['cookiedomain'],
+ 'cookie_secure' => $_CONF['cookiesecure'],
+ 'session_name' => $_CONF['cookie_session'],
+ ));
+ $sessId = Session::getSessionId();
+ $status = -1;
+
+ if ($sessionExists) {
if ($_SESS_VERBOSE) {
- COM_errorLog("Got $sessid as the session ID",1);
+ COM_errorLog("Got {$sessId} as the session ID",1);
}
- $userid = SESS_getUserIdFromSession($sessid, $_CONF['session_cookie_timeout'],
- $_SERVER['REMOTE_ADDR'], $_CONF['cookie_ip']);
-
+ $userId = Session::getUid();
if ($_SESS_VERBOSE) {
- COM_errorLog("Got $userid as User ID from the session ID",1);
+ COM_errorLog("Got {$userId} as User ID from the session ID",1);
}
- if ($userid > 1) {
+ if ($userId > Session::ANON_USER_ID) {
// Check user status
- $status = SEC_checkUserStatus($userid);
+ $status = SEC_checkUserStatus($userId);
if (($status == USER_ACCOUNT_ACTIVE) ||
($status == USER_ACCOUNT_AWAITING_ACTIVATION ||
$status == USER_ACCOUNT_LOCKED ||
$status == USER_ACCOUNT_NEW_EMAIL ||
$status == USER_ACCOUNT_NEW_PASSWORD)) {
- SESS_updateSessionTime($sessid, $_CONF['cookie_ip']);
- $_USER = SESS_getUserDataFromId($userid);
+ SESS_updateSessionTime($sessId);
+ $_USER = SESS_getUserDataFromId($userId);
if ($_SESS_VERBOSE) {
$str = "Got " . count($_USER) . " pieces of data from userdata \n";
- foreach ($_USER as $k => $v)
+ foreach ($_USER as $k => $v) {
$str .= sprintf("%15s [%s] \n", $k, $v);
+ }
COM_errorLog($str, 1);
}
- $_USER['auto_login'] = false;
+
+ SESS_issueAutoLoginCookie($userId);
+ }
+ } elseif ($userId === Session::ANON_USER_ID) {
+ // Check if the permanent cookie exists
+ $userId = SESS_handleAutoLogin();
+
+ if ($userId > Session::ANON_USER_ID) {
+ SESS_newSession($userId, $_SERVER['REMOTE_ADDR'], $_CONF['session_cookie_timeout']);
+ $_USER = SESS_getUserDataFromId($userId);
+ SESS_issueAutoLoginCookie($userId);
+ } else {
+ // Anonymous User has session so update any information
+ SESS_updateSessionTime($sessId);
}
- } elseif ($userid == 1) {
- // Anonymous User has session so update any information
- SESS_updateSessionTime($sessid, $_CONF['cookie_ip']);
- } else {
- // Session probably expired
- $session_exists = false;
}
} else {
+ // Session cookie was not found, but the Session class was initialized.
if ($_SESS_VERBOSE) {
COM_errorLog("Session cookie not found",1);
}
- $session_exists = false;
- }
- if ($session_exists === false) {
// Check if the permanent cookie exists
- $userid = '';
- if (isset($_COOKIE[$_CONF['cookie_name']])) {
- $userid = COM_applyFilter($_COOKIE[$_CONF['cookie_name']], true);
- }
+ $userId = SESS_handleAutoLogin();
- if (!empty($userid)) {
+ if ($userId > Session::ANON_USER_ID) {
// Session cookie or session data don't exist, but a permanent cookie does.
- // Start a new session cookie and session data;
if ($_SESS_VERBOSE) {
- COM_errorLog("Got $userid as User ID from the permanent cookie",1);
- }
-
- $cookie_password = '';
- $userpass = '';
- if (($userid > 1) &&
- isset($_COOKIE[$_CONF['cookie_password']])) {
- $cookie_password = $_COOKIE[$_CONF['cookie_password']];
- $userpass = DB_getItem($_TABLES['users'], 'passwd',
- "uid = $userid");
+ COM_errorLog("Got {$userId} as User ID from the permanent cookie", 1);
}
- if (empty($cookie_password) || ($cookie_password <> $userpass)) {
- if ($_SESS_VERBOSE) {
- COM_errorLog("Password comparison failed or cookie password missing",1);
- }
- // Invalid or manipulated cookie data
- $ctime = time() - 10000;
- SEC_setCookie($_CONF['cookie_session'], '', $ctime);
- SEC_setCookie($_CONF['cookie_password'], '', $ctime);
- SEC_setCookie($_CONF['cookie_name'], '', $ctime);
+ Session::setUid($userId);
- COM_clearSpeedlimit($_CONF['login_speedlimit'], 'login');
- if (COM_checkSpeedlimit('login', $_CONF['login_attempts']) > 0) {
- if (! defined('XHTML')) { define('XHTML', ''); }
- COM_displayMessageAndAbort(82, '', 403, 'Access denied');
- }
- COM_updateSpeedlimit('login');
- } elseif ($userid > 1) {
+ // Check user status
+ $status = SEC_checkUserStatus($userId);
+ if (($status == USER_ACCOUNT_ACTIVE) ||
+ ($status == USER_ACCOUNT_AWAITING_ACTIVATION)) {
if ($_SESS_VERBOSE) {
- COM_errorLog("Password comparison passed",1);
- }
- // Check user status
- $status = SEC_checkUserStatus($userid);
- if (($status == USER_ACCOUNT_ACTIVE) ||
- ($status == USER_ACCOUNT_AWAITING_ACTIVATION)) {
- if ($_SESS_VERBOSE) {
- COM_errorLog("Create new session and write cookie",1);
- }
- // Create new session and write cookie
- $sessid = SESS_newSession($userid, $_SERVER['REMOTE_ADDR'],
- $_CONF['session_cookie_timeout'], $_CONF['cookie_ip']);
- SESS_setSessionCookie($sessid, $_CONF['session_cookie_timeout'],
- $_CONF['cookie_session'], $_CONF['cookie_path'],
- $_CONF['cookiedomain'], $_CONF['cookiesecure']);
- $_USER = SESS_getUserDataFromId($userid);
- $_USER['auto_login'] = true;
+ COM_errorLog('Create new session', 1);
}
+
+ // Create new session and write cookie
+ SESS_newSession($userId, $_SERVER['REMOTE_ADDR'], $_CONF['session_cookie_timeout']);
+ $_USER = SESS_getUserDataFromId($userId);
+ $_USER['auto_login'] = true;
}
} else {
if ($_SESS_VERBOSE) {
@@ -197,12 +174,7 @@ function SESS_sessionCheck()
// Anonymous user has session id but it has been expired and wiped from the db so reset.
// Or new anonymous user so create new session and write cookie.
- $userid = 1;
- $sessid = SESS_newSession($userid, $_SERVER['REMOTE_ADDR'],
- $_CONF['session_cookie_timeout'], $_CONF['cookie_ip']);
- SESS_setSessionCookie($sessid, $_CONF['session_cookie_timeout'],
- $_CONF['cookie_session'], $_CONF['cookie_path'],
- $_CONF['cookiedomain'], $_CONF['cookiesecure']);
+ SESS_newSession($userId, $_SERVER['REMOTE_ADDR'], $_CONF['session_cookie_timeout']);
}
}
@@ -210,10 +182,8 @@ function SESS_sessionCheck()
COM_errorLog("*** Leaving SESS_sessionCheck ***",1);
}
- $_USER['session_id'] = $sessid;
-
// Check to see if user status is set to something we have to redirect the user too
- if (isset($_USER['uid']) && $_USER['uid'] > 1) {
+ if (isset($_USER['uid']) && $_USER['uid'] > Session::ANON_USER_ID) {
// Check if active user has email account and if required
// Doesn't matter if remote account or not
if ($_CONF['require_user_email'] && empty($_USER['email']) && $_USER['status'] == USER_ACCOUNT_ACTIVE) {
@@ -223,12 +193,12 @@ function SESS_sessionCheck()
if ($_USER['status'] == USER_ACCOUNT_LOCKED) {
// Account is locked so user shouldn't be logged in
- if ($_SERVER['PHP_SELF'] != '/users.php') {
+ if ($_SERVER['PHP_SELF'] !== '/users.php') {
COM_redirect($_CONF['site_url'] . '/users.php?mode=logout&msg=17');
}
} elseif ($_USER['status'] == USER_ACCOUNT_NEW_EMAIL || $_USER['status'] == USER_ACCOUNT_NEW_PASSWORD) {
// Account requires additional info so get it
- if ($_SERVER['PHP_SELF'] != '/users.php') {
+ if ($_SERVER['PHP_SELF'] !== '/users.php') {
if ($_USER['status'] == USER_ACCOUNT_NEW_EMAIL) {
COM_redirect($_CONF['site_url'] . '/users.php?mode=newemailstatus');
} elseif ($status == USER_ACCOUNT_NEW_PASSWORD) {
@@ -246,356 +216,300 @@ function SESS_sessionCheck()
* Adds a new session to the database for the given userid and returns a new session ID.
* Also deletes all expired sessions from the database, based on the given session lifespan.
*
-* @param int $userid User ID to create session for
-* @param string $remote_ip IP address user is connected from
-* @param string $lifespan How long (seconds) this cookie should persist
-* @param int $md5_based If 1 session will be MD5 hash of ip address
-* @return string Session ID
-*
+* @param int $userId User ID to create session for
+* @param string $remote_ip IP address user is connected from
+* @param string $lifespan How long (seconds) this cookie should persist
+* @return string Session ID
*/
-function SESS_newSession($userid, $remote_ip, $lifespan, $md5_based=0)
+function SESS_newSession($userId, $remote_ip, $lifespan)
{
global $_TABLES, $_CONF, $_SESS_VERBOSE;
if ($_SESS_VERBOSE) {
- COM_errorLog("*** Inside SESS_newSession ***",1);
- COM_errorLog("Args to SESS_newSession: userid = $userid, "
- . "remote_ip = $remote_ip, lifespan = $lifespan, "
- . "md5_based = $md5_based",1);
- }
- $sessid = mt_rand();
-
- // For added security we are adding the option to build a IP-based
- // session ID. This has the advantage of better security but it may
- // required dialed users to login every time. You can turn the below
- // code on in the configuration (it's turned off by default)
- $md5_sessid = '';
- if ($md5_based == 1) {
- $ip = str_replace('.','',$remote_ip);
- $md5_sessid = md5($ip + $sessid);
+ COM_errorLog("*** Inside SESS_newSession ***", 1);
+ COM_errorLog(
+ "Args to SESS_newSession: userid = {$userId}, remote_ip = {$remote_ip}, lifespan = {$lifespan}",
+ 1
+ );
}
+ // Delete expired sessions from database
$ctime = time();
- $currtime = (string) ($ctime);
- $expirytime = (string) ($ctime - $lifespan);
- if (!isset($_COOKIE[$_CONF['cookie_session']])) {
- // ok, delete any old sessons for this user
- if ($userid > 1) {
- DB_delete($_TABLES['sessions'], 'uid', $userid);
- } else {
- DB_delete($_TABLES['sessions'], array('uid', 'remote_ip'),
- array(1, $remote_ip));
- }
- } else {
+ $currentTime = (string) ($ctime);
+ $expiryTime = (string) ($ctime - $lifespan);
+ $deleteResult = false;
+ $retryMax = 3;
+ $wait = 50000; // 50 ms
+
+ for ($i = 0; $i < $retryMax; $i++) {
DB_lockTable($_TABLES['sessions']);
- $deleteSQL = "DELETE FROM {$_TABLES['sessions']} WHERE (start_time < $expirytime)";
- $delresult = DB_query($deleteSQL);
+ $deleteSQL = "DELETE FROM {$_TABLES['sessions']} WHERE (start_time < {$expiryTime})";
+ $deleteResult = DB_query($deleteSQL);
DB_unlockTable($_TABLES['sessions']);
-
if ($_SESS_VERBOSE) {
COM_errorLog("Attempted to delete rows from session table with following SQL\n$deleteSQL\n",1);
- COM_errorLog("Got $delresult as a result from the query",1);
+ COM_errorLog("Got $deleteResult as a result from the query",1);
}
- if (!$delresult) {
- die("Delete failed in SESS_newSession()");
+ if ($deleteResult) {
+ break;
}
+
+ usleep($wait);
}
- // Remove the anonymous session for this user
- if ($userid > 1) {
- // Retrieve any session variables that we need to add to the new logged in session
- // To come
- // Delete record
- DB_delete($_TABLES['sessions'], array('uid', 'remote_ip'),
- array(1, $remote_ip));
+
+ if (!$deleteResult) {
+ die("Delete failed in SESS_newSession()");
}
+ // Delete old session from database
+ $oldSessionId = Session::getSessionId();
+ $escOldSessionId = DB_escapeString($oldSessionId);
+ DB_query("DELETE FROM {$_TABLES['sessions']} WHERE sess_id = '{$escOldSessionId}'");
+
+ // Create new session ID and insert it into database
+ $sessId = Session::regenerateId();
+ $escSessionId = DB_escapeString($sessId);
+ $escRemoteIp = DB_escapeString($remote_ip);
+
// Create new session
- if ($md5_based == 1) {
- $sql = "INSERT INTO {$_TABLES['sessions']} "
- . "(sess_id, md5_sess_id, uid, start_time, remote_ip, whos_online) "
- . "VALUES ($sessid, '$md5_sessid', $userid, $currtime, '$remote_ip', 1)";
- } else {
- $sql = "INSERT INTO {$_TABLES['sessions']} "
- . "(sess_id, uid, start_time, remote_ip, whos_online) "
- . "VALUES ($sessid, $userid, $currtime, '$remote_ip', 1)";
- }
+ Session::setUid($userId);
+ $sql = "INSERT INTO {$_TABLES['sessions']} (sess_id, uid, start_time, remote_ip, whos_online) "
+ . "VALUES ('{$escSessionId}', {$userId}, {$currentTime}, '{$escRemoteIp}', 1)";
$result = DB_query($sql);
if (!$result) {
- echo DB_error().": ".DB_error()."
";
- die("Insert failed in SESS_newSession()");
+ echo DB_error() . ': ' . DB_error() . '
';
+ die('Insert failed in SESS_newSession()');
}
- if ($_CONF['lastlogin'] == true) {
+ if ($_CONF['lastlogin']) {
// Update userinfo record to record the date and time as lastlogin
- DB_query("UPDATE {$_TABLES['userinfo']} SET lastlogin = UNIX_TIMESTAMP() WHERE uid=$userid");
+ DB_query("UPDATE {$_TABLES['userinfo']} SET lastlogin = UNIX_TIMESTAMP() WHERE uid = {$userId}");
}
if ($_SESS_VERBOSE) {
- COM_errorLog("Assigned the following session id: $sessid",1);
- COM_errorLog("*** Leaving SESS_newSession ***",1);
- }
- if ($md5_based == 1) {
- return $md5_sessid;
+ COM_errorLog("Assigned the following session id: {$sessId}", 1);
+ COM_errorLog("*** Leaving SESS_newSession ***", 1);
}
- return $sessid;
+
+ return $sessId;
}
/**
-* Sets the session cookie
+* Updates a session cookie's timeout and the session id
*
-* This saves the session ID to the session cookie on client's machine for
-* later use
-*
-* @param string $sessid Session ID to save to cookie
-* @param int $cookietime Cookie timeout value (not used)
-* @param string $cookiename Name of cookie to save sessiond ID to
-* @param string $cookiepath Path in which cookie should be sent to server for
-* @param string $cookiedomain Domain in which cookie should be sent to server for
-* @param int $cookiesecure if =1, set cookie only on https connection
+* Refresh the start_time of the given session in the database.
+* This is called whenever a page is hit by a user with a valid session.
*
+* @param string $sessId Session ID to update time for
+* @return string a new session ID
*/
-function SESS_setSessionCookie($sessid, $cookietime, $cookiename, $cookiepath, $cookiedomain, $cookiesecure)
+function SESS_updateSessionTime($sessId)
{
- global $_SESS_VERBOSE;
+ global $_TABLES;
- // This sets a cookie that will persist until the user closes their browser
- // window. since session expiry is handled on the server-side, cookie expiry
- // time isn't a big deal.
- if ($_SESS_VERBOSE) {
- COM_errorLog("Setting session cookie: setcookie($cookiename, $sessid, 0, "
- . "$cookiepath, $cookiedomain, $cookiesecure);", 1);
- }
+ $escOldSessionId = DB_escapeString($sessId);
+ $newSessionId = Session::regenerateId();
+ $escNewSessionId = DB_escapeString($newSessionId);
+ $newTime = (string) time();
+ $sql = "UPDATE {$_TABLES['sessions']} SET start_time = {$newTime}, "
+ . "whos_online = 1, sess_id = '{$escNewSessionId}' "
+ . "WHERE sess_id = '{$escOldSessionId}'";
+ DB_query($sql);
- if (SEC_setCookie($cookiename, $sessid, 0, $cookiepath, $cookiedomain,
- $cookiesecure) === false) {
- COM_errorLog("Failed to set session cookie.", 1);
- }
+ return $newSessionId;
}
/**
-* Gets the user id from Session ID
+* This ends a user session
*
-* Returns the userID associated with the given session, based on
-* the given session lifespan $cookietime and the given remote IP
-* address. If no match found, returns 0.
+* Delete the given session from the database. Used by the logout page.
*
-* @param string $sessid Session ID to get user ID from
-* @param string $cookietime Used to query DB for valid sessions
-* @param string $remote_ip Used to pull session we need
-* @param int $md5_based Let's us now if we need to take MD5 hash into consideration
-* @return int User ID
+* @param int $userId User ID to end session of
+* @return bool Always true for some reason
*/
-function SESS_getUserIdFromSession($sessid, $cookietime, $remote_ip, $md5_based=0)
+function SESS_endUserSession($userId)
{
- global $_TABLES, $_SESS_VERBOSE;
-
- if ($_SESS_VERBOSE) {
- COM_errorLog("*** Inside SESS_getUserIdFromSession ***",1);
- }
-
- $mintime = (string) (time() - $cookietime);
-
- if ($md5_based == 1) {
- $sql_where = "md5_sess_id = '$sessid'";
- } else {
- $sql_where = "sess_id = '$sessid'";
- }
- $sql = "SELECT uid FROM {$_TABLES['sessions']} WHERE "
- . "($sql_where) AND (start_time > $mintime) AND (remote_ip = '$remote_ip')";
-
- if ($_SESS_VERBOSE) {
- COM_errorLog("SQL in SESS_getUserIdFromSession is: \n$sql \n", 1);
- }
+ global $_CONF, $_TABLES;
- $result = DB_query($sql);
- $numrows = DB_numRows($result);
+ $userId = (int) $userId;
- if ($_SESS_VERBOSE) {
- COM_errorLog("*** Leaving SESS_getUserIdFromSession ***",1);
+ if (!(isset($_CONF['demo_mode']) && $_CONF['demo_mode'])) {
+ DB_delete($_TABLES['sessions'], 'uid', $userId);
+ Session::setUid(Session::ANON_USER_ID);
}
- if ($numrows == 1) {
- $row = DB_fetchArray($result);
- return $row['uid'];
- }
- return 0;
+ return 1;
}
/**
-* Updates a session cookies timeout
-*
-* Refresh the start_time of the given session in the database.
-* This is called whenever a page is hit by a user with a valid session.
-*
-* @param string $sessid Session ID to update time for
-* @param int $md5_based Indicates if sessid is MD5 hash
-* @return boolean always true for some reason
+* Gets user's data based on their user id
*
+* @param int $userId User ID of user to get data for
+* @return array returns user's data in an array
*/
-function SESS_updateSessionTime($sessid, $md5_based=0)
+function SESS_getUserDataFromId($userId)
{
global $_TABLES;
- $newtime = (string) time();
+ $userId = (int) $userId;
+ if ($userId <= Session::ANON_USER_ID) {
+ return array(
+ 'uid' => Session::ANON_USER_ID,
+ 'username' => 'anonymous',
+ );
+ }
+
+ $sql = "SELECT *,format FROM {$_TABLES['dateformats']},{$_TABLES['users']},{$_TABLES['userprefs']} "
+ . "WHERE {$_TABLES['dateformats']}.dfid = {$_TABLES['userprefs']}.dfid AND "
+ . "{$_TABLES['userprefs']}.uid = $userId AND {$_TABLES['users']}.uid = {$userId}";
- if ($md5_based == 1) {
- $sql_where = "md5_sess_id = '$sessid'";
- } else {
- $sql_where = "sess_id = '$sessid'";
+ if ((!$result = DB_query($sql)) || (!$myRow = DB_fetchArray($result, false))) {
+ return array(
+ 'uid' => $userId,
+ 'username' => 'anonymous',
+ 'error' => '1',
+ );
}
- DB_query("UPDATE {$_TABLES['sessions']} "
- . "SET start_time = $newtime, whos_online = 1 WHERE ($sql_where)");
- return 1;
+ return $myRow;
}
/**
-* This ends a user session
-*
-* Delete the given session from the database. Used by the logout page.
-*
-* @param int $userid User ID to end session of
-* @return boolean Always true for some reason
+* Retrieves a session variable from the db
*
+* @param string $name Variable name to retrieve
+* @return mixed data from variable
*/
-function SESS_endUserSession($userid)
+function SESS_getVariable($name)
{
- global $_CONF, $_TABLES;
+ return Session::getVar($name, '');
+}
- if (!(isset($_CONF['demo_mode']) && $_CONF['demo_mode'])) {
- DB_delete($_TABLES['sessions'], 'uid', $userid);
- }
+/**
+* Updates a session variable from the db
+*
+* @param string $name Variable name to update
+* @param mixed $value Value of variable
+* @return bool Always true for some reason
+*/
+function SESS_setVariable($name, $value)
+{
+ Session::setVar($name, $value);
return 1;
}
/**
-* Gets a user's data
-*
-* Gets user's data based on their username
-*
-* @param string $username Username of user to get data for
-* @return array returns user's data in an array
-*
-*/
-function SESS_getUserData($username)
+ * Handle an auto-login key
+ *
+ * @param int $lifeTime cookie lifetime
+ * @return int user id or 1 when no auto-login key was found
+ */
+function SESS_handleAutoLogin($lifeTime = -1)
{
- global $_TABLES;
+ global $_CONF, $_TABLES;
- $sql = "SELECT *,format FROM {$_TABLES['users']}, {$_TABLES['userprefs']}, {$_TABLES['dateformats']} "
- . "WHERE {$_TABLES['dateformats']}.dfid = {$_TABLES['userprefs']}.dfid AND "
- . "{$_TABLES['userprefs']}.uid = {$_TABLES['users']}.uid AND username = '$username'";
+ // Get an auto-login key from cookie
+ $autoLoginKey = Input::cookie($_CONF['cookie_name'], '');
+ $autoLoginKey = preg_replace('/[^0-9a-f]/', '', $autoLoginKey);
- if (!$result = DB_query($sql)) {
- COM_errorLog("Error in SESS_getUserData", 1);
+ if ($autoLoginKey === '') {
+ // No auto-login key was found in the permanent cookie
+ return 1;
}
- if (!$myrow = DB_fetchArray($result)) {
- COM_errorLog("Error in SESS_getUserData", 1);
+ $escAutoLoginKey = DB_escapeString($autoLoginKey);
+ $sql = "SELECT uid FROM {$_TABLES['users']} WHERE autologin_key = '{$escAutoLoginKey}'";
+ $result = DB_query($sql);
+ if (DB_error()) {
+ return 1;
}
- return $myrow;
-}
+ switch (DB_numRows($result)) {
+ case 0:
+ // The Auto-login key given was not found in database. Possible attack
+ COM_clearSpeedlimit($_CONF['login_speedlimit'], 'login');
+ if (COM_checkSpeedlimit('login', $_CONF['login_attempts']) > 0) {
+ COM_displayMessageAndAbort(82, '', 403, 'Access denied');
+ }
+ COM_updateSpeedlimit('login');
-/**
-* Gets user's data
-*
-* Gets user's data based on their user id
-*
-* @param int $userid User ID of user to get data for
-* @return array returns user's data in an array
-*
-*/
-function SESS_getUserDataFromId($userid)
-{
- global $_TABLES;
+ return 1;
+ break;
- $sql = "SELECT *,format FROM {$_TABLES['dateformats']},{$_TABLES['users']},{$_TABLES['userprefs']} "
- . "WHERE {$_TABLES['dateformats']}.dfid = {$_TABLES['userprefs']}.dfid AND "
- . "{$_TABLES['userprefs']}.uid = $userid AND {$_TABLES['users']}.uid = $userid";
+ case 1:
+ $A = DB_fetchArray($result, false);
+ $uid = (int) $A['uid'];
- if (!$result = DB_query($sql)) {
- $userdata = array('error' => '1');
- return $userdata;
- }
+ // Issue a new auto-login key
+ SESS_issueAutoLoginCookie($uid);
- if (!$myrow = DB_fetchArray($result, false)) {
- $userdata = array('error' => '1');
- return $userdata;
- }
+ return $uid;
+ break;
- return $myrow;
-}
+ default:
+ // very unlikely case
+ $sql = "UPDATE {$_TABLES['users']} SET autologin_key = '' WHERE autologin_key = {$escAutoLoginKey}";
+ DB_query($sql);
+ return 1;
+ break;
+ }
+}
/**
-* Gets the Session ID from the User Id
-*
-* Returns the session id associated with the user if available.
-* This is not for anonymous users. If no match found, returns an empty string.
-*
-* @param int $uid User Id to retrieve session Id for
-* @return string Session ID
-*/
-function SESS_getSessionIdFromUserId($uid)
+ * Issue a cookie containing an auto-login cookie
+ *
+ * @param int $userId
+ * @param int $lifeTime
+ * @return string a newly created auto-login key or false on failure
+ */
+function SESS_issueAutoLoginCookie($userId, $lifeTime = -1)
{
- global $_TABLES;
+ global $_CONF, $_TABLES;
- $retval = '';
- if ($uid > 1) {
- $retval = DB_getItem($_TABLES['sessions'], "sess_id", "uid = $uid");
+ // We don't issue auto-login cookies for anonymous users
+ $userId = (int) $userId;
+ if ($userId <= Session::ANON_USER_ID) {
+ return false;
}
- return $retval;
-}
+ $lifeTime = (int) $lifeTime;
+ if ($lifeTime <= 0) {
+ $lifeTime = COM_getUserCookieTimeout();
-/**
-* Retrieves a session variable from the db
-*
-* @param string $variable Variable name to retrieve
-* @return string data from variable
-*
-*/
-function SESS_getVariable($variable)
-{
- global $_TABLES, $_CONF, $_USER;
+ // This user doesn't want auto-login feature
+ if ($lifeTime <= 0) {
+ return false;
+ }
+ }
- $session_id = $_USER['session_id'];
+ $autoLoginKey = SEC_randomBytes(80);
+ $autoLoginKey = sha1($autoLoginKey);
- if ($_CONF['cookie_ip'] == 1) { // $md5_based Indicates if sessid is MD5 hash
- $sql_where = "md5_sess_id = '$session_id'";
+ if (SEC_setCookie($_CONF['cookie_name'], $autoLoginKey, time() + $lifeTime)) {
+ $escAutoLoginKey = DB_escapeString($autoLoginKey);
+ $sql = "UPDATE {$_TABLES['users']} SET autologin_key = '{$escAutoLoginKey}' WHERE uid = {$userId}";
+ DB_query($sql);
+ return $autoLoginKey;
} else {
- $sql_where = "sess_id = '$session_id'";
+ return false;
}
- $retval = DB_getItem($_TABLES['sessions'], $variable, $sql_where);
-
- return $retval;
}
/**
-* Updates a session variable from the db
-*
-* @param string $variable Variable name to update
-* @param string $value Value of variable
-* @param string $session_id Session ID of variable to update (0 = current session)
-* @return boolean always true for some reason
-*
-*/
-function SESS_setVariable($variable, $value, $session_id = '')
+ * Delete an existing auto-login key for the current user
+ */
+function SESS_deleteAutoLoginKey()
{
- global $_TABLES, $_CONF, $_USER;
+ global $_CONF, $_TABLES;
- if ($session_id === '') {
- $session_id = $_USER['session_id'];
- }
+ $autoLoginKey = Input::fCookie($_CONF['cookie_name'], '');
- if ($_CONF['cookie_ip'] == 1) { // $md5_based Indicates if sessid is MD5 hash
- $sql_where = "md5_sess_id = '$session_id'";
- } else {
- $sql_where = "sess_id = '$session_id'";
+ if (!empty($autoLoginKey)) {
+ $escAutoLoginKey = DB_escapeString($autoLoginKey);
+ $sql = "UPDATE {$_TABLES['users']} SET autologin_key = '' WHERE autologin_key = '{$escAutoLoginKey}'";
+ DB_query($sql);
+ SEC_setCookie($_CONF['cookie_name'], '', time() - 10000);
}
- DB_query("UPDATE {$_TABLES['sessions']} "
- . "SET $variable = '$value' WHERE ($sql_where)");
-
- return 1;
}