432 lines
15 KiB
PHP
Executable File
432 lines
15 KiB
PHP
Executable File
<?php
|
|
/*** *** *** *** *** ***
|
|
* @package Quadodo Login Script
|
|
* @file Session.class.php
|
|
* @start July 18th, 2007
|
|
* @author Douglas Rennehan
|
|
* @license http://www.opensource.org/licenses/gpl-license.php
|
|
* @version 1.2.1
|
|
* @link http://www.quadodo.net
|
|
*** *** *** *** *** ***
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*** *** *** *** *** ***
|
|
* Comments are always before the code they are commenting.
|
|
*** *** *** *** *** ***/
|
|
if (!defined('QUADODO_IN_SYSTEM')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Contains all necessary session functions
|
|
*/
|
|
class Session {
|
|
|
|
/**
|
|
* @var object $qls - Will contain everything else
|
|
*/
|
|
var $qls;
|
|
|
|
/**
|
|
* Construct the class
|
|
* @param object $qls - Contains all other classes
|
|
*/
|
|
function __construct(&$qls) {
|
|
$this->qls = &$qls;
|
|
}
|
|
|
|
/**
|
|
* Removes any sessions that haven't been accessed in the defined time
|
|
* should be around 2 weeks
|
|
* @return void but will output error if found
|
|
*/
|
|
function clear_old_sessions() {
|
|
|
|
// Define the liftime threshold
|
|
$time_minus_defined = time() - $this->qls->config['cookie_length'];
|
|
|
|
// Find all sessions that have expired
|
|
$result = $this->qls->SQL->select(
|
|
'value',
|
|
'sessions',
|
|
array('time' =>
|
|
array(
|
|
'<',
|
|
$time_minus_defined
|
|
)
|
|
)
|
|
);
|
|
|
|
// Loop through expired sessions
|
|
while ($row = $this->qls->SQL->fetch_assoc($result)) {
|
|
// Find session id of all users that have expired sessions
|
|
$user_data = $this->qls->SQL->select(
|
|
array('username', 'last_session_cookie_id'),
|
|
'users',
|
|
array('last_session' =>
|
|
array(
|
|
'=',
|
|
$row['value']
|
|
)
|
|
)
|
|
);
|
|
if($this->qls->SQL->num_rows($user_data)) {
|
|
$user_data = $this->qls->SQL->fetch_assoc($user_data);
|
|
// Preserve current user session id,
|
|
// switch PHP session to expired session,
|
|
// delete expired session,
|
|
// resume session with preserved session id.
|
|
$original_session_id = session_id();
|
|
session_id($user_data['last_session_cookie_id']);
|
|
session_start();
|
|
session_unset();
|
|
session_destroy();
|
|
session_id($original_session_id);
|
|
session_start();
|
|
}
|
|
// Delete expired session from database
|
|
$this->qls->SQL->delete(
|
|
'sessions',
|
|
array(
|
|
'value' => array(
|
|
'=',
|
|
$row['value']
|
|
)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generates a new unique id
|
|
* @param string $password - The user's password
|
|
* @param string $user_code - The user's activation code
|
|
* @return string
|
|
*/
|
|
function generate_unique_id($password, $user_code) {
|
|
$hash[] = md5(uniqid(rand(), true));
|
|
$hash[] = sha1(uniqid(rand(), true)) . $hash[0] . md5($user_code);
|
|
$hash[] = sha1($password . $hash[0] . $hash[1] . md5(sha1($user_code) . sha1($user_code))) . sha1($password);
|
|
$hash[] = md5($hash[0] . $hash[1] . $hash[2]) . sha1($hash[0] . $hash[1] . $hash[0]);
|
|
return sha1($hash[0] . $hash[1]. $hash[2] . $hash[3] . md5($user_code . $password));
|
|
}
|
|
|
|
/**
|
|
* Generates a unique value
|
|
* @param string $password - The user's password
|
|
* @param string $user_code - The user's activation code
|
|
* @param string $unique_id - The unique id previously generated
|
|
* @param integer $time - The UNIX timestamp of the session
|
|
* @return string
|
|
*/
|
|
function generate_unique_value($password, $user_code, $unique_id, $time) {
|
|
$hash[] = sha1($unique_id . $password . $user_code) . sha1(time() * 2 + $time);
|
|
$hash[] = md5($password . $user_code . $hash[0] . time() . $time);
|
|
$hash[] = sha1($hash[0] . $hash[1] . $user_code . sha1($password));
|
|
return sha1($hash[0] . $hash[1] . $hash[2] . sha1($password . $user_code . $time . $hash[1]));
|
|
}
|
|
|
|
/**
|
|
* Creates a new session
|
|
* @param string $username - The user's username
|
|
* @param string $password - The user's password
|
|
* @param string $user_code - The user's activation code
|
|
* @param bool $remember
|
|
* @optional boolean $remember - Use cookies or sessions?
|
|
* @return void
|
|
*/
|
|
function create_session($username, $password, $user_code, $remember = false) {
|
|
$time = time();
|
|
|
|
// Get user id for cookie/session
|
|
$user_id = $this->qls->SQL->select('id',
|
|
'users',
|
|
array('username' =>
|
|
array(
|
|
'=',
|
|
$username
|
|
)
|
|
)
|
|
);
|
|
$user_id = $this->qls->SQL->fetch_array($user_id);
|
|
|
|
// Generate the unique id
|
|
$unique_id = $this->generate_unique_id($password, $user_code);
|
|
|
|
// Generate unique value to go in users table and sessions table
|
|
$value = $this->generate_unique_value($password, $user_code, $unique_id, $time);
|
|
$sha1_time = sha1($time);
|
|
|
|
// Insert new session info into database
|
|
$this->qls->SQL->insert('sessions',
|
|
array(
|
|
'id',
|
|
'value',
|
|
'time'
|
|
),
|
|
array(
|
|
$unique_id,
|
|
$value,
|
|
$time
|
|
)
|
|
);
|
|
// Update users table
|
|
$this->qls->SQL->update('users',
|
|
array(
|
|
'last_session' => $value,
|
|
'last_session_cookie_id' => session_id(),
|
|
'last_login' => time()
|
|
),
|
|
array('username' =>
|
|
array(
|
|
'=',
|
|
$username
|
|
)
|
|
)
|
|
);
|
|
$this->qls->SQL->transaction('COMMIT');
|
|
|
|
if ($remember === true) {
|
|
// Set the three cookies
|
|
setcookie($this->qls->config['cookie_prefix'] . 'user_id', $user_id['id'], time() + $this->qls->config['cookie_length'], $this->qls->config['cookie_path'], $this->qls->config['cookie_domain']);
|
|
setcookie($this->qls->config['cookie_prefix'] . 'user_time', sha1($time), time() + $this->qls->config['cookie_length'], $this->qls->config['cookie_path'], $this->qls->config['cookie_domain']);
|
|
setcookie($this->qls->config['cookie_prefix'] . 'user_unique', $unique_id, time() + $this->qls->config['cookie_length'], $this->qls->config['cookie_path'], $this->qls->config['cookie_domain']);
|
|
}
|
|
|
|
// Set the three sessions
|
|
$_SESSION[$this->qls->config['cookie_prefix'] . 'user_id'] = $user_id['id'];
|
|
$_SESSION[$this->qls->config['cookie_prefix'] . 'user_time'] = sha1($time);
|
|
$_SESSION[$this->qls->config['cookie_prefix'] . 'user_unique'] = $unique_id;
|
|
|
|
}
|
|
|
|
/**
|
|
* This will fetch session info from the database
|
|
* @param array $information - Contains cookie information
|
|
* @return true on success, false on failure
|
|
*/
|
|
function fetch_session($information, $login=false) {
|
|
// $information[0] is the user_id (int) $_SESSION[$this->qls->config['cookie_prefix'] . 'user_id']
|
|
// $information[1] is the time (SHA1) $_SESSION[$this->qls->config['cookie_prefix'] . 'user_time']
|
|
// $information[2] is the unique_id (SHA1) $_SESSION[$this->qls->config['cookie_prefix'] . 'user_unique']
|
|
|
|
/**
|
|
* Get the user's last session code. Will be stored
|
|
* in $user_session['last_session']
|
|
*/
|
|
$user_session = $this->qls->SQL->select('*',
|
|
//$user_session = $this->qls->SQL->select('last_session',
|
|
'users',
|
|
array('id' =>
|
|
array(
|
|
'=',
|
|
$information[0]
|
|
)
|
|
)
|
|
);
|
|
$user_session = $this->qls->SQL->fetch_array($user_session);
|
|
/**
|
|
* Grabs the info from the sessions table.
|
|
* Basically verifying the session.
|
|
*/
|
|
$session_info = $this->qls->SQL->query("SELECT * FROM `{$this->qls->config['sql_prefix']}sessions` WHERE `id`='{$information[2]}' AND `value`='{$user_session['last_session']}'");
|
|
$session_info = $this->qls->SQL->fetch_array($session_info);
|
|
|
|
// Did it return a blank id? (not existent)
|
|
if ($session_info['id'] != '') {
|
|
// Are the times equal?
|
|
if (sha1($session_info['time']) == $information[1]) {
|
|
//Was this function called because the user is logging in?
|
|
if (!$login) {
|
|
$auth_id = $_COOKIE[$this->qls->config['cookie_prefix'] . 'auth_id'];
|
|
$client_auth_token = $_COOKIE[$this->qls->config['cookie_prefix'] . 'auth_token'];
|
|
$session_auth_token = $_SESSION[$this->qls->config['cookie_prefix'] . 'auth' . $auth_id];
|
|
|
|
//Check that the client token matches the corresponding session token. This protects against session hijacking.
|
|
if ($client_auth_token == $session_auth_token) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This will validate a user cookie/session
|
|
* @param array $information - Contains cookie information
|
|
* @return bool
|
|
*/
|
|
function validate_session($information) {
|
|
// $information[0] is the user_id (int) $_SESSION[$this->qls->config['cookie_prefix'] . 'user_id']
|
|
// $information[1] is the time (SHA1) $_SESSION[$this->qls->config['cookie_prefix'] . 'user_time']
|
|
// $information[2] is the unique_id (SHA1) $_SESSION[$this->qls->config['cookie_prefix'] . 'user_unique']
|
|
|
|
// Has to be an array, or no admittance!
|
|
if (is_array($information)) {
|
|
// Make sure they are SHA-1 hashes
|
|
if (strlen($information[1]) == 40
|
|
&& strlen($information[2]) == 40
|
|
&& preg_match('/^[a-fA-F0-9]{40}$/', $information[1])
|
|
&& preg_match('/^[a-fA-F0-9]{40}$/', $information[2])) {
|
|
// Validate the session while fetching it
|
|
if ($this->fetch_session($information)) {
|
|
// Get all the user information
|
|
$result = $this->qls->SQL->select('*',
|
|
'users',
|
|
array('id' =>
|
|
array(
|
|
'=',
|
|
$information[0]
|
|
)
|
|
)
|
|
);
|
|
|
|
$row = $this->qls->SQL->fetch_array($result);
|
|
|
|
// We need to update the session information
|
|
$new_time = time();
|
|
$new_time_hash = sha1($new_time);
|
|
|
|
if (isset($_COOKIE[$this->qls->config['cookie_prefix'] . 'user_time'])) {
|
|
setcookie($this->qls->config['cookie_prefix'] . 'user_time', $new_time_hash, time() + $this->qls->config['cookie_length'], $this->qls->config['cookie_path'], $this->qls->config['cookie_domain']);
|
|
}
|
|
|
|
$_SESSION[$this->qls->config['cookie_prefix'] . 'user_time'] = $new_time_hash;
|
|
|
|
// Update the session time
|
|
$this->qls->SQL->update('sessions',
|
|
array('time' => $new_time),
|
|
array('id' =>
|
|
array(
|
|
'=',
|
|
$information[2]
|
|
)
|
|
)
|
|
);
|
|
|
|
// Loop through and add to $user_info
|
|
foreach ($row as $key => $value) {
|
|
$this->qls->user_info[$key] = stripslashes($value);
|
|
}
|
|
|
|
// These lines will retrieve the users permissions
|
|
if ($this->qls->user_info['mask_id'] == 0) {
|
|
// The user is using the group mask
|
|
$group_mask = $this->qls->SQL->select('*',
|
|
'groups',
|
|
array('id' =>
|
|
array(
|
|
'=',
|
|
$this->qls->user_info['group_id']
|
|
)
|
|
)
|
|
);
|
|
$group_mask = $this->qls->SQL->fetch_array($group_mask);
|
|
$user_permissions = $this->qls->SQL->select('*',
|
|
'masks',
|
|
array('id' =>
|
|
array(
|
|
'=',
|
|
$group_mask['mask_id']
|
|
)
|
|
)
|
|
);
|
|
$user_permissions = $this->qls->SQL->fetch_array($user_permissions);
|
|
|
|
foreach ($user_permissions as $key => $value) {
|
|
if (!array_key_exists($key, $this->qls->user_info)) {
|
|
$this->qls->user_info[$key] = $value;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// The user has their own mask assigned to them
|
|
$user_permissions = $this->qls->SQL->select('*',
|
|
'masks',
|
|
array('id' =>
|
|
array(
|
|
'=',
|
|
$this->qls->user_info['mask_id']
|
|
)
|
|
)
|
|
);
|
|
|
|
$user_permissions = $this->qls->SQL->fetch_array($user_permissions);
|
|
|
|
foreach ($user_permissions as $key => $value) {
|
|
if (!array_key_exists($key, $this->qls->user_info)) {
|
|
$this->qls->user_info[$key] = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This will grab a user session
|
|
* @return bool
|
|
*/
|
|
function find_session() {
|
|
/**
|
|
* Is the user using sessions or nothing?
|
|
* Make sure the {cookie_prefix}user_id is numeric
|
|
*/
|
|
if (isset($_SESSION[$this->qls->config['cookie_prefix'] . 'user_id'])
|
|
&& is_numeric($_SESSION[$this->qls->config['cookie_prefix'] . 'user_id'])) {
|
|
$information = array(
|
|
$_SESSION[$this->qls->config['cookie_prefix'] . 'user_id'],
|
|
$_SESSION[$this->qls->config['cookie_prefix'] . 'user_time'],
|
|
$_SESSION[$this->qls->config['cookie_prefix'] . 'user_unique']
|
|
);
|
|
return $this->validate_session($information);
|
|
}
|
|
elseif (isset($_COOKIE[$this->qls->config['cookie_prefix'] . 'user_id'])
|
|
&& is_numeric($_COOKIE[$this->qls->config['cookie_prefix'] . 'user_id'])) {
|
|
$information = array(
|
|
$_COOKIE[$this->qls->config['cookie_prefix'] . 'user_id'],
|
|
$_COOKIE[$this->qls->config['cookie_prefix'] . 'user_time'],
|
|
$_COOKIE[$this->qls->config['cookie_prefix'] . 'user_unique']
|
|
);
|
|
return $this->validate_session($information);
|
|
}
|
|
else {
|
|
return $this->validate_session('');
|
|
}
|
|
}
|
|
}
|
|
?>
|